diff options
author | Jes B. Klinke <jbk@chromium.org> | 2022-12-02 20:19:14 -0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-01-11 23:09:46 +0000 |
commit | d1af62d34e44f9b79b109e6c418671a35c599c81 (patch) | |
tree | c110696652b70bdeab60d7e2a078a2a42b45bf14 | |
parent | 3edc823aa218bb0989553e297744ab826ffa5cd2 (diff) | |
download | chrome-ec-d1af62d34e44f9b79b109e6c418671a35c599c81.tar.gz |
board/hyperdebug: Enumerate and configure SPI ports via USB
Add console commands: spiget and spisetspeed
The first can list information on all SPI port or a particular port.
The other, spisetspeed, can be used to modify the clock divisor between
SPI transactions.
BUG=b:192262089
TEST=Observed different clock speeds on analyzer
Change-Id: I113b8bdef48f58d5941212c8a8598f3293b5da91
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4078008
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Tested-by: Jes Klinke <jbk@chromium.org>
Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Commit-Queue: Jes Klinke <jbk@chromium.org>
-rw-r--r-- | board/hyperdebug/board.c | 145 | ||||
-rw-r--r-- | board/hyperdebug/board.h | 3 |
2 files changed, 146 insertions, 2 deletions
diff --git a/board/hyperdebug/board.c b/board/hyperdebug/board.c index 8e56c0359d..c9a3702d1e 100644 --- a/board/hyperdebug/board.c +++ b/board/hyperdebug/board.c @@ -131,7 +131,7 @@ USB_STREAM_CONFIG(usart5_usb, USB_IFACE_USART5_STREAM, #define SPI_CLOCK (16000000UL) /* SPI devices, default to 250 kb/s for all. */ -const struct spi_device_t spi_devices[] = { +struct spi_device_t spi_devices[] = { { .name = "SPI2", .port = 1, .div = 5, @@ -636,3 +636,146 @@ static int command_gpio_pull_mode(int argc, const char **argv) DECLARE_CONSOLE_COMMAND_FLAGS(gpiopullmode, command_gpio_pull_mode, "name <none | up | down>", "Set a GPIO weak pull mode", CMD_FLAG_RESTRICTED); + +/* + * Find spi device by name or by number. Returns an index into spi_devices[], + * or on error a negative value. + */ +static int find_spi_by_name(const char *name) +{ + int i; + char *e; + i = strtoi(name, &e, 0); + + if (!*e && i < spi_devices_used) + return i; + + for (i = 0; i < spi_devices_used; i++) { + if (!strcasecmp(name, spi_devices[i].name)) + return i; + } + + /* SPI device not found */ + return -1; +} + +static void print_spi_info(int index) +{ + uint32_t bits_per_second; + + if (spi_devices[index].usb_flags & USB_SPI_CUSTOM_SPI_DEVICE) { + // OCTOSPI as 8 bit prescaler, dividing clock by 1..256. + bits_per_second = OCTOSPI_CLOCK / (spi_devices[index].div + 1); + } else { + // Other SPIs have prescaler by power of two 2, 4, 8, ..., 256. + bits_per_second = SPI_CLOCK / (2 << spi_devices[index].div); + } + + ccprintf(" %d %s %d bps\n", index, spi_devices[index].name, + bits_per_second); + + /* Flush console to avoid truncating output */ + cflush(); +} + +/* + * Get information about one or all SPI ports. + */ +static int command_spi_info(int argc, const char **argv) +{ + int i; + + /* If a SPI target is specified, print only that one */ + if (argc == 3) { + int index = find_spi_by_name(argv[2]); + if (index < 0) { + ccprintf("SPI device not found\n"); + return EC_ERROR_PARAM2; + } + + print_spi_info(index); + return EC_SUCCESS; + } + + /* Otherwise print them all */ + for (i = 0; i < spi_devices_used; i++) { + print_spi_info(i); + } + + return EC_SUCCESS; +} + +static int command_spi_set_speed(int argc, const char **argv) +{ + int index; + uint32_t desired_speed; + char *e; + if (argc < 5) + return EC_ERROR_PARAM_COUNT; + + index = find_spi_by_name(argv[3]); + if (index < 0) + return EC_ERROR_PARAM3; + + desired_speed = strtoi(argv[4], &e, 0); + if (*e) + return EC_ERROR_PARAM4; + + if (spi_devices[index].usb_flags & USB_SPI_CUSTOM_SPI_DEVICE) { + /* + * Find prescaler value by division, rounding up in order to get + * slightly slower speed than requested, if it cannot be matched + * exactly. + */ + spi_devices[index].div = + (OCTOSPI_CLOCK + desired_speed - 1) / desired_speed - 1; + STM32_OCTOSPI_DCR2 = spi_devices[index].div; + } else { + int divisor = 7; + /* + * Find the smallest divisor that result in a speed not faster + * than what was requested. + */ + while (divisor > 0) { + if (SPI_CLOCK / (2 << (divisor - 1)) > desired_speed) { + /* One step further would make the clock too + * fast, stop here. */ + break; + } + divisor--; + } + + /* + * Re-initialize spi controller to apply the new clock divisor. + */ + spi_enable(&spi_devices[index], 0); + spi_devices[index].div = divisor; + spi_enable(&spi_devices[index], 1); + } + + return EC_SUCCESS; +} + +static int command_spi_set(int argc, const char **argv) +{ + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + if (!strcasecmp(argv[2], "speed")) + return command_spi_set_speed(argc, argv); + return EC_ERROR_PARAM2; +} + +static int command_spi(int argc, const char **argv) +{ + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + if (!strcasecmp(argv[1], "info")) + return command_spi_info(argc, argv); + if (!strcasecmp(argv[1], "set")) + return command_spi_set(argc, argv); + return EC_ERROR_PARAM1; +} +DECLARE_CONSOLE_COMMAND_FLAGS(spi, command_spi, + "info [PORT]" + "\nset speed PORT BPS", + "SPI bus manipulation", CMD_FLAG_RESTRICTED); diff --git a/board/hyperdebug/board.h b/board/hyperdebug/board.h index 86c2c88ad0..760e66aa37 100644 --- a/board/hyperdebug/board.h +++ b/board/hyperdebug/board.h @@ -97,13 +97,14 @@ #define CONFIG_USB_SPI #define CONFIG_USB_SPI_BUFFER_SIZE 2048 #define CONFIG_SPI_CONTROLLER +#define CONFIG_STM32_SPI1_CONTROLLER +#define CONFIG_SPI_MUTABLE_DEVICE_LIST /* Enable control of I2C over USB */ #define CONFIG_USB_I2C #define CONFIG_I2C #define CONFIG_I2C_CONTROLLER #define I2C_PORT_CONTROLLER 0 -#define CONFIG_STM32_SPI1_CONTROLLER /* See i2c_ite_flash_support.c for more information about these values */ /*#define CONFIG_ITE_FLASH_SUPPORT */ |