diff options
author | Anton Staaf <robotboy@chromium.org> | 2015-03-17 11:49:29 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-03-23 19:23:35 +0000 |
commit | a0158dd136b63b2daffd666d51d84a67481cb609 (patch) | |
tree | b3ceb010fbba052fb63825d862a0ef2eae2767a6 /chip/stm32/usb_spi.c | |
parent | 4002d66297f381c18e1118fa8e2cc156bc5baffd (diff) | |
download | chrome-ec-a0158dd136b63b2daffd666d51d84a67481cb609.tar.gz |
CCD: Add ability to enable and disable SPI bridgestabilize-6909.B
This required changing the USB-SPI implementation slightly
so that all work is done within the deferred callback. In
particular, this allows the board specific enable and disable
functions to do things that can only be done from a task
context, like sleeping.
Signed-off-by: Anton Staaf <robotboy@chromium.org>
BRANCH=None
BUG=None
TEST=make buildall -j
Change-Id: I3f6a01ed9d6f31a3259ba0a0f6b4e123d6d2e718
Reviewed-on: https://chromium-review.googlesource.com/260964
Trybot-Ready: Anton Staaf <robotboy@chromium.org>
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.c | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/chip/stm32/usb_spi.c b/chip/stm32/usb_spi.c index 24b8a530d7..c81f01ac23 100644 --- a/chip/stm32/usb_spi.c +++ b/chip/stm32/usb_spi.c @@ -59,32 +59,53 @@ static void usb_spi_write_packet(struct usb_spi_config const *config, STM32_TOGGLE_EP(config->endpoint, EP_TX_MASK, EP_TX_VALID, 0); } +static int rx_valid(struct usb_spi_config const *config) +{ + return (STM32_USB_EP(config->endpoint) & EP_RX_MASK) == EP_RX_VALID; +} + void usb_spi_deferred(struct usb_spi_config const *config) { - uint8_t count; - uint8_t write_count; - uint8_t read_count; - - count = usb_spi_read_packet(config); - write_count = (config->buffer[0] >> 0) & 0xff; - read_count = (config->buffer[0] >> 8) & 0xff; - - 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; - } else { - config->buffer[0] = usb_spi_map_error( - spi_transaction((uint8_t *)(config->buffer + 1), - write_count, - (uint8_t *)(config->buffer + 1), - read_count)); + /* + * If our overall enabled state has changed we call the board specific + * enable or disable routines and save our new state. + */ + int enabled = (config->state->enabled_host && + config->state->enabled_device); + + if (enabled ^ config->state->enabled) { + if (enabled) usb_spi_board_enable(config); + else usb_spi_board_disable(config); + + config->state->enabled = enabled; } - usb_spi_write_packet(config, read_count + 2); + /* + * And if there is a USB packet waiting we process it and generate a + * response. + */ + if (!rx_valid(config)) { + uint8_t count = usb_spi_read_packet(config); + uint8_t write_count = (config->buffer[0] >> 0) & 0xff; + uint8_t read_count = (config->buffer[0] >> 8) & 0xff; + + if (!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; + } else { + config->buffer[0] = usb_spi_map_error( + spi_transaction((uint8_t *)(config->buffer + 1), + write_count, + (uint8_t *)(config->buffer + 1), + read_count)); + } + + usb_spi_write_packet(config, read_count + 2); + } } void usb_spi_tx(struct usb_spi_config const *config) @@ -134,23 +155,27 @@ int usb_spi_interface(struct usb_spi_config const *config, setup.wLength != 0) return 1; - if (config->state->disabled) + if (!config->state->enabled_device) return 1; switch (setup.bRequest) { case USB_SPI_REQ_ENABLE: - usb_spi_board_enable(config); - config->state->enabled = 1; + config->state->enabled_host = 1; break; case USB_SPI_REQ_DISABLE: - config->state->enabled = 0; - usb_spi_board_disable(config); + config->state->enabled_host = 0; break; default: return 1; } + /* + * Our state has changed, call the deferred function to handle the + * state change. + */ + hook_call_deferred(config->deferred, 0); + btable_ep[0].tx_count = 0; STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, EP_STATUS_OUT); return 0; @@ -158,11 +183,7 @@ int usb_spi_interface(struct usb_spi_config const *config, void usb_spi_enable(struct usb_spi_config const *config, int enabled) { - config->state->disabled = !enabled; + config->state->enabled_device = enabled; - if (config->state->disabled && - config->state->enabled) { - config->state->enabled = 0; - usb_spi_board_disable(config); - } + hook_call_deferred(config->deferred, 0); } |