From 60b941b4e0f1afe1584d146550af61d9e88d3785 Mon Sep 17 00:00:00 2001 From: "Jes B. Klinke" Date: Tue, 14 Mar 2023 20:25:45 -0700 Subject: 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 Commit-Queue: Jes Klinke Tested-by: Jes Klinke --- chip/stm32/usb_spi.c | 22 +++++++---- chip/stm32/usb_spi.h | 109 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 114 insertions(+), 17 deletions(-) (limited to 'chip') 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 */ -- cgit v1.2.1