brdsetup.c revision 1.34
1/* $NetBSD: brdsetup.c,v 1.34 2014/08/05 17:55:20 joerg 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), "%s", 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), "%s", 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	(void) pcicfgread(ide, 0x08);
451	(void) pcicfgread(pmgt, 0x08);
452}
453
454void
455encpcifix(struct brdprop *brd)
456{
457	unsigned ide, irq, net, pcib, steer, val;
458
459#define	STEER(v, b) (((v) & (b)) ? "edge" : "level")
460	pcib = pcimaketag(0, 22, 0);
461	ide  = pcimaketag(0, 22, 1);
462	net  = pcimaketag(0, 25, 0);
463
464	/*
465	 * //// VIA PIRQ ////
466	 * 0x57/56/55/54 - Dx CB Ax xS
467	 */
468	val = pcicfgread(pcib, 0x54);	/* Dx CB Ax xs */
469	steer = val & 0xf;
470	irq = (val >> 12) & 0xf;	/* 15:12 */
471	if (irq) {
472		printf("pin A -> irq %d, %s\n",
473			irq, STEER(steer, 0x1));
474	}
475	irq = (val >> 16) & 0xf;	/* 19:16 */
476	if (irq) {
477		printf("pin B -> irq %d, %s\n",
478			irq, STEER(steer, 0x2));
479	}
480	irq = (val >> 20) & 0xf;	/* 23:20 */
481	if (irq) {
482		printf("pin C -> irq %d, %s\n",
483			irq, STEER(steer, 0x4));
484	}
485	irq = (val >> 28);		/* 31:28 */
486	if (irq) {
487		printf("pin D -> irq %d, %s\n",
488			irq, STEER(steer, 0x8));
489	}
490#if 0
491	/*
492	 * //// IDE fixup ////
493	 * - "native mode" (ide 0x09)
494	 */
495
496	/* ide: 0x09 - programming interface; 1000'SsPp */
497	val = pcicfgread(ide, 0x08) & 0xffff00ff;
498	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
499
500	/* ide: 0x10-20 - leave them PCI memory space assigned */
501#else
502	/*
503	 * //// IDE fixup ////
504	 * - "compatiblity mode" (ide 0x09)
505	 * - remove PCI pin assignment (ide 0x3d)
506	 */
507
508	/* ide: 0x09 - programming interface; 1000'SsPp */
509	val = pcicfgread(ide, 0x08) & 0xffff00ff;
510	val |= (0x8a << 8);
511	pcicfgwrite(ide, 0x08, val);
512
513	/* ide: 0x10-20 */
514	/*
515	 * experiment shows writing ide: 0x09 changes these
516	 * register behaviour. The pcicfgwrite() above writes
517	 * 0x8a at ide: 0x09 to make sure legacy IDE.  Then
518	 * reading BAR0-3 is to return value 0s even though
519	 * pcisetup() has written range assignments.  Value
520	 * overwrite makes no effect. Having 0x8f for native
521	 * PCIIDE doesn't change register values and brings no
522	 * weirdness.
523	 */
524
525	/* ide: 0x3d/3c - turn off PCI pin */
526	val = pcicfgread(ide, 0x3c) & 0xffff00ff;
527	pcicfgwrite(ide, 0x3c, val);
528#endif
529	/*
530	 * //// USBx2, audio, and modem fixup ////
531	 * - disable USB #0 and #1 (pcib 0x48 and 0x85)
532	 * - disable AC97 audio and MC97 modem (pcib 0x85)
533	 */
534
535	/* pcib: 0x48 - disable USB #0 at function 2 */
536	val = pcicfgread(pcib, 0x48);
537	pcicfgwrite(pcib, 0x48, val | 04);
538
539	/* pcib: 0x85 - disable USB #1 at function 3 */
540	/* pcib: 0x85 - disable AC97/MC97 at function 5/6 */
541	val = pcicfgread(pcib, 0x84);
542	pcicfgwrite(pcib, 0x84, val | 0x1c00);
543
544	/*
545	 * //// fxp fixup ////
546	 * - use PCI pin A line 25 (fxp 0x3d/3c)
547	 */
548	/* 0x3d/3c - PCI pin/line */
549	val = pcicfgread(net, 0x3c) & 0xffff0000;
550	val |= (('A' - '@') << 8) | 25;
551	pcicfgwrite(net, 0x3c, val);
552}
553
554void
555motsetup(struct brdprop *brd)
556{
557
558#ifdef COSNAME
559	brd->consname = CONSNAME;
560#endif
561#ifdef CONSPORT
562	brd->consport = CONSPORT;
563#endif
564#ifdef CONSSPEED
565	brd->consspeed = CONSSPEED;
566#endif
567}
568
569void
570motbrdfix(struct brdprop *brd)
571{
572
573/*
574 * WinBond/Symphony Lab 83C553 with PC87308 "SuperIO"
575 *
576 *	0.11.0	10ad.0565	PCI-ISA bridge
577 *	0.11.1	10ad.0105	IDE (slide)
578 */
579}
580
581void
582motpcifix(struct brdprop *brd)
583{
584	unsigned ide, net, pcib, steer, val;
585	int line;
586
587	pcib = pcimaketag(0, 11, 0);
588	ide  = pcimaketag(0, 11, 1);
589	net  = pcimaketag(0, 15, 0);
590
591	/*
592	 * //// WinBond PIRQ ////
593	 * 0x40 - bit 5 (0x20) indicates PIRQ presense
594	 * 0x60 - PIRQ interrupt routing steer
595	 */
596	if (pcicfgread(pcib, 0x40) & 0x20) {
597		steer = pcicfgread(pcib, 0x60);
598		if ((steer & 0x80808080) == 0x80808080)
599			printf("PIRQ[0-3] disabled\n");
600		else {
601			unsigned i, v = steer;
602			for (i = 0; i < 4; i++, v >>= 8) {
603				if ((v & 0x80) != 0 || (v & 0xf) == 0)
604					continue;
605				printf("PIRQ[%d]=%d\n", i, v & 0xf);
606				}
607			}
608		}
609#if 1
610	/*
611	 * //// IDE fixup -- case A ////
612	 * - "native PCI mode" (ide 0x09)
613	 * - don't use ISA IRQ14/15 (pcib 0x43)
614	 * - native IDE for both channels (ide 0x40)
615	 * - LEGIRQ bit 11 steers interrupt to pin C (ide 0x40)
616	 * - sign as PCI pin C line 11 (ide 0x3d/3c)
617	 */
618	/* ide: 0x09 - programming interface; 1000'SsPp */
619	val = pcicfgread(ide, 0x08);
620	val &= 0xffff00ff;
621	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
622
623	/* pcib: 0x43 - IDE interrupt routing */
624	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
625	pcicfgwrite(pcib, 0x40, val);
626
627	/* pcib: 0x45/44 - PCI interrupt routing */
628	val = pcicfgread(pcib, 0x44) & 0xffff0000;
629	pcicfgwrite(pcib, 0x44, val);
630
631	/* ide: 0x41/40 - IDE channel */
632	val = pcicfgread(ide, 0x40) & 0xffff0000;
633	val |= (1 << 11) | 0x33; /* LEGIRQ turns on PCI interrupt */
634	pcicfgwrite(ide, 0x40, val);
635
636	/* ide: 0x3d/3c - use PCI pin C/line 11 */
637	val = pcicfgread(ide, 0x3c) & 0xffffff00;
638	val |= 11; /* pin designation is hardwired to pin A */
639	pcicfgwrite(ide, 0x3c, val);
640#else
641	/*
642	 * //// IDE fixup -- case B ////
643	 * - "compatiblity mode" (ide 0x09)
644	 * - IDE primary/secondary interrupt routing (pcib 0x43)
645	 * - PCI interrupt routing (pcib 0x45/44)
646	 * - no PCI pin/line assignment (ide 0x3d/3c)
647	 */
648	/* ide: 0x09 - programming interface; 1000'SsPp */
649	val = pcicfgread(ide, 0x08);
650	val &= 0xffff00ff;
651	pcicfgwrite(ide, 0x08, val | (0x8a << 8));
652
653	/* pcib: 0x43 - IDE interrupt routing */
654	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
655	pcicfgwrite(pcib, 0x40, val | (0xee << 24));
656
657	/* ide: 0x45/44 - PCI interrupt routing */
658	val = pcicfgread(ide, 0x44) & 0xffff0000;
659	pcicfgwrite(ide, 0x44, val);
660
661	/* ide: 0x3d/3c - turn off PCI pin/line */
662	val = pcicfgread(ide, 0x3c) & 0xffff0000;
663	pcicfgwrite(ide, 0x3c, val);
664#endif
665
666	/*
667	 * //// fxp fixup ////
668	 * - use PCI pin A line 15 (fxp 0x3d/3c)
669	 */
670	val = pcicfgread(net, 0x3c) & 0xffff0000;
671	pcidecomposetag(net, NULL, &line, NULL);
672	val |= (('A' - '@') << 8) | line;
673	pcicfgwrite(net, 0x3c, val);
674}
675
676void
677kurosetup(struct brdprop *brd)
678{
679
680	if (PCI_VENDOR(pcicfgread(pcimaketag(0, 11, 0), PCI_ID_REG)) == 0x10ec)
681		brd->extclk = 32768000; /* decr 2457600Hz */
682	else
683		brd->extclk = 32521333; /* decr 2439100Hz */
684}
685
686void
687kurobrdfix(struct brdprop *brd)
688{
689
690	init_uart(uart2base, 9600, LCR_8BITS | LCR_PEVEN);
691	/* Stop Watchdog */
692	send_sat("AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK");
693}
694
695void
696kuroreset()
697{
698
699	send_sat("CCGG");
700	/*NOTREACHED*/
701}
702
703void
704synosetup(struct brdprop *brd)
705{
706
707	if (1) /* 200 and 266MHz models */
708		brd->extclk = 33164691; /* from Synology/Linux source */
709	else   /* 400MHz models XXX how to check? */
710		brd->extclk = 33165343;
711}
712
713void
714synobrdfix(struct brdprop *brd)
715{
716
717	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
718	/* beep, power LED on, status LED off */
719	send_sat("247");
720}
721
722void
723synopcifix(struct brdprop *brd)
724{
725	static const char csmodel[4][7] = {
726		"CS406e", "CS406", "RS406", "CS407e"
727	};
728	volatile uint8_t *cpld = (volatile uint8_t *)0xff000000;
729	uint8_t pwrstate;
730
731	if (nata > 1) {
732		/*
733		 * CS/RS stations power-up their disks one after another.
734		 * We have to watch over the current power state in a CPLD
735		 * register, until all disks become available.
736		 */
737		printf("CPLD V1.%d for model %s\n", cpld[2] & 3,
738		    csmodel[(cpld[2] & 0x0c) >> 2]);
739		cpld[0] = 0x00; /* all drive LEDs blinking yellow */
740		do {
741			delay(1000 * 1000);
742			pwrstate = cpld[1];
743			printf("Power state: %02x\r", pwrstate);
744		} while (pwrstate != 0xff);
745		putchar('\n');
746	}
747}
748
749void
750synolaunch(struct brdprop *brd)
751{
752	volatile uint8_t *cpld = (volatile uint8_t *)0xff000000;
753	struct dkdev_ata *sata1, *sata2;
754
755	if (nata > 1) {
756		/* enable drive LEDs for active disk drives on CS/RS models */
757		sata1 = lata[0].drv;
758		sata2 = lata[1].drv;
759		cpld[0] = (sata1->presense[0] ? 0x80 : 0xc0) |
760		    (sata1->presense[1] ? 0x20 : 0x30) |
761		    (sata2->presense[0] ? 0x08 : 0x0c) |
762		    (sata2->presense[1] ? 0x02 : 0x03);
763	}
764}
765
766void
767synoreset()
768{
769
770	send_sat("C");
771	/*NOTREACHED*/
772}
773
774void
775qnapbrdfix(struct brdprop *brd)
776{
777
778	init_uart(uart2base, 19200, LCR_8BITS | LCR_PNONE);
779	/* beep, status LED red */
780	send_sat("PW");
781}
782
783void
784qnapreset()
785{
786
787	send_sat("f");
788	/*NOTREACHED*/
789}
790
791void
792iomegabrdfix(struct brdprop *brd)
793{
794
795	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
796	/* LED flashing blue, fan auto, turn on at 50C, turn off at 45C */
797	send_iomega('b', 'd', 2, 'a', 50, 45);
798}
799
800void
801iomegareset()
802{
803
804	send_iomega('g', 0, 0, 0, 0, 0);
805	/*NOTREACHED*/
806}
807
808void
809dlinkbrdfix(struct brdprop *brd)
810{
811
812	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
813	send_sat("SYN\n");
814	send_sat("ZWO\n");	/* power LED solid on */
815}
816
817void
818nhnasbrdfix(struct brdprop *brd)
819{
820
821	/* status LED off, USB-LEDs on, low-speed fan */
822	NHGPIO_WRITE(0x04);
823}
824
825void
826nhnasreset()
827{
828
829	/* status LED on, assert system-reset to all devices */
830	NHGPIO_WRITE(0x02);
831	delay(100000);
832	/*NOTREACHED*/
833}
834
835void
836kurot4brdfix(struct brdprop *brd)
837{
838
839	init_uart(uart2base, 38400, LCR_8BITS | LCR_PEVEN);
840}
841
842void
843_rtt(void)
844{
845	uint32_t msr;
846
847	netif_shutdown_all();
848
849	if (brdprop->reset != NULL)
850		(*brdprop->reset)();
851	else {
852		msr = mfmsr();
853		msr &= ~PSL_EE;
854		mtmsr(msr);
855		asm volatile ("sync; isync");
856		asm volatile("mtspr %0,%1" : : "K"(81), "r"(0));
857		msr &= ~(PSL_ME | PSL_DR | PSL_IR);
858		mtmsr(msr);
859		asm volatile ("sync; isync");
860		run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */
861	}
862	/*NOTREACHED*/
863}
864
865satime_t
866getsecs(void)
867{
868	u_quad_t tb = mftb();
869
870	return (tb / ticks_per_sec);
871}
872
873/*
874 * Wait for about n microseconds (at least!).
875 */
876void
877delay(u_int n)
878{
879	u_quad_t tb;
880	u_long scratch, tbh, tbl;
881
882	tb = mftb();
883	tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
884	tbh = tb >> 32;
885	tbl = tb;
886	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));
887}
888
889void
890_wb(uint32_t adr, uint32_t siz)
891{
892	uint32_t bnd;
893
894	asm volatile("eieio");
895	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
896		asm volatile ("dcbst 0,%0" :: "r"(adr));
897	asm volatile ("sync");
898}
899
900void
901_wbinv(uint32_t adr, uint32_t siz)
902{
903	uint32_t bnd;
904
905	asm volatile("eieio");
906	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
907		asm volatile ("dcbf 0,%0" :: "r"(adr));
908	asm volatile ("sync");
909}
910
911void
912_inv(uint32_t adr, uint32_t siz)
913{
914	uint32_t bnd, off;
915
916	off = adr & (dcache_line_size - 1);
917	adr -= off;
918	siz += off;
919	asm volatile ("eieio");
920	if (off != 0) {
921		/* wbinv() leading unaligned dcache line */
922		asm volatile ("dcbf 0,%0" :: "r"(adr));
923		if (siz < dcache_line_size)
924			goto done;
925		adr += dcache_line_size;
926		siz -= dcache_line_size;
927	}
928	bnd = adr + siz;
929	off = bnd & (dcache_line_size - 1);
930	if (off != 0) {
931		/* wbinv() trailing unaligned dcache line */
932		asm volatile ("dcbf 0,%0" :: "r"(bnd)); /* it's OK */
933		if (siz < dcache_line_size)
934			goto done;
935		siz -= off;
936	}
937	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) {
938		/* inv() intermediate dcache lines if ever */
939		asm volatile ("dcbi 0,%0" :: "r"(adr));
940	}
941  done:
942	asm volatile ("sync");
943}
944
945static inline uint32_t
946mfmsr(void)
947{
948	uint32_t msr;
949
950	asm volatile ("mfmsr %0" : "=r"(msr));
951	return msr;
952}
953
954static inline void
955mtmsr(uint32_t msr)
956{
957	asm volatile ("mtmsr %0" : : "r"(msr));
958}
959
960static inline uint32_t
961cputype(void)
962{
963	uint32_t pvr;
964
965	asm volatile ("mfpvr %0" : "=r"(pvr));
966	return pvr >> 16;
967}
968
969static inline u_quad_t
970mftb(void)
971{
972	u_long scratch;
973	u_quad_t tb;
974
975	asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b"
976	    : "=r"(tb), "=r"(scratch));
977	return tb;
978}
979
980static void
981init_uart(unsigned base, unsigned speed, uint8_t lcr)
982{
983	unsigned div;
984
985	div = busclock / speed / 16;
986	UART_WRITE(base, LCR, 0x80);		/* turn on DLAB bit */
987	UART_WRITE(base, FCR, 0x00);
988	UART_WRITE(base, DMB, div >> 8);	/* set speed */
989	UART_WRITE(base, DLB, div & 0xff);
990	UART_WRITE(base, LCR, lcr);
991	UART_WRITE(base, FCR, 0x07);		/* FIFO on, TXRX FIFO reset */
992	UART_WRITE(base, IER, 0x00);		/* make sure INT disabled */
993}
994
995/* talk to satellite processor */
996static void
997send_sat(char *msg)
998{
999	unsigned savedbase;
1000
1001	savedbase = uart1base;
1002	uart1base = uart2base;
1003	while (*msg)
1004		putchar(*msg++);
1005	uart1base = savedbase;
1006}
1007
1008#ifdef DEBUG
1009static void
1010iomega_debug(const char *txt, uint8_t buf[])
1011{
1012	int i;
1013
1014	printf("%s:", txt);
1015	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
1016		printf(" %02x", buf[i]);
1017	putchar('\n');
1018}
1019#endif /* DEBUG */
1020
1021static void
1022send_iomega(int power, int led, int rate, int fan, int high, int low)
1023{
1024	uint8_t buf[IOMEGA_PACKETSIZE];
1025	unsigned i, savedbase;
1026
1027	savedbase = uart1base;
1028	uart1base = uart2base;
1029
1030	/* first flush the receive buffer */
1031  again:
1032	while (tstchar())
1033		(void)getchar();
1034	delay(20000);
1035	if (tstchar())
1036		goto again;
1037	/*
1038	 * Now synchronize the transmitter by sending 0x00
1039	 * until we receive a status reply.
1040	 */
1041	do {
1042		putchar(0);
1043		delay(50000);
1044	} while (!tstchar());
1045
1046	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
1047		buf[i] = getchar();
1048#ifdef DEBUG
1049	uart1base = savedbase;
1050	iomega_debug("68HC908 status", buf);
1051	uart1base = uart2base;
1052#endif
1053
1054	/* send command */
1055	buf[IOMEGA_POWER] = power;
1056	buf[IOMEGA_LED] = led;
1057	buf[IOMEGA_FLASH_RATE] = rate;
1058	buf[IOMEGA_FAN] = fan;
1059	buf[IOMEGA_HIGH_TEMP] = high;
1060	buf[IOMEGA_LOW_TEMP] = low;
1061	buf[IOMEGA_ID] = 7;	/* host id */
1062	buf[IOMEGA_CHECKSUM] = (buf[IOMEGA_POWER] + buf[IOMEGA_LED] +
1063	    buf[IOMEGA_FLASH_RATE] + buf[IOMEGA_FAN] +
1064	    buf[IOMEGA_HIGH_TEMP] + buf[IOMEGA_LOW_TEMP] +
1065	    buf[IOMEGA_ID]) & 0x7f;
1066#ifdef DEBUG
1067	uart1base = savedbase;
1068	iomega_debug("G2 sending", buf);
1069	uart1base = uart2base;
1070#endif
1071	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
1072		putchar(buf[i]);
1073
1074	/* receive the reply */
1075	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
1076		buf[i] = getchar();
1077#ifdef DEBUG
1078	uart1base = savedbase;
1079	iomega_debug("68HC908 reply", buf);
1080	uart1base = uart2base;
1081#endif
1082
1083	if (buf[0] == '#')
1084		goto again;  /* try again on error */
1085	uart1base = savedbase;
1086}
1087
1088void
1089putchar(int c)
1090{
1091	unsigned timo, lsr;
1092
1093	if (c == '\n')
1094		putchar('\r');
1095
1096	timo = 0x00100000;
1097	do {
1098		lsr = UART_READ(uart1base, LSR);
1099	} while (timo-- > 0 && (lsr & LSR_THRE) == 0);
1100	if (timo > 0)
1101		UART_WRITE(uart1base, THR, c);
1102}
1103
1104int
1105getchar(void)
1106{
1107	unsigned lsr;
1108
1109	do {
1110		lsr = UART_READ(uart1base, LSR);
1111	} while ((lsr & LSR_DRDY) == 0);
1112	return UART_READ(uart1base, RBR);
1113}
1114
1115int
1116tstchar(void)
1117{
1118
1119	return (UART_READ(uart1base, LSR) & LSR_DRDY) != 0;
1120}
1121
1122#define SAR_MASK 0x0ff00000
1123#define SAR_SHIFT    20
1124#define EAR_MASK 0x30000000
1125#define EAR_SHIFT    28
1126#define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s))
1127#define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s))
1128static void
1129set_mem_bounds(unsigned tag, unsigned bk_en, ...)
1130{
1131	unsigned mbst, mbxst, mben, mbxen;
1132	unsigned start, end;
1133	va_list ap;
1134	int i, sh;
1135
1136	va_start(ap, bk_en);
1137	mbst = mbxst = mben = mbxen = 0;
1138
1139	for (i = 0; i < 4; i++) {
1140		if ((bk_en & (1U << i)) != 0) {
1141			start = va_arg(ap, unsigned);
1142			end = va_arg(ap, unsigned);
1143		} else {
1144			start = 0x3ff00000;
1145			end = 0x3fffffff;
1146		}
1147		sh = i << 3;
1148		mbst |= AR(start, sh);
1149		mbxst |= XR(start, sh);
1150		mben |= AR(end, sh);
1151		mbxen |= XR(end, sh);
1152	}
1153	va_end(ap);
1154
1155	pcicfgwrite(tag, MPC106_MEMSTARTADDR1, mbst);
1156	pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, mbxst);
1157	pcicfgwrite(tag, MPC106_MEMENDADDR1, mben);
1158	pcicfgwrite(tag, MPC106_EXTMEMENDADDR1,	mbxen);
1159	pcicfgwrite(tag, MPC106_MEMEN,
1160	    (pcicfgread(tag, MPC106_MEMEN) & ~0xff) | (bk_en & 0xff));
1161}
1162
1163static unsigned
1164mpc107memsize(void)
1165{
1166	unsigned bankn, end, n, tag, val;
1167
1168	tag = pcimaketag(0, 0, 0);
1169
1170	if (brdtype == BRD_ENCOREPP1) {
1171		/* the brd's PPCBOOT looks to have erroneous values */
1172		set_mem_bounds(tag, 1, 0x00000000, (128 << 20) - 1);
1173	} else if (brdtype == BRD_NH230NAS) {
1174		/*
1175		 * PPCBoot sets the end address to 0x7ffffff, although the
1176		 * board has just 64MB (0x3ffffff).
1177		 */
1178		set_mem_bounds(tag, 1, 0x00000000, 0x03ffffff);
1179	}
1180
1181	bankn = 0;
1182	val = pcicfgread(tag, MPC106_MEMEN);
1183	for (n = 0; n < 4; n++) {
1184		if ((val & (1U << n)) == 0)
1185			break;
1186		bankn = n;
1187	}
1188	bankn <<= 3;
1189
1190	val = pcicfgread(tag, MPC106_EXTMEMENDADDR1);
1191	end =  ((val >> bankn) & 0x03) << 28;
1192	val = pcicfgread(tag, MPC106_MEMENDADDR1);
1193	end |= ((val >> bankn) & 0xff) << 20;
1194	end |= 0xfffff;
1195
1196	return (end + 1); /* assume the end address matches total amount */
1197}
1198
1199struct fis_dir_entry {
1200	char		name[16];
1201	uint32_t	startaddr;
1202	uint32_t	loadaddr;
1203	uint32_t	flashsize;
1204	uint32_t	entryaddr;
1205	uint32_t	filesize;
1206	char		pad[256 - (16 + 5 * sizeof(uint32_t))];
1207};
1208
1209#define FIS_LOWER_LIMIT	0xfff00000
1210
1211/*
1212 * Look for a Redboot-style Flash Image System FIS-directory and
1213 * return a pointer to the start address of the requested file.
1214 */
1215static void *
1216redboot_fis_lookup(const char *filename)
1217{
1218	static const char FISdirname[16] = {
1219	    'F', 'I', 'S', ' ',
1220	    'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0
1221	};
1222	struct fis_dir_entry *dir;
1223
1224	/*
1225	 * The FIS directory is usually in the last sector of the flash.
1226	 * But we do not know the sector size (erase size), so start
1227	 * at 0xffffff00 and scan backwards in steps of the FIS directory
1228	 * entry size (0x100).
1229	 */
1230	for (dir = (struct fis_dir_entry *)0xffffff00;
1231	    (uint32_t)dir >= FIS_LOWER_LIMIT; dir--)
1232		if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0)
1233			break;
1234	if ((uint32_t)dir < FIS_LOWER_LIMIT) {
1235		printf("No FIS directory found!\n");
1236		return NULL;
1237	}
1238
1239	/* Now find filename by scanning the directory from beginning. */
1240	dir = (struct fis_dir_entry *)dir->startaddr;
1241	while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) {
1242		if (strcmp(dir->name, filename) == 0)
1243			return (void *)dir->startaddr;	/* found */
1244		dir++;
1245	}
1246	printf("\"%s\" not found in FIS directory!\n", filename);
1247	return NULL;
1248}
1249
1250static void
1251read_mac_string(uint8_t *mac, char *p)
1252{
1253	int i;
1254
1255	for (i = 0; i < 6; i++, p += 3)
1256		*mac++ = read_hex(p);
1257}
1258
1259/*
1260 * Scan through the Flash memory and look for a string starting at 512 bytes
1261 * block boundaries, matching the format: xx:xx:xx:xx:xx:xx<NUL>, where "x"
1262 * are hexadecimal digits.
1263 * Read the first match as our MAC address.
1264 * The start address of the search, p, *must* be dividable by 512!
1265 * Return false when no suitable MAC string was found.
1266 */
1267static int
1268find_mac_string(uint8_t *mac, char *p)
1269{
1270	int i;
1271
1272	for (;;) {
1273		for (i = 0; i < 3 * 6; i += 3) {
1274			if (!isxdigit((unsigned)p[i]) ||
1275			    !isxdigit((unsigned)p[i + 1]))
1276				break;
1277			if ((i < 5 && p[i + 2] != ':') ||
1278			    (i >= 5 && p[i + 2] != '\0'))
1279				break;
1280		}
1281		if (i >= 6) {
1282			/* found a valid MAC address */
1283			read_mac_string(mac, p);
1284			return 1;
1285		}
1286		if (p >= (char *)0xfffffe00)
1287			break;
1288		p += 0x200;
1289	}
1290	return 0;
1291}
1292
1293
1294/*
1295 * For cost saving reasons some NAS boxes lack SEEPROM for NIC's
1296 * ethernet address and keep it in their Flash memory instead.
1297 */
1298void
1299read_mac_from_flash(uint8_t *mac)
1300{
1301	uint8_t *p;
1302
1303	switch (brdtype) {
1304	case BRD_SYNOLOGY:
1305		p = redboot_fis_lookup("vendor");
1306		if (p == NULL)
1307			break;
1308		memcpy(mac, p, 6);
1309		return;
1310	case BRD_DLINKDSM:
1311		read_mac_string(mac, (char *)0xfff0ff80);
1312		return;
1313	case BRD_QNAPTS:
1314		if (find_mac_string(mac, (char *)0xfff00000))
1315			return;
1316		break;
1317	default:
1318		printf("Warning: This board has no known method defined "
1319		    "to determine its MAC address!\n");
1320		break;
1321	}
1322
1323	/* set to 00:00:00:00:00:00 in case of error */
1324	memset(mac, 0, 6);
1325}
1326
1327#ifdef DEBUG
1328void
1329sat_write(char *p, int len)
1330{
1331	unsigned savedbase;
1332
1333	savedbase = uart1base;
1334	uart1base = uart2base;
1335	while (len--)
1336		putchar(*p++);
1337	uart1base = savedbase;
1338}
1339
1340int
1341sat_getch(void)
1342{
1343	unsigned lsr;
1344
1345	do {
1346		lsr = UART_READ(uart2base, LSR);
1347	} while ((lsr & LSR_DRDY) == 0);
1348	return UART_READ(uart2base, RBR);
1349}
1350
1351int
1352sat_tstch(void)
1353{
1354
1355	return (UART_READ(uart2base, LSR) & LSR_DRDY) != 0;
1356}
1357#endif /* DEBUG */
1358