xref: /plan9/sys/src/9/kw/archkw.c (revision b649930dd34d6bab2bb3fa27632347c57745aead)
1154abd99SDavid du Colombier /*
2154abd99SDavid du Colombier  * stuff specific to marvell's kirkwood architecture
3154abd99SDavid du Colombier  * as seen in the sheevaplug
4154abd99SDavid du Colombier  */
5154abd99SDavid du Colombier #include "u.h"
6154abd99SDavid du Colombier #include "../port/lib.h"
7154abd99SDavid du Colombier #include "mem.h"
8154abd99SDavid du Colombier #include "dat.h"
9154abd99SDavid du Colombier #include "fns.h"
10154abd99SDavid du Colombier #include "../port/error.h"
11154abd99SDavid du Colombier #include "io.h"
12154abd99SDavid du Colombier 
13154abd99SDavid du Colombier #include "../port/netif.h"
14154abd99SDavid du Colombier #include "etherif.h"
1506f6463aSDavid du Colombier #include "../port/flashif.h"
16154abd99SDavid du Colombier 
17b72bcbbfSDavid du Colombier #include "arm.h"
18b72bcbbfSDavid du Colombier 
19ffc08dc1SDavid du Colombier enum {
20a7a38e3eSDavid du Colombier 	L2writeback = 1,
2180f6c381SDavid du Colombier 	Debug = 0,
22ffc08dc1SDavid du Colombier };
23ffc08dc1SDavid du Colombier 
24154abd99SDavid du Colombier typedef struct GpioReg GpioReg;
25154abd99SDavid du Colombier struct GpioReg {
26154abd99SDavid du Colombier 	ulong	dataout;
27154abd99SDavid du Colombier 	ulong	dataoutena;
28154abd99SDavid du Colombier 	ulong	blinkena;
29154abd99SDavid du Colombier 	ulong	datainpol;
30154abd99SDavid du Colombier 	ulong	datain;
31154abd99SDavid du Colombier 	ulong	intrcause;
32154abd99SDavid du Colombier 	ulong	intrmask;
33154abd99SDavid du Colombier 	ulong	intrlevelmask;
34154abd99SDavid du Colombier };
35154abd99SDavid du Colombier 
36154abd99SDavid du Colombier typedef struct L2uncache L2uncache;
37154abd99SDavid du Colombier typedef struct L2win L2win;
38154abd99SDavid du Colombier struct L2uncache {
39154abd99SDavid du Colombier 	struct L2win {
40fee6e4b8SDavid du Colombier 		ulong	base;	/* phys addr */
41154abd99SDavid du Colombier 		ulong	size;
42154abd99SDavid du Colombier 	} win[4];
43154abd99SDavid du Colombier };
44154abd99SDavid du Colombier 
45154abd99SDavid du Colombier enum {
46154abd99SDavid du Colombier 	/* L2win->base bits */
47154abd99SDavid du Colombier 	L2enable	= 1<<0,
48154abd99SDavid du Colombier };
49154abd99SDavid du Colombier 
5056713243SDavid du Colombier typedef struct Dramctl Dramctl;
5156713243SDavid du Colombier struct Dramctl {
5256713243SDavid du Colombier 	ulong	ctl;
5356713243SDavid du Colombier 	ulong	ddrctllo;
5456713243SDavid du Colombier 	struct {
5556713243SDavid du Colombier 		ulong	lo;
5656713243SDavid du Colombier 		ulong	hi;
5756713243SDavid du Colombier 	} time;
5856713243SDavid du Colombier 	ulong	addrctl;
5956713243SDavid du Colombier 	ulong	opagectl;
6056713243SDavid du Colombier 	ulong	oper;
6156713243SDavid du Colombier 	ulong	mode;
6256713243SDavid du Colombier 	ulong	extmode;
6356713243SDavid du Colombier 	ulong	ddrctlhi;
6456713243SDavid du Colombier 	ulong	ddr2timelo;
6556713243SDavid du Colombier 	ulong	operctl;
6656713243SDavid du Colombier 	struct {
6756713243SDavid du Colombier 		ulong	lo;
6856713243SDavid du Colombier 		ulong	hi;
6956713243SDavid du Colombier 	} mbusctl;
7056713243SDavid du Colombier 	ulong	mbustimeout;
7156713243SDavid du Colombier 	ulong	ddrtimehi;
7256713243SDavid du Colombier 	ulong	sdinitctl;
7356713243SDavid du Colombier 	ulong	extsdmode1;
7456713243SDavid du Colombier 	ulong	extsdmode2;
7556713243SDavid du Colombier 	struct {
7656713243SDavid du Colombier 		ulong	lo;
7756713243SDavid du Colombier 		ulong	hi;
7856713243SDavid du Colombier 	} odtctl;
7956713243SDavid du Colombier 	ulong	ddrodtctl;
8056713243SDavid du Colombier 	ulong	rbuffsel;
8156713243SDavid du Colombier 
8256713243SDavid du Colombier 	ulong	accalib;
8356713243SDavid du Colombier 	ulong	dqcalib;
8456713243SDavid du Colombier 	ulong	dqscalib;
8556713243SDavid du Colombier };
8656713243SDavid du Colombier 
877365b686SDavid du Colombier /* unused so far */
8856713243SDavid du Colombier typedef struct SDramdReg SDramdReg;
8956713243SDavid du Colombier struct SDramdReg {
9056713243SDavid du Colombier 	struct {
9156713243SDavid du Colombier 		ulong	base;
9256713243SDavid du Colombier 		ulong	size;
9356713243SDavid du Colombier 	} win[4];
9456713243SDavid du Colombier };
9556713243SDavid du Colombier 
96154abd99SDavid du Colombier typedef struct Addrmap Addrmap;
97154abd99SDavid du Colombier typedef struct Addrwin Addrwin;
98154abd99SDavid du Colombier struct Addrmap {
99154abd99SDavid du Colombier 	struct Addrwin {
10006f6463aSDavid du Colombier 		ulong	ctl;		/* see Winenable in io.h */
101*b649930dSDavid du Colombier 		ulong	base;		/* virtual address */
102*b649930dSDavid du Colombier 		ulong	remaplo;	/* physical address sent to target */
103*b649930dSDavid du Colombier 		ulong	remaphi;	/* " */
104154abd99SDavid du Colombier 	} win[8];
1058a12d8dfSDavid du Colombier 	ulong	dirba;		/* device internal reg's base addr.: PHYSIO */
106154abd99SDavid du Colombier };
107154abd99SDavid du Colombier 
1087365b686SDavid du Colombier Soc soc = {
1097365b686SDavid du Colombier 	.cpu		= PHYSIO+0x20100,
1107365b686SDavid du Colombier 	.devid		= PHYSIO+0x10034,
1117365b686SDavid du Colombier 	.l2cache	= PHYSIO+0x20a00,  	/* uncachable addrs for L2 */
1127365b686SDavid du Colombier 	.sdramc		= PHYSIO+0x01400,
1137365b686SDavid du Colombier //	.sdramd		= PHYSIO+0x01500,	/* unused */
1147365b686SDavid du Colombier 
1157365b686SDavid du Colombier 	.iocfg		= PHYSIO+0x100e0,
116*b649930dSDavid du Colombier 	.addrmap	= PHYSIO+0x20000,	/* cpu address map */
1177365b686SDavid du Colombier 	.intr		= PHYSIO+0x20200,
1187365b686SDavid du Colombier 	.nand		= PHYSIO+0x10418,
1197365b686SDavid du Colombier 	.cesa		= PHYSIO+0x30000,	/* crypto accelerator */
1207365b686SDavid du Colombier 	.ehci		= PHYSIO+0x50000,
1217365b686SDavid du Colombier 	.spi		= PHYSIO+0x10600,
1227365b686SDavid du Colombier  	.twsi		= PHYSIO+0x11000,
1237365b686SDavid du Colombier 
1247365b686SDavid du Colombier 	.analog		= PHYSIO+0x1007c,
1257365b686SDavid du Colombier 	.pci		= PHYSIO+0x40000,
1267365b686SDavid du Colombier 	.pcibase	= PHYSIO+0x41800,
1277365b686SDavid du Colombier 
1287365b686SDavid du Colombier 	.rtc		= PHYSIO+0x10300,
1297365b686SDavid du Colombier 	.clock		= PHYSIO+0x20300,
1307365b686SDavid du Colombier //	.clockctl	= PHYSIO+0x1004c,	/* unused */
1317365b686SDavid du Colombier 
1321ecc8ef2SDavid du Colombier 	.ether		= { PHYSIO+0x72000, PHYSIO+0x76000, },
1337365b686SDavid du Colombier 	.sata		= { PHYSIO+0x80000,	/* sata config reg here */
1347365b686SDavid du Colombier 			PHYSIO+0x82000,		/* edma config reg here */
1357365b686SDavid du Colombier 			PHYSIO+0x84000,		/* edma config reg here */
1367365b686SDavid du Colombier 			},
1377365b686SDavid du Colombier 	.uart		= { PHYSIO+0x12000, PHYSIO+0x12100, },
1387365b686SDavid du Colombier 	.gpio		= { PHYSIO+0x10100, PHYSIO+0x10140, },
1397365b686SDavid du Colombier };
1407365b686SDavid du Colombier 
141154abd99SDavid du Colombier /*
142897ae9c1SDavid du Colombier  * sheeva/openrd u-boot leaves us with this address map:
143154abd99SDavid du Colombier  *
144154abd99SDavid du Colombier  * 0 targ 4 attr 0xe8 size 256MB addr 0x9::  remap addr 0x9::	pci mem
145154abd99SDavid du Colombier  * 1 targ 1 attr 0x2f size   8MB addr 0xf9:: remap addr 0xf9::	nand flash
146154abd99SDavid du Colombier  * 2 targ 4 attr 0xe0 size  16MB addr 0xf::  remap addr 0xc::	pci i/o
147154abd99SDavid du Colombier  * 3 targ 1 attr 0x1e size  16MB addr 0xf8:: remap addr 0x0	spi flash
148154abd99SDavid du Colombier  * 4 targ 1 attr 0x1d size  16MB addr 0xff::			boot rom
149154abd99SDavid du Colombier  * 5 targ 1 attr 0x1e size 128MB addr 0xe8::	disabled	spi flash
150154abd99SDavid du Colombier  * 6 targ 1 attr 0x1d size 128MB addr 0xf::	disabled	boot rom
151a0d13e95SDavid du Colombier  * 7 targ 3 attr 0x1  size  64K  addr 0xfb::			crypto sram
152*b649930dSDavid du Colombier  *
153*b649930dSDavid du Colombier  * dreamplug u-boot leaves us with this address map:
154*b649930dSDavid du Colombier  *
155*b649930dSDavid du Colombier  * 0 targ 4 attr 0xe8 size 256MB addr 0x9::  remap addr 0x9::	pci mem
156*b649930dSDavid du Colombier  * 1 targ 4 attr 0xe0 size  64KB addr 0xc::  remap addr 0xc::	pci i/o
157*b649930dSDavid du Colombier  * 2 targ 1 attr 0x2f size 128MB addr 0xd8:: remap addr 0xd8::	nand flash
158*b649930dSDavid du Colombier  * 3 targ 1 attr 0x1e size 128MB addr 0xe8:: remap addr 0xe8::	spi flash
159*b649930dSDavid du Colombier  * 4 targ 1 attr 0x1d size 128MB addr 0xf8::			boot rom
160*b649930dSDavid du Colombier  * 5 targ 3 attr 0x1  size  64K  addr 0xc801::			crypto sram
161*b649930dSDavid du Colombier  * 6 targ 0 attr 0x0  size  64K  addr 0xf::	disabled	ram?
162*b649930dSDavid du Colombier  * 7 targ 0 attr 0x0  size  64K  addr 0xf8::	disabled	ram?
163154abd99SDavid du Colombier  */
164*b649930dSDavid du Colombier 
165154abd99SDavid du Colombier #define WINTARG(ctl)	(((ctl) >> 4) & 017)
166154abd99SDavid du Colombier #define WINATTR(ctl)	(((ctl) >> 8) & 0377)
167154abd99SDavid du Colombier #define WIN64KSIZE(ctl)	(((ctl) >> 16) + 1)
168154abd99SDavid du Colombier 
169154abd99SDavid du Colombier static void
praddrwin(Addrwin * win,int i)170ffc08dc1SDavid du Colombier praddrwin(Addrwin *win, int i)
171ffc08dc1SDavid du Colombier {
172ffc08dc1SDavid du Colombier 	ulong ctl, targ, attr, size64k;
173ffc08dc1SDavid du Colombier 
17480f6c381SDavid du Colombier 	if (!Debug) {
17580f6c381SDavid du Colombier 		USED(win, i);
17680f6c381SDavid du Colombier 		return;
17780f6c381SDavid du Colombier 	}
178ffc08dc1SDavid du Colombier 	ctl = win->ctl;
179ffc08dc1SDavid du Colombier 	targ = WINTARG(ctl);
180ffc08dc1SDavid du Colombier 	attr = WINATTR(ctl);
181ffc08dc1SDavid du Colombier 	size64k = WIN64KSIZE(ctl);
182b72bcbbfSDavid du Colombier 	print("cpu addr map: %s window %d: targ %ld attr %#lux size %,ld addr %#lux",
183ffc08dc1SDavid du Colombier 		ctl & Winenable? "enabled": "disabled", i, targ, attr,
184ffc08dc1SDavid du Colombier 		size64k * 64*1024, win->base);
185ffc08dc1SDavid du Colombier 	if (i < 4)
186ffc08dc1SDavid du Colombier 		print(" remap addr %#llux", (uvlong)win->remaphi<<32 |
187ffc08dc1SDavid du Colombier 			win->remaplo);
188ffc08dc1SDavid du Colombier 	print("\n");
189ffc08dc1SDavid du Colombier }
190ffc08dc1SDavid du Colombier 
191ffc08dc1SDavid du Colombier static void
fixaddrmap(void)192ffc08dc1SDavid du Colombier fixaddrmap(void)
193154abd99SDavid du Colombier {
194897ae9c1SDavid du Colombier 	int i;
195154abd99SDavid du Colombier 	ulong ctl, targ, attr, size64k;
196154abd99SDavid du Colombier 	Addrmap *map;
197154abd99SDavid du Colombier 	Addrwin *win;
198154abd99SDavid du Colombier 
1997365b686SDavid du Colombier 	map = (Addrmap *)soc.addrmap;
200154abd99SDavid du Colombier 	for (i = 0; i < nelem(map->win); i++) {
201154abd99SDavid du Colombier 		win = &map->win[i];
202154abd99SDavid du Colombier 		ctl = win->ctl;
203154abd99SDavid du Colombier 		targ = WINTARG(ctl);
204154abd99SDavid du Colombier 		attr = WINATTR(ctl);
205154abd99SDavid du Colombier 		size64k = WIN64KSIZE(ctl);
206ffc08dc1SDavid du Colombier 
207897ae9c1SDavid du Colombier 		USED(attr, size64k);
208897ae9c1SDavid du Colombier 		if (targ == Targcesasram) {
209a0d13e95SDavid du Colombier 			win->ctl |= Winenable;
210a0d13e95SDavid du Colombier 			win->base = PHYSCESASRAM;
211a0d13e95SDavid du Colombier 			coherence();
212ffc08dc1SDavid du Colombier 			praddrwin(win, i);
213154abd99SDavid du Colombier 		}
214154abd99SDavid du Colombier 	}
215ffc08dc1SDavid du Colombier 	if (map->dirba != PHYSIO)
216ffc08dc1SDavid du Colombier 		panic("dirba not %#ux", PHYSIO);
217ffc08dc1SDavid du Colombier }
218ffc08dc1SDavid du Colombier 
219ffc08dc1SDavid du Colombier static void
praddrmap(void)220ffc08dc1SDavid du Colombier praddrmap(void)
221ffc08dc1SDavid du Colombier {
222ffc08dc1SDavid du Colombier 	int i;
223ffc08dc1SDavid du Colombier 	Addrmap *map;
224ffc08dc1SDavid du Colombier 
2257365b686SDavid du Colombier 	map = (Addrmap *)soc.addrmap;
226ffc08dc1SDavid du Colombier 	for (i = 0; i < nelem(map->win); i++)
227ffc08dc1SDavid du Colombier 		praddrwin(&map->win[i], i);
228154abd99SDavid du Colombier }
229154abd99SDavid du Colombier 
230b72bcbbfSDavid du Colombier int
ispow2(uvlong ul)231b72bcbbfSDavid du Colombier ispow2(uvlong ul)
232b72bcbbfSDavid du Colombier {
233b72bcbbfSDavid du Colombier 	/* see Hacker's Delight if this isn't obvious */
234b72bcbbfSDavid du Colombier 	return (ul & (ul - 1)) == 0;
235b72bcbbfSDavid du Colombier }
236b72bcbbfSDavid du Colombier 
237b72bcbbfSDavid du Colombier /*
238b72bcbbfSDavid du Colombier  * return exponent of smallest power of 2 ≥ n
239b72bcbbfSDavid du Colombier  */
240b72bcbbfSDavid du Colombier int
log2(ulong n)241b72bcbbfSDavid du Colombier log2(ulong n)
242b72bcbbfSDavid du Colombier {
243b72bcbbfSDavid du Colombier 	int i;
244b72bcbbfSDavid du Colombier 
24528620197SDavid du Colombier 	i = 31 - clz(n);
24628620197SDavid du Colombier 	if (!ispow2(n) || n == 0)
24728620197SDavid du Colombier 		i++;
248b72bcbbfSDavid du Colombier 	return i;
249b72bcbbfSDavid du Colombier }
250b72bcbbfSDavid du Colombier 
251b72bcbbfSDavid du Colombier void
cacheinfo(int level,int kind,Memcache * cp)25210dec6bfSDavid du Colombier cacheinfo(int level, int kind, Memcache *cp)		/* l1 only */
253b72bcbbfSDavid du Colombier {
254b72bcbbfSDavid du Colombier 	uint len, assoc, size;
255b72bcbbfSDavid du Colombier 	ulong setsways;
256b72bcbbfSDavid du Colombier 
25710dec6bfSDavid du Colombier 	/* get cache types & sizes (read-only reg) */
258b72bcbbfSDavid du Colombier 	setsways = cprdsc(0, CpID, CpIDidct, CpIDct);
259b72bcbbfSDavid du Colombier 
260b72bcbbfSDavid du Colombier 	cp->level = level;
26110dec6bfSDavid du Colombier 	cp->kind = kind;
262b72bcbbfSDavid du Colombier 
263b72bcbbfSDavid du Colombier 	if ((setsways & (1<<24)) == 0)
26410dec6bfSDavid du Colombier 		kind = Unified;
26510dec6bfSDavid du Colombier 	if (kind != Icache)
266b72bcbbfSDavid du Colombier 		setsways >>= 12;
267b72bcbbfSDavid du Colombier 
268b72bcbbfSDavid du Colombier 	assoc = (setsways >> 3) & MASK(3);
269b72bcbbfSDavid du Colombier 	cp->nways = 1 << assoc;
270b72bcbbfSDavid du Colombier 	size = (setsways >> 6) & MASK(4);
271b72bcbbfSDavid du Colombier 	cp->size  = 1 << (size + 9);
272b72bcbbfSDavid du Colombier 	len = setsways & MASK(2);
273b72bcbbfSDavid du Colombier 	cp->log2linelen = len + 3;
274b72bcbbfSDavid du Colombier 	cp->linelen = 1 << cp->log2linelen;
27510dec6bfSDavid du Colombier 	cp->setsways = setsways;
276b72bcbbfSDavid du Colombier 
277b72bcbbfSDavid du Colombier 	cp->nsets = 1 << (size + 6 - assoc - len);
278b72bcbbfSDavid du Colombier 	cp->setsh = cp->log2linelen;
279b72bcbbfSDavid du Colombier 	cp->waysh = 32 - log2(cp->nways);
280b72bcbbfSDavid du Colombier }
281b72bcbbfSDavid du Colombier 
28210dec6bfSDavid du Colombier static char *
wbtype(uint type)28310dec6bfSDavid du Colombier wbtype(uint type)
28410dec6bfSDavid du Colombier {
28510dec6bfSDavid du Colombier 	static char *types[] = {
28610dec6bfSDavid du Colombier 		"write-through",
28710dec6bfSDavid du Colombier 		"read data block",
28810dec6bfSDavid du Colombier 		"reg 7 ops, no lock-down",
28910dec6bfSDavid du Colombier 	[06]	"reg 7 ops, format A",
29010dec6bfSDavid du Colombier 	[07]	"reg 7 ops, format B deprecated",
29110dec6bfSDavid du Colombier 	[016]	"reg 7 ops, format C",
29210dec6bfSDavid du Colombier 	[05]	"reg 7 ops, format D",
29310dec6bfSDavid du Colombier 	};
29410dec6bfSDavid du Colombier 
29510dec6bfSDavid du Colombier 	if (type >= nelem(types) || types[type] == nil)
29610dec6bfSDavid du Colombier 		return "GOK";
29710dec6bfSDavid du Colombier 	return types[type];
29810dec6bfSDavid du Colombier }
29910dec6bfSDavid du Colombier 
30010dec6bfSDavid du Colombier static void
prcache(Memcache * mcp)30110dec6bfSDavid du Colombier prcache(Memcache *mcp)
30210dec6bfSDavid du Colombier {
30310dec6bfSDavid du Colombier 	int type;
30410dec6bfSDavid du Colombier 	char id;
30510dec6bfSDavid du Colombier 
30610dec6bfSDavid du Colombier 	if (mcp->kind == Unified)
30710dec6bfSDavid du Colombier 		id = 'U';
30810dec6bfSDavid du Colombier 	else if (mcp->kind == Icache)
30910dec6bfSDavid du Colombier 		id = 'I';
31010dec6bfSDavid du Colombier 	else if (mcp->kind == Dcache)
31110dec6bfSDavid du Colombier 		id = 'D';
31210dec6bfSDavid du Colombier 	else
31310dec6bfSDavid du Colombier 		id = '?';
31410dec6bfSDavid du Colombier 	print("l%d %c: %d bytes, %d ways %d sets %d bytes/line",
31510dec6bfSDavid du Colombier 		mcp->level, id, mcp->size, mcp->nways, mcp->nsets,
31610dec6bfSDavid du Colombier 		mcp->linelen);
31710dec6bfSDavid du Colombier 	if (mcp->linelen != CACHELINESZ)
31810dec6bfSDavid du Colombier 		print(" *should* be %d", CACHELINESZ);
31910dec6bfSDavid du Colombier 	type = (mcp->setsways >> 25) & MASK(4);
32010dec6bfSDavid du Colombier 	if (type == 0)
32110dec6bfSDavid du Colombier 		print("; write-through only");
32210dec6bfSDavid du Colombier 	else
32310dec6bfSDavid du Colombier 		print("; write-back type `%s' (%#o) possible",
32410dec6bfSDavid du Colombier 			wbtype(type), type);
32510dec6bfSDavid du Colombier 	if (mcp->setsways & (1<<11))
32610dec6bfSDavid du Colombier 		print("; page table mapping restrictions apply");
32710dec6bfSDavid du Colombier 	if (mcp->setsways & (1<<2))
32810dec6bfSDavid du Colombier 		print("; M bit is set in cache type reg");
32910dec6bfSDavid du Colombier 	print("\n");
33010dec6bfSDavid du Colombier }
33110dec6bfSDavid du Colombier 
332b72bcbbfSDavid du Colombier static void
prcachecfg(void)333b72bcbbfSDavid du Colombier prcachecfg(void)
334b72bcbbfSDavid du Colombier {
335b72bcbbfSDavid du Colombier 	Memcache mc;
336b72bcbbfSDavid du Colombier 
33710dec6bfSDavid du Colombier 	cacheinfo(1, Dcache, &mc);
33810dec6bfSDavid du Colombier 	prcache(&mc);
33910dec6bfSDavid du Colombier 	cacheinfo(1, Icache, &mc);
34010dec6bfSDavid du Colombier 	prcache(&mc);
341b72bcbbfSDavid du Colombier }
342b72bcbbfSDavid du Colombier 
343154abd99SDavid du Colombier void
l2cacheon(void)344154abd99SDavid du Colombier l2cacheon(void)
345154abd99SDavid du Colombier {
346b72bcbbfSDavid du Colombier 	ulong cfg;
34756713243SDavid du Colombier 	CpucsReg *cpu;
348154abd99SDavid du Colombier 	L2uncache *l2p;
349154abd99SDavid du Colombier 
350154abd99SDavid du Colombier 	cacheuwbinv();
35180f6c381SDavid du Colombier 	l2cacheuwbinv();
352b72bcbbfSDavid du Colombier 	l1cachesoff();			/* turns off L2 as a side effect */
353b72bcbbfSDavid du Colombier 
354b72bcbbfSDavid du Colombier 	cpwrsc(CpDef, CpCLD, 0, 0, 0);  /* GL-CPU-100: set D cache lockdown reg. */
355b72bcbbfSDavid du Colombier 
356b72bcbbfSDavid du Colombier 	/* marvell guideline GL-CPU-130 */
3577365b686SDavid du Colombier 	cpu = (CpucsReg *)soc.cpu;
358b72bcbbfSDavid du Colombier 	cfg = cpu->cpucfg | L2exists | L2ecc | Cfgiprefetch | Cfgdprefetch;
359b72bcbbfSDavid du Colombier 
360b72bcbbfSDavid du Colombier 	if (L2writeback)
361b72bcbbfSDavid du Colombier 		cfg &= ~L2writethru;	/* see PTE Cached & Buffered bits */
362b72bcbbfSDavid du Colombier 	else
363b72bcbbfSDavid du Colombier 		cfg |= L2writethru;
364b72bcbbfSDavid du Colombier 	cpu->l2cfg = cfg;
365b72bcbbfSDavid du Colombier 	coherence();			/* force l2 cache to pay attention */
366b72bcbbfSDavid du Colombier 	cpu->l2tm1 = cpu->l2tm0 = 0x66666666; /* marvell guideline GL-CPU-120 */
367b72bcbbfSDavid du Colombier 	coherence();
368b72bcbbfSDavid du Colombier 
369b72bcbbfSDavid du Colombier 	cpwrsc(CpL2, CpTESTCFG, CpTCl2waylck, CpTCl2waylock, 0);
370b72bcbbfSDavid du Colombier 
371b72bcbbfSDavid du Colombier 	cachedinv();
37280f6c381SDavid du Colombier 	l2cacheuinv();
373154abd99SDavid du Colombier 
374ffc08dc1SDavid du Colombier 	/* disable l2 caching of i/o registers */
3757365b686SDavid du Colombier 	l2p = (L2uncache *)soc.l2cache;
376154abd99SDavid du Colombier 	memset(l2p, 0, sizeof *l2p);
377fee6e4b8SDavid du Colombier 	/*
378fee6e4b8SDavid du Colombier 	 * l2: don't cache upper half of address space.
379fee6e4b8SDavid du Colombier 	 * the L2 cache is PIPT, so the addresses are physical.
380fee6e4b8SDavid du Colombier 	 */
381154abd99SDavid du Colombier 	l2p->win[0].base = 0x80000000 | L2enable;	/* 64K multiple */
382b72bcbbfSDavid du Colombier 	l2p->win[0].size = (32*1024-1) << 16;		/* 64K multiples */
383154abd99SDavid du Colombier 	coherence();
384154abd99SDavid du Colombier 
385154abd99SDavid du Colombier 	l2cachecfgon();
386b72bcbbfSDavid du Colombier 	l1cacheson();			/* turns L2 on as a side effect */
387fee6e4b8SDavid du Colombier 	print("l2 cache: 256K or 512K: 4 ways, 32-byte lines, write-%s, sdram only\n",
388b72bcbbfSDavid du Colombier 		cpu->l2cfg & L2writethru? "through": "back");
389154abd99SDavid du Colombier }
390154abd99SDavid du Colombier 
391154abd99SDavid du Colombier /* called late in main */
392154abd99SDavid du Colombier void
archconfinit(void)393154abd99SDavid du Colombier archconfinit(void)
394154abd99SDavid du Colombier {
395df2dbabfSDavid du Colombier 	m->cpuhz = Frequency;
3967bb09086SDavid du Colombier 	m->delayloop = m->cpuhz/2000; 	 /* initial estimate */
397ffc08dc1SDavid du Colombier 	fixaddrmap();
398897ae9c1SDavid du Colombier 	if (Debug)
399897ae9c1SDavid du Colombier 		praddrmap();
400b72bcbbfSDavid du Colombier 	prcachecfg();
401b72bcbbfSDavid du Colombier 
402ffc08dc1SDavid du Colombier 	l2cacheon();
403154abd99SDavid du Colombier }
404154abd99SDavid du Colombier 
405154abd99SDavid du Colombier void
archkwlink(void)406154abd99SDavid du Colombier archkwlink(void)
407154abd99SDavid du Colombier {
408154abd99SDavid du Colombier }
409154abd99SDavid du Colombier 
410154abd99SDavid du Colombier int
archether(unsigned ctlno,Ether * ether)411c6569576SDavid du Colombier archether(unsigned ctlno, Ether *ether)
412154abd99SDavid du Colombier {
413c6569576SDavid du Colombier 	if(ctlno >= 2)
414154abd99SDavid du Colombier 		return -1;
415897ae9c1SDavid du Colombier 	ether->type = "88e1116";
416154abd99SDavid du Colombier 	ether->port = ctlno;
417154abd99SDavid du Colombier //	ether->mbps = 1000;
418154abd99SDavid du Colombier 	return 1;
419154abd99SDavid du Colombier }
420154abd99SDavid du Colombier 
421154abd99SDavid du Colombier /* LED/USB gpios */
4225e27dea9SDavid du Colombier enum {
4235e27dea9SDavid du Colombier 	/*
4245e27dea9SDavid du Colombier 	 * the bit assignments are MPP pin numbers from the last page of the
4255e27dea9SDavid du Colombier 	 * sheevaplug 6.0.1 schematic.
4265e27dea9SDavid du Colombier 	 */
4275e27dea9SDavid du Colombier 	KWOEValHigh	= 1<<(49-32),	/* pin 49: LED pin */
4285e27dea9SDavid du Colombier 	KWOEValLow	= 1<<29,	/* pin 29: USB_PWEN, pin 28: usb_pwerr */
4295e27dea9SDavid du Colombier 	KWOELow		= ~0,
4305e27dea9SDavid du Colombier 	KWOEHigh	= ~0,
431154abd99SDavid du Colombier };
432154abd99SDavid du Colombier 
433154abd99SDavid du Colombier /* called early in main */
434154abd99SDavid du Colombier void
archreset(void)435154abd99SDavid du Colombier archreset(void)
436154abd99SDavid du Colombier {
4375e27dea9SDavid du Colombier 	ulong clocks;
4385e27dea9SDavid du Colombier 	CpucsReg *cpu;
43956713243SDavid du Colombier 	Dramctl *dram;
4407365b686SDavid du Colombier 	GpioReg *gpio;
4415e27dea9SDavid du Colombier 
44256713243SDavid du Colombier 	clockshutdown();		/* watchdog disabled */
443154abd99SDavid du Colombier 
444154abd99SDavid du Colombier 	/* configure gpios */
4457365b686SDavid du Colombier 	gpio = (GpioReg*)soc.gpio[0];
4467365b686SDavid du Colombier 	gpio->dataout = KWOEValLow;
447b72bcbbfSDavid du Colombier 	coherence();
4487365b686SDavid du Colombier 	gpio->dataoutena = KWOELow;
449154abd99SDavid du Colombier 
4507365b686SDavid du Colombier 	gpio = (GpioReg*)soc.gpio[1];
4517365b686SDavid du Colombier 	gpio->dataout = KWOEValHigh;
452b72bcbbfSDavid du Colombier 	coherence();
4537365b686SDavid du Colombier 	gpio->dataoutena = KWOEHigh;
454154abd99SDavid du Colombier 	coherence();
455154abd99SDavid du Colombier 
4567365b686SDavid du Colombier 	cpu = (CpucsReg *)soc.cpu;
4575e27dea9SDavid du Colombier 	cpu->mempm = 0;			/* turn everything on */
4585e27dea9SDavid du Colombier 	coherence();
45956713243SDavid du Colombier 
460ab6ce076SDavid du Colombier 	clocks = MASK(10);
461ab6ce076SDavid du Colombier 	clocks |= MASK(21) & ~MASK(14);
4625e27dea9SDavid du Colombier 	clocks &= ~(1<<18 | 1<<1);	/* reserved bits */
4635e27dea9SDavid du Colombier 	cpu->clockgate |= clocks;	/* enable all the clocks */
464ffc08dc1SDavid du Colombier 	cpu->l2cfg |= L2exists;		/* when L2exists is 0, the l2 ignores us */
465154abd99SDavid du Colombier 	coherence();
46656713243SDavid du Colombier 
4677365b686SDavid du Colombier 	dram = (Dramctl *)soc.sdramc;
46856713243SDavid du Colombier 	dram->ddrctllo &= ~(1<<6);	/* marvell guideline GL-MEM-70 */
46956713243SDavid du Colombier 
4707365b686SDavid du Colombier 	*(ulong *)soc.analog = 0x68;	/* marvell guideline GL-MISC-40 */
47156713243SDavid du Colombier 	coherence();
472154abd99SDavid du Colombier }
473154abd99SDavid du Colombier 
474154abd99SDavid du Colombier void
archreboot(void)475154abd99SDavid du Colombier archreboot(void)
476154abd99SDavid du Colombier {
4777365b686SDavid du Colombier 	CpucsReg *cpu;
4787365b686SDavid du Colombier 
479154abd99SDavid du Colombier 	iprint("reset!\n");
480b72bcbbfSDavid du Colombier 	delay(10);
481154abd99SDavid du Colombier 
4827365b686SDavid du Colombier 	cpu = (CpucsReg *)soc.cpu;
4837365b686SDavid du Colombier 	cpu->rstout = RstoutSoft;
4847365b686SDavid du Colombier 	cpu->softreset = ResetSystem;
485b72bcbbfSDavid du Colombier 	coherence();
4867365b686SDavid du Colombier 	cpu->cpucsr = Reset;
4875e27dea9SDavid du Colombier 	coherence();
488154abd99SDavid du Colombier 	delay(500);
489154abd99SDavid du Colombier 
490154abd99SDavid du Colombier 	splhi();
491154abd99SDavid du Colombier 	iprint("waiting...");
492154abd99SDavid du Colombier 	for(;;)
493154abd99SDavid du Colombier 		idlehands();
494154abd99SDavid du Colombier }
495154abd99SDavid du Colombier 
496154abd99SDavid du Colombier void
archconsole(void)497154abd99SDavid du Colombier archconsole(void)
498154abd99SDavid du Colombier {
499154abd99SDavid du Colombier //	uartconsole(0, "b115200");
500154abd99SDavid du Colombier //serialputs("uart0 console @ 115200\n", strlen("uart0 console @ 115200\n"));
501154abd99SDavid du Colombier }
502154abd99SDavid du Colombier 
503154abd99SDavid du Colombier void
archflashwp(Flash *,int)504154abd99SDavid du Colombier archflashwp(Flash*, int)
505154abd99SDavid du Colombier {
506154abd99SDavid du Colombier }
507154abd99SDavid du Colombier 
508897ae9c1SDavid du Colombier int	flashat(Flash *f, uintptr pa);
509897ae9c1SDavid du Colombier 
510154abd99SDavid du Colombier /*
511154abd99SDavid du Colombier  * for ../port/devflash.c:/^flashreset
512154abd99SDavid du Colombier  * retrieve flash type, virtual base and length and return 0;
513154abd99SDavid du Colombier  * return -1 on error (no flash)
514154abd99SDavid du Colombier  */
515154abd99SDavid du Colombier int
archflashreset(int bank,Flash * f)516154abd99SDavid du Colombier archflashreset(int bank, Flash *f)
517154abd99SDavid du Colombier {
518154abd99SDavid du Colombier 	if(bank != 0)
519154abd99SDavid du Colombier 		return -1;
520154abd99SDavid du Colombier 	f->type = "nand";
52106f6463aSDavid du Colombier 	if (flashat(f, PHYSNAND1))
52206f6463aSDavid du Colombier 		f->addr = (void*)PHYSNAND1;
52306f6463aSDavid du Colombier 	else if (flashat(f, PHYSNAND2))
52406f6463aSDavid du Colombier 		f->addr = (void*)PHYSNAND2;
52506f6463aSDavid du Colombier 	else
52606f6463aSDavid du Colombier 		f->addr = nil;
527154abd99SDavid du Colombier 	f->size = 0;		/* done by probe */
528154abd99SDavid du Colombier 	f->width = 1;
529154abd99SDavid du Colombier 	f->interleave = 0;
530154abd99SDavid du Colombier 	return 0;
531154abd99SDavid du Colombier }
532