summaryrefslogtreecommitdiff
path: root/os/pxa/gpio.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/pxa/gpio.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/pxa/gpio.c')
-rw-r--r--os/pxa/gpio.c88
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);
+}