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