Home | History | Annotate | Line # | Download | only in altboot
brdsetup.c revision 1.2
      1 /* $NetBSD: brdsetup.c,v 1.2 2011/02/07 12:45:21 nisimura 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/oea/spr.h>
     35 
     36 #include <lib/libsa/stand.h>
     37 #include <lib/libsa/net.h>
     38 #include <lib/libkern/libkern.h>
     39 
     40 #include <machine/bootinfo.h>
     41 
     42 #include "globals.h"
     43 
     44 #define BRD_DECL(xxx) \
     45     void xxx ## setup(struct brdprop *); \
     46     void xxx ## brdfix(struct brdprop *); \
     47     void xxx ## pcifix(struct brdprop *); \
     48     void xxx ## reset(void)
     49 
     50 BRD_DECL(mot);
     51 BRD_DECL(enc);
     52 BRD_DECL(kuro);
     53 BRD_DECL(syno);
     54 BRD_DECL(qnap);
     55 BRD_DECL(iomega);
     56 
     57 static struct brdprop brdlist[] = {
     58     {
     59 	"sandpoint",
     60 	"Sandpoint X3",
     61 	BRD_SANDPOINTX3,
     62 	0,
     63 	"com", 0x3f8, 115200,
     64 	motsetup, motbrdfix, motpcifix },
     65     {
     66 	"encpp1",
     67 	"EnCore PP1",
     68 	BRD_ENCOREPP1,
     69 	0,
     70 	"com", 0x3f8, 115200,
     71 	encsetup, encbrdfix, encpcifix },
     72     {
     73 	"kurobox",
     74 	"KuroBox",
     75 	BRD_KUROBOX,
     76 	32768000,
     77 	"eumb", 0x4600, 57600,
     78 	kurosetup, kurobrdfix, kuropcifix },
     79     {
     80 	"synology",
     81 	"Synology DS",
     82 	BRD_SYNOLOGY,
     83 	33164691,	/* from Synology/Linux source */
     84 	/* 33168000,		XXX better precision? */
     85 	"eumb", 0x4500, 115200,
     86 	synosetup, synobrdfix, synopcifix, synoreset },
     87     {
     88 	"qnap",
     89 	"QNAP TS-101",
     90 	BRD_QNAPTS101,
     91 	0,
     92 	"eumb", 0x4500, 115200,
     93 	NULL, NULL, qnappcifix },
     94     {
     95 	"iomega",
     96 	"IOMEGA StorCenter",
     97 	BRD_STORCENTER,
     98 	0,
     99 	"eumb", 0x4500, 115200,
    100 	NULL, iomegabrdfix, iomegapcifix },
    101     {
    102 	"unknown",
    103 	"Unknown board",
    104 	BRD_UNKNOWN,
    105 	0,
    106 	"eumb", 0x4500, 115200,
    107 	NULL, NULL, NULL }, /* must be the last */
    108 };
    109 
    110 static struct brdprop *brdprop;
    111 static uint32_t ticks_per_sec, ns_per_tick;
    112 
    113 static void brdfixup(void);
    114 static void setup(void);
    115 static inline uint32_t cputype(void);
    116 static inline u_quad_t mftb(void);
    117 static void init_uart(unsigned, unsigned, uint8_t);
    118 static void send_sat(char *);
    119 
    120 const unsigned dcache_line_size = 32;		/* 32B linesize */
    121 const unsigned dcache_range_size = 4 * 1024;	/* 16KB / 4-way */
    122 
    123 unsigned uart1base;	/* console */
    124 unsigned uart2base;	/* optional satellite processor */
    125 #define THR		0
    126 #define DLB		0
    127 #define DMB		1
    128 #define IER		1
    129 #define FCR		2
    130 #define LCR		3
    131 #define  LCR_DLAB	0x80
    132 #define  LCR_PEVEN	0x18
    133 #define  LCR_PNONE	0x00
    134 #define  LCR_8BITS	0x03
    135 #define MCR		4
    136 #define  MCR_RTS	0x02
    137 #define  MCR_DTR	0x01
    138 #define LSR		5
    139 #define  LSR_THRE	0x20
    140 #define DCR		0x11
    141 #define UART_READ(base, r)	*(volatile char *)(base + (r))
    142 #define UART_WRITE(base, r, v)	*(volatile char *)(base + (r)) = (v)
    143 
    144 void brdsetup(void);	/* called by entry.S */
    145 
    146 void
    147 brdsetup(void)
    148 {
    149 	static uint8_t pci_to_memclk[] = {
    150 		30, 30, 10, 10, 20, 10, 10, 10,
    151 		10, 20, 20, 15, 20, 15, 20, 30,
    152 		30, 40, 15, 40, 20, 25, 20, 40,
    153 		25, 20, 10, 20, 15, 15, 20, 00
    154 	};
    155 	static uint8_t mem_to_cpuclk[] = {
    156 		25, 30, 45, 20, 20, 00, 10, 30,
    157 		30, 20, 45, 30, 25, 35, 30, 35,
    158 		20, 25, 20, 30, 35, 40, 40, 20,
    159 		30, 25, 40, 30, 30, 25, 35, 00
    160 	};
    161 	char *consname;
    162 	int consport;
    163 	uint32_t extclk;
    164 	unsigned pchb, pcib, val;
    165 	extern struct btinfo_memory bi_mem;
    166 	extern struct btinfo_console bi_cons;
    167 	extern struct btinfo_clock bi_clk;
    168 	extern struct btinfo_prodfamily bi_fam;
    169 
    170 	/*
    171 	 * CHRP specification "Map-B" BAT012 layout
    172 	 *   BAT0 0000-0000 (256MB) SDRAM
    173 	 *   BAT1 8000-0000 (256MB) PCI mem space
    174 	 *   BAT2 fc00-0000 (64MB)  EUMB, PCI I/O space, misc devs, flash
    175 	 *
    176 	 * EUMBBAR is at fc00-0000.
    177 	 */
    178 	pchb = pcimaketag(0, 0, 0);
    179 	pcicfgwrite(pchb, 0x78, 0xfc000000);
    180 
    181 	brdtype = BRD_UNKNOWN;
    182 	extclk = EXT_CLK_FREQ;	/* usually 33MHz */
    183 	busclock = 0;
    184 
    185 	if (pcifinddev(0x10ad, 0x0565, &pcib) == 0) {
    186 		brdtype = BRD_SANDPOINTX3;
    187 	}
    188 	else if (pcifinddev(0x1106, 0x0686, &pcib) == 0) {
    189 		brdtype = BRD_ENCOREPP1;
    190 	}
    191 	else if ((pcicfgread(pcimaketag(0, 11, 0), PCI_CLASS_REG) >> 16) ==
    192 	    PCI_CLASS_ETH) {
    193 		/* tlp (ADMtek AN985) or re (RealTek 8169S) at dev 11 */
    194 		brdtype = BRD_KUROBOX;
    195 	}
    196 	else if (PCI_VENDOR(pcicfgread(pcimaketag(0, 15, 0), PCI_ID_REG)) ==
    197 	    0x11ab) {				/* PCI_VENDOR_MARVELL */
    198 		brdtype = BRD_SYNOLOGY;
    199 	}
    200 	else if (PCI_VENDOR(pcicfgread(pcimaketag(0, 15, 0), PCI_ID_REG)) ==
    201 	    0x8086) {				/* PCI_VENDOR_INTEL */
    202 		brdtype = BRD_QNAPTS101;
    203 	}
    204 	else if (PCI_VENDOR(pcicfgread(pcimaketag(0, 13, 0), PCI_ID_REG)) ==
    205 	    0x1106) {				/* PCI_VENDOR_VIA */
    206 		brdtype = BRD_STORCENTER;
    207 	}
    208 
    209 	brdprop = brd_lookup(brdtype);
    210 
    211 	/* brd dependent adjustments */
    212 	setup();
    213 
    214 	/* determine clock frequencies */
    215 	if (brdprop->extclk != 0)
    216 		extclk = brdprop->extclk;
    217 	if (busclock == 0) {
    218 		if (cputype() == MPC8245) {
    219 			/* PLL_CFG from PCI host bridge register 0xe2 */
    220 			val = pcicfgread(pchb, 0xe0);
    221 			busclock = (extclk *
    222 			    pci_to_memclk[(val >> 19) & 0x1f] + 10) / 10;
    223 			/* PLLRATIO from HID1 */
    224 			__asm ("mfspr %0,1009" : "=r"(val));
    225 			cpuclock = ((uint64_t)busclock *
    226 			    mem_to_cpuclk[val >> 27] + 10) / 10;
    227 		} else
    228 			busclock = 100000000;	/* 100MHz bus clock default */
    229 	}
    230 	ticks_per_sec = busclock >> 2;
    231 	ns_per_tick = 1000000000 / ticks_per_sec;
    232 
    233 	/* now prepare serial console */
    234 	consname = brdprop->consname;
    235 	consport = brdprop->consport;
    236 	if (strcmp(consname, "eumb") == 0) {
    237 		uart1base = 0xfc000000 + consport;	/* 0x4500, 0x4600 */
    238 		UART_WRITE(uart1base, DCR, 0x01);	/* enable DUART mode */
    239 		uart2base = uart1base ^ 0x0300;
    240 	} else
    241 		uart1base = 0xfe000000 + consport;	/* 0x3f8, 0x2f8 */
    242 
    243 	/* more brd adjustments */
    244 	brdfixup();
    245 
    246 	bi_mem.memsize = mpc107memsize();
    247 	snprintf(bi_cons.devname, sizeof(bi_cons.devname), consname);
    248 	bi_cons.addr = consport;
    249 	bi_cons.speed = brdprop->consspeed;
    250 	bi_clk.ticks_per_sec = ticks_per_sec;
    251 	snprintf(bi_fam.name, sizeof(bi_fam.name), brdprop->family);
    252 }
    253 
    254 struct brdprop *
    255 brd_lookup(int brd)
    256 {
    257 	u_int i;
    258 
    259 	for (i = 0; i < sizeof(brdlist)/sizeof(brdlist[0]); i++) {
    260 		if (brdlist[i].brdtype == brd)
    261 			return &brdlist[i];
    262 	}
    263 	return &brdlist[i - 1];
    264 }
    265 
    266 static void
    267 setup()
    268 {
    269 
    270 	if (brdprop->setup == NULL)
    271 		return;
    272 	(*brdprop->setup)(brdprop);
    273 }
    274 
    275 static void
    276 brdfixup()
    277 {
    278 
    279 	if (brdprop->brdfix == NULL)
    280 		return;
    281 	(*brdprop->brdfix)(brdprop);
    282 }
    283 
    284 void
    285 pcifixup()
    286 {
    287 
    288 	if (brdprop->pcifix == NULL)
    289 		return;
    290 	(*brdprop->pcifix)(brdprop);
    291 }
    292 
    293 void
    294 encsetup(struct brdprop *brd)
    295 {
    296 
    297 #ifdef COSNAME
    298 	brd->consname = CONSNAME;
    299 #endif
    300 #ifdef CONSPORT
    301 	brd->consport = CONSPORT;
    302 #endif
    303 #ifdef CONSSPEED
    304 	brd->consspeed = CONSSPEED;
    305 #endif
    306 }
    307 
    308 void
    309 encbrdfix(struct brdprop *brd)
    310 {
    311 	unsigned ac97, ide, pcib, pmgt, usb12, umot4, val;
    312 
    313 /*
    314  * VIA82C686B Southbridge
    315  *	0.22.0	1106.0686	PCI-ISA bridge
    316  *	0.22.1	1106.0571	IDE (viaide)
    317  *	0.22.2	1106.3038	USB 0/1 (uhci)
    318  *	0.22.3	1106.3038	USB 2/3 (uhci)
    319  *	0.22.4	1106.3057	power management
    320  *	0.22.5	1106.3058	AC97 (auvia)
    321  */
    322 	pcib  = pcimaketag(0, 22, 0);
    323 	ide   = pcimaketag(0, 22, 1);
    324 	usb12 = pcimaketag(0, 22, 2);
    325 	umot4 = pcimaketag(0, 22, 3);
    326 	pmgt  = pcimaketag(0, 22, 4);
    327 	ac97  = pcimaketag(0, 22, 5);
    328 
    329 #define	CFG(i,v) do { \
    330    *(volatile unsigned char *)(0xfe000000 + 0x3f0) = (i); \
    331    *(volatile unsigned char *)(0xfe000000 + 0x3f1) = (v); \
    332    } while (0)
    333 	val = pcicfgread(pcib, 0x84);
    334 	val |= (02 << 8);
    335 	pcicfgwrite(pcib, 0x84, val);
    336 	CFG(0xe2, 0x0f); /* use COM1/2, don't use FDC/LPT */
    337 	val = pcicfgread(pcib, 0x84);
    338 	val &= ~(02 << 8);
    339 	pcicfgwrite(pcib, 0x84, val);
    340 
    341 	/* route pin C to i8259 IRQ 5, pin D to 11 */
    342 	val = pcicfgread(pcib, 0x54);
    343 	val = (val & 0xff) | 0xb0500000; /* Dx CB Ax xS */
    344 	pcicfgwrite(pcib, 0x54, val);
    345 
    346 	/* enable EISA ELCR1 (0x4d0) and ELCR2 (0x4d1) */
    347 	val = pcicfgread(pcib, 0x44);
    348 	val = val | 0x20000000;
    349 	pcicfgwrite(pcib, 0x44, val);
    350 
    351 	/* select level trigger for IRQ 5/11 at ELCR1/2 */
    352 	*(volatile uint8_t *)0xfe0004d0 = 0x20; /* bit 5 */
    353 	*(volatile uint8_t *)0xfe0004d1 = 0x08; /* bit 11 */
    354 
    355 	/* USB and AC97 are hardwired with pin D and C */
    356 	val = pcicfgread(usb12, 0x3c) &~ 0xff;
    357 	val |= 11;
    358 	pcicfgwrite(usb12, 0x3c, val);
    359 	val = pcicfgread(umot4, 0x3c) &~ 0xff;
    360 	val |= 11;
    361 	pcicfgwrite(umot4, 0x3c, val);
    362 	val = pcicfgread(ac97, 0x3c) &~ 0xff;
    363 	val |= 5;
    364 	pcicfgwrite(ac97, 0x3c, val);
    365 }
    366 
    367 void
    368 motsetup(struct brdprop *brd)
    369 {
    370 
    371 #ifdef COSNAME
    372 	brd->consname = CONSNAME;
    373 #endif
    374 #ifdef CONSPORT
    375 	brd->consport = CONSPORT;
    376 #endif
    377 #ifdef CONSSPEED
    378 	brd->consspeed = CONSSPEED;
    379 #endif
    380 }
    381 
    382 void
    383 motbrdfix(struct brdprop *brd)
    384 {
    385 
    386 /*
    387  * WinBond/Symphony Lab 83C553 with PC87308 "SuperIO"
    388  *
    389  *	0.11.0	10ad.0565	PCI-ISA bridge
    390  *	0.11.1	10ad.0105	IDE (slide)
    391  */
    392 }
    393 
    394 void
    395 motpcifix(struct brdprop *brd)
    396 {
    397 	unsigned ide, nic, pcib, steer, val;
    398 	int line;
    399 
    400 	pcib = pcimaketag(0, 11, 0);
    401 	ide  = pcimaketag(0, 11, 1);
    402 	nic  = pcimaketag(0, 15, 0);
    403 
    404 	/*
    405 	 * //// WinBond PIRQ ////
    406 	 * 0x40 - bit 5 (0x20) indicates PIRQ presense
    407 	 * 0x60 - PIRQ interrupt routing steer
    408 	 */
    409 	if (pcicfgread(pcib, 0x40) & 0x20) {
    410 		steer = pcicfgread(pcib, 0x60);
    411 		if ((steer & 0x80808080) == 0x80808080)
    412 			printf("PIRQ[0-3] disabled\n");
    413 		else {
    414 			unsigned i, v = steer;
    415 			for (i = 0; i < 4; i++, v >>= 8) {
    416 				if ((v & 0x80) != 0 || (v & 0xf) == 0)
    417 					continue;
    418 				printf("PIRQ[%d]=%d\n", i, v & 0xf);
    419 				}
    420 			}
    421 		}
    422 #if 1
    423 	/*
    424 	 * //// IDE fixup -- case A ////
    425 	 * - "native PCI mode" (ide 0x09)
    426 	 * - don't use ISA IRQ14/15 (pcib 0x43)
    427 	 * - native IDE for both channels (ide 0x40)
    428 	 * - LEGIRQ bit 11 steers interrupt to pin C (ide 0x40)
    429 	 * - sign as PCI pin C line 11 (ide 0x3d/3c)
    430 	 */
    431 	/* ide: 0x09 - programming interface; 1000'SsPp */
    432 	val = pcicfgread(ide, 0x08);
    433 	val &= 0xffff00ff;
    434 	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
    435 
    436 	/* pcib: 0x43 - IDE interrupt routing */
    437 	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
    438 	pcicfgwrite(pcib, 0x40, val);
    439 
    440 	/* pcib: 0x45/44 - PCI interrupt routing */
    441 	val = pcicfgread(pcib, 0x44) & 0xffff0000;
    442 	pcicfgwrite(pcib, 0x44, val);
    443 
    444 	/* ide: 0x41/40 - IDE channel */
    445 	val = pcicfgread(ide, 0x40) & 0xffff0000;
    446 	val |= (1 << 11) | 0x33; /* LEGIRQ turns on PCI interrupt */
    447 	pcicfgwrite(ide, 0x40, val);
    448 
    449 	/* ide: 0x3d/3c - use PCI pin C/line 11 */
    450 	val = pcicfgread(ide, 0x3c) & 0xffffff00;
    451 	val |= 11; /* pin designation is hardwired to pin A */
    452 	pcicfgwrite(ide, 0x3c, val);
    453 #else
    454 	/*
    455 	 * //// IDE fixup -- case B ////
    456 	 * - "compatiblity mode" (ide 0x09)
    457 	 * - IDE primary/secondary interrupt routing (pcib 0x43)
    458 	 * - PCI interrupt routing (pcib 0x45/44)
    459 	 * - no PCI pin/line assignment (ide 0x3d/3c)
    460 	 */
    461 	/* ide: 0x09 - programming interface; 1000'SsPp */
    462 	val = pcicfgread(ide, 0x08);
    463 	val &= 0xffff00ff;
    464 	pcicfgwrite(ide, 0x08, val | (0x8a << 8));
    465 
    466 	/* pcib: 0x43 - IDE interrupt routing */
    467 	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
    468 	pcicfgwrite(pcib, 0x40, val | (0xee << 24));
    469 
    470 	/* ide: 0x45/44 - PCI interrupt routing */
    471 	val = pcicfgread(ide, 0x44) & 0xffff0000;
    472 	pcicfgwrite(ide, 0x44, val);
    473 
    474 	/* ide: 0x3d/3c - turn off PCI pin/line */
    475 	val = pcicfgread(ide, 0x3c) & 0xffff0000;
    476 	pcicfgwrite(ide, 0x3c, val);
    477 #endif
    478 
    479 	/*
    480 	 * //// fxp fixup ////
    481 	 * - use PCI pin A line 15 (fxp 0x3d/3c)
    482 	 */
    483 	val = pcicfgread(nic, 0x3c) & 0xffff0000;
    484 	pcidecomposetag(nic, NULL, &line, NULL);
    485 	val |= (('A' - '@') << 8) | line;
    486 	pcicfgwrite(nic, 0x3c, val);
    487 }
    488 
    489 void
    490 encpcifix(struct brdprop *brd)
    491 {
    492 	unsigned ide, irq, nic, pcib, steer, val;
    493 
    494 #define	STEER(v, b) (((v) & (b)) ? "edge" : "level")
    495 	pcib = pcimaketag(0, 22, 0);
    496 	ide  = pcimaketag(0, 22, 1);
    497 	nic  = pcimaketag(0, 25, 0);
    498 
    499 	/*
    500 	 * //// VIA PIRQ ////
    501 	 * 0x57/56/55/54 - Dx CB Ax xS
    502 	 */
    503 	val = pcicfgread(pcib, 0x54);	/* Dx CB Ax xs */
    504 	steer = val & 0xf;
    505 	irq = (val >> 12) & 0xf;	/* 15:12 */
    506 	if (irq) {
    507 		printf("pin A -> irq %d, %s\n",
    508 			irq, STEER(steer, 0x1));
    509 	}
    510 	irq = (val >> 16) & 0xf;	/* 19:16 */
    511 	if (irq) {
    512 		printf("pin B -> irq %d, %s\n",
    513 			irq, STEER(steer, 0x2));
    514 	}
    515 	irq = (val >> 20) & 0xf;	/* 23:20 */
    516 	if (irq) {
    517 		printf("pin C -> irq %d, %s\n",
    518 			irq, STEER(steer, 0x4));
    519 	}
    520 	irq = (val >> 28);		/* 31:28 */
    521 	if (irq) {
    522 		printf("pin D -> irq %d, %s\n",
    523 			irq, STEER(steer, 0x8));
    524 	}
    525 #if 0
    526 	/*
    527 	 * //// IDE fixup ////
    528 	 * - "native mode" (ide 0x09)
    529 	 * - use primary only (ide 0x40)
    530 	 */
    531 	/* ide: 0x09 - programming interface; 1000'SsPp */
    532 	val = pcicfgread(ide, 0x08) & 0xffff00ff;
    533 	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
    534 
    535 	/* ide: 0x10-20 - leave them PCI memory space assigned */
    536 
    537 	/* ide: 0x40 - use primary only */
    538 	val = pcicfgread(ide, 0x40) &~ 03;
    539 	val |= 02;
    540 	pcicfgwrite(ide, 0x40, val);
    541 #else
    542 	/*
    543 	 * //// IDE fixup ////
    544 	 * - "compatiblity mode" (ide 0x09)
    545 	 * - use primary only (ide 0x40)
    546 	 * - remove PCI pin assignment (ide 0x3d)
    547 	 */
    548 	/* ide: 0x09 - programming interface; 1000'SsPp */
    549 	val = pcicfgread(ide, 0x08) & 0xffff00ff;
    550 	val |= (0x8a << 8);
    551 	pcicfgwrite(ide, 0x08, val);
    552 
    553 	/* ide: 0x10-20 */
    554 	/*
    555 	experiment shows writing ide: 0x09 changes these
    556 	register behaviour. The pcicfgwrite() above writes
    557 	0x8a at ide: 0x09 to make sure legacy IDE.  Then
    558 	reading BAR0-3 is to return value 0s even though
    559 	pcisetup() has written range assignments.  Value
    560 	overwrite makes no effect. Having 0x8f for native
    561 	PCIIDE doesn't change register values and brings no
    562 	weirdness.
    563 	 */
    564 
    565 	/* ide: 0x40 - use primary only */
    566 	val = pcicfgread(ide, 0x40) &~ 03;
    567 	val |= 02;
    568 	pcicfgwrite(ide, 0x40, val);
    569 
    570 		/* ide: 0x3d/3c - turn off PCI pin */
    571 	val = pcicfgread(ide, 0x3c) & 0xffff00ff;
    572 	pcicfgwrite(ide, 0x3c, val);
    573 #endif
    574 	/*
    575 	 * //// USBx2, audio, and modem fixup ////
    576 	 * - disable USB #0 and #1 (pcib 0x48 and 0x85)
    577 	 * - disable AC97 audio and MC97 modem (pcib 0x85)
    578 	 */
    579 
    580 	/* pcib: 0x48 - disable USB #0 at function 2 */
    581 	val = pcicfgread(pcib, 0x48);
    582 	pcicfgwrite(pcib, 0x48, val | 04);
    583 
    584 	/* pcib: 0x85 - disable USB #1 at function 3 */
    585 	/* pcib: 0x85 - disable AC97/MC97 at function 5/6 */
    586 	val = pcicfgread(pcib, 0x84);
    587 	pcicfgwrite(pcib, 0x84, val | 0x1c00);
    588 
    589 	/*
    590 	 * //// fxp fixup ////
    591 	 * - use PCI pin A line 25 (fxp 0x3d/3c)
    592 	 */
    593 	/* 0x3d/3c - PCI pin/line */
    594 	val = pcicfgread(nic, 0x3c) & 0xffff0000;
    595 	val |= (('A' - '@') << 8) | 25;
    596 	pcicfgwrite(nic, 0x3c, val);
    597 }
    598 
    599 void
    600 kurosetup(struct brdprop *brd)
    601 {
    602 
    603 	if (PCI_VENDOR(pcicfgread(pcimaketag(0, 11, 0), PCI_ID_REG)) == 0x10ec)
    604 		brd->extclk = 32768000; /* decr 2457600Hz */
    605 	else
    606 		brd->extclk = 32521333; /* decr 2439100Hz */
    607 }
    608 
    609 void
    610 kurobrdfix(struct brdprop *brd)
    611 {
    612 
    613 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PEVEN);
    614 	/* Stop Watchdog */
    615 	send_sat("AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK");
    616 }
    617 
    618 void
    619 kuropcifix(struct brdprop *brd)
    620 {
    621 	unsigned ide, nic, usb, val;
    622 
    623 	nic = pcimaketag(0, 11, 0);
    624 	val = pcicfgread(nic, 0x3c) & 0xffffff00;
    625 	val |= 11;
    626 	pcicfgwrite(nic, 0x3c, val);
    627 
    628 	ide = pcimaketag(0, 12, 0);
    629 	val = pcicfgread(ide, 0x3c) & 0xffffff00;
    630 	val |= 12;
    631 	pcicfgwrite(ide, 0x3c, val);
    632 
    633 	usb = pcimaketag(0, 14, 0);
    634 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    635 	val |= 14;
    636 	pcicfgwrite(usb, 0x3c, val);
    637 
    638 	usb = pcimaketag(0, 14, 1);
    639 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    640 	val |= 14;
    641 	pcicfgwrite(usb, 0x3c, val);
    642 
    643 	usb = pcimaketag(0, 14, 2);
    644 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    645 	val |= 14;
    646 	pcicfgwrite(usb, 0x3c, val);
    647 }
    648 
    649 void
    650 synosetup(struct brdprop *brd)
    651 {
    652 
    653 	/* nothing */
    654 }
    655 
    656 void
    657 synobrdfix(struct brdprop *brd)
    658 {
    659 
    660 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
    661 	/* beep, power LED on, status LED off */
    662 	send_sat("247");
    663 }
    664 
    665 void
    666 synopcifix(struct brdprop *brd)
    667 {
    668 	unsigned ide, nic, usb, val;
    669 
    670 	ide = pcimaketag(0, 13, 0);
    671 	val = pcicfgread(ide, 0x3c) & 0xffffff00;
    672 	val |= 13;
    673 	pcicfgwrite(ide, 0x3c, val);
    674 
    675 	usb = pcimaketag(0, 14, 0);
    676 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    677 	val |= 14;
    678 	pcicfgwrite(usb, 0x3c, val);
    679 
    680 	usb = pcimaketag(0, 14, 1);
    681 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    682 	val |= 14;
    683 	pcicfgwrite(usb, 0x3c, val);
    684 
    685 	usb = pcimaketag(0, 14, 2);
    686 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    687 	val |= 14;
    688 	pcicfgwrite(usb, 0x3c, val);
    689 
    690 	nic = pcimaketag(0, 15, 0);
    691 	val = pcicfgread(nic, 0x3c) & 0xffffff00;
    692 	val |= 15;
    693 	pcicfgwrite(nic, 0x3c, val);
    694 }
    695 
    696 void
    697 synoreset()
    698 {
    699 
    700 	send_sat("C");
    701 	/*NOTRECHED*/
    702 }
    703 
    704 void
    705 qnappcifix(struct brdprop *brd)
    706 {
    707 	unsigned ide, nic, usb, val;
    708 
    709 	ide = pcimaketag(0, 13, 0);
    710 	val = pcicfgread(ide, 0x3c) & 0xffffff00;
    711 	val |= 13;
    712 	pcicfgwrite(ide, 0x3c, val);
    713 
    714 	usb = pcimaketag(0, 14, 0);
    715 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    716 	val |= 14;
    717 	pcicfgwrite(usb, 0x3c, val);
    718 
    719 	usb = pcimaketag(0, 14, 1);
    720 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    721 	val |= 14;
    722 	pcicfgwrite(usb, 0x3c, val);
    723 
    724 	usb = pcimaketag(0, 14, 2);
    725 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    726 	val |= 14;
    727 	pcicfgwrite(usb, 0x3c, val);
    728 
    729 	nic = pcimaketag(0, 15, 0);
    730 	val = pcicfgread(nic, 0x3c) & 0xffffff00;
    731 	val |= 15;
    732 	pcicfgwrite(nic, 0x3c, val);
    733 }
    734 
    735 void
    736 iomegabrdfix(struct brdprop *brd)
    737 {
    738 
    739 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
    740 }
    741 
    742 void
    743 iomegapcifix(struct brdprop *brd)
    744 {
    745 	unsigned ide, nic, usb, val;
    746 
    747 	ide = pcimaketag(0, 13, 0);
    748 	val = pcicfgread(ide, 0x3c) & 0xffffff00;
    749 	val |= 13;
    750 	pcicfgwrite(ide, 0x3c, val);
    751 
    752 	usb = pcimaketag(0, 14, 0);
    753 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    754 	val |= 14;
    755 	pcicfgwrite(usb, 0x3c, val);
    756 
    757 	usb = pcimaketag(0, 14, 1);
    758 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    759 	val |= 14;
    760 	pcicfgwrite(usb, 0x3c, val);
    761 
    762 	usb = pcimaketag(0, 14, 2);
    763 	val = pcicfgread(usb, 0x3c) & 0xffffff00;
    764 	val |= 14;
    765 	pcicfgwrite(usb, 0x3c, val);
    766 
    767 	nic = pcimaketag(0, 15, 0);
    768 	val = pcicfgread(nic, 0x3c) & 0xffffff00;
    769 	val |= 15;
    770 	pcicfgwrite(nic, 0x3c, val);
    771 }
    772 
    773 void
    774 _rtt(void)
    775 {
    776 
    777 	if (brdprop->reset != NULL)
    778 		(*brdprop->reset)();
    779 	else
    780 		run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */
    781 	/*NOTREACHED*/
    782 }
    783 
    784 satime_t
    785 getsecs(void)
    786 {
    787 	u_quad_t tb = mftb();
    788 
    789 	return (tb / ticks_per_sec);
    790 }
    791 
    792 /*
    793  * Wait for about n microseconds (at least!).
    794  */
    795 void
    796 delay(u_int n)
    797 {
    798 	u_quad_t tb;
    799 	u_long scratch, tbh, tbl;
    800 
    801 	tb = mftb();
    802 	tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
    803 	tbh = tb >> 32;
    804 	tbl = tb;
    805 	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));
    806 }
    807 
    808 void
    809 _wb(uint32_t adr, uint32_t siz)
    810 {
    811 	uint32_t bnd;
    812 
    813 	asm volatile("eieio");
    814 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
    815 		asm volatile ("dcbst 0,%0" :: "r"(adr));
    816 	asm volatile ("sync");
    817 }
    818 
    819 void
    820 _wbinv(uint32_t adr, uint32_t siz)
    821 {
    822 	uint32_t bnd;
    823 
    824 	asm volatile("eieio");
    825 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
    826 		asm volatile ("dcbf 0,%0" :: "r"(adr));
    827 	asm volatile ("sync");
    828 }
    829 
    830 void
    831 _inv(uint32_t adr, uint32_t siz)
    832 {
    833 	uint32_t bnd, off;
    834 
    835 	off = adr & (dcache_line_size - 1);
    836 	adr -= off;
    837 	siz += off;
    838 	asm volatile ("eieio");
    839 	if (off != 0) {
    840 		/* wbinv() leading unaligned dcache line */
    841 		asm volatile ("dcbf 0,%0" :: "r"(adr));
    842 		if (siz < dcache_line_size)
    843 			goto done;
    844 		adr += dcache_line_size;
    845 		siz -= dcache_line_size;
    846 	}
    847 	bnd = adr + siz;
    848 	off = bnd & (dcache_line_size - 1);
    849 	if (off != 0) {
    850 		/* wbinv() trailing unaligned dcache line */
    851 		asm volatile ("dcbf 0,%0" :: "r"(bnd)); /* it's OK */
    852 		if (siz < dcache_line_size)
    853 			goto done;
    854 		siz -= off;
    855 	}
    856 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) {
    857 		/* inv() intermediate dcache lines if ever */
    858 		asm volatile ("dcbi 0,%0" :: "r"(adr));
    859 	}
    860   done:
    861 	asm volatile ("sync");
    862 }
    863 
    864 static inline uint32_t
    865 cputype(void)
    866 {
    867 	uint32_t pvr;
    868 
    869 	__asm volatile ("mfpvr %0" : "=r"(pvr));
    870 	return pvr >> 16;
    871 }
    872 
    873 static inline u_quad_t
    874 mftb(void)
    875 {
    876 	u_long scratch;
    877 	u_quad_t tb;
    878 
    879 	asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b"
    880 	    : "=r"(tb), "=r"(scratch));
    881 	return (tb);
    882 }
    883 
    884 static void
    885 init_uart(unsigned base, unsigned speed, uint8_t lcr)
    886 {
    887 	unsigned div;
    888 
    889 	div = busclock / speed / 16;
    890 	UART_WRITE(base, LCR, 0x80);		/* turn on DLAB bit */
    891 	UART_WRITE(base, FCR, 0x00);
    892 	UART_WRITE(base, DMB, div >> 8);	/* set speed */
    893 	UART_WRITE(base, DLB, div & 0xff);
    894 	UART_WRITE(base, LCR, lcr);
    895 	UART_WRITE(base, FCR, 0x07);		/* FIFO on, TXRX FIFO reset */
    896 	UART_WRITE(base, IER, 0x00);		/* make sure INT disabled */
    897 }
    898 
    899 /* talk to satellite processor */
    900 static void
    901 send_sat(char *msg)
    902 {
    903 	unsigned savedbase;
    904 
    905 	savedbase = uart1base;
    906 	uart1base = uart2base;
    907 	while (*msg)
    908 		putchar(*msg++);
    909 	uart1base = savedbase;
    910 }
    911 
    912 void
    913 putchar(int c)
    914 {
    915 	unsigned timo, lsr;
    916 
    917 	if (c == '\n')
    918 		putchar('\r');
    919 
    920 	timo = 0x00100000;
    921 	do {
    922 		lsr = UART_READ(uart1base, LSR);
    923 	} while (timo-- > 0 && (lsr & LSR_THRE) == 0);
    924 	if (timo > 0)
    925 		UART_WRITE(uart1base, THR, c);
    926 }
    927 
    928 unsigned
    929 mpc107memsize()
    930 {
    931 	unsigned bankn, end, n, tag, val;
    932 
    933 	tag = pcimaketag(0, 0, 0);
    934 
    935 	if (brdtype == BRD_ENCOREPP1) {
    936 		/* the brd's PPCBOOT looks to have erroneous values */
    937 		unsigned tbl[] = {
    938 #define MPC106_MEMSTARTADDR1	0x80
    939 #define MPC106_EXTMEMSTARTADDR1	0x88
    940 #define MPC106_MEMENDADDR1	0x90
    941 #define MPC106_EXTMEMENDADDR1	0x98
    942 #define MPC106_MEMEN		0xa0
    943 #define	BK0_S	0x00000000
    944 #define	BK0_E	(128 << 20) - 1
    945 #define BK1_S	0x3ff00000
    946 #define BK1_E	0x3fffffff
    947 #define BK2_S	0x3ff00000
    948 #define BK2_E	0x3fffffff
    949 #define BK3_S	0x3ff00000
    950 #define BK3_E	0x3fffffff
    951 #define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s))
    952 #define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s))
    953 #define SAR_MASK 0x0ff00000
    954 #define SAR_SHIFT    20
    955 #define EAR_MASK 0x30000000
    956 #define EAR_SHIFT    28
    957 		AR(BK0_S, 0) | AR(BK1_S, 8) | AR(BK2_S, 16) | AR(BK3_S, 24),
    958 		XR(BK0_S, 0) | XR(BK1_S, 8) | XR(BK2_S, 16) | XR(BK3_S, 24),
    959 		AR(BK0_E, 0) | AR(BK1_E, 8) | AR(BK2_E, 16) | AR(BK3_E, 24),
    960 		XR(BK0_E, 0) | XR(BK1_E, 8) | XR(BK2_E, 16) | XR(BK3_E, 24),
    961 		};
    962 		tag = pcimaketag(0, 0, 0);
    963 		pcicfgwrite(tag, MPC106_MEMSTARTADDR1, tbl[0]);
    964 		pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, tbl[1]);
    965 		pcicfgwrite(tag, MPC106_MEMENDADDR1, tbl[2]);
    966 		pcicfgwrite(tag, MPC106_EXTMEMENDADDR1,	tbl[3]);
    967 		pcicfgwrite(tag, MPC106_MEMEN, 1);
    968 	}
    969 
    970 	bankn = 0;
    971 	val = pcicfgread(tag, MPC106_MEMEN);
    972 	for (n = 0; n < 4; n++) {
    973 		if ((val & (1U << n)) == 0)
    974 			break;
    975 		bankn = n;
    976 	}
    977 	bankn = bankn * 8;
    978 
    979 	val = pcicfgread(tag, MPC106_EXTMEMENDADDR1);
    980 	end =  ((val >> bankn) & 0x03) << 28;
    981 	val = pcicfgread(tag, MPC106_MEMENDADDR1);
    982 	end |= ((val >> bankn) & 0xff) << 20;
    983 	end |= 0xfffff;
    984 
    985 	return (end + 1); /* assume the end address matches total amount */
    986 }
    987 
    988 struct fis_dir_entry {
    989 	char		name[16];
    990 	uint32_t	startaddr;
    991 	uint32_t	loadaddr;
    992 	uint32_t	flashsize;
    993 	uint32_t	entryaddr;
    994 	uint32_t	filesize;
    995 	char		pad[256 - (16 + 5 * sizeof(uint32_t))];
    996 };
    997 
    998 #define FIS_LOWER_LIMIT	0xfff00000
    999 
   1000 /*
   1001  * Look for a Redboot-style Flash Image System FIS-directory and
   1002  * return a pointer to the start address of the requested file.
   1003  */
   1004 static void *
   1005 redboot_fis_lookup(const char *filename)
   1006 {
   1007 	static const char FISdirname[16] = {
   1008 	    'F', 'I', 'S', ' ',
   1009 	    'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0
   1010 	};
   1011 	struct fis_dir_entry *dir;
   1012 
   1013 	/*
   1014 	 * The FIS directory is usually in the last sector of the flash.
   1015 	 * But we do not know the sector size (erase size), so start
   1016 	 * at 0xffffff00 and scan backwards in steps of the FIS directory
   1017 	 * entry size (0x100).
   1018 	 */
   1019 	for (dir = (struct fis_dir_entry *)0xffffff00;
   1020 	    (uint32_t)dir >= FIS_LOWER_LIMIT; dir--)
   1021 		if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0)
   1022 			break;
   1023 	if ((uint32_t)dir < FIS_LOWER_LIMIT) {
   1024 		printf("No FIS directory found!\n");
   1025 		return NULL;
   1026 	}
   1027 
   1028 	/* Now find filename by scanning the directory from beginning. */
   1029 	dir = (struct fis_dir_entry *)dir->startaddr;
   1030 	while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) {
   1031 		if (strcmp(dir->name, filename) == 0)
   1032 			return (void *)dir->startaddr;	/* found */
   1033 		dir++;
   1034 	}
   1035 	printf("\"%s\" not found in FIS directory!\n", filename);
   1036 	return NULL;
   1037 }
   1038 
   1039 /*
   1040  * For cost saving reasons some NAS boxes are missing the ROM for the
   1041  * NIC's ethernet address and keep it in their Flash memory.
   1042  */
   1043 void
   1044 read_mac_from_flash(uint8_t *mac)
   1045 {
   1046 	uint8_t *p;
   1047 
   1048 	if (brdtype == BRD_SYNOLOGY) {
   1049 		p = redboot_fis_lookup("vendor");
   1050 		if (p != NULL) {
   1051 			memcpy(mac, p, 6);
   1052 			return;
   1053 		}
   1054 	} else
   1055 		printf("Warning: This board has no known method defined "
   1056 		    "to determine its MAC address!\n");
   1057 
   1058 	/* set to 00:00:00:00:00:00 in case of error */
   1059 	memset(mac, 0, 6);
   1060 }
   1061