summaryrefslogtreecommitdiff
path: root/chip/stm32/usb_spi.c
diff options
context:
space:
mode:
authorAnton Staaf <robotboy@chromium.org>2014-12-02 10:37:54 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-12-08 21:51:52 +0000
commit731a2e74872159ecfa910c3174e9d3ae50ff2dae (patch)
tree84de2d9b11eee75f206c0dc008d98813e4e32c03 /chip/stm32/usb_spi.c
parent0f4550468fac985711ef10629ad9d5129c9e4539 (diff)
downloadchrome-ec-731a2e74872159ecfa910c3174e9d3ae50ff2dae.tar.gz
USB-SPI: Support board enable/disable functionality
This allows the USB SPI bridge to be controlled from the host at a larger timescale than a single SPI transaction. This allows the host to signal that many transactions will take place and that the device should keep the SPI bridge enabled across them. This allows the device to hold the AP or other possible user of the SPI bus in reset while the bridge is enabled. Signed-off-by: Anton Staaf <robotboy@chromium.org> BRANCH=None BUG=None TEST=make buildall -j Change-Id: Ifd6f96b0ff47f35d853735d44e255a205b0e677a Reviewed-on: https://chromium-review.googlesource.com/232732 Tested-by: Anton Staaf <robotboy@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Commit-Queue: Anton Staaf <robotboy@chromium.org>
Diffstat (limited to 'chip/stm32/usb_spi.c')
-rw-r--r--chip/stm32/usb_spi.c69
1 files changed, 61 insertions, 8 deletions
diff --git a/chip/stm32/usb_spi.c b/chip/stm32/usb_spi.c
index 6140f4629b..f0e163cb1b 100644
--- a/chip/stm32/usb_spi.c
+++ b/chip/stm32/usb_spi.c
@@ -13,10 +13,10 @@
static int16_t usb_spi_map_error(int error)
{
switch (error) {
- case EC_SUCCESS: return usb_spi_success;
- case EC_ERROR_TIMEOUT: return usb_spi_timeout;
- case EC_ERROR_BUSY: return usb_spi_busy;
- default: return usb_spi_unknown_error | (error & 0x7fff);
+ case EC_SUCCESS: return USB_SPI_SUCCESS;
+ case EC_ERROR_TIMEOUT: return USB_SPI_TIMEOUT;
+ case EC_ERROR_BUSY: return USB_SPI_BUSY;
+ default: return USB_SPI_UNKNOWN_ERROR | (error & 0x7fff);
}
}
@@ -77,11 +77,13 @@ int usb_spi_service_request(struct usb_spi_config const *config)
write_count = (config->buffer[0] >> 0) & 0xff;
read_count = (config->buffer[0] >> 8) & 0xff;
- if (write_count > USB_SPI_MAX_WRITE_COUNT ||
- write_count != (count - 2)) {
- config->buffer[0] = usb_spi_write_count_invalid;
+ if (config->state->disabled || !config->state->enabled) {
+ config->buffer[0] = USB_SPI_DISABLED;
+ } else if (write_count > USB_SPI_MAX_WRITE_COUNT ||
+ write_count != (count - 2)) {
+ config->buffer[0] = USB_SPI_WRITE_COUNT_INVALID;
} else if (read_count > USB_SPI_MAX_READ_COUNT) {
- config->buffer[0] = usb_spi_read_count_invalid;
+ config->buffer[0] = USB_SPI_READ_COUNT_INVALID;
} else {
config->buffer[0] = usb_spi_map_error(
spi_transaction((uint8_t *)(config->buffer + 1),
@@ -122,3 +124,54 @@ void usb_spi_reset(struct usb_spi_config const *config)
(0 << 9) | /* Bulk EP */
(3 << 12)); /* RX Valid */
}
+
+int usb_spi_interface(struct usb_spi_config const *config,
+ usb_uint *rx_buf,
+ usb_uint *tx_buf)
+{
+ struct usb_setup_packet setup;
+
+ usb_read_setup_packet(rx_buf, &setup);
+
+ if (setup.bmRequestType != (USB_DIR_OUT |
+ USB_TYPE_VENDOR |
+ USB_RECIP_INTERFACE))
+ return 1;
+
+ if (setup.wValue != 0 ||
+ setup.wIndex != config->interface ||
+ setup.wLength != 0)
+ return 1;
+
+ if (config->state->disabled)
+ return 1;
+
+ switch (setup.bRequest) {
+ case USB_SPI_REQ_ENABLE:
+ usb_spi_board_enable(config);
+ config->state->enabled = 1;
+ break;
+
+ case USB_SPI_REQ_DISABLE:
+ config->state->enabled = 0;
+ usb_spi_board_disable(config);
+ break;
+
+ default: return 1;
+ }
+
+ btable_ep[0].tx_count = 0;
+ STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, EP_STATUS_OUT);
+ return 0;
+}
+
+void usb_spi_enable(struct usb_spi_config const *config, int enabled)
+{
+ config->state->disabled = !enabled;
+
+ if (config->state->disabled &&
+ config->state->enabled) {
+ config->state->enabled = 0;
+ usb_spi_board_disable(config);
+ }
+}