diff options
author | Jes B. Klinke <jbk@chromium.org> | 2023-03-24 11:05:43 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-05-03 22:29:10 +0000 |
commit | fda81700ebb777cd61100eeaa7b8b0b1202473d6 (patch) | |
tree | 925f3b3668632bf6011966897b0cf537841cbd3e /chip/stm32/usb_spi.c | |
parent | 310b3033ac604b87256b2bb2a99eabc5993d70fd (diff) | |
download | chrome-ec-fda81700ebb777cd61100eeaa7b8b0b1202473d6.tar.gz |
chip/stm32: Simplify usb_spi.c macro use
Moving the body of the USB_SPI_CONFIG() macro into usb_spi.c allows
eliminating the "trampoline functions", for a slight performance
improvement, and simplification of the code.
BUG=b:273601311
TEST=HyperDebug still able to forward SPI requests
Change-Id: Id64c0a30c791962dbe4360c92dc512e6c2adc2f6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4370998
Tested-by: Jes Klinke <jbk@chromium.org>
Reviewed-by: Brian Nemec <bnemec@google.com>
Commit-Queue: Jes Klinke <jbk@chromium.org>
Diffstat (limited to 'chip/stm32/usb_spi.c')
-rw-r--r-- | chip/stm32/usb_spi.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/chip/stm32/usb_spi.c b/chip/stm32/usb_spi.c index 0ddde1b0d8..7e45563e4a 100644 --- a/chip/stm32/usb_spi.c +++ b/chip/stm32/usb_spi.c @@ -26,6 +26,136 @@ static bool usb_spi_transmitted_packet(void); static void usb_spi_read_packet(struct usb_spi_packet_ctx *packet); static void usb_spi_write_packet(struct usb_spi_packet_ctx *packet); +struct usb_spi_transfer_ctx { + /* Address of transfer buffer. */ + uint8_t *buffer; + /* Number of bytes in the transfer. */ + size_t transfer_size; + /* Number of bytes transferred. */ + size_t transfer_index; +}; + +enum usb_spi_mode { + /* No tasks are required. */ + USB_SPI_MODE_IDLE = 0, + /* Indicates the device needs to send it's USB SPI configuration.*/ + USB_SPI_MODE_SEND_CONFIGURATION, + /* Indicates the device needs to respond to chip select. */ + USB_SPI_MODE_SEND_CHIP_SELECT_RESPONSE, + /* Indicates we device needs start the SPI transfer. */ + USB_SPI_MODE_START_SPI, + /* Indicates we should start a transfer response. */ + USB_SPI_MODE_START_RESPONSE, + /* Indicates we need to continue a transfer response. */ + USB_SPI_MODE_CONTINUE_RESPONSE, +}; + +struct usb_spi_state { + /* + * 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. + */ + uint8_t enabled_host; + uint8_t 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. + */ + uint8_t enabled; + + /* + * The index of the SPI port currently receiving forwarded transactions, + * default is zero. + */ + uint8_t current_spi_device_idx; + + /* Mark the current operating mode. */ + enum usb_spi_mode mode; + + /* + * Stores the status code response for the transfer, delivered in the + * header for the first response packet. Error code is cleared during + * first RX packet and set if a failure occurs. + */ + uint16_t status_code; + + /* Stores the content from the USB packets */ + struct usb_spi_packet_ctx receive_packet; + struct usb_spi_packet_ctx transmit_packet; + + /* + * Flags describing if and how multi-lane (dual/quad), double transfer + * rate, and other advanced flash protocol features are to be used. + */ + uint32_t flash_flags; + + /* + * Context structures representing the progress receiving the SPI + * write data and transmitting the SPI read data. + */ + struct usb_spi_transfer_ctx spi_write_ctx; + struct usb_spi_transfer_ctx spi_read_ctx; +}; + +/* + * 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_spi_config { + /* Interface and endpoint indices. */ + int interface; + int endpoint; + + /* Deferred function to call to handle SPI request. */ + const struct deferred_data *deferred; + + /* Pointers to USB endpoint buffers. */ + usb_uint *ep_rx_ram; + usb_uint *ep_tx_ram; +}; + +/* + * Handle SPI request in a deferred callback. + */ +void usb_spi_deferred(void); + +/* + * Storage of configuration and state of USB->SPI bridge. + */ +static uint16_t usb_spi_buffer_[(USB_SPI_BUFFER_SIZE + 1) / 2]; +static usb_uint usb_spi_ep_rx_buffer_[USB_MAX_PACKET_SIZE / 2] __usb_ram; +static usb_uint usb_spi_ep_tx_buffer_[USB_MAX_PACKET_SIZE / 2] __usb_ram; + +static struct usb_spi_state usb_spi_state = { + .enabled_host = 0, + .enabled_device = 0, + .enabled = 0, + .current_spi_device_idx = 0, + .spi_write_ctx.buffer = (uint8_t *)usb_spi_buffer_, + .spi_read_ctx.buffer = (uint8_t *)usb_spi_buffer_, +}; + +DECLARE_DEFERRED(usb_spi_deferred); + +struct usb_spi_config const usb_spi = { + .interface = USB_IFACE_SPI, + .endpoint = USB_EP_SPI, + .deferred = &usb_spi_deferred_data, + .ep_rx_ram = usb_spi_ep_rx_buffer_, + .ep_tx_ram = usb_spi_ep_tx_buffer_, +}; + /* * Map EC error codes to USB_SPI error codes. * @@ -825,3 +955,36 @@ usb_spi_board_transaction(const struct spi_device_t *spi_device, { return EC_ERROR_UNIMPLEMENTED; } + +/* + * Register this file with the low-level USB driver. + */ +const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_SPI) = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = USB_IFACE_SPI, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_SPI, + .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_SPI, + .iInterface = USB_STR_SPI_NAME, +}; +const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_SPI, 0) = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x80 | USB_EP_SPI, + .bmAttributes = 0x02 /* Bulk IN */, + .wMaxPacketSize = USB_MAX_PACKET_SIZE, + .bInterval = 10, +}; +const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_SPI, 1) = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_EP_SPI, + .bmAttributes = 0x02 /* Bulk OUT */, + .wMaxPacketSize = USB_MAX_PACKET_SIZE, + .bInterval = 0, +}; +USB_DECLARE_EP(USB_EP_SPI, usb_spi_tx, usb_spi_rx, usb_spi_event); +USB_DECLARE_IFACE(USB_IFACE_SPI, usb_spi_interface); |