summaryrefslogtreecommitdiff
path: root/sys/src/9/imx8
diff options
context:
space:
mode:
authorSigrid Solveig Haflínudóttir <sigrid@ftrv.se>2022-08-20 03:36:11 +0000
committerSigrid Solveig Haflínudóttir <sigrid@ftrv.se>2022-08-20 03:36:11 +0000
commit3dbca6b9fbd1d797a9e92504f950506dad2570ed (patch)
tree1f2e1e9e7975f148b123e947401a02fce4d98f47 /sys/src/9/imx8
parent5a5318473e00aa854d00573abba1725af7b140dd (diff)
imx8/gpio: add interrupt handlers support
Diffstat (limited to 'sys/src/9/imx8')
-rw-r--r--sys/src/9/imx8/dat.h6
-rw-r--r--sys/src/9/imx8/fns.h3
-rw-r--r--sys/src/9/imx8/gpio.c90
-rw-r--r--sys/src/9/imx8/io.h11
4 files changed, 110 insertions, 0 deletions
diff --git a/sys/src/9/imx8/dat.h b/sys/src/9/imx8/dat.h
index c642931ae..03d2d7e67 100644
--- a/sys/src/9/imx8/dat.h
+++ b/sys/src/9/imx8/dat.h
@@ -10,6 +10,12 @@
enum {
Mhz = 1000 * 1000,
+
+ GpioLow = 0,
+ GpioHigh,
+ GpioRising,
+ GpioFalling,
+ GpioEdge,
};
typedef struct Conf Conf;
diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h
index 9958da735..59622d693 100644
--- a/sys/src/9/imx8/fns.h
+++ b/sys/src/9/imx8/fns.h
@@ -159,6 +159,9 @@ extern uint iomuxgpr(int gpr, uint set, uint mask);
#define GPIO_PIN(n, m) ((n)<<5 | (m))
extern void gpioout(uint pin, int set);
extern int gpioin(uint pin);
+void gpiointrenable(uint pin, int mode, void (*f)(uint pin, void *a), void *a);
+void gpiointrdisable(uint pin);
+void gpioinit(void);
/* pciimx */
extern int pcicfgrw8(int tbdf, int rno, int data, int read);
diff --git a/sys/src/9/imx8/gpio.c b/sys/src/9/imx8/gpio.c
index 0fdb3aefd..27092a17e 100644
--- a/sys/src/9/imx8/gpio.c
+++ b/sys/src/9/imx8/gpio.c
@@ -18,6 +18,13 @@ enum {
GPIO_EDGE_SEL = 0x1C/4,
};
+typedef struct Ivec Ivec;
+struct Ivec
+{
+ void (*f)(uint pin, void *a);
+ void *a;
+};
+
typedef struct Ctlr Ctlr;
struct Ctlr
{
@@ -25,6 +32,8 @@ struct Ctlr
char *clk;
u32int dir;
int enabled;
+ Ivec vec[32];
+ Lock;
};
static Ctlr ctlrs[5] = {
@@ -80,3 +89,84 @@ gpioin(uint pin)
ctlr->reg[GPIO_GDIR] = ctlr->dir &= ~bit;
return (ctlr->reg[GPIO_DR] & bit) != 0;
}
+
+void
+gpiointrenable(uint pin, int mode, void (*f)(uint pin, void *a), void *a)
+{
+ u32int bit = 1 << (pin % 32);
+ Ctlr *ctlr = enable(pin);
+ if(ctlr == nil)
+ return;
+ ctlr->reg[GPIO_IMR] &= ~bit;
+
+ ilock(ctlr);
+ if(ctlr->dir & bit)
+ ctlr->reg[GPIO_GDIR] = ctlr->dir &= ~bit;
+
+ if(mode == GpioEdge)
+ ctlr->reg[GPIO_EDGE_SEL] |= bit;
+ else if(bit < 16)
+ ctlr->reg[GPIO_ICR1] |= mode << (bit*2);
+ else
+ ctlr->reg[GPIO_ICR2] |= mode << (bit-16)*2;
+
+ ctlr->vec[pin % 32].f = f;
+ ctlr->vec[pin % 32].a = a;
+ iunlock(ctlr);
+
+ ctlr->reg[GPIO_IMR] |= bit;
+}
+
+void
+gpiointrdisable(uint pin)
+{
+ u32int bit = 1 << (pin % 32);
+ Ctlr *ctlr = enable(pin);
+ if(ctlr == nil)
+ return;
+
+ ctlr->reg[GPIO_IMR] &= ~bit;
+
+ ilock(ctlr);
+ ctlr->vec[pin % 32].f = nil;
+ ctlr->vec[pin % 32].a = nil;
+ iunlock(ctlr);
+}
+
+static void
+gpiointerrupt(Ureg *, void *arg)
+{
+ Ctlr *ctlr = arg;
+ u32int status;
+ Ivec *vec;
+ int pin;
+
+ status = ctlr->reg[GPIO_ISR];
+ if(status == 0)
+ return;
+ ctlr->reg[GPIO_ISR] = status;
+
+ ilock(ctlr);
+ for(vec = ctlr->vec; status != 0 && vec < &ctlr->vec[nelem(ctlr->vec)]; vec++, status >>= 1){
+ if((status & 1) != 0 && vec->f != nil){
+ pin = (ctlr - ctlrs + 1)<<5 | (vec - ctlr->vec);
+ (*vec->f)(pin, vec->a);
+ }
+ }
+ iunlock(ctlr);
+}
+
+void
+gpioinit(void)
+{
+ intrenable(IRQgpio1l, gpiointerrupt, &ctlrs[0], BUSUNKNOWN, "gpio1");
+ intrenable(IRQgpio1h, gpiointerrupt, &ctlrs[0], BUSUNKNOWN, "gpio1");
+ intrenable(IRQgpio2l, gpiointerrupt, &ctlrs[1], BUSUNKNOWN, "gpio2");
+ intrenable(IRQgpio2h, gpiointerrupt, &ctlrs[1], BUSUNKNOWN, "gpio2");
+ intrenable(IRQgpio3l, gpiointerrupt, &ctlrs[2], BUSUNKNOWN, "gpio3");
+ intrenable(IRQgpio3h, gpiointerrupt, &ctlrs[2], BUSUNKNOWN, "gpio3");
+ intrenable(IRQgpio4l, gpiointerrupt, &ctlrs[3], BUSUNKNOWN, "gpio4");
+ intrenable(IRQgpio4h, gpiointerrupt, &ctlrs[3], BUSUNKNOWN, "gpio4");
+ intrenable(IRQgpio5l, gpiointerrupt, &ctlrs[4], BUSUNKNOWN, "gpio5");
+ intrenable(IRQgpio5h, gpiointerrupt, &ctlrs[4], BUSUNKNOWN, "gpio5");
+}
diff --git a/sys/src/9/imx8/io.h b/sys/src/9/imx8/io.h
index bbd015ed5..ab4fd0a53 100644
--- a/sys/src/9/imx8/io.h
+++ b/sys/src/9/imx8/io.h
@@ -28,6 +28,17 @@ enum {
IRQsctr0 = SPI+47,
IRQsctr1 = SPI+48,
+ IRQgpio1l = SPI+64,
+ IRQgpio1h = SPI+65,
+ IRQgpio2l = SPI+66,
+ IRQgpio2h = SPI+67,
+ IRQgpio3l = SPI+68,
+ IRQgpio3h = SPI+69,
+ IRQgpio4l = SPI+70,
+ IRQgpio4h = SPI+71,
+ IRQgpio5l = SPI+72,
+ IRQgpio5h = SPI+73,
+
IRQpci2 = SPI+74,
IRQsai2 = SPI+96,