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