1 /*
2 * Raspberry Pi GPIO support
3 */
4
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "../port/error.h"
8 #include "mem.h"
9 #include "dat.h"
10 #include "fns.h"
11 #include "io.h"
12
13 #define GPIOREGS (VIRTIO+0x200000)
14
15 /* GPIO regs */
16 enum {
17 Fsel0 = 0x00>>2,
18 FuncMask= 0x7,
19 Set0 = 0x1c>>2,
20 Clr0 = 0x28>>2,
21 Lev0 = 0x34>>2,
22 PUD = 0x94>>2,
23 Off = 0x0,
24 Pulldown= 0x1,
25 Pullup = 0x2,
26 PUDclk0 = 0x98>>2,
27 PUDclk1 = 0x9c>>2,
28 /* BCM2711 only */
29 PUPPDN0 = 0xe4>>2,
30 PUPPDN1 = 0xe8>>2,
31 PUPPDN2 = 0xec>>2,
32 PUPPDN3 = 0xf0>>2,
33 };
34
35 void
gpiosel(uint pin,int func)36 gpiosel(uint pin, int func)
37 {
38 u32int *gp, *fsel;
39 int off;
40
41 gp = (u32int*)GPIOREGS;
42 fsel = &gp[Fsel0 + pin/10];
43 off = (pin % 10) * 3;
44 *fsel = (*fsel & ~(FuncMask<<off)) | func<<off;
45 }
46
47 static void
gpiopull(uint pin,int func)48 gpiopull(uint pin, int func)
49 {
50 u32int *gp, *reg;
51 u32int mask;
52 int shift;
53 static uchar map[4] = {0x00,0x02,0x01,0x00};
54
55 gp = (u32int*)GPIOREGS;
56 if(gp[PUPPDN3] == 0x6770696f){
57 /* BCM2835, BCM2836, BCM2837 */
58 reg = &gp[PUDclk0 + pin/32];
59 mask = 1 << (pin % 32);
60 gp[PUD] = func;
61 microdelay(1);
62 *reg = mask;
63 microdelay(1);
64 *reg = 0;
65 } else {
66 /* BCM2711 */
67 reg = &gp[PUPPDN0 + pin/16];
68 shift = 2*(pin % 16);
69 *reg = (map[func] << shift) | (*reg & ~(3<<shift));
70 }
71
72 }
73
74 void
gpiopulloff(uint pin)75 gpiopulloff(uint pin)
76 {
77 gpiopull(pin, Off);
78 }
79
80 void
gpiopullup(uint pin)81 gpiopullup(uint pin)
82 {
83 gpiopull(pin, Pullup);
84 }
85
86 void
gpiopulldown(uint pin)87 gpiopulldown(uint pin)
88 {
89 gpiopull(pin, Pulldown);
90 }
91
92 void
gpioout(uint pin,int set)93 gpioout(uint pin, int set)
94 {
95 u32int *gp;
96 int v;
97
98 gp = (u32int*)GPIOREGS;
99 v = set? Set0 : Clr0;
100 gp[v + pin/32] = 1 << (pin % 32);
101 }
102
103 int
gpioin(uint pin)104 gpioin(uint pin)
105 {
106 u32int *gp;
107
108 gp = (u32int*)GPIOREGS;
109 return (gp[Lev0 + pin/32] & (1 << (pin % 32))) != 0;
110 }
111
112