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