summaryrefslogtreecommitdiff
path: root/chip/stm32/usb_spi.c
diff options
context:
space:
mode:
authorAnton Staaf <robotboy@chromium.org>2015-03-17 11:49:29 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-03-23 19:23:35 +0000
commita0158dd136b63b2daffd666d51d84a67481cb609 (patch)
treeb3ceb010fbba052fb63825d862a0ef2eae2767a6 /chip/stm32/usb_spi.c
parent4002d66297f381c18e1118fa8e2cc156bc5baffd (diff)
downloadchrome-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.c87
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);
}