summaryrefslogtreecommitdiff
path: root/common/ioexpander.c
diff options
context:
space:
mode:
authorCHLin <CHLIN56@nuvoton.com>2019-08-05 15:02:19 +0800
committerCommit Bot <commit-bot@chromium.org>2019-08-20 18:12:14 +0000
commit5040fdcc897188ad674b0503bf31d5c26f9f76d4 (patch)
tree646e5033fcf570b1a4d3267280ba2ee31813e747 /common/ioexpander.c
parent8aaeb9fd05ab185a7807f3650e491d2c3042637a (diff)
downloadchrome-ec-5040fdcc897188ad674b0503bf31d5c26f9f76d4.tar.gz
IO Expander: add the interrupt support to IOEX framework
This CL creates interfaces which bring the IOEX framework to support interrupt feature. To declare an IOEX IO which supports the interrupt function, file its declaration in gpio.inc with the format: IOEX_INT(name, expin, flags, signal) Note: like GPIO, all IOEX IOs with interrupt handlers must be declared at the top of the IOEX's declaration in the gpio.inc The following two APIs are added to enable/disable each IOEX IO's interrupt function: 1. ioex_enable_interrupt 2. ioex_disable_interrupt BRANCH=none BUG=none TEST=No error for "make buildall" TEST=Apply this and related CLs, manually test each IO pins; make sure each pin's interrupt handler is correctly executed. Change-Id: Icbf54c09120e37b68c647c884cd6aa28d9313167 Signed-off-by: CHLin <CHLIN56@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1734947 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org> Tested-by: CH Lin <chlin56@nuvoton.com> Commit-Queue: Edward Hill <ecgh@chromium.org>
Diffstat (limited to 'common/ioexpander.c')
-rw-r--r--common/ioexpander.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/common/ioexpander.c b/common/ioexpander.c
index 8e00f9337a..796673a668 100644
--- a/common/ioexpander.c
+++ b/common/ioexpander.c
@@ -29,6 +29,55 @@ static int last_val_changed(int i, int v)
}
}
+static int ioex_is_valid_interrupt_signal(enum ioex_signal signal)
+{
+ const struct ioexpander_drv *drv;
+ const struct ioex_info *g = ioex_list + signal;
+
+ /* Fail if no interrupt handler */
+ if (signal >= ioex_ih_count)
+ return EC_ERROR_PARAM1;
+
+ drv = ioex_config[g->ioex].drv;
+ /*
+ * Not every IOEX chip can support interrupt, check it before enabling
+ * the interrupt function
+ */
+ if (drv->enable_interrupt == NULL) {
+ CPRINTS("IOEX chip port %d doesn't support INT", g->ioex);
+ return EC_ERROR_UNIMPLEMENTED;
+ }
+
+ return EC_SUCCESS;
+}
+int ioex_enable_interrupt(enum ioex_signal signal)
+{
+ int rv;
+ const struct ioex_info *g = ioex_list + signal;
+ const struct ioexpander_drv *drv;
+
+ rv = ioex_is_valid_interrupt_signal(signal);
+ if (rv != EC_SUCCESS)
+ return rv;
+
+ drv = ioex_config[g->ioex].drv;
+ return drv->enable_interrupt(g->ioex, g->port, g->mask, 1);
+}
+
+int ioex_disable_interrupt(enum ioex_signal signal)
+{
+ int rv;
+ const struct ioexpander_drv *drv;
+ const struct ioex_info *g = ioex_list + signal;
+
+ rv = ioex_is_valid_interrupt_signal(signal);
+ if (rv != EC_SUCCESS)
+ return rv;
+
+ drv = ioex_config[g->ioex].drv;
+ return drv->enable_interrupt(g->ioex, g->port, g->mask, 0);
+}
+
int ioex_get_flags_by_mask(int ioex, int port, int mask, int *flags)
{
return ioex_config[ioex].drv->get_flags_by_mask(ioex, port, mask,