this is a raw import of bls' work to implement gpio, i²c, and spi interfaces. this will be followed by a few patches to do minor cleanup. the cleanup should be pushed to bls. i'm not sure what the mechanism is. the biggest thing i see immediately is the external enums for gpio need to fit in with the rest of the defines in io.h Reference: /n/atom/patch/applied/pidevicesarego Date: Mon Jan 4 03:05:47 CET 2016 Signed-off-by: quanstro@quanstro.net --- /sys/src/9/bcm/io.h Mon Jan 4 03:05:02 2016 +++ /sys/src/9/bcm/io.h Mon Jan 4 03:05:04 2016 @@ -54,5 +54,15 @@ ClkPixel, ClkPwm, + /* gpio */ + Input = 0x0, + Output = 0x1, + Alt0 = 0x4, + Alt1 = 0x5, + Alt2 = 0x6, + Alt3 = 0x7, + Alt4 = 0x3, + Alt5 = 0x2, + TempCpu = 0, }; --- /sys/src/9/bcm/devgpio.c Thu Jan 1 00:00:00 1970 +++ /sys/src/9/bcm/devgpio.c Mon Jan 4 03:05:04 2016 @@ -0,0 +1,163 @@ +/* + * Raspberry Pi (BCM2835) GPIO + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "io.h" + +enum { + // GPIO registers + GPLEV = 0x7e200034, +}; + +enum{ + Qdir = 0, + Qgpio, +}; + +Dirtab gpiodir[]={ + ".", {Qdir, 0, QTDIR}, 0, 0555, + "gpio", {Qgpio, 0}, 0, 0664, +}; + +enum { + // commands + CMfunc, + CMset, + CMpullup, + CMpulldown, + CMfloat, +}; + +static Cmdtab gpiocmd[] = { + {CMfunc, "function", 3}, + {CMset, "set", 3}, + {CMpullup, "pullup", 2}, + {CMpulldown, "pulldown", 2}, + {CMfloat, "float", 2}, +}; + +static char *funcs[] = { "in", "out", "alt5", "alt4", "alt0", + "alt1", "alt2", "alt3", "pulse"}; +static int ifuncs[] = { Input, Output, Alt5, Alt4, Alt0, + Alt1, Alt2, Alt3, -1}; + +static Chan* +gpioattach(char* spec) +{ + return devattach('G', spec); +} + +static Walkqid* +gpiowalk(Chan* c, Chan *nc, char** name, int nname) +{ + return devwalk(c, nc, name, nname, gpiodir, nelem(gpiodir), devgen); +} + +static int +gpiostat(Chan* c, uchar* dp, int n) +{ + return devstat(c, dp, n, gpiodir, nelem(gpiodir), devgen); +} + +static Chan* +gpioopen(Chan* c, int omode) +{ + return devopen(c, omode, gpiodir, nelem(gpiodir), devgen); +} + +static void +gpioclose(Chan*) +{ +} + +static long +gpioread(Chan* c, void *buf, long n, vlong) +{ + char lbuf[20]; + char *e; + + USED(c); + if(c->qid.path == Qdir) + return devdirread(c, buf, n, gpiodir, nelem(gpiodir), devgen); + e = lbuf + sizeof(lbuf); + seprint(lbuf, e, "%08ulx%08ulx", ((ulong *)GPLEV)[1], ((ulong *)GPLEV)[0]); + return readstr(0, buf, n, lbuf); +} + +static long +gpiowrite(Chan* c, void *buf, long n, vlong) +{ + Cmdbuf *cb; + Cmdtab *ct; + int pin, i; + + if(c->qid.type & QTDIR) + error(Eperm); + cb = parsecmd(buf, n); + if(waserror()) { + free(cb); + nexterror(); + } + ct = lookupcmd(cb, gpiocmd, nelem(gpiocmd)); + pin = atoi(cb->f[1]); + switch(ct->index) { + case CMfunc: + for(i = 0; + i < nelem(funcs) + && strcmp(funcs[i], cb->f[2]) != 0; + ++i); + if(i >= nelem(funcs)) + error(Ebadctl); + if(ifuncs[i] == -1) { + gpiosel(pin, Output); + microdelay(2); + gpiosel(pin, Input); + } + else { + gpiosel(pin, ifuncs[i]); + } + break; + case CMset: + gpioout(pin, atoi(cb->f[2])); + break; + case CMpullup: + gpiopullup(pin); + break; + case CMpulldown: + gpiopulldown(pin); + break; + case CMfloat: + gpiopulloff(pin); + break; + } + free(cb); + poperror(); + return n; +} + +Dev gpiodevtab = { + 'G', + "gpio", + + devreset, + devinit, + devshutdown, + gpioattach, + gpiowalk, + gpiostat, + gpioopen, + devcreate, + gpioclose, + gpioread, + devbread, + gpiowrite, + devbwrite, + devremove, + devwstat, +}; --- /sys/src/9/bcm/uartmini.c Mon Jan 4 03:05:07 2016 +++ /sys/src/9/bcm/uartmini.c Mon Jan 4 03:05:08 2016 @@ -10,35 +10,11 @@ #include "fns.h" #include "io.h" -#define GPIOREGS (VIRTIO+0x200000) #define AUXREGS (VIRTIO+0x215000) #define OkLed 16 #define TxPin 14 #define RxPin 15 -/* GPIO regs */ -enum { - Fsel0 = 0x00>>2, - FuncMask = 0x7, - Input = 0x0, - Output = 0x1, - Alt0 = 0x4, - Alt1 = 0x5, - Alt2 = 0x6, - Alt3 = 0x7, - Alt4 = 0x3, - Alt5 = 0x2, - Set0 = 0x1c>>2, - Clr0 = 0x28>>2, - Lev0 = 0x34>>2, - PUD = 0x94>>2, - Off = 0x0, - Pulldown = 0x1, - Pullup = 0x2, - PUDclk0 = 0x98>>2, - PUDclk1 = 0x9c>>2, -}; - /* AUX regs */ enum { Irq = 0x00>>2, @@ -76,54 +52,6 @@ .phys = &miniphysuart, }; -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<