| /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #ifndef __CROS_EC_USB_GPIO_H |
| #define __CROS_EC_USB_GPIO_H |
| |
| /* STM32 USB GPIO driver for Chrome EC */ |
| |
| #include "compile_time_macros.h" |
| #include "usb_descriptor.h" |
| #include "usb_hw.h" |
| |
| struct usb_gpio_state { |
| uint32_t set_mask; |
| uint32_t clear_mask; |
| }; |
| |
| /* |
| * Compile time Per-USB gpio configuration stored in flash. Instances of this |
| * structure are provided by the user of the USB gpio. This structure binds |
| * together all information required to operate a USB gpio. |
| */ |
| struct usb_gpio_config { |
| struct usb_gpio_state *state; |
| |
| /* |
| * Endpoint index, and pointers to the USB packet RAM buffers. |
| */ |
| int endpoint; |
| |
| usb_uint *rx_ram; |
| usb_uint *tx_ram; |
| |
| /* |
| * GPIO list |
| */ |
| enum gpio_signal const *gpios; |
| size_t num_gpios; |
| }; |
| |
| #define USB_GPIO_RX_PACKET_SIZE 8 |
| #define USB_GPIO_TX_PACKET_SIZE 4 |
| |
| /* |
| * Convenience macro for defining a USB GPIO driver and its associated state. |
| * |
| * NAME is used to construct the names of the trampoline functions, |
| * usb_gpio_state struct, and usb_gpio_config struct, the latter is just |
| * called NAME. |
| * |
| * INTERFACE is the index of the USB interface to associate with this |
| * GPIO driver. |
| * |
| * ENDPOINT is the index of the USB bulk endpoint used for receiving and |
| * transmitting bytes. |
| */ |
| #define USB_GPIO_CONFIG(NAME, \ |
| GPIO_LIST, \ |
| INTERFACE, \ |
| ENDPOINT) \ |
| BUILD_ASSERT(ARRAY_SIZE(GPIO_LIST) <= 32); \ |
| static usb_uint CONCAT2(NAME, _ep_rx_buffer)[USB_GPIO_RX_PACKET_SIZE / 2] __usb_ram; \ |
| static usb_uint CONCAT2(NAME, _ep_tx_buffer)[USB_GPIO_TX_PACKET_SIZE / 2] __usb_ram; \ |
| struct usb_gpio_config const NAME = { \ |
| .state = &((struct usb_gpio_state){}), \ |
| .endpoint = ENDPOINT, \ |
| .rx_ram = CONCAT2(NAME, _ep_rx_buffer), \ |
| .tx_ram = CONCAT2(NAME, _ep_tx_buffer), \ |
| .gpios = GPIO_LIST, \ |
| .num_gpios = ARRAY_SIZE(GPIO_LIST), \ |
| }; \ |
| const struct usb_interface_descriptor \ |
| USB_IFACE_DESC(INTERFACE) = { \ |
| .bLength = USB_DT_INTERFACE_SIZE, \ |
| .bDescriptorType = USB_DT_INTERFACE, \ |
| .bInterfaceNumber = INTERFACE, \ |
| .bAlternateSetting = 0, \ |
| .bNumEndpoints = 2, \ |
| .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ |
| .bInterfaceSubClass = 0, \ |
| .bInterfaceProtocol = 0, \ |
| .iInterface = 0, \ |
| }; \ |
| const struct usb_endpoint_descriptor \ |
| USB_EP_DESC(INTERFACE, 0) = { \ |
| .bLength = USB_DT_ENDPOINT_SIZE, \ |
| .bDescriptorType = USB_DT_ENDPOINT, \ |
| .bEndpointAddress = 0x80 | ENDPOINT, \ |
| .bmAttributes = 0x02 /* Bulk IN */, \ |
| .wMaxPacketSize = USB_GPIO_TX_PACKET_SIZE, \ |
| .bInterval = 10, \ |
| }; \ |
| const struct usb_endpoint_descriptor \ |
| USB_EP_DESC(INTERFACE, 1) = { \ |
| .bLength = USB_DT_ENDPOINT_SIZE, \ |
| .bDescriptorType = USB_DT_ENDPOINT, \ |
| .bEndpointAddress = ENDPOINT, \ |
| .bmAttributes = 0x02 /* Bulk OUT */, \ |
| .wMaxPacketSize = USB_GPIO_RX_PACKET_SIZE, \ |
| .bInterval = 0, \ |
| }; \ |
| static void CONCAT2(NAME, _ep_tx)(void) \ |
| { \ |
| usb_gpio_tx(&NAME); \ |
| } \ |
| static void CONCAT2(NAME, _ep_rx)(void) \ |
| { \ |
| usb_gpio_rx(&NAME); \ |
| } \ |
| static void CONCAT2(NAME, _ep_reset)(void) \ |
| { \ |
| usb_gpio_reset(&NAME); \ |
| } \ |
| USB_DECLARE_EP(ENDPOINT, \ |
| CONCAT2(NAME, _ep_tx), \ |
| CONCAT2(NAME, _ep_rx), \ |
| CONCAT2(NAME, _ep_reset)) |
| |
| |
| /* |
| * These functions are used by the trampoline functions defined above to |
| * connect USB endpoint events with the generic USB GPIO driver. |
| */ |
| void usb_gpio_tx(struct usb_gpio_config const *config); |
| void usb_gpio_rx(struct usb_gpio_config const *config); |
| void usb_gpio_reset(struct usb_gpio_config const *config); |
| |
| #endif /* __CROS_EC_USB_GPIO_H */ |