diff options
author | Jes B. Klinke <jbk@chromium.org> | 2023-05-08 13:18:37 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-05-09 00:16:58 +0000 |
commit | a46e9d233b0d094256459f613101070f84133a6a (patch) | |
tree | e591eadf63f5562675875b0f8569e61b895efb6d | |
parent | cde085221a5b3313c5c479a8611990313f06db78 (diff) | |
download | chrome-ec-a46e9d233b0d094256459f613101070f84133a6a.tar.gz |
board/hyperdebug: Properly enter alternate mode
HyperDebug allows host software to change the mode of most pins. Some
of them have pre-defined alternate modes, such as UART, SPI or I2C. The
I2C pins in particular must operate as open-drain, when in their
"alternate" mode. The EC codebase usually does this as part of
gpio_config_module() when all pins used by a particular module are put
into alternate mode, based on the flags field in ALTERNATE()
declarations in gpio.inc.
HyperDebug however, operates on a single pin at a time using
gpio_set_flags() which does not look at ALTERNATE() declarations.
This CL introduces a helper method to find out which additional flags
need to be applied, when switching a particular pin into alternate mode.
BUG=none
TEST=HyperDebug can continue I2C communication after `transport init`
Change-Id: I8e7c9ed081635c6166e9487cff02f0b0e3d059cc
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4513887
Tested-by: Jes Klinke <jbk@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Commit-Queue: Jes Klinke <jbk@chromium.org>
-rw-r--r-- | board/hyperdebug/gpio.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/board/hyperdebug/gpio.c b/board/hyperdebug/gpio.c index 5bcabe226d..a12b424032 100644 --- a/board/hyperdebug/gpio.c +++ b/board/hyperdebug/gpio.c @@ -28,6 +28,34 @@ const struct dac_t dac_channels[GPIO_COUNT] = { }; /* + * GPIO structure for keeping extra flags such as GPIO_OPEN_DRAIN, to be applied + * whenever the pin is switched into "alternate" mode. + */ +struct gpio_alt_flags { + /* Port base address */ + uint32_t port; + + /* Bitmask on that port (multiple bits allowed) */ + uint32_t mask; + + /* Flags (GPIO_*; see above). */ + uint32_t flags; +}; + +/* + * Construct the gpio_alt_flags array, this really is just a subset of the + * columns in the gpio_alt_funcs array in common/gpio.c (which is not accessible + * from here). This array is used by extra_alternate_flags(). + */ +#define ALTERNATE(pinmask, function, module, flagz) \ + { GPIO_##pinmask, .flags = (flagz) }, + +static __const_data const struct gpio_alt_flags gpio_alt_flags[] = { +#include "gpio.wrap" +}; +#undef ALTERNATE + +/* * 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 * signal that changed (the direction of change is not explicitly recorded). @@ -284,6 +312,30 @@ static void stop_all_gpio_monitoring(void) } } +/* + * Return GPIO_OPEN_DRAIN or any other special flags to apply when the given + * signal is in "alternate" mode. + */ +static uint32_t extra_alternate_flags(enum gpio_signal signal) +{ + const struct gpio_info *g = gpio_list + signal; + const struct gpio_alt_flags *af; + + /* Find the first ALTERNATE() declaration for the given pin. */ + for (af = gpio_alt_flags; + af < gpio_alt_flags + ARRAY_SIZE(gpio_alt_flags); af++) { + if (af->port != g->port) + continue; + + if (af->mask & g->mask) { + return af->flags; + } + } + + /* No ALTERNATE() declaration mention the given pin. */ + return 0; +} + /** * Find a GPIO signal by name. * @@ -344,7 +396,7 @@ static int command_gpio_mode(int argc, const char **argv) /* Disable digital output, when DAC is overriding. */ flags |= GPIO_INPUT; } else if (strcasecmp(argv[2], "alternate") == 0) - flags |= GPIO_ALTERNATE; + flags |= GPIO_ALTERNATE | extra_alternate_flags(gpio); else return EC_ERROR_PARAM2; @@ -484,7 +536,7 @@ static int command_gpio_multiset(int argc, const char **argv) /* Disable digital output, when DAC is overriding. */ flags |= GPIO_INPUT; } else if (strcasecmp(argv[4], "alternate") == 0) - flags |= GPIO_ALTERNATE; + flags |= GPIO_ALTERNATE | extra_alternate_flags(gpio); else return EC_ERROR_PARAM4; } @@ -872,6 +924,9 @@ static int command_reinit(int argc, const char **argv) if (flags & GPIO_DEFAULT) continue; + if (flags & GPIO_ALTERNATE) + flags |= extra_alternate_flags(i); + /* Set up GPIO based on flags */ gpio_set_flags_by_mask(g->port, g->mask, flags); } |