diff options
author | Jes B. Klinke <jbk@chromium.org> | 2023-02-15 15:18:43 -0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-02-16 21:59:22 +0000 |
commit | ca113941bd005b738b8895c2d525eca7302474f9 (patch) | |
tree | 06e553cbd2785deafe93c7d3689058e2cdd7286a | |
parent | 2fa17baa833de281f79d8b62bd7f52241d3690b5 (diff) | |
download | chrome-ec-ca113941bd005b738b8895c2d525eca7302474f9.tar.gz |
board/hyperdebug: Add DAC support
The HyperDebug board is a versatile debugger, serving a similar purpose
to uServo for development boards for Google Security Chips or other
microcontrollers, rather than full Chromebooks.
This change allows the DAC circuits of HyperDebug to be enabled, and
particular voltages specified, through console commands.
BUG=b:269621551
TEST=Observe AndreiBoard detect CCD connect/disconnect
Change-Id: I6850821da9b7a3ef576eee9a458f43466df0692c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4259215
Reviewed-by: Wai-Hong Tam <waihong@google.com>
Commit-Queue: Jes Klinke <jbk@chromium.org>
Tested-by: Jes Klinke <jbk@chromium.org>
-rw-r--r-- | board/hyperdebug/board.c | 3 | ||||
-rw-r--r-- | board/hyperdebug/gpio.c | 125 |
2 files changed, 117 insertions, 11 deletions
diff --git a/board/hyperdebug/board.c b/board/hyperdebug/board.c index 7e6b412c02..1fe4b1b9d1 100644 --- a/board/hyperdebug/board.c +++ b/board/hyperdebug/board.c @@ -200,6 +200,9 @@ static void board_init(void) /* Configure SPI GPIOs */ gpio_config_module(MODULE_SPI, 1); + /* Enable DAC */ + STM32_RCC_APB1ENR |= STM32_RCC_APB1ENR1_DAC1EN; + /* * Enable SPI2. */ diff --git a/board/hyperdebug/gpio.c b/board/hyperdebug/gpio.c index 7dbc063237..8ab9f7ce6b 100644 --- a/board/hyperdebug/gpio.c +++ b/board/hyperdebug/gpio.c @@ -17,6 +17,17 @@ #include "timer.h" #include "util.h" +struct dac_t { + uint32_t enable_mask; + volatile uint32_t *data_register; +}; + +/* Sparse array of DAC capabilities for GPIO pins. */ +const struct dac_t dac_channels[GPIO_COUNT] = { + [GPIO_CN7_9] = { STM32_DAC_CR_EN1, &STM32_DAC_DHR12R1 }, + [GPIO_CN7_10] = { STM32_DAC_CR_EN2, &STM32_DAC_DHR12R2 }, +}; + /* * A cyclic buffer is used to record events (edges) of one or more GPIO * signals. Each event records the time since the previous event, and the @@ -275,6 +286,7 @@ static int command_gpio_mode(int argc, const char **argv) { int gpio; int flags; + uint32_t dac_enable_value = STM32_DAC_CR; if (argc < 3) return EC_ERROR_PARAM_COUNT; @@ -285,24 +297,35 @@ static int command_gpio_mode(int argc, const char **argv) flags = gpio_get_flags(gpio); flags = flags & ~(GPIO_INPUT | GPIO_OUTPUT | GPIO_OPEN_DRAIN); + dac_enable_value &= ~dac_channels[gpio].enable_mask; if (strcasecmp(argv[2], "input") == 0) flags |= GPIO_INPUT; else if (strcasecmp(argv[2], "opendrain") == 0) flags |= GPIO_OUTPUT | GPIO_OPEN_DRAIN; else if (strcasecmp(argv[2], "pushpull") == 0) flags |= GPIO_OUTPUT; - else if (strcasecmp(argv[2], "alternate") == 0) + else if (strcasecmp(argv[2], "dac") == 0) { + if (dac_channels[gpio].enable_mask == 0) { + ccprintf("Error: Pin does not support dac\n"); + return EC_ERROR_PARAM2; + } + dac_enable_value |= dac_channels[gpio].enable_mask; + /* Disable digital output, when DAC is overriding. */ + flags |= GPIO_INPUT; + } else if (strcasecmp(argv[2], "alternate") == 0) flags |= GPIO_ALTERNATE; else return EC_ERROR_PARAM2; /* Update GPIO flags. */ gpio_set_flags(gpio, flags); + STM32_DAC_CR = dac_enable_value; return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND_FLAGS(gpiomode, command_gpio_mode, - "name <input | opendrain | pushpull | alternate>", - "Set a GPIO mode", CMD_FLAG_RESTRICTED); +DECLARE_CONSOLE_COMMAND_FLAGS( + gpiomode, command_gpio_mode, + "name <input | opendrain | pushpull | dac | alternate>", + "Set a GPIO mode", CMD_FLAG_RESTRICTED); /* * Set the weak pulling of a GPIO pin: up/down/none. @@ -338,6 +361,48 @@ DECLARE_CONSOLE_COMMAND_FLAGS(gpiopullmode, command_gpio_pull_mode, "name <none | up | down>", "Set a GPIO weak pull mode", CMD_FLAG_RESTRICTED); +static int set_dac(int gpio, const char *value) +{ + int milli_volts; + char *e; + if (dac_channels[gpio].enable_mask == 0) { + ccprintf("Error: Pin does not support dac\n"); + return EC_ERROR_PARAM6; + } + + milli_volts = strtoi(value, &e, 0); + if (*e) + return EC_ERROR_PARAM6; + + if (milli_volts <= 0) + *dac_channels[gpio].data_register = 0; + else if (milli_volts >= 3300) + *dac_channels[gpio].data_register = 4095; + else + *dac_channels[gpio].data_register = milli_volts * 4096 / 3300; + + return EC_SUCCESS; +} + +/* + * Set the value in millivolts for driving the DAC of a given pin. + */ +static int command_gpio_analog_set(int argc, const char **argv) +{ + int gpio; + + if (argc < 4) + return EC_ERROR_PARAM_COUNT; + + gpio = find_signal_by_name(argv[2]); + if (gpio == GPIO_COUNT) + return EC_ERROR_PARAM2; + + if (set_dac(gpio, argv[3]) != EC_SUCCESS) + return EC_ERROR_PARAM3; + return EC_SUCCESS; +} + /* * Set multiple aspects of a GPIO pin simultaneously, that is, can switch output * level, opendrain/pushpull, and pullup simultaneously, eliminating the risk of @@ -347,6 +412,7 @@ static int command_gpio_multiset(int argc, const char **argv) { int gpio; int flags; + uint32_t dac_enable_value = STM32_DAC_CR; if (argc < 4) return EC_ERROR_PARAM_COUNT; @@ -368,13 +434,22 @@ static int command_gpio_multiset(int argc, const char **argv) if (argc > 4 && strcasecmp(argv[4], "-") != 0) { flags = flags & ~(GPIO_INPUT | GPIO_OUTPUT | GPIO_OPEN_DRAIN); + dac_enable_value &= ~dac_channels[gpio].enable_mask; if (strcasecmp(argv[4], "input") == 0) flags |= GPIO_INPUT; else if (strcasecmp(argv[4], "opendrain") == 0) flags |= GPIO_OUTPUT | GPIO_OPEN_DRAIN; else if (strcasecmp(argv[4], "pushpull") == 0) flags |= GPIO_OUTPUT; - else if (strcasecmp(argv[4], "alternate") == 0) + else if (strcasecmp(argv[4], "dac") == 0) { + if (dac_channels[gpio].enable_mask == 0) { + ccprintf("Error: Pin does not support dac\n"); + return EC_ERROR_PARAM2; + } + dac_enable_value |= dac_channels[gpio].enable_mask; + /* Disable digital output, when DAC is overriding. */ + flags |= GPIO_INPUT; + } else if (strcasecmp(argv[4], "alternate") == 0) flags |= GPIO_ALTERNATE; else return EC_ERROR_PARAM4; @@ -392,8 +467,14 @@ static int command_gpio_multiset(int argc, const char **argv) return EC_ERROR_PARAM5; } + if (argc > 6 && strcasecmp(argv[6], "-") != 0) { + if (set_dac(gpio, argv[6]) != EC_SUCCESS) + return EC_ERROR_PARAM6; + } + /* Update GPIO flags. */ gpio_set_flags(gpio, flags); + STM32_DAC_CR = dac_enable_value; return EC_SUCCESS; } @@ -725,22 +806,44 @@ static int command_gpio(int argc, const char **argv) { if (argc < 2) return EC_ERROR_PARAM_COUNT; + if (!strcasecmp(argv[1], "analog-set")) + return command_gpio_analog_set(argc, argv); if (!strcasecmp(argv[1], "monitoring")) return command_gpio_monitoring(argc, argv); if (!strcasecmp(argv[1], "multiset")) return command_gpio_multiset(argc, argv); return EC_ERROR_PARAM1; } -DECLARE_CONSOLE_COMMAND_FLAGS(gpio, command_gpio, - "multiset PIN [level] [mode] [pullmode]" - "\nmonitoring start PIN" - "\nmonitoring read PIN" - "\nmonitoring stop PIN", - "GPIO manipulation", CMD_FLAG_RESTRICTED); +DECLARE_CONSOLE_COMMAND_FLAGS( + gpio, command_gpio, + "multiset name [level] [mode] [pullmode] [milli_volts]" + "\nanalog-set name milli_volts" + "\nmonitoring start name..." + "\nmonitoring read name..." + "\nmonitoring stop name...", + "GPIO manipulation", CMD_FLAG_RESTRICTED); static int command_reinit(int argc, const char **argv) { + const struct gpio_info *g = gpio_list; + int i; + stop_all_gpio_monitoring(); + + /* Set all GPIOs to defaults */ + for (i = 0; i < GPIO_COUNT; i++, g++) { + int flags = g->flags; + + if (flags & GPIO_DEFAULT) + continue; + + /* Set up GPIO based on flags */ + gpio_set_flags_by_mask(g->port, g->mask, flags); + } + + /* Disable any DAC (which would override GPIO function of pins) */ + STM32_DAC_CR = 0; + return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND_FLAGS(reinit, command_reinit, "", |