xref: /plan9-contrib/sys/src/9/kw/archkw.c (revision 22402af72e824b13a03306b380e882c0b67c2e73)
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