]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/zynq/devarch.c
bootrc: allow kbmap to be set via plan9.ini (thanks Aaron Bieber)
[plan9front.git] / sys / src / 9 / zynq / devarch.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "ureg.h"
8 #include "../port/error.h"
9
10 enum {
11         Qdir = 0,
12         Qtemp,
13         Qpl,
14         Qfbctl,
15         Qbase,
16
17         Qmax = 16,
18 };
19
20 static Dirtab archdir[Qmax] = {
21         ".",            { Qdir, 0, QTDIR },     0,      0555,
22         "temp",         { Qtemp, 0},            0,      0440,
23         "pl",           { Qpl, 0 },             0,      0660,
24         "fbctl",        { Qfbctl, 0 },          0,      0660,
25 };
26 static int narchdir = Qbase;
27
28 static int temp = -128;
29 static ulong *devc;
30 static int dmadone;
31 enum { PLBUFSIZ = 8192 };
32 static uchar *plbuf;
33 static Rendez plinitr, pldoner, pldmar;
34 static QLock plrlock, plwlock;
35 static Ref plwopen;
36 static Physseg *axi;
37
38 enum {
39         DEVCTRL = 0,
40         DEVISTS = 0xc/4,
41         DEVMASK,
42         DEVSTS,
43         DMASRC = 0x18/4,
44         DMADST,
45         DMASRCL,
46         DMADSTL,
47         XADCCFG = 0x100/4,
48         XADCSTS,
49         XADCMASK,
50         XADCMSTS,
51         XADCCMD,
52         XADCREAD,
53         XADCMCTL,
54         
55         FPGA0_CLK_CTRL = 0x170/4,
56 };
57
58 enum {
59         PROG = 1<<30,
60         DONE = 1<<2,
61         INITPE = 1<<1,
62         INIT = 1<<4,
63         DMADONE = 1<<13,
64 };
65
66 static void
67 scram(void)
68 {
69         splhi();
70         slcr[0x100/4] |= 1<<4;
71         slcr[0x104/4] |= 1<<4;
72         slcr[0x108/4] |= 1<<4;
73         slcr[DEVCTRL] &= ~PROG;
74         slcr[0x244/4] = 1<<4|1<<5;
75 }
76
77 static void
78 xadcirq(Ureg *, void *)
79 {
80         int v;
81         static int al, notfirst;
82         
83         while((devc[XADCMSTS] & 1<<8) == 0){
84                 v = ((u16int)devc[XADCREAD]) >> 4;
85                 if(v == 0){
86                         if(notfirst)
87                                 print("temperature sensor reads 0, shouldn't happen\n");
88                         break;
89                 }
90                 notfirst = 1;
91                 temp = v * 5040 / 4096 - 2732;
92                 if(temp >= 800){
93                         if(al == 0)
94                                 print("temperature exceeds 80 deg C\n");
95                         al = 1;
96                 }
97                 if(temp <= 750)
98                         al = 0;
99                 if(temp >= 900){
100                         print("chip temperature exceeds 90 deg C, shutting down");
101                         scram();
102                 }
103         }
104         devc[XADCSTS] = -1;
105 }
106
107 static void
108 xadctimer(void)
109 {
110         devc[XADCCMD] = 1<<26 | 0<<16;
111 }
112
113 static void
114 xadcinit(void)
115 {
116         int i;
117         int x;
118
119         devc = vmap(DEVC_BASE, 0x11C);
120         devc[XADCMCTL] |= 1<<4;
121         devc[XADCMCTL] &= ~(1<<4);
122         devc[XADCCMD] = 0x08030000;
123         for(i = 0; i < 15; i++)
124                 devc[XADCCMD] = 0;
125         while((devc[XADCMSTS] & 1<<10) == 0)
126                 ;
127         while((devc[XADCMSTS] & 1<<8) == 0){
128                 x = devc[XADCREAD];
129                 USED(x);
130         }
131         devc[XADCCFG] = 0x80001114;
132         devc[XADCMASK] = ~(1<<8);
133         devc[XADCSTS] = -1;
134         intrenable(XADCIRQ, xadcirq, nil, LEVEL, "xadc");
135         addclock0link(xadctimer, XADCINTERVAL);
136 }
137
138 static int
139 isplinit(void *)
140 {
141         return devc[DEVSTS] & INIT;
142 }
143
144 static int
145 ispldone(void *)
146 {
147         return devc[DEVISTS] & DONE;
148 }
149
150 static int
151 isdmadone(void *)
152 {
153         return dmadone;
154 }
155
156 static void
157 plirq(Ureg *, void *)
158 {
159         ulong fl;
160         
161         fl = devc[DEVISTS];
162         if((fl & INITPE) != 0)
163                 wakeup(&plinitr);
164         if((fl & DONE) != 0){
165                 slcr[0x900/4] = 0xf;
166                 slcr[0x240/4] = 0;
167                 devc[DEVMASK] |= DONE;
168                 axi->attr &= ~SG_FAULT;
169                 wakeup(&pldoner);
170         }
171         if((fl & DMADONE) != 0){
172                 dmadone++;
173                 wakeup(&pldmar);
174         }
175         devc[DEVISTS] = fl;
176 }
177
178 static void
179 plinit(void)
180 {
181         Physseg seg;
182
183         memset(&seg, 0, sizeof seg);
184         seg.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC | SG_FAULT;
185         seg.name = "axi";
186         seg.pa = 0x40000000;
187         seg.size = 0x8000000;
188         axi = addphysseg(&seg);
189
190         devc[DEVCTRL] &= ~(PROG|1<<25);
191         devc[DEVCTRL] |= 3<<26|PROG;
192         devc[DEVISTS] = -1;
193         devc[DEVMASK] = ~(DONE|INITPE|DMADONE);
194         intrenable(DEVCIRQ, plirq, nil, LEVEL, "pl");
195         
196         slcr[FPGA0_CLK_CTRL] = 1<<20 | 10<<8;
197 }
198
199 static void
200 plconf(void)
201 {
202         axi->attr |= SG_FAULT;
203         procflushpseg(axi);
204         flushmmu();
205
206         slcr[0x240/4] = 0xf;
207         slcr[0x900/4] = 0xa;
208         devc[DEVISTS] = DONE|INITPE|DMADONE;
209         devc[DEVCTRL] |= PROG;
210         devc[DEVCTRL] &= ~PROG;
211         devc[DEVMASK] &= ~DONE;
212         devc[DEVCTRL] |= PROG;
213
214         while(waserror())
215                 ;
216         sleep(&plinitr, isplinit, nil);
217         poperror();
218 }
219
220 static long
221 plwrite(uintptr pa, long n)
222 {
223         dmadone = 0;
224         coherence();
225         devc[DMASRC] = pa;
226         devc[DMADST] = -1;
227         devc[DMASRCL] = n>>2;
228         devc[DMADSTL] = 0;
229
230         while(waserror())
231                 ;
232         sleep(&pldmar, isdmadone, nil);
233         poperror();
234
235         return n;
236 }
237
238 static long
239 plcopy(uchar *d, long n)
240 {
241         long ret;
242         ulong nn;
243         uintptr pa;
244         
245         if((n & 3) != 0 || n <= 0)
246                 error(Eshort);
247
248         eqlock(&plwlock);
249         if(waserror()){
250                 qunlock(&plwlock);
251                 nexterror();
252         }
253
254         ret = n;
255         pa = PADDR(plbuf);
256         while(n > 0){
257                 if(n > PLBUFSIZ)
258                         nn = PLBUFSIZ;
259                 else
260                         nn = n;
261                 memmove(plbuf, d, nn);
262                 cleandse(plbuf, plbuf + nn);
263                 clean2pa(pa, pa + nn);
264                 n -= plwrite(pa, nn);
265         }
266
267         qunlock(&plwlock);
268         poperror();
269
270         return ret;
271 }
272
273 void
274 archinit(void)
275 {
276         slcr[2] = 0xDF0D;
277         xadcinit();
278         plinit();
279 }
280
281 static long
282 archread(Chan *c, void *a, long n, vlong offset)
283 {
284         char buf[64];
285
286         switch((ulong)c->qid.path){
287         case Qdir:
288                 return devdirread(c, a, n, archdir, narchdir, devgen);
289         case Qtemp:
290                 snprint(buf, sizeof(buf), "%d.%d\n", temp/10, temp%10);
291                 return readstr(offset, a, n, buf);
292         case Qpl:
293                 eqlock(&plrlock);
294                 if(waserror()){
295                         qunlock(&plrlock);
296                         nexterror();
297                 }
298                 sleep(&pldoner, ispldone, nil);
299                 qunlock(&plrlock);
300                 poperror();
301                 return 0;
302         case Qfbctl:
303                 return fbctlread(c, a, n, offset);
304         default:
305                 error(Egreg);
306                 return -1;
307         }
308 }
309
310 static long
311 archwrite(Chan *c, void *a, long n, vlong offset)
312 {
313         switch((ulong)c->qid.path){
314         case Qpl:
315                 return plcopy(a, n);
316         case Qfbctl:
317                 return fbctlwrite(c, a, n, offset);
318         default:
319                 error(Egreg);
320                 return -1;
321         }
322 }
323
324 Walkqid*
325 archwalk(Chan* c, Chan *nc, char** name, int nname)
326 {
327         return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
328 }
329
330 static int
331 archstat(Chan* c, uchar* dp, int n)
332 {
333         return devstat(c, dp, n, archdir, narchdir, devgen);
334 }
335
336 static Chan*
337 archopen(Chan* c, int omode)
338 {
339         devopen(c, omode, archdir, narchdir, devgen);
340         if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
341                 if(incref(&plwopen) != 1){
342                         c->flag &= ~COPEN;
343                         decref(&plwopen);
344                         error(Einuse);
345                 }
346                 plbuf = smalloc(PLBUFSIZ);
347                 plconf();
348         }
349         return c;
350 }
351
352 static void
353 archclose(Chan* c)
354 {
355         if((c->flag & COPEN) != 0)
356         if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
357                 free(plbuf);
358                 plbuf = nil;
359                 decref(&plwopen);
360         }
361 }
362
363 static Chan*
364 archattach(char* spec)
365 {
366         return devattach('P', spec);
367 }
368
369 Dev archdevtab = {
370         'P',
371         "arch",
372         
373         devreset,
374         devinit,
375         devshutdown,
376         archattach,
377         archwalk,
378         archstat,
379         archopen,
380         devcreate,
381         archclose,
382         archread,
383         devbread,
384         archwrite,
385         devbwrite,
386         devremove,
387         devwstat,
388 };
389