xref: /inferno-os/os/sa1110/devgpio.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
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*
gpioattach(char * spec)28 gpioattach(char* spec)
29 {
30 	return devattach('G', spec);
31 }
32 
33 static Walkqid*
gpiowalk(Chan * c,Chan * nc,char ** name,int nname)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
gpiostat(Chan * c,uchar * dp,int n)40 gpiostat(Chan* c, uchar *dp, int n)
41 {
42 	return devstat(c, dp, n, gpiodir, nelem(gpiodir), devgen);
43 }
44 
45 static Chan*
gpioopen(Chan * c,int omode)46 gpioopen(Chan* c, int omode)
47 {
48 	return devopen(c, omode, gpiodir, nelem(gpiodir), devgen);
49 }
50 
51 static void
gpioclose(Chan *)52 gpioclose(Chan*)
53 {
54 }
55 
56 static long
gpioread(Chan * c,void * buf,long n,vlong offset)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
gpiowrite(Chan * c,void * a,long n,vlong)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