diff options
author | Jes B. Klinke <jbk@chromium.org> | 2023-03-14 20:25:45 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-03-17 21:28:25 +0000 |
commit | 60b941b4e0f1afe1584d146550af61d9e88d3785 (patch) | |
tree | 7aea70ed4f0f2c252fe4ad7ebe473ebe4e51c1ad | |
parent | 768903a5bf71508226d5adf52b8cabef8a783e42 (diff) | |
download | chrome-ec-60b941b4e0f1afe1584d146550af61d9e88d3785.tar.gz |
chip/stm32: Interface extensions for serial flash
Enhance the interface to board-specific SPI driver such that it can take
flags for advanced serial flash chip protocols (dual/quad lanes, dummy
cycles, double transfer rate).
BUG=b:273601311
TEST=c2d2 can still flash (using single-lane)
Change-Id: Iee6a17077ea8c382c7d59bd404bf5d033bd9b517
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4336273
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Commit-Queue: Jes Klinke <jbk@chromium.org>
Tested-by: Jes Klinke <jbk@chromium.org>
-rw-r--r-- | board/hyperdebug/spi.c | 11 | ||||
-rw-r--r-- | chip/stm32/usb_spi.c | 22 | ||||
-rw-r--r-- | chip/stm32/usb_spi.h | 109 |
3 files changed, 122 insertions, 20 deletions
diff --git a/board/hyperdebug/spi.c b/board/hyperdebug/spi.c index 51270ca91d..36fede34ac 100644 --- a/board/hyperdebug/spi.c +++ b/board/hyperdebug/spi.c @@ -27,7 +27,9 @@ struct spi_device_t spi_devices[] = { .port = -1 /* OCTOSPI */, .div = 255, .gpio_cs = GPIO_CN10_6, - .usb_flags = USB_SPI_ENABLED | USB_SPI_CUSTOM_SPI_DEVICE }, + .usb_flags = USB_SPI_ENABLED | USB_SPI_CUSTOM_SPI_DEVICE | + USB_SPI_FLASH_DUAL_SUPPORT | + USB_SPI_FLASH_QUAD_SUPPORT }, }; const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); @@ -366,12 +368,15 @@ void usb_spi_board_disable(struct usb_spi_config const *config) * the only spi device declared as requiring board specific driver is OCTOSPI. */ int usb_spi_board_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, uint8_t *rxdata, - int rxlen) + uint32_t flash_flags, const uint8_t *txdata, + int txlen, uint8_t *rxdata, int rxlen) { int rv = EC_SUCCESS; bool previous_cs; + if (flash_flags & FLASH_FLAGS_REQUIRING_SUPPORT) + return EC_ERROR_UNIMPLEMENTED; + previous_cs = gpio_get_level(spi_device->gpio_cs); /* Drive chip select low */ diff --git a/chip/stm32/usb_spi.c b/chip/stm32/usb_spi.c index 555e201b0b..a350415dab 100644 --- a/chip/stm32/usb_spi.c +++ b/chip/stm32/usb_spi.c @@ -442,11 +442,19 @@ void usb_spi_deferred(struct usb_spi_config const *config) } #endif - status_code = (custom_board_driver ? usb_spi_board_transaction : - spi_transaction)( - current_device, config->state->spi_write_ctx.buffer, - config->state->spi_write_ctx.transfer_size, - config->state->spi_read_ctx.buffer, read_count); + if (custom_board_driver) { + status_code = usb_spi_board_transaction( + current_device, 0 /* flash_flags */, + config->state->spi_write_ctx.buffer, + config->state->spi_write_ctx.transfer_size, + config->state->spi_read_ctx.buffer, read_count); + } else { + status_code = spi_transaction( + current_device, + config->state->spi_write_ctx.buffer, + config->state->spi_write_ctx.transfer_size, + config->state->spi_read_ctx.buffer, read_count); + } /* Cast the EC status code to USB SPI and start the response. */ status_code = usb_spi_map_error(status_code); @@ -669,8 +677,8 @@ int usb_spi_interface(struct usb_spi_config const *config, usb_uint *rx_buf, __overridable int usb_spi_board_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, uint8_t *rxdata, - int rxlen) + uint32_t flash_flags, const uint8_t *txdata, + int txlen, uint8_t *rxdata, int rxlen) { return EC_ERROR_UNIMPLEMENTED; } diff --git a/chip/stm32/usb_spi.h b/chip/stm32/usb_spi.h index 28462caea8..34d69225cf 100644 --- a/chip/stm32/usb_spi.h +++ b/chip/stm32/usb_spi.h @@ -285,10 +285,15 @@ */ /* Is the USB host allowed to operate on SPI device. */ -#define USB_SPI_ENABLED (BIT(0)) - +#define USB_SPI_ENABLED BIT(0) /* Use board specific SPI driver when forwarding to this device. */ -#define USB_SPI_CUSTOM_SPI_DEVICE (BIT(1)) +#define USB_SPI_CUSTOM_SPI_DEVICE BIT(1) +/* This SPI device supports dual lane mode. */ +#define USB_SPI_FLASH_DUAL_SUPPORT BIT(2) +/* This SPI device supports four lane mode. */ +#define USB_SPI_FLASH_QUAD_SUPPORT BIT(3) +/* This SPI device supports eight lane mode. */ +#define USB_SPI_FLASH_OCTO_SUPPORT BIT(4) enum packet_id_type { /* Request USB SPI configuration data from device. */ @@ -668,14 +673,98 @@ void usb_spi_board_enable(struct usb_spi_config const *config); void usb_spi_board_disable(struct usb_spi_config const *config); /* - * In order to facilitate odd cases of e.g. a SPI bus sitting behind a second - * microcontroller, or otherwise needing a non-standard driver, setting the - * USB_SPI_CUSTOM_SPI_DEVICE_MASK bit of spi_device->port will cause the - * USB->SPI forwarding logic to invoke this method rather than the standard - * spi_transaction(). + * In order to facilitate special SPI busses not covered by standard EC + * drivers, setting the USB_SPI_CUSTOM_SPI_DEVICE_MASK bit of spi_device->port + * will cause the USB to SPI forwarding logic to invoke this method rather + * than the standard spi_transaction_async(). */ int usb_spi_board_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, uint8_t *rxdata, - int rxlen); + uint32_t flash_flags, const uint8_t *txdata, + int txlen, uint8_t *rxdata, int rxlen); + +/* + * Flags to use in usb_spi_board_transaction_async() for advanced serial flash + * communication, when supported. + */ + +/* Data width during the opcode stage. */ +#define FLASH_FLAG_OPCODE_WIDTH_POS 0 +#define FLASH_FLAG_OPCODE_WIDTH_MSK (0x3U << FLASH_FLAG_OPCODE_WIDTH_POS) +#define FLASH_FLAG_OPCODE_WIDTH_1WIRE (0x0U << FLASH_FLAG_OPCODE_WIDTH_POS) +#define FLASH_FLAG_OPCODE_WIDTH_2WIRE (0x1U << FLASH_FLAG_OPCODE_WIDTH_POS) +#define FLASH_FLAG_OPCODE_WIDTH_4WIRE (0x2U << FLASH_FLAG_OPCODE_WIDTH_POS) +#define FLASH_FLAG_OPCODE_WIDTH_8WIRE (0x3U << FLASH_FLAG_OPCODE_WIDTH_POS) + +/* Transmit opcode bits at both rising and falling clock edges. */ +#define FLASH_FLAG_OPCODE_DTR_POS 2 +#define FLASH_FLAG_OPCODE_DTR (0x1U << FLASH_FLAG_OPCODE_DTR_POS) + +/* Number of bytes of opcode (0-4). */ +#define FLASH_FLAG_OPCODE_LEN_POS 3 +#define FLASH_FLAG_OPCODE_LEN_MSK (0x7U << FLASH_FLAG_OPCODE_LEN_POS) + +/* Data width during the address stage. */ +#define FLASH_FLAG_ADDR_WIDTH_POS 6 +#define FLASH_FLAG_ADDR_WIDTH_MSK (0x3U << FLASH_FLAG_ADDR_WIDTH_POS) +#define FLASH_FLAG_ADDR_WIDTH_1WIRE (0x0U << FLASH_FLAG_ADDR_WIDTH_POS) +#define FLASH_FLAG_ADDR_WIDTH_2WIRE (0x1U << FLASH_FLAG_ADDR_WIDTH_POS) +#define FLASH_FLAG_ADDR_WIDTH_4WIRE (0x2U << FLASH_FLAG_ADDR_WIDTH_POS) +#define FLASH_FLAG_ADDR_WIDTH_8WIRE (0x3U << FLASH_FLAG_ADDR_WIDTH_POS) + +/* Transmit address bits at both rising and falling clock edges. */ +#define FLASH_FLAG_ADDR_DTR_POS 8 +#define FLASH_FLAG_ADDR_DTR (0x1U << FLASH_FLAG_ADDR_DTR_POS) + +/* Number of bytes of address (0-4). */ +#define FLASH_FLAG_ADDR_LEN_POS 9 +#define FLASH_FLAG_ADDR_LEN_MSK (0x7U << FLASH_FLAG_ADDR_LEN_POS) + +/* Data width during the "alternate bytes" stage. */ +#define FLASH_FLAG_ALT_WIDTH_POS 12 +#define FLASH_FLAG_ALT_WIDTH_MSK (0x3U << FLASH_FLAG_ALT_WIDTH_POS) +#define FLASH_FLAG_ALT_WIDTH_1WIRE (0x0U << FLASH_FLAG_ALT_WIDTH_POS) +#define FLASH_FLAG_ALT_WIDTH_2WIRE (0x1U << FLASH_FLAG_ALT_WIDTH_POS) +#define FLASH_FLAG_ALT_WIDTH_4WIRE (0x2U << FLASH_FLAG_ALT_WIDTH_POS) +#define FLASH_FLAG_ALT_WIDTH_8WIRE (0x3U << FLASH_FLAG_ALT_WIDTH_POS) + +/* Transmit alternate bits at both rising and falling clock edges. */ +#define FLASH_FLAG_ALT_DTR_POS 14 +#define FLASH_FLAG_ALT_DTR (0x1U << FLASH_FLAG_ALT_DTR_POS) + +/* Number of bytes of alternate data (0-4). */ +#define FLASH_FLAG_ALT_LEN_POS 15 +#define FLASH_FLAG_ALT_LEN_MSK (0x7U << FLASH_FLAG_ALT_LEN_POS) + +/* Number of dummy clock cycles (0-31). */ +#define FLASH_FLAG_DUMMY_CYCLES_POS 18 +#define FLASH_FLAG_DUMMY_CYCLES_MSK (0x1FU << FLASH_FLAG_DUMMY_CYCLES_POS) + +/* Data width during the data stage. */ +#define FLASH_FLAG_DATA_WIDTH_POS 23 +#define FLASH_FLAG_DATA_WIDTH_MSK (0x3U << FLASH_FLAG_DATA_WIDTH_POS) +#define FLASH_FLAG_DATA_WIDTH_1WIRE (0x0U << FLASH_FLAG_DATA_WIDTH_POS) +#define FLASH_FLAG_DATA_WIDTH_2WIRE (0x1U << FLASH_FLAG_DATA_WIDTH_POS) +#define FLASH_FLAG_DATA_WIDTH_4WIRE (0x2U << FLASH_FLAG_DATA_WIDTH_POS) +#define FLASH_FLAG_DATA_WIDTH_8WIRE (0x3U << FLASH_FLAG_DATA_WIDTH_POS) + +/* Transmit data bits at both rising and falling clock edges. */ +#define FLASH_FLAG_DATA_DTR_POS 25 +#define FLASH_FLAG_DATA_DTR (0x1U << FLASH_FLAG_DATA_DTR_POS) + +/* + * Mask of the flags that cannot be ignored. This is basically any flags + * which call for wires to switch direction, or data being clocked on both + * rising and falling edges. As long as none of these are present, then the + * remaining flags specifying the length of opcode/address can be ignored, as + * the entire data buffer can be transmitted as a sequence of bytes, without + * the controller knowing which parts are to be interpreted as + * opcode/address/data. + */ +#define FLASH_FLAGS_REQUIRING_SUPPORT \ + (FLASH_FLAG_OPCODE_WIDTH_MSK | FLASH_FLAG_OPCODE_DTR | \ + FLASH_FLAG_ADDR_WIDTH_MSK | FLASH_FLAG_ADDR_DTR | \ + FLASH_FLAG_ALT_WIDTH_MSK | FLASH_FLAG_ALT_DTR | \ + FLASH_FLAG_DUMMY_CYCLES_MSK | FLASH_FLAG_DATA_WIDTH_MSK | \ + FLASH_FLAG_DATA_DTR) #endif /* __CROS_EC_USB_SPI_H */ |