diff options
Diffstat (limited to 'chip/stm32/usb_spi.h')
-rw-r--r-- | chip/stm32/usb_spi.h | 594 |
1 files changed, 0 insertions, 594 deletions
diff --git a/chip/stm32/usb_spi.h b/chip/stm32/usb_spi.h deleted file mode 100644 index 591975234d..0000000000 --- a/chip/stm32/usb_spi.h +++ /dev/null @@ -1,594 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#ifndef __CROS_EC_USB_SPI_H -#define __CROS_EC_USB_SPI_H - -/* STM32 USB SPI driver for Chrome EC */ - -#include "compile_time_macros.h" -#include "hooks.h" -#include "usb_descriptor.h" -#include "usb_hw.h" - -/* - * This SPI flash programming interface is designed to talk to a Chromium OS - * device over a Raiden USB connection. - * - * USB SPI Version 2: - * - * USB SPI version 2 adds support for larger SPI transfers and reduces the - * number of USB packets transferred. This improves performance when - * writing or reading large chunks of memory from a device. A packet ID - * field is used to distinguish the different packet types. Additional - * packets have been included to query the device for its configuration - * allowing the interface to be used on platforms with different SPI - * limitations. It includes validation and a packet to recover from the - * situations where USB packets are lost. - * - * The USB SPI hosts which support packet version 2 are backwards compatible - * and use the bInterfaceProtocol field to identify which type of target - * they are connected to. - * - * - * Example: USB SPI request with 128 byte write and 0 byte read. - * - * Packet #1 Host to Device: - * packet id = USB_SPI_PKT_ID_CMD_TRANSFER_START - * write count = 128 - * read count = 0 - * payload = First 58 bytes from the write buffer, - * starting at byte 0 in the buffer - * packet size = 64 bytes - * - * Packet #2 Host to Device: - * packet id = USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE - * data index = 58 - * payload = Next 60 bytes from the write buffer, - * starting at byte 58 in the buffer - * packet size = 64 bytes - * - * Packet #3 Host to Device: - * packet id = USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE - * data index = 118 - * payload = Next 10 bytes from the write buffer, - * starting at byte 118 in the buffer - * packet size = 14 bytes - * - * Packet #4 Device to Host: - * packet id = USB_SPI_PKT_ID_RSP_TRANSFER_START - * status code = status code from device - * payload = 0 bytes - * packet size = 4 bytes - * - * Example: USB SPI request with 2 byte write and 100 byte read. - * - * Packet #1 Host to Device: - * packet id = USB_SPI_PKT_ID_CMD_TRANSFER_START - * write count = 2 - * read count = 100 - * payload = The 2 byte write buffer - * packet size = 8 bytes - * - * Packet #2 Device to Host: - * packet id = USB_SPI_PKT_ID_RSP_TRANSFER_START - * status code = status code from device - * payload = First 60 bytes from the read buffer, - * starting at byte 0 in the buffer - * packet size = 64 bytes - * - * Packet #3 Device to Host: - * packet id = USB_SPI_PKT_ID_RSP_TRANSFER_CONTINUE - * data index = 60 - * payload = Next 40 bytes from the read buffer, - * starting at byte 60 in the buffer - * packet size = 44 bytes - * - * - * Message Packets: - * - * Command Start Packet (Host to Device): - * - * Start of the USB SPI command, contains the number of bytes to write - * and read on SPI and up to the first 58 bytes of write payload. - * Longer writes will use the continue packets with packet id - * USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE to transmit the remaining data. - * - * +----------------+------------------+-----------------+---------------+ - * | packet id : 2B | write count : 2B | read count : 2B | w.p. : <= 58B | - * +----------------+------------------+-----------------+---------------+ - * - * packet id: 2 byte enum defined by packet_id_type - * Valid values packet id = USB_SPI_PKT_ID_CMD_TRANSFER_START - * - * write count: 2 byte, zero based count of bytes to write - * - * read count: 2 byte, zero based count of bytes to read - * UINT16_MAX indicates full duplex mode with a read count - * equal to the write count. - * - * write payload: Up to 58 bytes of data to write to SPI, the total - * length of all TX packets must match write count. - * Due to data alignment constraints, this must be an - * even number of bytes unless this is the final packet. - * - * - * Response Start Packet (Device to Host): - * - * Start of the USB SPI response, contains the status code and up to - * the first 60 bytes of read payload. Longer reads will use the - * continue packets with packet id USB_SPI_PKT_ID_RSP_TRANSFER_CONTINUE - * to transmit the remaining data. - * - * +----------------+------------------+-----------------------+ - * | packet id : 2B | status code : 2B | read payload : <= 60B | - * +----------------+------------------+-----------------------+ - * - * packet id: 2 byte enum defined by packet_id_type - * Valid values packet id = USB_SPI_PKT_ID_RSP_TRANSFER_START - * - * status code: 2 byte status code - * 0x0000: Success - * 0x0001: SPI timeout - * 0x0002: Busy, try again - * This can happen if someone else has acquired the shared memory - * buffer that the SPI driver uses as /dev/null - * 0x0003: Write count invalid. The byte limit is platform specific - * and is set during the configure USB SPI response. - * 0x0004: Read count invalid. The byte limit is platform specific - * and is set during the configure USB SPI response. - * 0x0005: The SPI bridge is disabled. - * 0x0006: The RX continue packet's data index is invalid. This - * can indicate a USB transfer failure to the device. - * 0x0007: The RX endpoint has received more data than write count. - * This can indicate a USB transfer failure to the device. - * 0x0008: An unexpected packet arrived that the device could not - * process. - * 0x0009: The device does not support full duplex mode. - * 0x8000: Unknown error mask - * The bottom 15 bits will contain the bottom 15 bits from the EC - * error code. - * - * read payload: Up to 60 bytes of data read from SPI, the total - * length of all RX packets must match read count - * unless an error status was returned. Due to data - * alignment constraints, this must be a even number - * of bytes unless this is the final packet. - * - * - * Continue Packet (Bidirectional): - * - * Continuation packet for the writes and read buffers. Both packets - * follow the same format, a data index counts the number of bytes - * previously transferred in the USB SPI transfer and a payload of bytes. - * - * +----------------+-----------------+-------------------------------+ - * | packet id : 2B | data index : 2B | write / read payload : <= 60B | - * +----------------+-----------------+-------------------------------+ - * - * packet id: 2 byte enum defined by packet_id_type - * The packet id has 2 values depending on direction: - * packet id = USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE - * indicates the packet is being transmitted from the host - * to the device and contains SPI write payload. - * packet id = USB_SPI_PKT_ID_RSP_TRANSFER_CONTINUE - * indicates the packet is being transmitted from the device - * to the host and contains SPI read payload. - * - * data index: The data index indicates the number of bytes in the - * read or write buffers that have already been transmitted. - * It is used to validate that no packets have been dropped - * and that the prior packets have been correctly decoded. - * This value corresponds to the offset bytes in the buffer - * to start copying the payload into. - * - * read and write payload: - * Contains up to 60 bytes of payload data to transfer to - * the SPI write buffer or from the SPI read buffer. - * - * - * Command Get Configuration Packet (Host to Device): - * - * Query the device to request it's USB SPI configuration indicating - * the number of bytes it can write and read. - * - * +----------------+ - * | packet id : 2B | - * +----------------+ - * - * packet id: 2 byte enum USB_SPI_PKT_ID_CMD_GET_USB_SPI_CONFIG - * - * Response Configuration Packet (Device to Host): - * - * Response packet form the device to report the maximum write and - * read size supported by the device. - * - * +----------------+----------------+---------------+----------------+ - * | packet id : 2B | max write : 2B | max read : 2B | feature bitmap | - * +----------------+----------------+---------------+----------------+ - * - * packet id: 2 byte enum USB_SPI_PKT_ID_RSP_USB_SPI_CONFIG - * - * max write count: 2 byte count of the maximum number of bytes - * the device can write to SPI in one transaction. - * - * max read count: 2 byte count of the maximum number of bytes - * the device can read from SPI in one transaction. - * - * feature bitmap: Bitmap of supported features. - * BIT(0): Full duplex SPI mode is supported - * BIT(1:15): Reserved for future use - * - * Command Restart Response Packet (Host to Device): - * - * Command to restart the response transfer from the device. This enables - * the host to recover from a lost packet when reading the response - * without restarting the SPI transfer. - * - * +----------------+ - * | packet id : 2B | - * +----------------+ - * - * packet id: 2 byte enum USB_SPI_PKT_ID_CMD_RESTART_RESPONSE - * - * USB Error Codes: - * - * send_command return codes have the following format: - * - * 0x00000: Status code success. - * 0x00001-0x0FFFF: Error code returned by the USB SPI device. - * 0x10001-0x1FFFF: USB SPI Host error codes - * 0x20001-0x20063 Lower bits store the positive value representation - * of the libusb_error enum. See the libusb documentation: - * http://libusb.sourceforge.net/api-1.0/group__misc.html - */ - -#define USB_SPI_FULL_DUPLEX_ENABLED (UINT16_MAX) - -#define USB_SPI_PAYLOAD_SIZE_V2_START (58) - -#define USB_SPI_PAYLOAD_SIZE_V2_RESPONSE (60) - -#define USB_SPI_PAYLOAD_SIZE_V2_CONTINUE (60) - -#define USB_SPI_PAYLOAD_SIZE_V2_ERROR (60) - -#define USB_SPI_MIN_PACKET_SIZE (2) - -enum packet_id_type { - /* Request USB SPI configuration data from device. */ - USB_SPI_PKT_ID_CMD_GET_USB_SPI_CONFIG = 0, - /* USB SPI configuration data from device. */ - USB_SPI_PKT_ID_RSP_USB_SPI_CONFIG = 1, - /* - * Start a USB SPI transfer specifying number of bytes to write, - * read and deliver first packet of data to write. - */ - USB_SPI_PKT_ID_CMD_TRANSFER_START = 2, - /* Additional packets containing write payload. */ - USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE = 3, - /* - * Request the device restart the response enabling us to recover - * from packet loss without another SPI transfer. - */ - USB_SPI_PKT_ID_CMD_RESTART_RESPONSE = 4, - /* - * First packet of USB SPI response with the status code - * and read payload if it was successful. - */ - USB_SPI_PKT_ID_RSP_TRANSFER_START = 5, - /* Additional packets containing read payload. */ - USB_SPI_PKT_ID_RSP_TRANSFER_CONTINUE = 6, -}; - -enum feature_bitmap { - /* Indicates the platform supports full duplex mode. */ - USB_SPI_FEATURE_FULL_DUPLEX_SUPPORTED = BIT(0) -}; - -struct usb_spi_response_configuration_v2 { - uint16_t packet_id; - uint16_t max_write_count; - uint16_t max_read_count; - uint16_t feature_bitmap; -} __packed; - -struct usb_spi_command_v2 { - uint16_t packet_id; - uint16_t write_count; - /* UINT16_MAX Indicates readback all on halfduplex compliant devices. */ - uint16_t read_count; - uint8_t data[USB_SPI_PAYLOAD_SIZE_V2_START]; -} __packed; - -struct usb_spi_response_v2 { - uint16_t packet_id; - uint16_t status_code; - uint8_t data[USB_SPI_PAYLOAD_SIZE_V2_RESPONSE]; -} __packed; - -struct usb_spi_continue_v2 { - uint16_t packet_id; - uint16_t data_index; - uint8_t data[USB_SPI_PAYLOAD_SIZE_V2_CONTINUE]; -} __packed; - -struct usb_spi_packet_ctx { - union { - uint8_t bytes[USB_MAX_PACKET_SIZE]; - uint16_t packet_id; - struct usb_spi_command_v2 cmd_start; - struct usb_spi_continue_v2 cmd_continue; - struct usb_spi_response_configuration_v2 rsp_config; - struct usb_spi_response_v2 rsp_start; - struct usb_spi_continue_v2 rsp_continue; - } __packed; - /* - * By storing the number of bytes in the header and knowing that the - * USB data packets are all 64B long, we are able to use the header - * size to store the offset of the buffer and it's size without - * duplicating variables that can go out of sync. - */ - size_t header_size; - /* Number of bytes in the packet. */ - size_t packet_size; -}; - -enum usb_spi_error { - USB_SPI_SUCCESS = 0x0000, - USB_SPI_TIMEOUT = 0x0001, - USB_SPI_BUSY = 0x0002, - USB_SPI_WRITE_COUNT_INVALID = 0x0003, - USB_SPI_READ_COUNT_INVALID = 0x0004, - USB_SPI_DISABLED = 0x0005, - /* The RX continue packet's data index is invalid. */ - USB_SPI_RX_BAD_DATA_INDEX = 0x0006, - /* The RX endpoint has received more data than write count. */ - USB_SPI_RX_DATA_OVERFLOW = 0x0007, - /* An unexpected packet arrived on the device. */ - USB_SPI_RX_UNEXPECTED_PACKET = 0x0008, - /* The device does not support full duplex mode. */ - USB_SPI_UNSUPPORTED_FULL_DUPLEX = 0x0009, - USB_SPI_UNKNOWN_ERROR = 0x8000, -}; - -enum usb_spi_request { - USB_SPI_REQ_ENABLE = 0x0000, - USB_SPI_REQ_DISABLE = 0x0001, -}; - -/* - * To optimize for speed, we want to fill whole packets for each transfer - * This is done by setting the read and write counts to the payload sizes - * of the smaller start packet + N * continue packets. - * - * If a platform has a small maximum SPI transfer size, it can be optimized - * by setting these limits to the maximum transfer size. - */ -#define USB_SPI_BUFFER_SIZE (USB_SPI_PAYLOAD_SIZE_V2_START + \ - (4 * USB_SPI_PAYLOAD_SIZE_V2_CONTINUE)) -#define USB_SPI_MAX_WRITE_COUNT USB_SPI_BUFFER_SIZE -#define USB_SPI_MAX_READ_COUNT USB_SPI_BUFFER_SIZE - -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 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. - */ - 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 enabled; - - /* 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; - - /* - * 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 { - /* In RAM state of the USB SPI bridge. */ - struct usb_spi_state *state; - - /* 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; - - /* Flags. See USB_SPI_CONFIG_FLAGS_* for definitions */ - uint32_t flags; -}; - -/* - * Use when you want the SPI subsystem to be enabled even when the USB SPI - * endpoint is not enabled by the host. This means that when this firmware - * enables SPI, then the HW SPI module is enabled (i.e. SPE bit is set) until - * this firmware disables the SPI module; it ignores the host's enables state. - */ -#define USB_SPI_CONFIG_FLAGS_IGNORE_HOST_SIDE_ENABLE BIT(0) - -/* - * Convenience macro for defining a USB SPI bridge driver. - * - * NAME is used to construct the names of the trampoline functions and the - * usb_spi_config struct, the latter is just called NAME. - * - * INTERFACE is the index of the USB interface to associate with this - * SPI driver. - * - * ENDPOINT is the index of the USB bulk endpoint used for receiving and - * transmitting bytes. - * - * FLAGS encodes different run-time control parameters. See - * USB_SPI_CONFIG_FLAGS_* for definitions. - */ -#define USB_SPI_CONFIG(NAME, \ - INTERFACE, \ - ENDPOINT, \ - FLAGS) \ - static uint16_t CONCAT2(NAME, _buffer_)[(USB_SPI_BUFFER_SIZE + 1) / 2];\ - static usb_uint CONCAT2(NAME, _ep_rx_buffer_)[USB_MAX_PACKET_SIZE / 2] __usb_ram; \ - static usb_uint CONCAT2(NAME, _ep_tx_buffer_)[USB_MAX_PACKET_SIZE / 2] __usb_ram; \ - static void CONCAT2(NAME, _deferred_)(void); \ - DECLARE_DEFERRED(CONCAT2(NAME, _deferred_)); \ - struct usb_spi_state CONCAT2(NAME, _state_) = { \ - .enabled_host = 0, \ - .enabled_device = 0, \ - .enabled = 0, \ - .spi_write_ctx.buffer = (uint8_t *)CONCAT2(NAME, _buffer_), \ - .spi_read_ctx.buffer = (uint8_t *)CONCAT2(NAME, _buffer_), \ - }; \ - struct usb_spi_config const NAME = { \ - .state = &CONCAT2(NAME, _state_), \ - .interface = INTERFACE, \ - .endpoint = ENDPOINT, \ - .deferred = &CONCAT2(NAME, _deferred__data), \ - .ep_rx_ram = CONCAT2(NAME, _ep_rx_buffer_), \ - .ep_tx_ram = CONCAT2(NAME, _ep_tx_buffer_), \ - .flags = FLAGS, \ - }; \ - const struct usb_interface_descriptor \ - USB_IFACE_DESC(INTERFACE) = { \ - .bLength = USB_DT_INTERFACE_SIZE, \ - .bDescriptorType = USB_DT_INTERFACE, \ - .bInterfaceNumber = INTERFACE, \ - .bAlternateSetting = 0, \ - .bNumEndpoints = 2, \ - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ - .bInterfaceSubClass = USB_SUBCLASS_GOOGLE_SPI, \ - .bInterfaceProtocol = USB_PROTOCOL_GOOGLE_SPI, \ - .iInterface = 0, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 0) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = 0x80 | ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk IN */, \ - .wMaxPacketSize = USB_MAX_PACKET_SIZE, \ - .bInterval = 10, \ - }; \ - const struct usb_endpoint_descriptor \ - USB_EP_DESC(INTERFACE, 1) = { \ - .bLength = USB_DT_ENDPOINT_SIZE, \ - .bDescriptorType = USB_DT_ENDPOINT, \ - .bEndpointAddress = ENDPOINT, \ - .bmAttributes = 0x02 /* Bulk OUT */, \ - .wMaxPacketSize = USB_MAX_PACKET_SIZE, \ - .bInterval = 0, \ - }; \ - static void CONCAT2(NAME, _ep_tx_) (void) { usb_spi_tx (&NAME); } \ - static void CONCAT2(NAME, _ep_rx_) (void) { usb_spi_rx (&NAME); } \ - static void CONCAT2(NAME, _ep_event_)(enum usb_ep_event evt) \ - { \ - usb_spi_event(&NAME, evt); \ - } \ - USB_DECLARE_EP(ENDPOINT, \ - CONCAT2(NAME, _ep_tx_), \ - CONCAT2(NAME, _ep_rx_), \ - CONCAT2(NAME, _ep_event_)); \ - static int CONCAT2(NAME, _interface_)(usb_uint *rx_buf, \ - usb_uint *tx_buf) \ - { return usb_spi_interface(&NAME, rx_buf, tx_buf); } \ - USB_DECLARE_IFACE(INTERFACE, \ - CONCAT2(NAME, _interface_)); \ - static void CONCAT2(NAME, _deferred_)(void) \ - { usb_spi_deferred(&NAME); } - -/* - * Handle SPI request in a deferred callback. - */ -void usb_spi_deferred(struct usb_spi_config const *config); - -/* - * Set the enable state for the USB-SPI bridge. - * - * The bridge must be enabled from both the host and device side - * before the SPI bus is usable. This allows the bridge to be - * available for host tools to use without forcing the device to - * disconnect or disable whatever else might be using the SPI bus. - */ -void usb_spi_enable(struct usb_spi_config const *config, int enabled); - -/* - * These functions are used by the trampoline functions defined above to - * connect USB endpoint events with the generic USB GPIO driver. - */ -void usb_spi_tx(struct usb_spi_config const *config); -void usb_spi_rx(struct usb_spi_config const *config); -void usb_spi_event(struct usb_spi_config const *config, enum usb_ep_event evt); -int usb_spi_interface(struct usb_spi_config const *config, - usb_uint *rx_buf, - usb_uint *tx_buf); - -/* - * These functions should be implemented by the board to provide any board - * specific operations required to enable or disable access to the SPI device. - */ -void usb_spi_board_enable(struct usb_spi_config const *config); -void usb_spi_board_disable(struct usb_spi_config const *config); - -#endif /* __CROS_EC_USB_SPI_H */ |