brdsetup.c revision 1.31
1/* $NetBSD: brdsetup.c,v 1.31 2012/04/16 16:55:29 phx Exp $ */
2
3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33
34#include <powerpc/psl.h>
35#include <powerpc/oea/spr.h>
36
37#include <lib/libsa/stand.h>
38#include <lib/libsa/net.h>
39#include <lib/libkern/libkern.h>
40
41#include <machine/bootinfo.h>
42
43#include "globals.h"
44
45#define BRD_DECL(xxx) \
46    void xxx ## setup(struct brdprop *); \
47    void xxx ## brdfix(struct brdprop *); \
48    void xxx ## pcifix(struct brdprop *); \
49    void xxx ## launch(struct brdprop *); \
50    void xxx ## reset(void)
51
52BRD_DECL(mot);
53BRD_DECL(enc);
54BRD_DECL(kuro);
55BRD_DECL(syno);
56BRD_DECL(qnap);
57BRD_DECL(iomega);
58BRD_DECL(dlink);
59BRD_DECL(nhnas);
60BRD_DECL(kurot4);
61
62static void brdfixup(void);
63static void setup(void);
64static void send_iomega(int, int, int, int, int, int);
65static inline uint32_t mfmsr(void);
66static inline void mtmsr(uint32_t);
67static inline uint32_t cputype(void);
68static inline u_quad_t mftb(void);
69static void init_uart(unsigned, unsigned, uint8_t);
70static void send_sat(char *);
71static unsigned mpc107memsize(void);
72
73/* UART registers */
74#define RBR		0
75#define THR		0
76#define DLB		0
77#define DMB		1
78#define IER		1
79#define FCR		2
80#define LCR		3
81#define  LCR_DLAB	0x80
82#define  LCR_PEVEN	0x18
83#define  LCR_PNONE	0x00
84#define  LCR_8BITS	0x03
85#define MCR		4
86#define  MCR_RTS	0x02
87#define  MCR_DTR	0x01
88#define LSR		5
89#define  LSR_THRE	0x20
90#define  LSR_DRDY	0x01
91#define DCR		0x11
92#define UART_READ(base, r)	in8(base + (r))
93#define UART_WRITE(base, r, v)	out8(base + (r), (v))
94
95/* MPC106 and MPC824x PCI bridge memory configuration */
96#define MPC106_MEMSTARTADDR1	0x80
97#define MPC106_EXTMEMSTARTADDR1	0x88
98#define MPC106_MEMENDADDR1	0x90
99#define MPC106_EXTMEMENDADDR1	0x98
100#define MPC106_MEMEN		0xa0
101
102/* Iomega StorCenter MC68HC908 microcontroller data packet */
103#define IOMEGA_POWER		0
104#define IOMEGA_LED		1
105#define IOMEGA_FLASH_RATE	2
106#define IOMEGA_FAN		3
107#define IOMEGA_HIGH_TEMP	4
108#define IOMEGA_LOW_TEMP		5
109#define IOMEGA_ID		6
110#define IOMEGA_CHECKSUM		7
111#define IOMEGA_PACKETSIZE	8
112
113/* NH230/231 GPIO */
114#define NHGPIO_WRITE(x)		*((uint8_t *)0x70000000) = x
115
116static struct brdprop brdlist[] = {
117    {
118	"sandpoint",
119	"Sandpoint X3",
120	BRD_SANDPOINTX3,
121	0,
122	"com", 0x3f8, 115200,
123	motsetup, motbrdfix, motpcifix, NULL, NULL },
124    {
125	"encpp1",
126	"EnCore PP1",
127	BRD_ENCOREPP1,
128	0,
129	"com", 0x3f8, 115200,
130	encsetup, encbrdfix, encpcifix, NULL, NULL },
131    {
132	"kurobox",
133	"KuroBox",
134	BRD_KUROBOX,
135	0,
136	"eumb", 0x4600, 57600,
137	kurosetup, kurobrdfix, NULL, NULL, kuroreset },
138    {
139	"synology",
140	"Synology CS/DS/RS",
141	BRD_SYNOLOGY,
142	0,
143	"eumb", 0x4500, 115200,
144	synosetup, synobrdfix, synopcifix, synolaunch, synoreset },
145    {
146	"qnap",
147	"QNAP TS",
148	BRD_QNAPTS,
149	33164691,	/* Linux source says 33000000, but the Synology  */
150			/* clock value delivers a much better precision. */
151	"eumb", 0x4500, 115200,
152	NULL, qnapbrdfix, NULL, NULL, qnapreset },
153    {
154	"iomega",
155	"IOMEGA StorCenter G2",
156	BRD_STORCENTER,
157	0,
158	"eumb", 0x4500, 115200,
159	NULL, iomegabrdfix, NULL, NULL, iomegareset },
160    {
161	"dlink",
162	"D-Link DSM-G600",
163	BRD_DLINKDSM,
164	33000000,
165	"eumb", 0x4500, 9600,
166	NULL, dlinkbrdfix, NULL, NULL, NULL },
167    {
168	"nhnas",
169	"Netronix NH-230/231",
170	BRD_NH230NAS,
171	33000000,
172	"eumb", 0x4500, 9600,
173	NULL, nhnasbrdfix, NULL, NULL, nhnasreset },
174    {
175	"kurot4",
176	"KuroBox/T4",
177	BRD_KUROBOXT4,
178	32768000,
179	"eumb", 0x4600, 57600,
180	NULL, kurot4brdfix, NULL, NULL, NULL },
181    {
182	"unknown",
183	"Unknown board",
184	BRD_UNKNOWN,
185	0,
186	"eumb", 0x4500, 115200,
187	NULL, NULL, NULL, NULL, NULL }, /* must be the last */
188};
189
190static struct brdprop *brdprop;
191static uint32_t ticks_per_sec, ns_per_tick;
192
193const unsigned dcache_line_size = 32;		/* 32B linesize */
194const unsigned dcache_range_size = 4 * 1024;	/* 16KB / 4-way */
195
196unsigned uart1base;	/* console */
197unsigned uart2base;	/* optional satellite processor */
198
199void brdsetup(void);	/* called by entry.S */
200
201void
202brdsetup(void)
203{
204	static uint8_t pci_to_memclk[] = {
205		30, 30, 10, 10, 20, 10, 10, 10,
206		10, 20, 20, 15, 20, 15, 20, 30,
207		30, 40, 15, 40, 20, 25, 20, 40,
208		25, 20, 10, 20, 15, 15, 20, 00
209	};
210	static uint8_t mem_to_cpuclk[] = {
211		25, 30, 45, 20, 20, 00, 10, 30,
212		30, 20, 45, 30, 25, 35, 30, 35,
213		20, 25, 20, 30, 35, 40, 40, 20,
214		30, 25, 40, 30, 30, 25, 35, 00
215	};
216	char *consname;
217	int consport;
218	uint32_t extclk;
219	unsigned pchb, pcib, dev11, dev12, dev13, dev15, dev16, val;
220	extern struct btinfo_memory bi_mem;
221	extern struct btinfo_console bi_cons;
222	extern struct btinfo_clock bi_clk;
223	extern struct btinfo_prodfamily bi_fam;
224
225	/*
226	 * CHRP specification "Map-B" BAT012 layout
227	 *   BAT0 0000-0000 (256MB) SDRAM
228	 *   BAT1 8000-0000 (256MB) PCI mem space
229	 *   BAT2 fc00-0000 (64MB)  EUMB, PCI I/O space, misc devs, flash
230	 *
231	 * EUMBBAR is at fc00-0000.
232	 */
233	pchb = pcimaketag(0, 0, 0);
234	pcicfgwrite(pchb, 0x78, 0xfc000000);
235
236	brdtype = BRD_UNKNOWN;
237	extclk = EXT_CLK_FREQ;	/* usually 33MHz */
238	busclock = 0;
239
240	dev11 = pcimaketag(0, 11, 0);
241	dev12 = pcimaketag(0, 12, 0);
242	dev13 = pcimaketag(0, 13, 0);
243	dev15 = pcimaketag(0, 15, 0);
244	dev16 = pcimaketag(0, 16, 0);
245
246	if (pcifinddev(0x10ad, 0x0565, &pcib) == 0) {
247		/* WinBond 553 southbridge at dev 11 */
248		brdtype = BRD_SANDPOINTX3;
249	}
250	else if (pcifinddev(0x1106, 0x0686, &pcib) == 0) {
251		/* VIA 686B southbridge at dev 22 */
252		brdtype = BRD_ENCOREPP1;
253	}
254	else if (PCI_CLASS(pcicfgread(dev11, PCI_CLASS_REG)) == PCI_CLASS_ETH) {
255		/* ADMtek AN985 (tlp) or RealTek 8169S (re) at dev 11 */
256		if (PCI_VENDOR(pcicfgread(dev12, PCI_ID_REG)) != 0x1095)
257			brdtype = BRD_KUROBOX;
258		else
259			brdtype = BRD_KUROBOXT4;
260	}
261	else if (PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x11ab) {
262		/* SKnet/Marvell (sk) at dev 15 */
263		brdtype = BRD_SYNOLOGY;
264	}
265	else if (PCI_VENDOR(pcicfgread(dev13, PCI_ID_REG)) == 0x1106) {
266		/* VIA 6410 (viaide) at dev 13 */
267		brdtype = BRD_STORCENTER;
268	}
269	else if (PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1191) {
270		/* ACARD ATP865 (acardide) at dev 16 */
271		brdtype = BRD_DLINKDSM;
272	}
273	else if (PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1283
274	    || PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1095) {
275		/* ITE (iteide) or SiI (satalink) at dev 16 */
276		brdtype = BRD_NH230NAS;
277	}
278	else if (PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x8086
279	    || PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x10ec) {
280		/* Intel (wm) or RealTek (re) at dev 15 */
281		brdtype = BRD_QNAPTS;
282	}
283
284	brdprop = brd_lookup(brdtype);
285
286	/* brd dependent adjustments */
287	setup();
288
289	/* determine clock frequencies */
290	if (brdprop->extclk != 0)
291		extclk = brdprop->extclk;
292	if (busclock == 0) {
293		if (cputype() == MPC8245) {
294			/* PLL_CFG from PCI host bridge register 0xe2 */
295			val = pcicfgread(pchb, 0xe0);
296			busclock = (extclk *
297			    pci_to_memclk[(val >> 19) & 0x1f] + 10) / 10;
298			/* PLLRATIO from HID1 */
299			asm volatile ("mfspr %0,1009" : "=r"(val));
300			cpuclock = ((uint64_t)busclock *
301			    mem_to_cpuclk[val >> 27] + 10) / 10;
302		} else
303			busclock = 100000000;	/* 100MHz bus clock default */
304	}
305	ticks_per_sec = busclock >> 2;
306	ns_per_tick = 1000000000 / ticks_per_sec;
307
308	/* now prepare serial console */
309	consname = brdprop->consname;
310	consport = brdprop->consport;
311	if (strcmp(consname, "eumb") == 0) {
312		uart1base = 0xfc000000 + consport;	/* 0x4500, 0x4600 */
313		UART_WRITE(uart1base, DCR, 0x01);	/* enable DUART mode */
314		uart2base = uart1base ^ 0x0300;
315	} else
316		uart1base = 0xfe000000 + consport;	/* 0x3f8, 0x2f8 */
317
318	/* more brd adjustments */
319	brdfixup();
320
321	bi_mem.memsize = mpc107memsize();
322	snprintf(bi_cons.devname, sizeof(bi_cons.devname), consname);
323	bi_cons.addr = consport;
324	bi_cons.speed = brdprop->consspeed;
325	bi_clk.ticks_per_sec = ticks_per_sec;
326	snprintf(bi_fam.name, sizeof(bi_fam.name), brdprop->family);
327}
328
329struct brdprop *
330brd_lookup(int brd)
331{
332	u_int i;
333
334	for (i = 0; i < sizeof(brdlist)/sizeof(brdlist[0]); i++) {
335		if (brdlist[i].brdtype == brd)
336			return &brdlist[i];
337	}
338	return &brdlist[i - 1];
339}
340
341static void
342setup()
343{
344
345	if (brdprop->setup == NULL)
346		return;
347	(*brdprop->setup)(brdprop);
348}
349
350static void
351brdfixup()
352{
353
354	if (brdprop->brdfix == NULL)
355		return;
356	(*brdprop->brdfix)(brdprop);
357}
358
359void
360pcifixup()
361{
362
363	if (brdprop->pcifix == NULL)
364		return;
365	(*brdprop->pcifix)(brdprop);
366}
367
368void
369launchfixup()
370{
371
372	if (brdprop->launch == NULL)
373		return;
374	(*brdprop->launch)(brdprop);
375}
376
377void
378encsetup(struct brdprop *brd)
379{
380
381#ifdef COSNAME
382	brd->consname = CONSNAME;
383#endif
384#ifdef CONSPORT
385	brd->consport = CONSPORT;
386#endif
387#ifdef CONSSPEED
388	brd->consspeed = CONSSPEED;
389#endif
390}
391
392void
393encbrdfix(struct brdprop *brd)
394{
395	unsigned ac97, ide, pcib, pmgt, usb12, usb34, val;
396
397/*
398 * VIA82C686B Southbridge
399 *	0.22.0	1106.0686	PCI-ISA bridge
400 *	0.22.1	1106.0571	IDE (viaide)
401 *	0.22.2	1106.3038	USB 0/1 (uhci)
402 *	0.22.3	1106.3038	USB 2/3 (uhci)
403 *	0.22.4	1106.3057	power management
404 *	0.22.5	1106.3058	AC97 (auvia)
405 */
406	pcib  = pcimaketag(0, 22, 0);
407	ide   = pcimaketag(0, 22, 1);
408	usb12 = pcimaketag(0, 22, 2);
409	usb34 = pcimaketag(0, 22, 3);
410	pmgt  = pcimaketag(0, 22, 4);
411	ac97  = pcimaketag(0, 22, 5);
412
413#define	CFG(i,v) do { \
414   *(volatile unsigned char *)(0xfe000000 + 0x3f0) = (i); \
415   *(volatile unsigned char *)(0xfe000000 + 0x3f1) = (v); \
416   } while (0)
417	val = pcicfgread(pcib, 0x84);
418	val |= (02 << 8);
419	pcicfgwrite(pcib, 0x84, val);
420	CFG(0xe2, 0x0f); /* use COM1/2, don't use FDC/LPT */
421	val = pcicfgread(pcib, 0x84);
422	val &= ~(02 << 8);
423	pcicfgwrite(pcib, 0x84, val);
424
425	/* route pin C to i8259 IRQ 5, pin D to 11 */
426	val = pcicfgread(pcib, 0x54);
427	val = (val & 0xff) | 0xb0500000; /* Dx CB Ax xS */
428	pcicfgwrite(pcib, 0x54, val);
429
430	/* enable EISA ELCR1 (0x4d0) and ELCR2 (0x4d1) */
431	val = pcicfgread(pcib, 0x44);
432	val = val | 0x20000000;
433	pcicfgwrite(pcib, 0x44, val);
434
435	/* select level trigger for IRQ 5/11 at ELCR1/2 */
436	*(volatile uint8_t *)0xfe0004d0 = 0x20; /* bit 5 */
437	*(volatile uint8_t *)0xfe0004d1 = 0x08; /* bit 11 */
438
439	/* USB and AC97 are hardwired with pin D and C */
440	val = pcicfgread(usb12, 0x3c) &~ 0xff;
441	val |= 11;
442	pcicfgwrite(usb12, 0x3c, val);
443	val = pcicfgread(usb34, 0x3c) &~ 0xff;
444	val |= 11;
445	pcicfgwrite(usb34, 0x3c, val);
446	val = pcicfgread(ac97, 0x3c) &~ 0xff;
447	val |= 5;
448	pcicfgwrite(ac97, 0x3c, val);
449}
450
451void
452encpcifix(struct brdprop *brd)
453{
454	unsigned ide, irq, net, pcib, steer, val;
455
456#define	STEER(v, b) (((v) & (b)) ? "edge" : "level")
457	pcib = pcimaketag(0, 22, 0);
458	ide  = pcimaketag(0, 22, 1);
459	net  = pcimaketag(0, 25, 0);
460
461	/*
462	 * //// VIA PIRQ ////
463	 * 0x57/56/55/54 - Dx CB Ax xS
464	 */
465	val = pcicfgread(pcib, 0x54);	/* Dx CB Ax xs */
466	steer = val & 0xf;
467	irq = (val >> 12) & 0xf;	/* 15:12 */
468	if (irq) {
469		printf("pin A -> irq %d, %s\n",
470			irq, STEER(steer, 0x1));
471	}
472	irq = (val >> 16) & 0xf;	/* 19:16 */
473	if (irq) {
474		printf("pin B -> irq %d, %s\n",
475			irq, STEER(steer, 0x2));
476	}
477	irq = (val >> 20) & 0xf;	/* 23:20 */
478	if (irq) {
479		printf("pin C -> irq %d, %s\n",
480			irq, STEER(steer, 0x4));
481	}
482	irq = (val >> 28);		/* 31:28 */
483	if (irq) {
484		printf("pin D -> irq %d, %s\n",
485			irq, STEER(steer, 0x8));
486	}
487#if 0
488	/*
489	 * //// IDE fixup ////
490	 * - "native mode" (ide 0x09)
491	 */
492
493	/* ide: 0x09 - programming interface; 1000'SsPp */
494	val = pcicfgread(ide, 0x08) & 0xffff00ff;
495	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
496
497	/* ide: 0x10-20 - leave them PCI memory space assigned */
498#else
499	/*
500	 * //// IDE fixup ////
501	 * - "compatiblity mode" (ide 0x09)
502	 * - remove PCI pin assignment (ide 0x3d)
503	 */
504
505	/* ide: 0x09 - programming interface; 1000'SsPp */
506	val = pcicfgread(ide, 0x08) & 0xffff00ff;
507	val |= (0x8a << 8);
508	pcicfgwrite(ide, 0x08, val);
509
510	/* ide: 0x10-20 */
511	/*
512	 * experiment shows writing ide: 0x09 changes these
513	 * register behaviour. The pcicfgwrite() above writes
514	 * 0x8a at ide: 0x09 to make sure legacy IDE.  Then
515	 * reading BAR0-3 is to return value 0s even though
516	 * pcisetup() has written range assignments.  Value
517	 * overwrite makes no effect. Having 0x8f for native
518	 * PCIIDE doesn't change register values and brings no
519	 * weirdness.
520	 */
521
522	/* ide: 0x3d/3c - turn off PCI pin */
523	val = pcicfgread(ide, 0x3c) & 0xffff00ff;
524	pcicfgwrite(ide, 0x3c, val);
525#endif
526	/*
527	 * //// USBx2, audio, and modem fixup ////
528	 * - disable USB #0 and #1 (pcib 0x48 and 0x85)
529	 * - disable AC97 audio and MC97 modem (pcib 0x85)
530	 */
531
532	/* pcib: 0x48 - disable USB #0 at function 2 */
533	val = pcicfgread(pcib, 0x48);
534	pcicfgwrite(pcib, 0x48, val | 04);
535
536	/* pcib: 0x85 - disable USB #1 at function 3 */
537	/* pcib: 0x85 - disable AC97/MC97 at function 5/6 */
538	val = pcicfgread(pcib, 0x84);
539	pcicfgwrite(pcib, 0x84, val | 0x1c00);
540
541	/*
542	 * //// fxp fixup ////
543	 * - use PCI pin A line 25 (fxp 0x3d/3c)
544	 */
545	/* 0x3d/3c - PCI pin/line */
546	val = pcicfgread(net, 0x3c) & 0xffff0000;
547	val |= (('A' - '@') << 8) | 25;
548	pcicfgwrite(net, 0x3c, val);
549}
550
551void
552motsetup(struct brdprop *brd)
553{
554
555#ifdef COSNAME
556	brd->consname = CONSNAME;
557#endif
558#ifdef CONSPORT
559	brd->consport = CONSPORT;
560#endif
561#ifdef CONSSPEED
562	brd->consspeed = CONSSPEED;
563#endif
564}
565
566void
567motbrdfix(struct brdprop *brd)
568{
569
570/*
571 * WinBond/Symphony Lab 83C553 with PC87308 "SuperIO"
572 *
573 *	0.11.0	10ad.0565	PCI-ISA bridge
574 *	0.11.1	10ad.0105	IDE (slide)
575 */
576}
577
578void
579motpcifix(struct brdprop *brd)
580{
581	unsigned ide, net, pcib, steer, val;
582	int line;
583
584	pcib = pcimaketag(0, 11, 0);
585	ide  = pcimaketag(0, 11, 1);
586	net  = pcimaketag(0, 15, 0);
587
588	/*
589	 * //// WinBond PIRQ ////
590	 * 0x40 - bit 5 (0x20) indicates PIRQ presense
591	 * 0x60 - PIRQ interrupt routing steer
592	 */
593	if (pcicfgread(pcib, 0x40) & 0x20) {
594		steer = pcicfgread(pcib, 0x60);
595		if ((steer & 0x80808080) == 0x80808080)
596			printf("PIRQ[0-3] disabled\n");
597		else {
598			unsigned i, v = steer;
599			for (i = 0; i < 4; i++, v >>= 8) {
600				if ((v & 0x80) != 0 || (v & 0xf) == 0)
601					continue;
602				printf("PIRQ[%d]=%d\n", i, v & 0xf);
603				}
604			}
605		}
606#if 1
607	/*
608	 * //// IDE fixup -- case A ////
609	 * - "native PCI mode" (ide 0x09)
610	 * - don't use ISA IRQ14/15 (pcib 0x43)
611	 * - native IDE for both channels (ide 0x40)
612	 * - LEGIRQ bit 11 steers interrupt to pin C (ide 0x40)
613	 * - sign as PCI pin C line 11 (ide 0x3d/3c)
614	 */
615	/* ide: 0x09 - programming interface; 1000'SsPp */
616	val = pcicfgread(ide, 0x08);
617	val &= 0xffff00ff;
618	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
619
620	/* pcib: 0x43 - IDE interrupt routing */
621	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
622	pcicfgwrite(pcib, 0x40, val);
623
624	/* pcib: 0x45/44 - PCI interrupt routing */
625	val = pcicfgread(pcib, 0x44) & 0xffff0000;
626	pcicfgwrite(pcib, 0x44, val);
627
628	/* ide: 0x41/40 - IDE channel */
629	val = pcicfgread(ide, 0x40) & 0xffff0000;
630	val |= (1 << 11) | 0x33; /* LEGIRQ turns on PCI interrupt */
631	pcicfgwrite(ide, 0x40, val);
632
633	/* ide: 0x3d/3c - use PCI pin C/line 11 */
634	val = pcicfgread(ide, 0x3c) & 0xffffff00;
635	val |= 11; /* pin designation is hardwired to pin A */
636	pcicfgwrite(ide, 0x3c, val);
637#else
638	/*
639	 * //// IDE fixup -- case B ////
640	 * - "compatiblity mode" (ide 0x09)
641	 * - IDE primary/secondary interrupt routing (pcib 0x43)
642	 * - PCI interrupt routing (pcib 0x45/44)
643	 * - no PCI pin/line assignment (ide 0x3d/3c)
644	 */
645	/* ide: 0x09 - programming interface; 1000'SsPp */
646	val = pcicfgread(ide, 0x08);
647	val &= 0xffff00ff;
648	pcicfgwrite(ide, 0x08, val | (0x8a << 8));
649
650	/* pcib: 0x43 - IDE interrupt routing */
651	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
652	pcicfgwrite(pcib, 0x40, val | (0xee << 24));
653
654	/* ide: 0x45/44 - PCI interrupt routing */
655	val = pcicfgread(ide, 0x44) & 0xffff0000;
656	pcicfgwrite(ide, 0x44, val);
657
658	/* ide: 0x3d/3c - turn off PCI pin/line */
659	val = pcicfgread(ide, 0x3c) & 0xffff0000;
660	pcicfgwrite(ide, 0x3c, val);
661#endif
662
663	/*
664	 * //// fxp fixup ////
665	 * - use PCI pin A line 15 (fxp 0x3d/3c)
666	 */
667	val = pcicfgread(net, 0x3c) & 0xffff0000;
668	pcidecomposetag(net, NULL, &line, NULL);
669	val |= (('A' - '@') << 8) | line;
670	pcicfgwrite(net, 0x3c, val);
671}
672
673void
674kurosetup(struct brdprop *brd)
675{
676
677	if (PCI_VENDOR(pcicfgread(pcimaketag(0, 11, 0), PCI_ID_REG)) == 0x10ec)
678		brd->extclk = 32768000; /* decr 2457600Hz */
679	else
680		brd->extclk = 32521333; /* decr 2439100Hz */
681}
682
683void
684kurobrdfix(struct brdprop *brd)
685{
686
687	init_uart(uart2base, 9600, LCR_8BITS | LCR_PEVEN);
688	/* Stop Watchdog */
689	send_sat("AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK");
690}
691
692void
693kuroreset()
694{
695
696	send_sat("CCGG");
697	/*NOTREACHED*/
698}
699
700void
701synosetup(struct brdprop *brd)
702{
703
704	if (1) /* 200 and 266MHz models */
705		brd->extclk = 33164691; /* from Synology/Linux source */
706	else   /* 400MHz models XXX how to check? */
707		brd->extclk = 33165343;
708}
709
710void
711synobrdfix(struct brdprop *brd)
712{
713
714	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
715	/* beep, power LED on, status LED off */
716	send_sat("247");
717}
718
719void
720synopcifix(struct brdprop *brd)
721{
722	static const char csmodel[4][7] = {
723		"CS406e", "CS406", "RS406", "CS407e"
724	};
725	volatile uint8_t *cpld = (volatile uint8_t *)0xff000000;
726	uint8_t pwrstate;
727
728	if (nata > 1) {
729		/*
730		 * CS/RS stations power-up their disks one after another.
731		 * We have to watch over the current power state in a CPLD
732		 * register, until all disks become available.
733		 */
734		printf("CPLD V1.%d for model %s\n", cpld[2] & 3,
735		    csmodel[(cpld[2] & 0x0c) >> 2]);
736		cpld[0] = 0x00; /* all drive LEDs blinking yellow */
737		do {
738			delay(1000 * 1000);
739			pwrstate = cpld[1];
740			printf("Power state: %02x\r", pwrstate);
741		} while (pwrstate != 0xff);
742		putchar('\n');
743	}
744}
745
746void
747synolaunch(struct brdprop *brd)
748{
749	volatile uint8_t *cpld = (volatile uint8_t *)0xff000000;
750	struct dkdev_ata *sata1, *sata2;
751
752	if (nata > 1) {
753		/* enable drive LEDs for active disk drives on CS/RS models */
754		sata1 = lata[0].drv;
755		sata2 = lata[1].drv;
756		cpld[0] = (sata1->presense[0] ? 0x80 : 0xc0) |
757		    (sata1->presense[1] ? 0x20 : 0x30) |
758		    (sata2->presense[0] ? 0x08 : 0x0c) |
759		    (sata2->presense[1] ? 0x02 : 0x03);
760	}
761}
762
763void
764synoreset()
765{
766
767	send_sat("C");
768	/*NOTREACHED*/
769}
770
771void
772qnapbrdfix(struct brdprop *brd)
773{
774
775	init_uart(uart2base, 19200, LCR_8BITS | LCR_PNONE);
776	/* beep, status LED red */
777	send_sat("PW");
778}
779
780void
781qnapreset()
782{
783
784	send_sat("f");
785	/*NOTREACHED*/
786}
787
788void
789iomegabrdfix(struct brdprop *brd)
790{
791
792	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
793	/* LED flashing blue, fan auto, turn on at 50C, turn off at 45C */
794	send_iomega('b', 'd', 2, 'a', 50, 45);
795}
796
797void
798iomegareset()
799{
800
801	send_iomega('g', 0, 0, 0, 0, 0);
802	/*NOTREACHED*/
803}
804
805void
806dlinkbrdfix(struct brdprop *brd)
807{
808
809	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
810	send_sat("SYN\n");
811	send_sat("ZWO\n");	/* power LED solid on */
812}
813
814void
815nhnasbrdfix(struct brdprop *brd)
816{
817
818	/* status LED off, USB-LEDs on, low-speed fan */
819	NHGPIO_WRITE(0x04);
820}
821
822void
823nhnasreset()
824{
825
826	/* status LED on, assert system-reset to all devices */
827	NHGPIO_WRITE(0x02);
828	delay(100000);
829	/*NOTREACHED*/
830}
831
832void
833kurot4brdfix(struct brdprop *brd)
834{
835
836	init_uart(uart2base, 38400, LCR_8BITS | LCR_PEVEN);
837}
838
839void
840_rtt(void)
841{
842	uint32_t msr;
843
844	netif_shutdown_all();
845
846	if (brdprop->reset != NULL)
847		(*brdprop->reset)();
848	else {
849		msr = mfmsr();
850		msr &= ~PSL_EE;
851		mtmsr(msr);
852		asm volatile ("sync; isync");
853		asm volatile("mtspr %0,%1" : : "K"(81), "r"(0));
854		msr &= ~(PSL_ME | PSL_DR | PSL_IR);
855		mtmsr(msr);
856		asm volatile ("sync; isync");
857		run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */
858	}
859	/*NOTREACHED*/
860}
861
862satime_t
863getsecs(void)
864{
865	u_quad_t tb = mftb();
866
867	return (tb / ticks_per_sec);
868}
869
870/*
871 * Wait for about n microseconds (at least!).
872 */
873void
874delay(u_int n)
875{
876	u_quad_t tb;
877	u_long scratch, tbh, tbl;
878
879	tb = mftb();
880	tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
881	tbh = tb >> 32;
882	tbl = tb;
883	asm volatile ("1: mftbu %0; cmpw %0,%1; blt 1b; bgt 2f; mftb %0; cmpw 0, %0,%2; blt 1b; 2:" : "=&r"(scratch) : "r"(tbh), "r"(tbl));
884}
885
886void
887_wb(uint32_t adr, uint32_t siz)
888{
889	uint32_t bnd;
890
891	asm volatile("eieio");
892	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
893		asm volatile ("dcbst 0,%0" :: "r"(adr));
894	asm volatile ("sync");
895}
896
897void
898_wbinv(uint32_t adr, uint32_t siz)
899{
900	uint32_t bnd;
901
902	asm volatile("eieio");
903	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
904		asm volatile ("dcbf 0,%0" :: "r"(adr));
905	asm volatile ("sync");
906}
907
908void
909_inv(uint32_t adr, uint32_t siz)
910{
911	uint32_t bnd, off;
912
913	off = adr & (dcache_line_size - 1);
914	adr -= off;
915	siz += off;
916	asm volatile ("eieio");
917	if (off != 0) {
918		/* wbinv() leading unaligned dcache line */
919		asm volatile ("dcbf 0,%0" :: "r"(adr));
920		if (siz < dcache_line_size)
921			goto done;
922		adr += dcache_line_size;
923		siz -= dcache_line_size;
924	}
925	bnd = adr + siz;
926	off = bnd & (dcache_line_size - 1);
927	if (off != 0) {
928		/* wbinv() trailing unaligned dcache line */
929		asm volatile ("dcbf 0,%0" :: "r"(bnd)); /* it's OK */
930		if (siz < dcache_line_size)
931			goto done;
932		siz -= off;
933	}
934	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) {
935		/* inv() intermediate dcache lines if ever */
936		asm volatile ("dcbi 0,%0" :: "r"(adr));
937	}
938  done:
939	asm volatile ("sync");
940}
941
942static inline uint32_t
943mfmsr(void)
944{
945	uint32_t msr;
946
947	asm volatile ("mfmsr %0" : "=r"(msr));
948	return msr;
949}
950
951static inline void
952mtmsr(uint32_t msr)
953{
954	asm volatile ("mtmsr %0" : : "r"(msr));
955}
956
957static inline uint32_t
958cputype(void)
959{
960	uint32_t pvr;
961
962	asm volatile ("mfpvr %0" : "=r"(pvr));
963	return pvr >> 16;
964}
965
966static inline u_quad_t
967mftb(void)
968{
969	u_long scratch;
970	u_quad_t tb;
971
972	asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b"
973	    : "=r"(tb), "=r"(scratch));
974	return tb;
975}
976
977static void
978init_uart(unsigned base, unsigned speed, uint8_t lcr)
979{
980	unsigned div;
981
982	div = busclock / speed / 16;
983	UART_WRITE(base, LCR, 0x80);		/* turn on DLAB bit */
984	UART_WRITE(base, FCR, 0x00);
985	UART_WRITE(base, DMB, div >> 8);	/* set speed */
986	UART_WRITE(base, DLB, div & 0xff);
987	UART_WRITE(base, LCR, lcr);
988	UART_WRITE(base, FCR, 0x07);		/* FIFO on, TXRX FIFO reset */
989	UART_WRITE(base, IER, 0x00);		/* make sure INT disabled */
990}
991
992/* talk to satellite processor */
993static void
994send_sat(char *msg)
995{
996	unsigned savedbase;
997
998	savedbase = uart1base;
999	uart1base = uart2base;
1000	while (*msg)
1001		putchar(*msg++);
1002	uart1base = savedbase;
1003}
1004
1005#ifdef DEBUG
1006static void
1007iomega_debug(const char *txt, uint8_t buf[])
1008{
1009	int i;
1010
1011	printf("%s:", txt);
1012	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
1013		printf(" %02x", buf[i]);
1014	putchar('\n');
1015}
1016#endif /* DEBUG */
1017
1018static void
1019send_iomega(int power, int led, int rate, int fan, int high, int low)
1020{
1021	uint8_t buf[IOMEGA_PACKETSIZE];
1022	unsigned i, savedbase;
1023
1024	savedbase = uart1base;
1025	uart1base = uart2base;
1026
1027	/* first flush the receive buffer */
1028  again:
1029	while (tstchar())
1030		(void)getchar();
1031	delay(20000);
1032	if (tstchar())
1033		goto again;
1034	/*
1035	 * Now synchronize the transmitter by sending 0x00
1036	 * until we receive a status reply.
1037	 */
1038	do {
1039		putchar(0);
1040		delay(50000);
1041	} while (!tstchar());
1042
1043	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
1044		buf[i] = getchar();
1045#ifdef DEBUG
1046	uart1base = savedbase;
1047	iomega_debug("68HC908 status", buf);
1048	uart1base = uart2base;
1049#endif
1050
1051	/* send command */
1052	buf[IOMEGA_POWER] = power;
1053	buf[IOMEGA_LED] = led;
1054	buf[IOMEGA_FLASH_RATE] = rate;
1055	buf[IOMEGA_FAN] = fan;
1056	buf[IOMEGA_HIGH_TEMP] = high;
1057	buf[IOMEGA_LOW_TEMP] = low;
1058	buf[IOMEGA_ID] = 7;	/* host id */
1059	buf[IOMEGA_CHECKSUM] = (buf[IOMEGA_POWER] + buf[IOMEGA_LED] +
1060	    buf[IOMEGA_FLASH_RATE] + buf[IOMEGA_FAN] +
1061	    buf[IOMEGA_HIGH_TEMP] + buf[IOMEGA_LOW_TEMP] +
1062	    buf[IOMEGA_ID]) & 0x7f;
1063#ifdef DEBUG
1064	uart1base = savedbase;
1065	iomega_debug("G2 sending", buf);
1066	uart1base = uart2base;
1067#endif
1068	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
1069		putchar(buf[i]);
1070
1071	/* receive the reply */
1072	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
1073		buf[i] = getchar();
1074#ifdef DEBUG
1075	uart1base = savedbase;
1076	iomega_debug("68HC908 reply", buf);
1077	uart1base = uart2base;
1078#endif
1079
1080	if (buf[0] == '#')
1081		goto again;  /* try again on error */
1082	uart1base = savedbase;
1083}
1084
1085void
1086putchar(int c)
1087{
1088	unsigned timo, lsr;
1089
1090	if (c == '\n')
1091		putchar('\r');
1092
1093	timo = 0x00100000;
1094	do {
1095		lsr = UART_READ(uart1base, LSR);
1096	} while (timo-- > 0 && (lsr & LSR_THRE) == 0);
1097	if (timo > 0)
1098		UART_WRITE(uart1base, THR, c);
1099}
1100
1101int
1102getchar(void)
1103{
1104	unsigned lsr;
1105
1106	do {
1107		lsr = UART_READ(uart1base, LSR);
1108	} while ((lsr & LSR_DRDY) == 0);
1109	return UART_READ(uart1base, RBR);
1110}
1111
1112int
1113tstchar(void)
1114{
1115
1116	return (UART_READ(uart1base, LSR) & LSR_DRDY) != 0;
1117}
1118
1119#define SAR_MASK 0x0ff00000
1120#define SAR_SHIFT    20
1121#define EAR_MASK 0x30000000
1122#define EAR_SHIFT    28
1123#define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s))
1124#define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s))
1125static void
1126set_mem_bounds(unsigned tag, unsigned bk_en, ...)
1127{
1128	unsigned mbst, mbxst, mben, mbxen;
1129	unsigned start, end;
1130	va_list ap;
1131	int i, sh;
1132
1133	va_start(ap, bk_en);
1134	mbst = mbxst = mben = mbxen = 0;
1135
1136	for (i = 0; i < 4; i++) {
1137		if ((bk_en & (1U << i)) != 0) {
1138			start = va_arg(ap, unsigned);
1139			end = va_arg(ap, unsigned);
1140		} else {
1141			start = 0x3ff00000;
1142			end = 0x3fffffff;
1143		}
1144		sh = i << 3;
1145		mbst |= AR(start, sh);
1146		mbxst |= XR(start, sh);
1147		mben |= AR(end, sh);
1148		mbxen |= XR(end, sh);
1149	}
1150	va_end(ap);
1151
1152	pcicfgwrite(tag, MPC106_MEMSTARTADDR1, mbst);
1153	pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, mbxst);
1154	pcicfgwrite(tag, MPC106_MEMENDADDR1, mben);
1155	pcicfgwrite(tag, MPC106_EXTMEMENDADDR1,	mbxen);
1156	pcicfgwrite(tag, MPC106_MEMEN,
1157	    (pcicfgread(tag, MPC106_MEMEN) & ~0xff) | (bk_en & 0xff));
1158}
1159
1160static unsigned
1161mpc107memsize(void)
1162{
1163	unsigned bankn, end, n, tag, val;
1164
1165	tag = pcimaketag(0, 0, 0);
1166
1167	if (brdtype == BRD_ENCOREPP1) {
1168		/* the brd's PPCBOOT looks to have erroneous values */
1169		set_mem_bounds(tag, 1, 0x00000000, (128 << 20) - 1);
1170	} else if (brdtype == BRD_NH230NAS) {
1171		/*
1172		 * PPCBoot sets the end address to 0x7ffffff, although the
1173		 * board has just 64MB (0x3ffffff).
1174		 */
1175		set_mem_bounds(tag, 1, 0x00000000, 0x03ffffff);
1176	}
1177
1178	bankn = 0;
1179	val = pcicfgread(tag, MPC106_MEMEN);
1180	for (n = 0; n < 4; n++) {
1181		if ((val & (1U << n)) == 0)
1182			break;
1183		bankn = n;
1184	}
1185	bankn <<= 3;
1186
1187	val = pcicfgread(tag, MPC106_EXTMEMENDADDR1);
1188	end =  ((val >> bankn) & 0x03) << 28;
1189	val = pcicfgread(tag, MPC106_MEMENDADDR1);
1190	end |= ((val >> bankn) & 0xff) << 20;
1191	end |= 0xfffff;
1192
1193	return (end + 1); /* assume the end address matches total amount */
1194}
1195
1196struct fis_dir_entry {
1197	char		name[16];
1198	uint32_t	startaddr;
1199	uint32_t	loadaddr;
1200	uint32_t	flashsize;
1201	uint32_t	entryaddr;
1202	uint32_t	filesize;
1203	char		pad[256 - (16 + 5 * sizeof(uint32_t))];
1204};
1205
1206#define FIS_LOWER_LIMIT	0xfff00000
1207
1208/*
1209 * Look for a Redboot-style Flash Image System FIS-directory and
1210 * return a pointer to the start address of the requested file.
1211 */
1212static void *
1213redboot_fis_lookup(const char *filename)
1214{
1215	static const char FISdirname[16] = {
1216	    'F', 'I', 'S', ' ',
1217	    'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0
1218	};
1219	struct fis_dir_entry *dir;
1220
1221	/*
1222	 * The FIS directory is usually in the last sector of the flash.
1223	 * But we do not know the sector size (erase size), so start
1224	 * at 0xffffff00 and scan backwards in steps of the FIS directory
1225	 * entry size (0x100).
1226	 */
1227	for (dir = (struct fis_dir_entry *)0xffffff00;
1228	    (uint32_t)dir >= FIS_LOWER_LIMIT; dir--)
1229		if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0)
1230			break;
1231	if ((uint32_t)dir < FIS_LOWER_LIMIT) {
1232		printf("No FIS directory found!\n");
1233		return NULL;
1234	}
1235
1236	/* Now find filename by scanning the directory from beginning. */
1237	dir = (struct fis_dir_entry *)dir->startaddr;
1238	while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) {
1239		if (strcmp(dir->name, filename) == 0)
1240			return (void *)dir->startaddr;	/* found */
1241		dir++;
1242	}
1243	printf("\"%s\" not found in FIS directory!\n", filename);
1244	return NULL;
1245}
1246
1247static void
1248read_mac_string(uint8_t *mac, char *p)
1249{
1250	int i;
1251
1252	for (i = 0; i < 6; i++, p += 3)
1253		*mac++ = read_hex(p);
1254}
1255
1256/*
1257 * For cost saving reasons some NAS boxes lack SEEPROM for NIC's
1258 * ethernet address and keep it in their Flash memory instead.
1259 */
1260void
1261read_mac_from_flash(uint8_t *mac)
1262{
1263	uint8_t *p;
1264
1265	switch (brdtype) {
1266	case BRD_SYNOLOGY:
1267		p = redboot_fis_lookup("vendor");
1268		if (p == NULL)
1269			break;
1270		memcpy(mac, p, 6);
1271		return;
1272	case BRD_DLINKDSM:
1273		read_mac_string(mac, (char *)0xfff0ff80);
1274		return;
1275	default:
1276		printf("Warning: This board has no known method defined "
1277		    "to determine its MAC address!\n");
1278		break;
1279	}
1280
1281	/* set to 00:00:00:00:00:00 in case of error */
1282	memset(mac, 0, 6);
1283}
1284
1285#ifdef DEBUG
1286void
1287sat_write(char *p, int len)
1288{
1289	unsigned savedbase;
1290
1291	savedbase = uart1base;
1292	uart1base = uart2base;
1293	while (len--)
1294		putchar(*p++);
1295	uart1base = savedbase;
1296}
1297
1298int
1299sat_getch(void)
1300{
1301	unsigned lsr;
1302
1303	do {
1304		lsr = UART_READ(uart2base, LSR);
1305	} while ((lsr & LSR_DRDY) == 0);
1306	return UART_READ(uart2base, RBR);
1307}
1308
1309int
1310sat_tstch(void)
1311{
1312
1313	return (UART_READ(uart2base, LSR) & LSR_DRDY) != 0;
1314}
1315#endif /* DEBUG */
1316