diff options
Diffstat (limited to 'os/pxa/gpio.c')
| -rw-r--r-- | os/pxa/gpio.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/os/pxa/gpio.c b/os/pxa/gpio.c new file mode 100644 index 00000000..5914f8c4 --- /dev/null +++ b/os/pxa/gpio.c @@ -0,0 +1,88 @@ +#include "u.h" +#include "mem.h" +#include "../port/lib.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +static ulong gpioreserved[3]; +static Lock gpiolock; + +void +gpioreserve(int n) +{ + ulong mask, *r; + + r = &gpioreserved[GPR(n)]; + mask = GPB(n); + ilock(&gpiolock); + if(*r & mask) + panic("gpioreserve: duplicate use of GPIO %d", n); + *r |= mask; + iunlock(&gpiolock); +} + +/* + * set direction and alternative function bits in the GPIO control register, + * following the configuration bits in cfg. + */ +void +gpioconfig(int n, ulong cfg) +{ + GpioReg *g; + ulong o, m, *r; + + m = GPB(n); + o = n>>5; + ilock(&gpiolock); + g = GPIOREG; + r = &g->gpdr[o]; + if(cfg & Gpio_out) + *r |= m; + else + *r &= ~m; + r = &g->gafr[o*2]; + *r = (*r & ~GPAF(n, 3)) | GPAF(n, cfg&3); + iunlock(&gpiolock); +} + +ulong +gpioget(int n) +{ + ulong mask, o; + + mask = GPB(n); + o = GPR(n); + return GPIOREG->gplr[o] & mask; +} + +void +gpioset(int n, int v) +{ + GpioReg *g; + ulong mask, o; + + g = GPIOREG; + mask = GPB(n); + o = GPR(n); + ilock(&gpiolock); + if(v) + g->gpsr[o] = mask; + else + g->gpcr[o] = mask; + iunlock(&gpiolock); +} + +void +gpiorelease(int n) +{ + ulong mask, *r; + + mask = GPB(n); + r = &gpioreserved[GPR(n)]; + ilock(&gpiolock); + if((*r & mask) != mask) + panic("gpiorelease: unexpected release of GPIO %d", n); + *r &= ~mask; + iunlock(&gpiolock); +} |
