diff options
-rw-r--r-- | chip/stm32/build.mk | 1 | ||||
-rw-r--r-- | chip/stm32/usb_gpio.c | 81 | ||||
-rw-r--r-- | chip/stm32/usb_gpio.h | 119 | ||||
-rw-r--r-- | include/config.h | 4 |
4 files changed, 205 insertions, 0 deletions
diff --git a/chip/stm32/build.mk b/chip/stm32/build.mk index b23f044554..1c5081a5da 100644 --- a/chip/stm32/build.mk +++ b/chip/stm32/build.mk @@ -39,6 +39,7 @@ chip-$(CONFIG_ADC)+=adc-$(CHIP_FAMILY).o chip-$(CONFIG_PWM)+=pwm.o chip-$(CONFIG_USB)+=usb.o usb_endpoints.o chip-$(CONFIG_USB_CONSOLE)+=usb_console.o +chip-$(CONFIG_USB_GPIO)+=usb_gpio.o chip-$(CONFIG_USB_HID)+=usb_hid.o chip-$(CONFIG_USB_MS)+=usb_ms.o usb_ms_scsi.o chip-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_phy.o diff --git a/chip/stm32/usb_gpio.c b/chip/stm32/usb_gpio.c new file mode 100644 index 0000000000..027ddadaae --- /dev/null +++ b/chip/stm32/usb_gpio.c @@ -0,0 +1,81 @@ +/* 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. + */ + +#include "common.h" +#include "gpio.h" +#include "link_defs.h" +#include "registers.h" +#include "usb_gpio.h" + +void usb_gpio_tx(struct usb_gpio_config const *config) +{ + size_t i; + uint32_t mask = 1; + uint32_t value = 0; + + for (i = 0; i < config->num_gpios; ++i, mask <<= 1) + value |= (gpio_get_level(config->gpios[i])) ? mask : 0; + + config->tx_ram[0] = value; + config->tx_ram[1] = value >> 16; + + btable_ep[config->endpoint].tx_count = USB_GPIO_TX_PACKET_SIZE; + + /* + * TX packet updated, mark the packet as VALID. + */ + STM32_TOGGLE_EP(config->endpoint, EP_TX_MASK, EP_TX_VALID, 0); +} + +void usb_gpio_rx(struct usb_gpio_config const *config) +{ + size_t i; + uint32_t mask = 1; + uint32_t set_mask = ((uint32_t)(config->rx_ram[0]) | + (uint32_t)(config->rx_ram[1]) << 16); + uint32_t clear_mask = ((uint32_t)(config->rx_ram[2]) | + (uint32_t)(config->rx_ram[3]) << 16); + uint32_t ignore_mask = set_mask & clear_mask; + + if ((btable_ep[config->endpoint].rx_count & 0x3ff) == + USB_GPIO_RX_PACKET_SIZE) { + for (i = 0; i < config->num_gpios; ++i, mask <<= 1) { + if (ignore_mask & mask) + ; + else if (set_mask & mask) + gpio_set_level(config->gpios[i], 1); + else if (clear_mask & mask) + gpio_set_level(config->gpios[i], 0); + } + } + + /* + * RX packet consumed, mark the packet as VALID. + */ + STM32_TOGGLE_EP(config->endpoint, EP_RX_MASK, EP_RX_VALID, 0); +} + +void usb_gpio_reset(struct usb_gpio_config const *config) +{ + int i = config->endpoint; + + btable_ep[i].tx_addr = usb_sram_addr(config->tx_ram); + btable_ep[i].tx_count = USB_GPIO_TX_PACKET_SIZE; + + btable_ep[i].rx_addr = usb_sram_addr(config->rx_ram); + btable_ep[i].rx_count = ((USB_GPIO_RX_PACKET_SIZE / 2) << 10); + + /* + * Initialize TX buffer with zero, the first IN transaction will fill + * this in with a valid value. + */ + config->tx_ram[0] = 0; + config->tx_ram[1] = 0; + + STM32_USB_EP(i) = ((i << 0) | /* Endpoint Addr*/ + (3 << 4) | /* TX Valid */ + (0 << 9) | /* Bulk EP */ + (3 << 12)); /* RX Valid */ +} diff --git a/chip/stm32/usb_gpio.h b/chip/stm32/usb_gpio.h new file mode 100644 index 0000000000..2027df9d21 --- /dev/null +++ b/chip/stm32/usb_gpio.h @@ -0,0 +1,119 @@ +/* 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 CHIP_STM32_USB_GPIO_H +#define CHIP_STM32_USB_GPIO_H + +/* STM32 USB GPIO driver for Chrome EC */ + +#include "compile_time_macros.h" +#include "usb.h" + +/* + * 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 { + /* + * 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 = { \ + .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 /* CHIP_STM32_USB_GPIO_H */ diff --git a/include/config.h b/include/config.h index fdb980eb4c..e6cb68c132 100644 --- a/include/config.h +++ b/include/config.h @@ -1092,6 +1092,10 @@ #undef CONFIG_USB_SWITCH_PI3USB9281_MUX_GPIO /*****************************************************************************/ +/* USB GPIO config */ +#undef CONFIG_USB_GPIO + +/*****************************************************************************/ /* Support computing hash of code for verified boot */ #undef CONFIG_VBOOT_HASH |