diff options
author | Rob Barnes <robbarnes@google.com> | 2022-01-05 10:31:40 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-01-13 18:03:16 +0000 |
commit | f0accb6b9c809bb18ca7f9d0c69fdf8527408678 (patch) | |
tree | f92989e8c0b3a9f57f48bf30e666e04a92e06350 | |
parent | 9a74b1cdbb5f9024d29393ba5c59c626051d4e82 (diff) | |
download | chrome-ec-f0accb6b9c809bb18ca7f9d0c69fdf8527408678.tar.gz |
ioexpander: Introduce GPIO save and restore functions
Add common ioexpander functions for saving a restoring GPIO state. This
is useful for restoring GPIO after the ioexpander is reset.
BUG=b:211452276
BRANCH=None
TEST=ioexpander state restored on nipperkin
Change-Id: Id81c5457f1c33fdf7490a963317e11a2b9441831
Signed-off-by: Rob Barnes <robbarnes@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3368321
Reviewed-by: Diana Z <dzigterman@chromium.org>
-rw-r--r-- | common/ioexpander.c | 54 | ||||
-rw-r--r-- | include/ioexpander.h | 20 |
2 files changed, 74 insertions, 0 deletions
diff --git a/common/ioexpander.c b/common/ioexpander.c index 6caa7f4bc1..2bed1039f4 100644 --- a/common/ioexpander.c +++ b/common/ioexpander.c @@ -154,6 +154,60 @@ int ioex_get_port(int ioex, int port, int *val) } #endif +int ioex_save_gpio_state(int ioex, int *state, int state_len) +{ + int rv; + const struct ioex_info *g = ioex_list; + const struct ioexpander_drv *drv = ioex_config[ioex].drv; + int state_offset = 0; + + for (int i = 0; i < IOEX_COUNT; i++, g++) { + if (g->ioex != ioex) + continue; + + if (state_offset >= state_len) { + CPRINTS("%s state buffer is too small", __func__); + return EC_ERROR_UNKNOWN; + } + + rv = drv->get_flags_by_mask(g->ioex, g->port, g->mask, + &state[state_offset++]); + if (rv) { + CPRINTS("%s failed to get flags rv=%d", __func__, rv); + return rv; + } + } + + return EC_SUCCESS; +} + +int ioex_restore_gpio_state(int ioex, const int *state, int state_len) +{ + int rv; + const struct ioex_info *g = ioex_list; + const struct ioexpander_drv *drv = ioex_config[ioex].drv; + int state_offset = 0; + + for (int i = 0; i < IOEX_COUNT; i++, g++) { + if (g->ioex != ioex) + continue; + + if (state_offset >= state_len) { + CPRINTS("%s state buffer is too small", __func__); + return EC_ERROR_UNKNOWN; + } + + rv = drv->set_flags_by_mask(g->ioex, g->port, g->mask, + state[state_offset++]); + if (rv) { + CPRINTS("%s failed to set flags rv=%d", __func__, rv); + return rv; + } + } + + return EC_SUCCESS; +} + int ioex_init(int ioex) { const struct ioex_info *g = ioex_list; diff --git a/include/ioexpander.h b/include/ioexpander.h index 4024a5a267..fb47b874a5 100644 --- a/include/ioexpander.h +++ b/include/ioexpander.h @@ -179,4 +179,24 @@ const char *ioex_get_name(enum ioex_signal signal); */ int signal_is_ioex(int signal); +/* + * Save gpio state of IO expander + * + * @param ioex IO expander chip's port number + * @param state Buffer to hold gpio state + * @param state_len Length of state buffer, IOEX_COUNT is recommended + * @return EC_SUCCESS if successful, non-zero if error. + */ +int ioex_save_gpio_state(int ioex, int *state, int state_len); + +/* + * Restore gpio state of IO expander + * + * @param ioex IO expander chip's port number + * @param state Buffer with gpio state saved by ioex_save_gpio_state + * @param state_len Length of state buffer, IOEX_COUNT is recommended + * @return EC_SUCCESS if successful, non-zero if error. + */ +int ioex_restore_gpio_state(int ioex, const int *state, int state_len); + #endif /* __CROS_EC_IOEXPANDER_H */ |