Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/9/kw/archkw.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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 *
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
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
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
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
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
406
archkwlink(void)
407
{
408
}
409
 
410
int
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
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
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
497
archconsole(void)
498
{
499
//	uartconsole(0, "b115200");
500
//serialputs("uart0 console @ 115200\n", strlen("uart0 console @ 115200\n"));
501
}
502
 
503
void
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
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
}