1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "../port/error.h" 7 #include "io.h" 8 9 enum{ 10 Qdir, 11 Qgpioset, 12 Qgpioclear, 13 Qgpioedge, 14 Qgpioctl, 15 Qgpiostatus, 16 }; 17 18 Dirtab gpiodir[]={ 19 ".", {Qdir,0}, 0, 0555, 20 "gpioset", {Qgpioset, 0}, 0, 0664, 21 "gpioclear", {Qgpioclear, 0}, 0, 0664, 22 "gpioedge", {Qgpioedge, 0}, 0, 0664, 23 "gpioctl", {Qgpioctl,0}, 0, 0664, 24 "gpiostatus", {Qgpiostatus,0}, 0, 0444, 25 }; 26 27 static Chan* 28 gpioattach(char* spec) 29 { 30 return devattach('G', spec); 31 } 32 33 static Walkqid* 34 gpiowalk(Chan* c, Chan *nc, char **name, int nname) 35 { 36 return devwalk(c, nc, name, nname, gpiodir, nelem(gpiodir), devgen); 37 } 38 39 static int 40 gpiostat(Chan* c, uchar *dp, int n) 41 { 42 return devstat(c, dp, n, gpiodir, nelem(gpiodir), devgen); 43 } 44 45 static Chan* 46 gpioopen(Chan* c, int omode) 47 { 48 return devopen(c, omode, gpiodir, nelem(gpiodir), devgen); 49 } 50 51 static void 52 gpioclose(Chan*) 53 { 54 } 55 56 static long 57 gpioread(Chan* c, void *buf, long n, vlong offset) 58 { 59 char str[128]; 60 GpioReg *g; 61 62 if(c->qid.type & QTDIR) 63 return devdirread(c, buf, n, gpiodir, nelem(gpiodir), devgen); 64 65 g = GPIOREG; 66 switch((ulong)c->qid.path){ 67 case Qgpioset: 68 case Qgpioclear: 69 sprint(str, "%8.8lux", g->gplr); 70 break; 71 case Qgpioedge: 72 sprint(str, "%8.8lux", g->gedr); 73 break; 74 case Qgpioctl: 75 /* return 0; */ 76 case Qgpiostatus: 77 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); 78 break; 79 default: 80 error(Ebadarg); 81 return 0; 82 } 83 return readstr(offset, buf, n, str); 84 } 85 86 static long 87 gpiowrite(Chan *c, void *a, long n, vlong) 88 { 89 char buf[128], *field[3]; 90 int pin, set; 91 ulong *r; 92 GpioReg *g; 93 94 if(n >= sizeof(buf)) 95 n = sizeof(buf)-1; 96 memmove(buf, a, n); 97 buf[n] = 0; 98 g = GPIOREG; 99 switch((ulong)c->qid.path){ 100 case Qgpioset: 101 g->gpsr = strtol(buf, 0, 16); 102 break; 103 case Qgpioclear: 104 g->gpcr = strtol(buf, 0, 16); 105 break; 106 case Qgpioedge: 107 g->gedr = strtol(buf, 0, 16); 108 break; 109 case Qgpioctl: 110 if(getfields(buf, field, 3, 1, " \n\t") == 3) { 111 pin = strtol(field[1], 0, 0); 112 if(pin < 0 || pin >= 32) 113 error(Ebadarg); 114 set = strtol(field[2], 0, 0); 115 switch(*field[0]) { 116 case 'd': 117 r = &g->gpdr; 118 break; 119 case 'r': 120 r = &g->grer; 121 break; 122 case 'f': 123 r = &g->gfer; 124 break; 125 case 'a': 126 r = &g->gafr; 127 break; 128 default: 129 error(Ebadarg); 130 return 0; 131 } 132 if(set) 133 *r |= 1 << pin; 134 else 135 *r &= ~(1 << pin); 136 } else 137 error(Ebadarg); 138 break; 139 default: 140 error(Ebadusefd); 141 return 0; 142 } 143 return n; 144 } 145 146 Dev gpiodevtab = { 147 'G', 148 "gpio", 149 150 devreset, 151 devinit, 152 devshutdown, 153 gpioattach, 154 gpiowalk, 155 gpiostat, 156 gpioopen, 157 devcreate, 158 gpioclose, 159 gpioread, 160 devbread, 161 gpiowrite, 162 devbwrite, 163 devremove, 164 devwstat, 165 }; 166