diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /os/sa1110/devgpio.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'os/sa1110/devgpio.c')
| -rw-r--r-- | os/sa1110/devgpio.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/os/sa1110/devgpio.c b/os/sa1110/devgpio.c new file mode 100644 index 00000000..f12d5951 --- /dev/null +++ b/os/sa1110/devgpio.c @@ -0,0 +1,165 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "io.h" + +enum{ + Qdir, + Qgpioset, + Qgpioclear, + Qgpioedge, + Qgpioctl, + Qgpiostatus, +}; + +Dirtab gpiodir[]={ + ".", {Qdir,0}, 0, 0555, + "gpioset", {Qgpioset, 0}, 0, 0664, + "gpioclear", {Qgpioclear, 0}, 0, 0664, + "gpioedge", {Qgpioedge, 0}, 0, 0664, + "gpioctl", {Qgpioctl,0}, 0, 0664, + "gpiostatus", {Qgpiostatus,0}, 0, 0444, +}; + +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 offset) +{ + char str[128]; + GpioReg *g; + + if(c->qid.type & QTDIR) + return devdirread(c, buf, n, gpiodir, nelem(gpiodir), devgen); + + g = GPIOREG; + switch((ulong)c->qid.path){ + case Qgpioset: + case Qgpioclear: + sprint(str, "%8.8lux", g->gplr); + break; + case Qgpioedge: + sprint(str, "%8.8lux", g->gedr); + break; + case Qgpioctl: + /* return 0; */ + case Qgpiostatus: + snprint(str, sizeof(str), "GPDR:%8.8lux\nGRER:%8.8lux\nGFER:%8.8lux\nGAFR:%8.8lux\nGPLR:%8.8lux\n", g->gpdr, g->grer, g->gfer, g->gafr, g->gplr); + break; + default: + error(Ebadarg); + return 0; + } + return readstr(offset, buf, n, str); +} + +static long +gpiowrite(Chan *c, void *a, long n, vlong) +{ + char buf[128], *field[3]; + int pin, set; + ulong *r; + GpioReg *g; + + if(n >= sizeof(buf)) + n = sizeof(buf)-1; + memmove(buf, a, n); + buf[n] = 0; + g = GPIOREG; + switch((ulong)c->qid.path){ + case Qgpioset: + g->gpsr = strtol(buf, 0, 16); + break; + case Qgpioclear: + g->gpcr = strtol(buf, 0, 16); + break; + case Qgpioedge: + g->gedr = strtol(buf, 0, 16); + break; + case Qgpioctl: + if(getfields(buf, field, 3, 1, " \n\t") == 3) { + pin = strtol(field[1], 0, 0); + if(pin < 0 || pin >= 32) + error(Ebadarg); + set = strtol(field[2], 0, 0); + switch(*field[0]) { + case 'd': + r = &g->gpdr; + break; + case 'r': + r = &g->grer; + break; + case 'f': + r = &g->gfer; + break; + case 'a': + r = &g->gafr; + break; + default: + error(Ebadarg); + return 0; + } + if(set) + *r |= 1 << pin; + else + *r &= ~(1 << pin); + } else + error(Ebadarg); + break; + default: + error(Ebadusefd); + return 0; + } + return n; +} + +Dev gpiodevtab = { + 'G', + "gpio", + + devreset, + devinit, + devshutdown, + gpioattach, + gpiowalk, + gpiostat, + gpioopen, + devcreate, + gpioclose, + gpioread, + devbread, + gpiowrite, + devbwrite, + devremove, + devwstat, +}; |
