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 void
cacheinfo(int level,int kind,Memcache * cp)231 cacheinfo(int level, int kind, Memcache *cp) /* l1 only */
232 {
233 uint len, assoc, size;
234 ulong setsways;
235
236 /* get cache types & sizes (read-only reg) */
237 setsways = cprdsc(0, CpID, CpIDidct, CpIDct);
238
239 cp->level = level;
240 cp->kind = kind;
241
242 if ((setsways & (1<<24)) == 0)
243 kind = Unified;
244 if (kind != Icache)
245 setsways >>= 12;
246
247 assoc = (setsways >> 3) & MASK(3);
248 cp->nways = 1 << assoc;
249 size = (setsways >> 6) & MASK(4);
250 cp->size = 1 << (size + 9);
251 len = setsways & MASK(2);
252 cp->log2linelen = len + 3;
253 cp->linelen = 1 << cp->log2linelen;
254 cp->setsways = setsways;
255
256 cp->nsets = 1 << (size + 6 - assoc - len);
257 cp->setsh = cp->log2linelen;
258 cp->waysh = 32 - log2(cp->nways);
259 }
260
261 static char *
wbtype(uint type)262 wbtype(uint type)
263 {
264 static char *types[] = {
265 "write-through",
266 "read data block",
267 "reg 7 ops, no lock-down",
268 [06] "reg 7 ops, format A",
269 [07] "reg 7 ops, format B deprecated",
270 [016] "reg 7 ops, format C",
271 [05] "reg 7 ops, format D",
272 };
273
274 if (type >= nelem(types) || types[type] == nil)
275 return "GOK";
276 return types[type];
277 }
278
279 static void
prcache(Memcache * mcp)280 prcache(Memcache *mcp)
281 {
282 int type;
283 char id;
284
285 if (mcp->kind == Unified)
286 id = 'U';
287 else if (mcp->kind == Icache)
288 id = 'I';
289 else if (mcp->kind == Dcache)
290 id = 'D';
291 else
292 id = '?';
293 print("l%d %c: %d bytes, %d ways %d sets %d bytes/line",
294 mcp->level, id, mcp->size, mcp->nways, mcp->nsets,
295 mcp->linelen);
296 if (mcp->linelen != CACHELINESZ)
297 print(" *should* be %d", CACHELINESZ);
298 type = (mcp->setsways >> 25) & MASK(4);
299 if (type == 0)
300 print("; write-through only");
301 else
302 print("; write-back type `%s' (%#o) possible",
303 wbtype(type), type);
304 if (mcp->setsways & (1<<11))
305 print("; page table mapping restrictions apply");
306 if (mcp->setsways & (1<<2))
307 print("; M bit is set in cache type reg");
308 print("\n");
309 }
310
311 static void
prcachecfg(void)312 prcachecfg(void)
313 {
314 Memcache mc;
315
316 cacheinfo(1, Dcache, &mc);
317 prcache(&mc);
318 cacheinfo(1, Icache, &mc);
319 prcache(&mc);
320 }
321
322 void
l2cacheon(void)323 l2cacheon(void)
324 {
325 ulong cfg;
326 CpucsReg *cpu;
327 L2uncache *l2p;
328
329 cacheuwbinv();
330 l2cacheuwbinv();
331 l1cachesoff(); /* turns off L2 as a side effect */
332
333 cpwrsc(CpDef, CpCLD, 0, 0, 0); /* GL-CPU-100: set D cache lockdown reg. */
334
335 /* marvell guideline GL-CPU-130 */
336 cpu = (CpucsReg *)soc.cpu;
337 cfg = cpu->cpucfg | L2exists | L2ecc | Cfgiprefetch | Cfgdprefetch;
338
339 if (L2writeback)
340 cfg &= ~L2writethru; /* see PTE Cached & Buffered bits */
341 else
342 cfg |= L2writethru;
343 cpu->l2cfg = cfg;
344 coherence(); /* force l2 cache to pay attention */
345 cpu->l2tm1 = cpu->l2tm0 = 0x66666666; /* marvell guideline GL-CPU-120 */
346 coherence();
347
348 cpwrsc(CpL2, CpTESTCFG, CpTCl2waylck, CpTCl2waylock, 0);
349
350 cachedinv();
351 l2cacheuinv();
352
353 /* disable l2 caching of i/o registers */
354 l2p = (L2uncache *)soc.l2cache;
355 memset(l2p, 0, sizeof *l2p);
356 /*
357 * l2: don't cache upper half of address space.
358 * the L2 cache is PIPT, so the addresses are physical.
359 */
360 l2p->win[0].base = 0x80000000 | L2enable; /* 64K multiple */
361 l2p->win[0].size = (32*1024-1) << 16; /* 64K multiples */
362 coherence();
363
364 l2cachecfgon();
365 l1cacheson(); /* turns L2 on as a side effect */
366 print("l2 cache: 256K or 512K: 4 ways, 32-byte lines, write-%s, sdram only\n",
367 cpu->l2cfg & L2writethru? "through": "back");
368 }
369
370 /* called late in main */
371 void
archconfinit(void)372 archconfinit(void)
373 {
374 m->cpuhz = Frequency;
375 m->delayloop = m->cpuhz/2000; /* initial estimate */
376 fixaddrmap();
377 if (Debug)
378 praddrmap();
379 prcachecfg();
380
381 l2cacheon();
382 }
383
384 void
archkwlink(void)385 archkwlink(void)
386 {
387 }
388
389 int
archether(unsigned ctlno,Ether * ether)390 archether(unsigned ctlno, Ether *ether)
391 {
392 if(ctlno >= 2)
393 return -1;
394 ether->type = "88e1116";
395 ether->port = ctlno;
396 // ether->mbps = 1000;
397 return 1;
398 }
399
400 /* LED/USB gpios */
401 enum {
402 /*
403 * the bit assignments are MPP pin numbers from the last page of the
404 * sheevaplug 6.0.1 schematic.
405 */
406 KWOEValHigh = 1<<(49-32), /* pin 49: LED pin */
407 KWOEValLow = 1<<29, /* pin 29: USB_PWEN, pin 28: usb_pwerr */
408 KWOELow = ~0,
409 KWOEHigh = ~0,
410 };
411
412 /* called early in main */
413 void
archreset(void)414 archreset(void)
415 {
416 ulong clocks;
417 CpucsReg *cpu;
418 Dramctl *dram;
419 GpioReg *gpio;
420
421 clockshutdown(); /* watchdog disabled */
422
423 /* configure gpios */
424 gpio = (GpioReg*)soc.gpio[0];
425 gpio->dataout = KWOEValLow;
426 coherence();
427 gpio->dataoutena = KWOELow;
428
429 gpio = (GpioReg*)soc.gpio[1];
430 gpio->dataout = KWOEValHigh;
431 coherence();
432 gpio->dataoutena = KWOEHigh;
433 coherence();
434
435 cpu = (CpucsReg *)soc.cpu;
436 cpu->mempm = 0; /* turn everything on */
437 coherence();
438
439 clocks = MASK(10);
440 clocks |= MASK(21) & ~MASK(14);
441 clocks &= ~(1<<18 | 1<<1); /* reserved bits */
442 cpu->clockgate |= clocks; /* enable all the clocks */
443 cpu->l2cfg |= L2exists; /* when L2exists is 0, the l2 ignores us */
444 coherence();
445
446 dram = (Dramctl *)soc.sdramc;
447 dram->ddrctllo &= ~(1<<6); /* marvell guideline GL-MEM-70 */
448
449 *(ulong *)soc.analog = 0x68; /* marvell guideline GL-MISC-40 */
450 coherence();
451 }
452
453 void
archreboot(void)454 archreboot(void)
455 {
456 CpucsReg *cpu;
457
458 iprint("reset!\n");
459 delay(10);
460
461 cpu = (CpucsReg *)soc.cpu;
462 cpu->rstout = RstoutSoft;
463 cpu->softreset = ResetSystem;
464 coherence();
465 cpu->cpucsr = Reset;
466 coherence();
467 delay(500);
468
469 splhi();
470 iprint("waiting...");
471 for(;;)
472 idlehands();
473 }
474
475 void
archconsole(void)476 archconsole(void)
477 {
478 // uartconsole(0, "b115200");
479 //serialputs("uart0 console @ 115200\n", strlen("uart0 console @ 115200\n"));
480 }
481
482 void
archflashwp(Flash *,int)483 archflashwp(Flash*, int)
484 {
485 }
486
487 int flashat(Flash *f, uintptr pa);
488
489 /*
490 * for ../port/devflash.c:/^flashreset
491 * retrieve flash type, virtual base and length and return 0;
492 * return -1 on error (no flash)
493 */
494 int
archflashreset(int bank,Flash * f)495 archflashreset(int bank, Flash *f)
496 {
497 if(bank != 0)
498 return -1;
499 f->type = "nand";
500 if (flashat(f, PHYSNAND1))
501 f->addr = (void*)PHYSNAND1;
502 else if (flashat(f, PHYSNAND2))
503 f->addr = (void*)PHYSNAND2;
504 else
505 f->addr = nil;
506 f->size = 0; /* done by probe */
507 f->width = 1;
508 f->interleave = 0;
509 return 0;
510 }
511