diff options
author | Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> | 2022-08-20 03:36:11 +0000 |
---|---|---|
committer | Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> | 2022-08-20 03:36:11 +0000 |
commit | 3dbca6b9fbd1d797a9e92504f950506dad2570ed (patch) | |
tree | 1f2e1e9e7975f148b123e947401a02fce4d98f47 /sys/src/9 | |
parent | 5a5318473e00aa854d00573abba1725af7b140dd (diff) |
imx8/gpio: add interrupt handlers support
Diffstat (limited to 'sys/src/9')
-rw-r--r-- | sys/src/9/imx8/dat.h | 6 | ||||
-rw-r--r-- | sys/src/9/imx8/fns.h | 3 | ||||
-rw-r--r-- | sys/src/9/imx8/gpio.c | 90 | ||||
-rw-r--r-- | sys/src/9/imx8/io.h | 11 |
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, |