summaryrefslogtreecommitdiff
path: root/sys/src/9/bcm/gpio.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2018-10-20 19:56:31 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2018-10-20 19:56:31 +0200
commit83e20b4df18d539db59c8e1090f77a6565df250e (patch)
treed42f2d4c7fdd8cb1526131515690bc9229150505 /sys/src/9/bcm/gpio.c
parent796e5e6000677a39577d545e4603ce251e7cbfe9 (diff)
bcm: import changes for raspi2/3 from richard miller
Diffstat (limited to 'sys/src/9/bcm/gpio.c')
-rw-r--r--sys/src/9/bcm/gpio.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/sys/src/9/bcm/gpio.c b/sys/src/9/bcm/gpio.c
new file mode 100644
index 000000000..b970e96f6
--- /dev/null
+++ b/sys/src/9/bcm/gpio.c
@@ -0,0 +1,142 @@
+/*
+ * Raspberry Pi GPIO support
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "../port/error.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#define GPIOREGS (VIRTIO+0x200000)
+
+/* GPIO regs */
+enum {
+ Fsel0 = 0x00>>2,
+ FuncMask= 0x7,
+ Set0 = 0x1c>>2,
+ Clr0 = 0x28>>2,
+ Lev0 = 0x34>>2,
+ Evds0 = 0x40>>2,
+ Redge0 = 0x4C>>2,
+ Fedge0 = 0x58>>2,
+ Hpin0 = 0x64>>2,
+ Lpin0 = 0x70>>2,
+ ARedge0 = 0x7C>>2,
+ AFedge0 = 0x88>2,
+ PUD = 0x94>>2,
+ Off = 0x0,
+ Pulldown= 0x1,
+ Pullup = 0x2,
+ PUDclk0 = 0x98>>2,
+ PUDclk1 = 0x9c>>2,
+};
+
+void
+gpiosel(uint pin, int func)
+{
+ u32int *gp, *fsel;
+ int off;
+
+ gp = (u32int*)GPIOREGS;
+ fsel = &gp[Fsel0 + pin/10];
+ off = (pin % 10) * 3;
+ *fsel = (*fsel & ~(FuncMask<<off)) | func<<off;
+}
+
+void
+gpiopull(uint pin, int func)
+{
+ u32int *gp, *reg;
+ u32int mask;
+
+ gp = (u32int*)GPIOREGS;
+ reg = &gp[PUDclk0 + pin/32];
+ mask = 1 << (pin % 32);
+ gp[PUD] = func;
+ microdelay(1);
+ *reg = mask;
+ microdelay(1);
+ *reg = 0;
+}
+
+void
+gpiopulloff(uint pin)
+{
+ gpiopull(pin, Off);
+}
+
+void
+gpiopullup(uint pin)
+{
+ gpiopull(pin, Pullup);
+}
+
+void
+gpiopulldown(uint pin)
+{
+ gpiopull(pin, Pulldown);
+}
+
+void
+gpioout(uint pin, int set)
+{
+ u32int *gp;
+ int v;
+
+ gp = (u32int*)GPIOREGS;
+ v = set? Set0 : Clr0;
+ gp[v + pin/32] = 1 << (pin % 32);
+}
+
+int
+gpioin(uint pin)
+{
+ u32int *gp;
+
+ gp = (u32int*)GPIOREGS;
+ return (gp[Lev0 + pin/32] & (1 << (pin % 32))) != 0;
+}
+
+void
+gpioselevent(uint pin, int falling, int enable)
+{
+ u32int *gp, *field;
+ int reg;
+
+ enable = enable != 0;
+ if(falling)
+ reg = Fedge0;
+ else
+ reg = Redge0;
+ gp = (u32int*)GPIOREGS;
+ field = &gp[reg + pin/32];
+ *field = (*field & ~(enable<<pin)) | (enable<<pin);
+}
+
+int
+gpiogetevent(uint pin)
+{
+ u32int *gp, *reg, val;
+
+ gp = (u32int*)GPIOREGS;
+ reg = &gp[Evds0 + pin/32];
+ val = *reg & (1 << (pin % 32));
+ *reg |= val;
+ return val != 0;
+}
+
+void
+gpiomeminit(void)
+{
+ Physseg seg;
+
+ memset(&seg, 0, sizeof seg);
+ seg.attr = SG_PHYSICAL;
+ seg.name = "gpio";
+ seg.pa = GPIOREGS;
+ seg.size = BY2PG;
+ addphysseg(&seg);
+}