mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
CCD: Add ability to enable and disable SPI bridge
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>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
4002d66297
commit
a0158dd136
@@ -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;
|
||||
/*
|
||||
* 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);
|
||||
|
||||
count = usb_spi_read_packet(config);
|
||||
write_count = (config->buffer[0] >> 0) & 0xff;
|
||||
read_count = (config->buffer[0] >> 8) & 0xff;
|
||||
if (enabled ^ config->state->enabled) {
|
||||
if (enabled) usb_spi_board_enable(config);
|
||||
else usb_spi_board_disable(config);
|
||||
|
||||
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));
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -69,12 +69,25 @@ BUILD_ASSERT(USB_MAX_PACKET_SIZE == (2 + USB_SPI_MAX_READ_COUNT));
|
||||
|
||||
struct usb_spi_state {
|
||||
/*
|
||||
* The SPI bridge must be both not disabled and enabled to allow access
|
||||
* to the SPI device. The disabled bit is dictated by the caller of
|
||||
* usb_spi_enable. The enabled bit is set by the USB host, most likely
|
||||
* flashrom, by sending a USB_SPI_REQ_ENABLE message to the device.
|
||||
* The SPI bridge must be enabled both locally and by the host to allow
|
||||
* access to the SPI device. The enabled_host flag is set and cleared
|
||||
* by sending USB_SPI_REQ_ENABLE and USB_SPI_REQ_DISABLE to the device
|
||||
* control endpoint. The enabled_device flag is set by calling
|
||||
* usb_spi_enable.
|
||||
*/
|
||||
int enabled_host;
|
||||
int enabled_device;
|
||||
|
||||
/*
|
||||
* The current enabled state. This is only updated in the deferred
|
||||
* callback. Whenever either of the host or device specific enable
|
||||
* flags is changed the deferred callback is queued, and it will check
|
||||
* their combined state against this flag. If the combined state is
|
||||
* different, then one of usb_spi_board_enable or usb_spi_board_disable
|
||||
* is called and this flag is updated. This ensures that the board
|
||||
* specific state update routines are only called from the deferred
|
||||
* callback.
|
||||
*/
|
||||
int disabled;
|
||||
int enabled;
|
||||
};
|
||||
|
||||
@@ -128,8 +141,9 @@ struct usb_spi_config {
|
||||
static usb_uint CONCAT2(NAME, _ep_tx_buffer_)[USB_MAX_PACKET_SIZE / 2] __usb_ram; \
|
||||
static void CONCAT2(NAME, _deferred_)(void); \
|
||||
struct usb_spi_state CONCAT2(NAME, _state_) = { \
|
||||
.disabled = 1, \
|
||||
.enabled = 0, \
|
||||
.enabled_host = 0, \
|
||||
.enabled_device = 0, \
|
||||
.enabled = 0, \
|
||||
}; \
|
||||
struct usb_spi_config const NAME = { \
|
||||
.state = &CONCAT2(NAME, _state_), \
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "common.h"
|
||||
#include "usb_api.h"
|
||||
#include "usb_console.h"
|
||||
#include "usb_spi.h"
|
||||
|
||||
#if !defined(CONFIG_USB)
|
||||
#error "CONFIG_USB must be defined to use Case Closed Debugging"
|
||||
@@ -23,6 +24,10 @@
|
||||
#error "CONFIG_USB_INHIBIT_INIT must be defined to use Case Closed Debugging"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USB_SPI)
|
||||
USB_SPI_CONFIG(ccd_usb_spi, USB_IFACE_SPI, USB_EP_SPI);
|
||||
#endif
|
||||
|
||||
static enum ccd_mode current_mode = CCD_MODE_DISABLED;
|
||||
|
||||
void ccd_set_mode(enum ccd_mode new_mode)
|
||||
@@ -41,6 +46,10 @@ void ccd_set_mode(enum ccd_mode new_mode)
|
||||
*/
|
||||
usb_console_enable(new_mode == CCD_MODE_ENABLED);
|
||||
|
||||
#if defined(CONFIG_USB_SPI)
|
||||
usb_spi_enable(&ccd_usb_spi, new_mode == CCD_MODE_ENABLED);
|
||||
#endif
|
||||
|
||||
if (new_mode != CCD_MODE_DISABLED)
|
||||
usb_init();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user