xref: /plan9-contrib/sys/src/9/bcm/gpio.c (revision 5c47fe09a0cc86dfb02c0ea4a2b6aec7eda2361f)
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