summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorAnton Staaf <robotboy@chromium.org>2014-09-02 10:36:00 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-08 02:50:48 +0000
commita3ddf04ca9904e73ae6b7bec0218f5861b3f2a74 (patch)
tree5c4efa1d5f50a90b052dd2549c68326a382314d1 /chip
parentbd59d5bfb6a9e6fa116e19f11fe31ae98cc00e88 (diff)
downloadchrome-ec-a3ddf04ca9904e73ae6b7bec0218f5861b3f2a74.tar.gz
stm32-USB: USB GPIO control driver
Simple control of GPIOs over USB. Signed-off-by: Anton Staaf <robotboy@chromium.org> BRANCH=None BUG=None TEST=make buildall -j Change-Id: Ic5deccd1a70080742d5ac745b537ebecd56d7443 Reviewed-on: https://chromium-review.googlesource.com/217528 Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Commit-Queue: Anton Staaf <robotboy@chromium.org> Tested-by: Anton Staaf <robotboy@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/stm32/build.mk1
-rw-r--r--chip/stm32/usb_gpio.c81
-rw-r--r--chip/stm32/usb_gpio.h119
3 files changed, 201 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 */