summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Barnes <robbarnes@google.com>2022-01-05 10:31:40 -0700
committerCommit Bot <commit-bot@chromium.org>2022-01-13 18:03:16 +0000
commitf0accb6b9c809bb18ca7f9d0c69fdf8527408678 (patch)
treef92989e8c0b3a9f57f48bf30e666e04a92e06350
parent9a74b1cdbb5f9024d29393ba5c59c626051d4e82 (diff)
downloadchrome-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.c54
-rw-r--r--include/ioexpander.h20
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 */