diff options
Diffstat (limited to 'chip')
-rw-r--r-- | chip/host/clock.c | 4 | ||||
-rw-r--r-- | chip/ish/clock.c | 4 | ||||
-rw-r--r-- | chip/it83xx/clock.c | 4 | ||||
-rw-r--r-- | chip/max32660/clock_chip.c | 4 | ||||
-rw-r--r-- | chip/mchp/clock.c | 4 | ||||
-rw-r--r-- | chip/mt_scp/mt818x/clock_mt8183.c | 4 | ||||
-rw-r--r-- | chip/mt_scp/mt818x/clock_mt8186.c | 4 | ||||
-rw-r--r-- | chip/mt_scp/mt8192/clock.c | 4 | ||||
-rw-r--r-- | chip/mt_scp/mt8195/clock.c | 4 | ||||
-rw-r--r-- | chip/npcx/clock.c | 11 | ||||
-rw-r--r-- | chip/stm32/trng.c | 2 | ||||
-rw-r--r-- | chip/stm32/usb_spi.c | 227 | ||||
-rw-r--r-- | chip/stm32/usb_spi.h | 220 |
13 files changed, 395 insertions, 101 deletions
diff --git a/chip/host/clock.c b/chip/host/clock.c index 4f90067f3a..defb12f4f0 100644 --- a/chip/host/clock.c +++ b/chip/host/clock.c @@ -11,3 +11,7 @@ int clock_get_freq(void) { return 16000000; } + +void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/ish/clock.c b/chip/ish/clock.c index f9fec0b7d2..2fefa11c2f 100644 --- a/chip/ish/clock.c +++ b/chip/ish/clock.c @@ -29,3 +29,7 @@ void clock_refresh_console_in_use(void) */ ish_pm_refresh_console_in_use(); } + +void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/it83xx/clock.c b/chip/it83xx/clock.c index fccc62eee7..abbbcf3b58 100644 --- a/chip/it83xx/clock.c +++ b/chip/it83xx/clock.c @@ -701,3 +701,7 @@ DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, "", #endif /* CONFIG_CMD_IDLE_STATS */ #endif /* CONFIG_LOW_POWER_IDLE */ + +void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/max32660/clock_chip.c b/chip/max32660/clock_chip.c index 26225401ba..8e497c846b 100644 --- a/chip/max32660/clock_chip.c +++ b/chip/max32660/clock_chip.c @@ -139,3 +139,7 @@ void clock_init(void) } } } + +void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mchp/clock.c b/chip/mchp/clock.c index 0323d16f8f..8732e21117 100644 --- a/chip/mchp/clock.c +++ b/chip/mchp/clock.c @@ -750,3 +750,7 @@ DECLARE_CONSOLE_COMMAND( "Give a timeout value for the console in use timeout.\n" "See also 'sleep mask'."); #endif /* CONFIG_LOW_POWER_IDLE */ + +void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mt_scp/mt818x/clock_mt8183.c b/chip/mt_scp/mt818x/clock_mt8183.c index fca89cd2a5..a48eee952a 100644 --- a/chip/mt_scp/mt818x/clock_mt8183.c +++ b/chip/mt_scp/mt818x/clock_mt8183.c @@ -370,3 +370,7 @@ static int command_ulposc(int argc, const char *argv[]) } DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[calibrate]", "Calibrate ULPOSC frequency"); + +void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mt_scp/mt818x/clock_mt8186.c b/chip/mt_scp/mt818x/clock_mt8186.c index cb0d339b5f..eafc5992fd 100644 --- a/chip/mt_scp/mt818x/clock_mt8186.c +++ b/chip/mt_scp/mt818x/clock_mt8186.c @@ -376,3 +376,7 @@ static int command_ulposc(int argc, const char *argv[]) } DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[calibrate]", "Calibrate ULPOSC frequency"); + +void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mt_scp/mt8192/clock.c b/chip/mt_scp/mt8192/clock.c index 21d07d410a..ec6e3f2537 100644 --- a/chip/mt_scp/mt8192/clock.c +++ b/chip/mt_scp/mt8192/clock.c @@ -381,3 +381,7 @@ int command_ulposc(int argc, const char *argv[]) DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[ulposc]", "Measure ULPOSC frequency"); #endif + +void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/mt_scp/mt8195/clock.c b/chip/mt_scp/mt8195/clock.c index 779f356bab..e41a360ae8 100644 --- a/chip/mt_scp/mt8195/clock.c +++ b/chip/mt_scp/mt8195/clock.c @@ -501,3 +501,7 @@ int command_ulposc(int argc, const char *argv[]) DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[ulposc]", "Measure ULPOSC frequency"); #endif + +void clock_enable_module(enum module_id module, int enable) +{ +} diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c index 1ab4d1063a..992fc1b628 100644 --- a/chip/npcx/clock.c +++ b/chip/npcx/clock.c @@ -162,6 +162,11 @@ void clock_turbo(void) */ NPCX_HFCBCD = NPCX_HFCBCD & 0xF3; } + +void clock_enable_module(enum module_id module, int enable) +{ +} + #elif NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 void clock_turbo(void) { @@ -200,6 +205,12 @@ void clock_enable_module(enum module_id module, int enable) } } +#else + +void clock_enable_module(enum module_id module, int enable) +{ +} + #endif /** diff --git a/chip/stm32/trng.c b/chip/stm32/trng.c index aafc0e89c1..67d3700cf1 100644 --- a/chip/stm32/trng.c +++ b/chip/stm32/trng.c @@ -16,7 +16,7 @@ #include "trng.h" #include "util.h" -uint32_t trng_rand(void) +static uint32_t trng_rand(void) { int tries = 300; /* Wait for a valid random number */ diff --git a/chip/stm32/usb_spi.c b/chip/stm32/usb_spi.c index c45ea3520d..0ddde1b0d8 100644 --- a/chip/stm32/usb_spi.c +++ b/chip/stm32/usb_spi.c @@ -8,11 +8,18 @@ #include "link_defs.h" #include "registers.h" #include "spi.h" +#include "timer.h" #include "usb_descriptor.h" #include "usb_hw.h" #include "usb_spi.h" #include "util.h" +/* How long to wait for a flash page programming. */ +#define FLASH_BUSY_POLL_TIMEOUT_USEC (1000 * MSEC) + +const uint8_t JEDEC_READ_STATUS = 0x05; +const uint8_t JEDEC_STATUS_BUSY = 0x01; + /* Forward declare platform specific functions. */ static bool usb_spi_received_packet(void); static bool usb_spi_transmitted_packet(void); @@ -164,6 +171,9 @@ static void setup_transfer_response(uint16_t status_code) */ static void create_spi_config_response(struct usb_spi_packet_ctx *packet) { + const struct spi_device_t *current_device = + &spi_devices[usb_spi_state.current_spi_device_idx]; + /* Construct the response packet. */ packet->rsp_config.packet_id = USB_SPI_PKT_ID_RSP_USB_SPI_CONFIG; packet->rsp_config.max_write_count = USB_SPI_MAX_WRITE_COUNT; @@ -174,6 +184,23 @@ static void create_spi_config_response(struct usb_spi_packet_ctx *packet) packet->rsp_config.feature_bitmap |= USB_SPI_FEATURE_FULL_DUPLEX_SUPPORTED; #endif +#ifdef CONFIG_USB_SPI_FLASH_EXTENSIONS + packet->rsp_config.feature_bitmap |= USB_SPI_FEATURE_FLASH_EXTENSIONS; + if (current_device->usb_flags & USB_SPI_FLASH_DUAL_SUPPORT) + packet->rsp_config.feature_bitmap |= + USB_SPI_FEATURE_DUAL_MODE_SUPPORTED; + if (current_device->usb_flags & USB_SPI_FLASH_QUAD_SUPPORT) + packet->rsp_config.feature_bitmap |= + USB_SPI_FEATURE_QUAD_MODE_SUPPORTED; + if (current_device->usb_flags & USB_SPI_FLASH_OCTO_SUPPORT) + packet->rsp_config.feature_bitmap |= + USB_SPI_FEATURE_OCTO_MODE_SUPPORTED; + if (current_device->usb_flags & USB_SPI_FLASH_DTR_SUPPORT) + packet->rsp_config.feature_bitmap |= + USB_SPI_FEATURE_DTR_SUPPORTED; +#else + (void)current_device; /* Avoid warning about unused variable. */ +#endif packet->packet_size = sizeof(struct usb_spi_response_configuration_v2); } @@ -231,6 +258,45 @@ usb_spi_create_spi_transfer_response(struct usb_spi_packet_ctx *transmit_packet) } } +#ifdef CONFIG_USB_SPI_FLASH_EXTENSIONS +/* + * Decodes the header fields of a Flash Command Start Packet, and sets up the + * transaction depending on if it is read or write. + */ +static void setup_flash_transfer(struct usb_spi_packet_ctx *packet) +{ + const uint32_t flags = packet->cmd_flash_start.flags; + usb_spi_state.flash_flags = flags; + const uint8_t opcode_count = (flags & FLASH_FLAG_OPCODE_LEN_MSK) >> + FLASH_FLAG_OPCODE_LEN_POS; + const uint8_t addr_count = (flags & FLASH_FLAG_ADDR_LEN_MSK) >> + FLASH_FLAG_ADDR_LEN_POS; + const bool write_enable = !!(flags & FLASH_FLAG_WRITE_ENABLE); + if ((packet->cmd_flash_start.flags & FLASH_FLAG_READ_WRITE_MSK) == + FLASH_FLAG_READ_WRITE_WRITE) { + size_t write_count = packet->cmd_flash_start.count; + if (write_count > USB_SPI_MAX_WRITE_COUNT) { + usb_spi_state.status_code = USB_SPI_WRITE_COUNT_INVALID; + return; + } + usb_spi_setup_transfer(write_enable + opcode_count + + addr_count + write_count, + 0); + } else { + size_t read_count = packet->cmd_flash_start.count; + if (read_count > USB_SPI_MAX_READ_COUNT) { + usb_spi_state.status_code = USB_SPI_WRITE_COUNT_INVALID; + return; + } + usb_spi_setup_transfer(write_enable + opcode_count + addr_count, + read_count); + } + packet->header_size = offsetof(struct usb_spi_flash_command, data); + usb_spi_state.status_code = + usb_spi_read_usb_packet(&usb_spi_state.spi_write_ctx, packet); +} +#endif + /* * Process the rx packet. * @@ -266,6 +332,7 @@ static void usb_spi_process_rx_packet(struct usb_spi_packet_ctx *packet) /* The host started a new USB SPI transfer */ size_t write_count = packet->cmd_start.write_count; size_t read_count = packet->cmd_start.read_count; + usb_spi_state.flash_flags = 0; if (!usb_spi_state.enabled) { setup_transfer_response(USB_SPI_DISABLED); @@ -302,6 +369,30 @@ static void usb_spi_process_rx_packet(struct usb_spi_packet_ctx *packet) break; } +#ifdef CONFIG_USB_SPI_FLASH_EXTENSIONS + case USB_SPI_PKT_ID_CMD_FLASH_TRANSFER_START: { + /* The host started a new USB serial flash SPI transfer */ + if (!usb_spi_state.enabled) { + setup_transfer_response(USB_SPI_DISABLED); + } else { + setup_flash_transfer(packet); + } + + /* Send responses if we encountered an error. */ + if (usb_spi_state.status_code != USB_SPI_SUCCESS) { + setup_transfer_response(usb_spi_state.status_code); + break; + } + + /* Start the SPI transfer when we've read all data. */ + if (usb_spi_state.spi_write_ctx.transfer_index == + usb_spi_state.spi_write_ctx.transfer_size) { + usb_spi_state.mode = USB_SPI_MODE_START_SPI; + } + + break; + } +#endif case USB_SPI_PKT_ID_CMD_TRANSFER_CONTINUE: { /* * The host has sent a continue packet for the SPI transfer @@ -355,6 +446,107 @@ static void usb_spi_process_rx_packet(struct usb_spi_packet_ctx *packet) } } +/* + * Perform a SPI write-then-read transaction, optionally preceded by a single + * byte "write enable" (separated by deasserting chip select), and optionally + * followed by polling the "busy bit" until clear. + */ +static uint16_t do_spi_transfer(void) +{ + const struct spi_device_t *current_device = + &spi_devices[usb_spi_state.current_spi_device_idx]; + bool custom_board_driver = current_device->usb_flags & + USB_SPI_CUSTOM_SPI_DEVICE; + /* + * If CONFIG_USB_SPI_FLASH_EXTENSIONS is not enabled, then the below + * value being zero will allow the compiler to optimize away several + * large if-blocks in this function. + */ + const uint32_t flash_flags = + IS_ENABLED(CONFIG_USB_SPI_FLASH_EXTENSIONS) ? + usb_spi_state.flash_flags : + 0; + uint16_t status_code = EC_SUCCESS; + int read_count = usb_spi_state.spi_read_ctx.transfer_size; + const char *write_data_ptr = usb_spi_state.spi_write_ctx.buffer; + int write_count = usb_spi_state.spi_write_ctx.transfer_size; +#ifndef CONFIG_SPI_HALFDUPLEX + /* + * Handle the full duplex mode on supported platforms. + * The read count is equal to the write count. + */ + if (read_count == USB_SPI_FULL_DUPLEX_ENABLED) { + usb_spi_state.spi_read_ctx.transfer_size = + usb_spi_state.spi_write_ctx.transfer_size; + read_count = SPI_READBACK_ALL; + } +#endif + + if (!custom_board_driver && + (flash_flags & FLASH_FLAGS_REQUIRING_SUPPORT)) { + /* + * The standard spi_transaction() does not support + * any multi-lane modes. + */ + return USB_SPI_UNSUPPORTED_FLASH_MODE; + } + + if (status_code == EC_SUCCESS && + flash_flags & FLASH_FLAG_WRITE_ENABLE) { + /* Precede main transaction with one-byte "write enable". */ + if (custom_board_driver) { + status_code = usb_spi_board_transaction( + current_device, 0, write_data_ptr, 1, NULL, 0); + } else { + status_code = spi_transaction( + current_device, write_data_ptr, 1, NULL, 0); + } + write_data_ptr += 1; + write_count -= 1; + } + + if (status_code == EC_SUCCESS) { + if (custom_board_driver) { + status_code = usb_spi_board_transaction( + current_device, flash_flags, write_data_ptr, + write_count, usb_spi_state.spi_read_ctx.buffer, + read_count); + } else { + status_code = spi_transaction( + current_device, write_data_ptr, write_count, + usb_spi_state.spi_read_ctx.buffer, read_count); + } + } + + if (flash_flags & FLASH_FLAG_POLL) { + /* After main transaction, poll until no longer "busy". */ + static timestamp_t deadline; + deadline.val = get_time().val + FLASH_BUSY_POLL_TIMEOUT_USEC; + + while (status_code == EC_SUCCESS) { + timestamp_t now; + uint8_t status_byte; + if (custom_board_driver) { + status_code = usb_spi_board_transaction( + current_device, 0, &JEDEC_READ_STATUS, + 1, &status_byte, 1); + } else { + status_code = spi_transaction( + current_device, &JEDEC_READ_STATUS, 1, + &status_byte, 1); + } + if ((status_byte & JEDEC_STATUS_BUSY) == 0) + break; + now = get_time(); + if (timestamp_expired(deadline, &now)) { + status_code = EC_ERROR_TIMEOUT; + break; + } + } + } + return usb_spi_map_error(status_code); +} + /* Deferred function to handle state changes, process USB SPI packets, * and construct responses. * @@ -412,40 +604,7 @@ void usb_spi_deferred(void) /* Start a new SPI transfer. */ if (usb_spi_state.mode == USB_SPI_MODE_START_SPI) { - const struct spi_device_t *current_device = - &spi_devices[usb_spi_state.current_spi_device_idx]; - bool custom_board_driver = current_device->usb_flags & - USB_SPI_CUSTOM_SPI_DEVICE; - uint16_t status_code; - int read_count = usb_spi_state.spi_read_ctx.transfer_size; -#ifndef CONFIG_SPI_HALFDUPLEX - /* - * Handle the full duplex mode on supported platforms. - * The read count is equal to the write count. - */ - if (read_count == USB_SPI_FULL_DUPLEX_ENABLED) { - usb_spi_state.spi_read_ctx.transfer_size = - usb_spi_state.spi_write_ctx.transfer_size; - read_count = SPI_READBACK_ALL; - } -#endif - - if (custom_board_driver) { - status_code = usb_spi_board_transaction( - current_device, 0 /* flash_flags */, - usb_spi_state.spi_write_ctx.buffer, - usb_spi_state.spi_write_ctx.transfer_size, - usb_spi_state.spi_read_ctx.buffer, read_count); - } else { - status_code = spi_transaction( - current_device, - usb_spi_state.spi_write_ctx.buffer, - usb_spi_state.spi_write_ctx.transfer_size, - usb_spi_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); + uint16_t status_code = do_spi_transfer(); setup_transfer_response(status_code); } diff --git a/chip/stm32/usb_spi.h b/chip/stm32/usb_spi.h index 385aaaf730..e0dfd34b18 100644 --- a/chip/stm32/usb_spi.h +++ b/chip/stm32/usb_spi.h @@ -146,6 +146,7 @@ * 0x0008: An unexpected packet arrived that the device could not * process. * 0x0009: The device does not support full duplex mode. + * 0x000A: Requested serial flash mode not supported * 0x8000: Unknown error mask * The bottom 15 bits will contain the bottom 15 bits from the EC * error code. @@ -218,7 +219,12 @@ * * feature bitmap: Bitmap of supported features. * BIT(0): Full duplex SPI mode is supported - * BIT(1:15): Reserved for future use + * BIT(1): Serial flash extensions are supported + * BIT(2): Dual mode flash supported + * BIT(3): Quad mode flash supported + * BIT(4): Octo mode flash supported + * BIT(5): Double transfer rate supported + * BIT(6:15): Reserved for future use * * Command Restart Response Packet (Host to Device): * @@ -256,6 +262,64 @@ * 0x0000: Success * others: Error * + * Flash Command Start Packet (Host to Device): + * + * Start of the USB serial flash SPI command, contains the number of + * bytes to write or 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. + * + * The reading or writing of the "main" data will be preceded by an + * short sequence of opcode, optional address, optional "alternate data", + * and optional 'dummy cycles" on the SPI bus. Flags indicate how many + * bytes of each stage to send, and whether to use advanced features such + * as dual or quad signal lanes for each stage of the transfer". + * + * The indicated number of opcode, address and alternate bytes will be + * the first in the "write payload". The "count" field will contain the + * number of data bytes to be written/read after the opcode, address and + * alternate bytes. + * + * This request is only supported if bit 1 of the "feature bitmap" + * indicates that serial flash extensions are supported. Implementations + * will further advertise whether they support dual, quad or octo modes, if + * none of these are supported, then support for "dummy cycles" is not + * guaranteed either, and callers should use one or two bytes of "extra + * address data" for dummy cycles, address length can be up to 7 bytes for + * this reason. + * + * +----------------+------------+------------+---------------+ + * | packet id : 2B | count : 2B | flags : 4B | w.p. : <= 56B | + * +----------------+------------+------------+---------------+ + * + * packet id: 2 byte enum defined by packet_id_type + * Valid values packet id = + * USB_SPI_PKT_ID_CMD_FLASH_TRANSFER_START + * + * count: 2 byte, zero based count of bytes to read or write + * + * flags: 4 byte, flags + * bits 0:1 opcode length in bytes (0-3) + * bits 2:4 address length in bytes (0-7) + * bits 5:6 mode (0: 1-1-1, 1: 1-1-N, 2: 1-N-N, 3: N-N-N) + * bits 7:8 width (0: N=1, 1: N=2, 2: N=4, 3: N=8) + * bit 9 double transfer rate (in phases marked as N) + * bits 10:14 number of dummy cycles (0-31) + * bits 15:27 reserved, must be zero + * bit 28 write to be preceded by "write enable" + * bit 29 write to be followed by polling of JEDEC "busy bit" + * bit 30 reserved, must be zero + * bit 31 read (0) / write (1) + * + * write payload: Up to 56 bytes of data to write to SPI, the total length + * of all TX packets must match: write enable length (zero or + * one, depending on bit 27) + opcode length + address length + * + count, (the last one only if bit 31 indicates a write + * operation). Due to data alignment constraints, this must + * be an even number of bytes unless this is the final + * packet. + * + * * USB Error Codes: * * send_command return codes have the following format: @@ -278,6 +342,8 @@ #define USB_SPI_PAYLOAD_SIZE_V2_ERROR (60) +#define USB_SPI_PAYLOAD_SIZE_FLASH_START (56) + #define USB_SPI_MIN_PACKET_SIZE (2) /* @@ -294,6 +360,8 @@ #define USB_SPI_FLASH_QUAD_SUPPORT BIT(3) /* This SPI device supports eight lane mode. */ #define USB_SPI_FLASH_OCTO_SUPPORT BIT(4) +/* This SPI device supports double transfer rate (data on both clock edges). */ +#define USB_SPI_FLASH_DTR_SUPPORT BIT(5) enum packet_id_type { /* Request USB SPI configuration data from device. */ @@ -325,11 +393,34 @@ enum packet_id_type { USB_SPI_PKT_ID_CMD_CHIP_SELECT = 7, /* Response to above request. */ USB_SPI_PKT_ID_RSP_CHIP_SELECT = 8, + /* + * Start a USB serial flash SPI transfer. + */ + USB_SPI_PKT_ID_CMD_FLASH_TRANSFER_START = 9, }; enum feature_bitmap { /* Indicates the platform supports full duplex mode. */ - USB_SPI_FEATURE_FULL_DUPLEX_SUPPORTED = BIT(0) + USB_SPI_FEATURE_FULL_DUPLEX_SUPPORTED = BIT(0), + /* Indicates support for USB_SPI_PKT_ID_CMD_FLASH_TRANSFER_START. */ + USB_SPI_FEATURE_FLASH_EXTENSIONS = BIT(1), + /* + * Indicates that chip and any MUXes support bidirectional data on the + * two SPI data lines. + */ + USB_SPI_FEATURE_DUAL_MODE_SUPPORTED = BIT(2), + /* + * Indicates that chip and any MUXes support bidirectional data on the + * "hold" and "write protect" lines. + */ + USB_SPI_FEATURE_QUAD_MODE_SUPPORTED = BIT(3), + /* Indicates support for eight-line bidirectional data. */ + USB_SPI_FEATURE_OCTO_MODE_SUPPORTED = BIT(4), + /* + * Indicates support for double transfer rate, i.e. data bit shift on + * both rising and falling clock edges. + */ + USB_SPI_FEATURE_DTR_SUPPORTED = BIT(5), }; struct usb_spi_response_configuration_v2 { @@ -374,11 +465,36 @@ struct usb_spi_chip_select_response { uint16_t status_code; } __packed; +struct usb_spi_flash_command { + uint16_t packet_id; + uint16_t count; + uint32_t flags; + uint8_t data[USB_SPI_PAYLOAD_SIZE_FLASH_START]; +} __packed; + +/* + * Mask of the flags that are handled by logic in sub_spi.c, and not passed to + * SPI drivers through usb_spi_board_transaction(). + */ +#define FLASH_FLAGS_NONBOARD 0xF0000000UL + +#define FLASH_FLAG_WRITE_ENABLE_POS 28U +#define FLASH_FLAG_WRITE_ENABLE (0x1UL << FLASH_FLAG_WRITE_ENABLE_POS) + +#define FLASH_FLAG_POLL_POS 29U +#define FLASH_FLAG_POLL (0x1UL << FLASH_FLAG_POLL_POS) + +#define FLASH_FLAG_READ_WRITE_POS 31U +#define FLASH_FLAG_READ_WRITE_MSK (0x1UL << FLASH_FLAG_READ_WRITE_POS) +#define FLASH_FLAG_READ_WRITE_READ 0 +#define FLASH_FLAG_READ_WRITE_WRITE (0x1UL << FLASH_FLAG_READ_WRITE_POS) + 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_flash_command cmd_flash_start; struct usb_spi_continue_v2 cmd_continue; struct usb_spi_response_configuration_v2 rsp_config; struct usb_spi_response_v2 rsp_start; @@ -412,6 +528,8 @@ enum usb_spi_error { USB_SPI_RX_UNEXPECTED_PACKET = 0x0008, /* The device does not support full duplex mode. */ USB_SPI_UNSUPPORTED_FULL_DUPLEX = 0x0009, + /* The device does not support dual/quad wire mode. */ + USB_SPI_UNSUPPORTED_FLASH_MODE = 0x000A, USB_SPI_UNKNOWN_ERROR = 0x8000, }; @@ -508,6 +626,12 @@ struct usb_spi_state { 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. */ @@ -666,70 +790,38 @@ int usb_spi_board_transaction(const struct spi_device_t *spi_device, * 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) +/* Number of bytes of opcode (0-3). */ +#define FLASH_FLAG_OPCODE_LEN_POS 0 +#define FLASH_FLAG_OPCODE_LEN_MSK (0x3U << FLASH_FLAG_OPCODE_LEN_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 address plus additional data bytes (0-7). */ +#define FLASH_FLAG_ADDR_LEN_POS 2 +#define FLASH_FLAG_ADDR_LEN_MSK (0x7U << FLASH_FLAG_ADDR_LEN_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) +/* At what stage to switch to multi-lane mode (if any). */ +#define FLASH_FLAG_MODE_POS 5 +#define FLASH_FLAG_MODE_MSK (0x3U << FLASH_FLAG_MODE_POS) +#define FLASH_FLAG_MODE_111 (0x0U << FLASH_FLAG_MODE_POS) +#define FLASH_FLAG_MODE_11N (0x1U << FLASH_FLAG_MODE_POS) +#define FLASH_FLAG_MODE_1NN (0x2U << FLASH_FLAG_MODE_POS) +#define FLASH_FLAG_MODE_NNN (0x3U << FLASH_FLAG_MODE_POS) + +/* Data width during the later stages (value of N, above). */ +#define FLASH_FLAG_WIDTH_POS 7 +#define FLASH_FLAG_WIDTH_MSK (0x3U << FLASH_FLAG_WIDTH_POS) +#define FLASH_FLAG_WIDTH_1WIRE (0x0U << FLASH_FLAG_WIDTH_POS) +#define FLASH_FLAG_WIDTH_2WIRE (0x1U << FLASH_FLAG_WIDTH_POS) +#define FLASH_FLAG_WIDTH_4WIRE (0x2U << FLASH_FLAG_WIDTH_POS) +#define FLASH_FLAG_WIDTH_8WIRE (0x3U << FLASH_FLAG_WIDTH_POS) + +/* Transmit opcode bits at both clock edges in later stages. */ +#define FLASH_FLAG_DTR_POS 9 +#define FLASH_FLAG_DTR (0x1U << FLASH_FLAG_DTR_POS) /* Number of dummy clock cycles (0-31). */ -#define FLASH_FLAG_DUMMY_CYCLES_POS 18 +#define FLASH_FLAG_DUMMY_CYCLES_POS 10 #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 @@ -739,11 +831,7 @@ int usb_spi_board_transaction(const struct spi_device_t *spi_device, * 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) +#define FLASH_FLAGS_REQUIRING_SUPPORT \ + (FLASH_FLAG_MODE_MSK | FLASH_FLAG_DTR | FLASH_FLAG_DUMMY_CYCLES_MSK) #endif /* __CROS_EC_USB_SPI_H */ |