1 /*
2 * stuff specific to marvell's kirkwood architecture
3 * as seen in the sheevaplug
4 */
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "../port/error.h"
11 #include "io.h"
12
13 #include "../port/netif.h"
14 #include "etherif.h"
15 #include "../port/flashif.h"
16
17 #include "arm.h"
18
19 enum {
20 L2writeback = 1,
21 Debug = 0,
22 };
23
24 typedef struct GpioReg GpioReg;
25 struct GpioReg {
26 ulong dataout;
27 ulong dataoutena;
28 ulong blinkena;
29 ulong datainpol;
30 ulong datain;
31 ulong intrcause;
32 ulong intrmask;
33 ulong intrlevelmask;
34 };
35
36 typedef struct L2uncache L2uncache;
37 typedef struct L2win L2win;
38 struct L2uncache {
39 struct L2win {
40 ulong base; /* phys addr */
41 ulong size;
42 } win[4];
43 };
44
45 enum {
46 /* L2win->base bits */
47 L2enable = 1<<0,
48 };
49
50 typedef struct Dramctl Dramctl;
51 struct Dramctl {
52 ulong ctl;
53 ulong ddrctllo;
54 struct {
55 ulong lo;
56 ulong hi;
57 } time;
58 ulong addrctl;
59 ulong opagectl;
60 ulong oper;
61 ulong mode;
62 ulong extmode;
63 ulong ddrctlhi;
64 ulong ddr2timelo;
65 ulong operctl;
66 struct {
67 ulong lo;
68 ulong hi;
69 } mbusctl;
70 ulong mbustimeout;
71 ulong ddrtimehi;
72 ulong sdinitctl;
73 ulong extsdmode1;
74 ulong extsdmode2;
75 struct {
76 ulong lo;
77 ulong hi;
78 } odtctl;
79 ulong ddrodtctl;
80 ulong rbuffsel;
81
82 ulong accalib;
83 ulong dqcalib;
84 ulong dqscalib;
85 };
86
87 /* unused so far */
88 typedef struct SDramdReg SDramdReg;
89 struct SDramdReg {
90 struct {
91 ulong base;
92 ulong size;
93 } win[4];
94 };
95
96 typedef struct Addrmap Addrmap;
97 typedef struct Addrwin Addrwin;
98 struct Addrmap {
99 struct Addrwin {
100 ulong ctl; /* see Winenable in io.h */
101 ulong base; /* virtual address */
102 ulong remaplo; /* physical address sent to target */
103 ulong remaphi; /* " */
104 } win[8];
105 ulong dirba; /* device internal reg's base addr.: PHYSIO */
106 };
107
108 Soc soc = {
109 .cpu = PHYSIO+0x20100,
110 .devid = PHYSIO+0x10034,
111 .l2cache = PHYSIO+0x20a00, /* uncachable addrs for L2 */
112 .sdramc = PHYSIO+0x01400,
113 // .sdramd = PHYSIO+0x01500, /* unused */
114
115 .iocfg = PHYSIO+0x100e0,
116 .addrmap = PHYSIO+0x20000, /* cpu address map */
117 .intr = PHYSIO+0x20200,
118 .nand = PHYSIO+0x10418,
119 .cesa = PHYSIO+0x30000, /* crypto accelerator */
120 .ehci = PHYSIO+0x50000,
121 .spi = PHYSIO+0x10600,
122 .twsi = PHYSIO+0x11000,
123
124 .analog = PHYSIO+0x1007c,
125 .pci = PHYSIO+0x40000,
126 .pcibase = PHYSIO+0x41800,
127
128 .rtc = PHYSIO+0x10300,
129 .clock = PHYSIO+0x20300,
130 // .clockctl = PHYSIO+0x1004c, /* unused */
131
132 .ether = { PHYSIO+0x72000, PHYSIO+0x76000, },
133 .sata = { PHYSIO+0x80000, /* sata config reg here */
134 PHYSIO+0x82000, /* edma config reg here */
135 PHYSIO+0x84000, /* edma config reg here */
136 },
137 .uart = { PHYSIO+0x12000, PHYSIO+0x12100, },
138 .gpio = { PHYSIO+0x10100, PHYSIO+0x10140, },
139 };
140
141 /*
142 * sheeva/openrd u-boot leaves us with this address map:
143 *
144 * 0 targ 4 attr 0xe8 size 256MB addr 0x9:: remap addr 0x9:: pci mem
145 * 1 targ 1 attr 0x2f size 8MB addr 0xf9:: remap addr 0xf9:: nand flash
146 * 2 targ 4 attr 0xe0 size 16MB addr 0xf:: remap addr 0xc:: pci i/o
147 * 3 targ 1 attr 0x1e size 16MB addr 0xf8:: remap addr 0x0 spi flash
148 * 4 targ 1 attr 0x1d size 16MB addr 0xff:: boot rom
149 * 5 targ 1 attr 0x1e size 128MB addr 0xe8:: disabled spi flash
150 * 6 targ 1 attr 0x1d size 128MB addr 0xf:: disabled boot rom
151 * 7 targ 3 attr 0x1 size 64K addr 0xfb:: crypto sram
152 *
153 * dreamplug u-boot leaves us with this address map:
154 *
155 * 0 targ 4 attr 0xe8 size 256MB addr 0x9:: remap addr 0x9:: pci mem
156 * 1 targ 4 attr 0xe0 size 64KB addr 0xc:: remap addr 0xc:: pci i/o
157 * 2 targ 1 attr 0x2f size 128MB addr 0xd8:: remap addr 0xd8:: nand flash
158 * 3 targ 1 attr 0x1e size 128MB addr 0xe8:: remap addr 0xe8:: spi flash
159 * 4 targ 1 attr 0x1d size 128MB addr 0xf8:: boot rom
160 * 5 targ 3 attr 0x1 size 64K addr 0xc801:: crypto sram
161 * 6 targ 0 attr 0x0 size 64K addr 0xf:: disabled ram?
162 * 7 targ 0 attr 0x0 size 64K addr 0xf8:: disabled ram?
163 */
164
165 #define WINTARG(ctl) (((ctl) >> 4) & 017)
166 #define WINATTR(ctl) (((ctl) >> 8) & 0377)
167 #define WIN64KSIZE(ctl) (((ctl) >> 16) + 1)
168
169 static void
praddrwin(Addrwin * win,int i)170 praddrwin(Addrwin *win, int i)
171 {
172 ulong ctl, targ, attr, size64k;
173
174 if (!Debug) {
175 USED(win, i);
176 return;
177 }
178 ctl = win->ctl;
179 targ = WINTARG(ctl);
180 attr = WINATTR(ctl);
181 size64k = WIN64KSIZE(ctl);
182 print("cpu addr map: %s window %d: targ %ld attr %#lux size %,ld addr %#lux",
183 ctl & Winenable? "enabled": "disabled", i, targ, attr,
184 size64k * 64*1024, win->base);
185 if (i < 4)
186 print(" remap addr %#llux", (uvlong)win->remaphi<<32 |
187 win->remaplo);
188 print("\n");
189 }
190
191 static void
fixaddrmap(void)192 fixaddrmap(void)
193 {
194 int i;
195 ulong ctl, targ, attr, size64k;
196 Addrmap *map;
197 Addrwin *win;
198
199 map = (Addrmap *)soc.addrmap;
200 for (i = 0; i < nelem(map->win); i++) {
201 win = &map->win[i];
202 ctl = win->ctl;
203 targ = WINTARG(ctl);
204 attr = WINATTR(ctl);
205 size64k = WIN64KSIZE(ctl);
206
207 USED(attr, size64k);
208 if (targ == Targcesasram) {
209 win->ctl |= Winenable;
210 win->base = PHYSCESASRAM;
211 coherence();
212 praddrwin(win, i);
213 }
214 }
215 if (map->dirba != PHYSIO)
216 panic("dirba not %#ux", PHYSIO);
217 }
218
219 static void
praddrmap(void)220 praddrmap(void)
221 {
222 int i;
223 Addrmap *map;
224
225 map = (Addrmap *)soc.addrmap;
226 for (i = 0; i < nelem(map->win); i++)
227 praddrwin(&map->win[i], i);
228 }
229
230 int
ispow2(uvlong ul)231 ispow2(uvlong ul)
232 {
233 /* see Hacker's Delight if this isn't obvious */
234 return (ul & (ul - 1)) == 0;
235 }
236
237 /*
238 * return exponent of smallest power of 2 ≥ n
239 */
240 int
log2(ulong n)241 log2(ulong n)
242 {
243 int i;
244
245 i = 31 - clz(n);
246 if (!ispow2(n) || n == 0)
247 i++;
248 return i;
249 }
250
251 void
cacheinfo(int level,int kind,Memcache * cp)252 cacheinfo(int level, int kind, Memcache *cp) /* l1 only */
253 {
254 uint len, assoc, size;
255 ulong setsways;
256
257 /* get cache types & sizes (read-only reg) */
258 setsways = cprdsc(0, CpID, CpIDidct, CpIDct);
259
260 cp->level = level;
261 cp->kind = kind;
262
263 if ((setsways & (1<<24)) == 0)
264 kind = Unified;
265 if (kind != Icache)
266 setsways >>= 12;
267
268 assoc = (setsways >> 3) & MASK(3);
269 cp->nways = 1 << assoc;
270 size = (setsways >> 6) & MASK(4);
271 cp->size = 1 << (size + 9);
272 len = setsways & MASK(2);
273 cp->log2linelen = len + 3;
274 cp->linelen = 1 << cp->log2linelen;
275 cp->setsways = setsways;
276
277 cp->nsets = 1 << (size + 6 - assoc - len);
278 cp->setsh = cp->log2linelen;
279 cp->waysh = 32 - log2(cp->nways);
280 }
281
282 static char *
wbtype(uint type)283 wbtype(uint type)
284 {
285 static char *types[] = {
286 "write-through",
287 "read data block",
288 "reg 7 ops, no lock-down",
289 [06] "reg 7 ops, format A",
290 [07] "reg 7 ops, format B deprecated",
291 [016] "reg 7 ops, format C",
292 [05] "reg 7 ops, format D",
293 };
294
295 if (type >= nelem(types) || types[type] == nil)
296 return "GOK";
297 return types[type];
298 }
299
300 static void
prcache(Memcache * mcp)301 prcache(Memcache *mcp)
302 {
303 int type;
304 char id;
305
306 if (mcp->kind == Unified)
307 id = 'U';
308 else if (mcp->kind == Icache)
309 id = 'I';
310 else if (mcp->kind == Dcache)
311 id = 'D';
312 else
313 id = '?';
314 print("l%d %c: %d bytes, %d ways %d sets %d bytes/line",
315 mcp->level, id, mcp->size, mcp->nways, mcp->nsets,
316 mcp->linelen);
317 if (mcp->linelen != CACHELINESZ)
318 print(" *should* be %d", CACHELINESZ);
319 type = (mcp->setsways >> 25) & MASK(4);
320 if (type == 0)
321 print("; write-through only");
322 else
323 print("; write-back type `%s' (%#o) possible",
324 wbtype(type), type);
325 if (mcp->setsways & (1<<11))
326 print("; page table mapping restrictions apply");
327 if (mcp->setsways & (1<<2))
328 print("; M bit is set in cache type reg");
329 print("\n");
330 }
331
332 static void
prcachecfg(void)333 prcachecfg(void)
334 {
335 Memcache mc;
336
337 cacheinfo(1, Dcache, &mc);
338 prcache(&mc);
339 cacheinfo(1, Icache, &mc);
340 prcache(&mc);
341 }
342
343 void
l2cacheon(void)344 l2cacheon(void)
345 {
346 ulong cfg;
347 CpucsReg *cpu;
348 L2uncache *l2p;
349
350 cacheuwbinv();
351 l2cacheuwbinv();
352 l1cachesoff(); /* turns off L2 as a side effect */
353
354 cpwrsc(CpDef, CpCLD, 0, 0, 0); /* GL-CPU-100: set D cache lockdown reg. */
355
356 /* marvell guideline GL-CPU-130 */
357 cpu = (CpucsReg *)soc.cpu;
358 cfg = cpu->cpucfg | L2exists | L2ecc | Cfgiprefetch | Cfgdprefetch;
359
360 if (L2writeback)
361 cfg &= ~L2writethru; /* see PTE Cached & Buffered bits */
362 else
363 cfg |= L2writethru;
364 cpu->l2cfg = cfg;
365 coherence(); /* force l2 cache to pay attention */
366 cpu->l2tm1 = cpu->l2tm0 = 0x66666666; /* marvell guideline GL-CPU-120 */
367 coherence();
368
369 cpwrsc(CpL2, CpTESTCFG, CpTCl2waylck, CpTCl2waylock, 0);
370
371 cachedinv();
372 l2cacheuinv();
373
374 /* disable l2 caching of i/o registers */
375 l2p = (L2uncache *)soc.l2cache;
376 memset(l2p, 0, sizeof *l2p);
377 /*
378 * l2: don't cache upper half of address space.
379 * the L2 cache is PIPT, so the addresses are physical.
380 */
381 l2p->win[0].base = 0x80000000 | L2enable; /* 64K multiple */
382 l2p->win[0].size = (32*1024-1) << 16; /* 64K multiples */
383 coherence();
384
385 l2cachecfgon();
386 l1cacheson(); /* turns L2 on as a side effect */
387 print("l2 cache: 256K or 512K: 4 ways, 32-byte lines, write-%s, sdram only\n",
388 cpu->l2cfg & L2writethru? "through": "back");
389 }
390
391 /* called late in main */
392 void
archconfinit(void)393 archconfinit(void)
394 {
395 m->cpuhz = Frequency;
396 m->delayloop = m->cpuhz/2000; /* initial estimate */
397 fixaddrmap();
398 if (Debug)
399 praddrmap();
400 prcachecfg();
401
402 l2cacheon();
403 }
404
405 void
archkwlink(void)406 archkwlink(void)
407 {
408 }
409
410 int
archether(unsigned ctlno,Ether * ether)411 archether(unsigned ctlno, Ether *ether)
412 {
413 if(ctlno >= 2)
414 return -1;
415 ether->type = "88e1116";
416 ether->port = ctlno;
417 // ether->mbps = 1000;
418 return 1;
419 }
420
421 /* LED/USB gpios */
422 enum {
423 /*
424 * the bit assignments are MPP pin numbers from the last page of the
425 * sheevaplug 6.0.1 schematic.
426 */
427 KWOEValHigh = 1<<(49-32), /* pin 49: LED pin */
428 KWOEValLow = 1<<29, /* pin 29: USB_PWEN, pin 28: usb_pwerr */
429 KWOELow = ~0,
430 KWOEHigh = ~0,
431 };
432
433 /* called early in main */
434 void
archreset(void)435 archreset(void)
436 {
437 ulong clocks;
438 CpucsReg *cpu;
439 Dramctl *dram;
440 GpioReg *gpio;
441
442 clockshutdown(); /* watchdog disabled */
443
444 /* configure gpios */
445 gpio = (GpioReg*)soc.gpio[0];
446 gpio->dataout = KWOEValLow;
447 coherence();
448 gpio->dataoutena = KWOELow;
449
450 gpio = (GpioReg*)soc.gpio[1];
451 gpio->dataout = KWOEValHigh;
452 coherence();
453 gpio->dataoutena = KWOEHigh;
454 coherence();
455
456 cpu = (CpucsReg *)soc.cpu;
457 cpu->mempm = 0; /* turn everything on */
458 coherence();
459
460 clocks = MASK(10);
461 clocks |= MASK(21) & ~MASK(14);
462 clocks &= ~(1<<18 | 1<<1); /* reserved bits */
463 cpu->clockgate |= clocks; /* enable all the clocks */
464 cpu->l2cfg |= L2exists; /* when L2exists is 0, the l2 ignores us */
465 coherence();
466
467 dram = (Dramctl *)soc.sdramc;
468 dram->ddrctllo &= ~(1<<6); /* marvell guideline GL-MEM-70 */
469
470 *(ulong *)soc.analog = 0x68; /* marvell guideline GL-MISC-40 */
471 coherence();
472 }
473
474 void
archreboot(void)475 archreboot(void)
476 {
477 CpucsReg *cpu;
478
479 iprint("reset!\n");
480 delay(10);
481
482 cpu = (CpucsReg *)soc.cpu;
483 cpu->rstout = RstoutSoft;
484 cpu->softreset = ResetSystem;
485 coherence();
486 cpu->cpucsr = Reset;
487 coherence();
488 delay(500);
489
490 splhi();
491 iprint("waiting...");
492 for(;;)
493 idlehands();
494 }
495
496 void
archconsole(void)497 archconsole(void)
498 {
499 // uartconsole(0, "b115200");
500 //serialputs("uart0 console @ 115200\n", strlen("uart0 console @ 115200\n"));
501 }
502
503 void
archflashwp(Flash *,int)504 archflashwp(Flash*, int)
505 {
506 }
507
508 int flashat(Flash *f, uintptr pa);
509
510 /*
511 * for ../port/devflash.c:/^flashreset
512 * retrieve flash type, virtual base and length and return 0;
513 * return -1 on error (no flash)
514 */
515 int
archflashreset(int bank,Flash * f)516 archflashreset(int bank, Flash *f)
517 {
518 if(bank != 0)
519 return -1;
520 f->type = "nand";
521 if (flashat(f, PHYSNAND1))
522 f->addr = (void*)PHYSNAND1;
523 else if (flashat(f, PHYSNAND2))
524 f->addr = (void*)PHYSNAND2;
525 else
526 f->addr = nil;
527 f->size = 0; /* done by probe */
528 f->width = 1;
529 f->interleave = 0;
530 return 0;
531 }
532