summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJes B. Klinke <jbk@chromium.org>2022-12-02 20:19:14 -0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-01-11 23:09:46 +0000
commitd1af62d34e44f9b79b109e6c418671a35c599c81 (patch)
treec110696652b70bdeab60d7e2a078a2a42b45bf14
parent3edc823aa218bb0989553e297744ab826ffa5cd2 (diff)
downloadchrome-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.c145
-rw-r--r--board/hyperdebug/board.h3
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 */