diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-07-27 20:00:53 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-07-27 20:00:53 +0200 |
commit | 8630bd35a636a463bcf7211aaa0f014600013463 (patch) | |
tree | d9c69886519b587a61487924796544111bebc986 /sys/src/9/bcm | |
parent | ea2a5a33ca880e4f5e3950350bf4dbb4187f51b8 (diff) |
bcm, bcm64: add BCM2711 support for gpiopull(), fix gpiomeminit(), cleanup
according to the following linux change, BCM2711 uses a different
method for changing pullup/down mode:
https://github.com/raspberrypi/linux/commit/abcfd092860760087b87acbdda0963fe7906839c#diff-cf078559c38543ac72c5db99323e236d
gpiomeminit() was broken, using virtual address for the gpio physseg
instead of the physical one.
cleanup the code, avoid repetition by declaring static u32int *regs
variable. make local variable names consistent.
Diffstat (limited to 'sys/src/9/bcm')
-rw-r--r-- | sys/src/9/bcm/gpio.c | 82 |
1 files changed, 39 insertions, 43 deletions
diff --git a/sys/src/9/bcm/gpio.c b/sys/src/9/bcm/gpio.c index b970e96f6..fbb66343b 100644 --- a/sys/src/9/bcm/gpio.c +++ b/sys/src/9/bcm/gpio.c @@ -30,36 +30,50 @@ enum { Off = 0x0, Pulldown= 0x1, Pullup = 0x2, + PudMask = 0x3, + PUDclk0 = 0x98>>2, PUDclk1 = 0x9c>>2, + + /* BCM2711 only */ + PUPPDN0 = 0xe4>>2, + PUPPDN1 = 0xe8>>2, + PUPPDN2 = 0xec>>2, + PUPPDN3 = 0xf0>>2, }; +static u32int *regs = (u32int*)GPIOREGS; + 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; + int shift = (pin % 10) * 3; + u32int *reg = ®s[Fsel0 + pin/10]; + func &= FuncMask; + *reg = (*reg & ~(FuncMask<<shift)) | (func<<shift); } 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; + u32int *reg; + func &= PudMask; + if(regs[PUPPDN3] == 0x6770696f){ + /* BCM2835, BCM2836, BCM2837 */ + u32int mask = 1 << (pin % 32); + reg = ®s[PUDclk0 + pin/32]; + regs[PUD] = func; + microdelay(1); + *reg = mask; + microdelay(1); + *reg = 0; + } else { + /* BCM2711 */ + int shift = 2*(pin % 16); + static u32int map[PudMask+1] = {0x00,0x02,0x01}; + reg = ®s[PUPPDN0 + pin/16]; + *reg = (*reg & ~(3<<shift)) | (map[func] << shift); + } } void @@ -83,46 +97,28 @@ gpiopulldown(uint pin) void gpioout(uint pin, int set) { - u32int *gp; - int v; - - gp = (u32int*)GPIOREGS; - v = set? Set0 : Clr0; - gp[v + pin/32] = 1 << (pin % 32); + regs[(set? Set0: Clr0) + pin/32] = 1 << (pin % 32); } int gpioin(uint pin) { - u32int *gp; - - gp = (u32int*)GPIOREGS; - return (gp[Lev0 + pin/32] & (1 << (pin % 32))) != 0; + return (regs[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); + u32int *reg = ®s[(falling? Fedge0: Redge0) + pin/32]; + *reg = (*reg & ~(1<<pin)) | ((enable != 0)<<pin); } int gpiogetevent(uint pin) { - u32int *gp, *reg, val; + u32int *reg, val; - gp = (u32int*)GPIOREGS; - reg = &gp[Evds0 + pin/32]; + reg = ®s[Evds0 + pin/32]; val = *reg & (1 << (pin % 32)); *reg |= val; return val != 0; @@ -136,7 +132,7 @@ gpiomeminit(void) memset(&seg, 0, sizeof seg); seg.attr = SG_PHYSICAL; seg.name = "gpio"; - seg.pa = GPIOREGS; + seg.pa = (GPIOREGS - soc.virtio) + soc.physio; seg.size = BY2PG; addphysseg(&seg); } |