brdsetup.c revision 1.22
1/* $NetBSD: brdsetup.c,v 1.22 2011/11/07 21:11:55 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 51BRD_DECL(mot); 52BRD_DECL(enc); 53BRD_DECL(kuro); 54BRD_DECL(syno); 55BRD_DECL(qnap); 56BRD_DECL(iomega); 57BRD_DECL(dlink); 58BRD_DECL(nhnas); 59 60static 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, iomegareset }, 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 139static struct brdprop *brdprop; 140static uint32_t ticks_per_sec, ns_per_tick; 141 142static void brdfixup(void); 143static void setup(void); 144static int send_iomega(int, int, int, int, int, int); 145static inline uint32_t mfmsr(void); 146static inline void mtmsr(uint32_t); 147static inline uint32_t cputype(void); 148static inline u_quad_t mftb(void); 149static void init_uart(unsigned, unsigned, uint8_t); 150static void send_sat(char *); 151 152const unsigned dcache_line_size = 32; /* 32B linesize */ 153const unsigned dcache_range_size = 4 * 1024; /* 16KB / 4-way */ 154 155unsigned uart1base; /* console */ 156unsigned 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) in8(base + (r)) 176#define UART_WRITE(base, r, v) out8(base + (r), (v)) 177 178void brdsetup(void); /* called by entry.S */ 179 180void 181brdsetup(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 304struct brdprop * 305brd_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 316static void 317setup() 318{ 319 320 if (brdprop->setup == NULL) 321 return; 322 (*brdprop->setup)(brdprop); 323} 324 325static void 326brdfixup() 327{ 328 329 if (brdprop->brdfix == NULL) 330 return; 331 (*brdprop->brdfix)(brdprop); 332} 333 334void 335pcifixup() 336{ 337 338 if (brdprop->pcifix == NULL) 339 return; 340 (*brdprop->pcifix)(brdprop); 341} 342 343void 344encsetup(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 358void 359encbrdfix(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 417void 418encpcifix(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 */ 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#else 465 /* 466 * //// IDE fixup //// 467 * - "compatiblity mode" (ide 0x09) 468 * - remove PCI pin assignment (ide 0x3d) 469 */ 470 471 /* ide: 0x09 - programming interface; 1000'SsPp */ 472 val = pcicfgread(ide, 0x08) & 0xffff00ff; 473 val |= (0x8a << 8); 474 pcicfgwrite(ide, 0x08, val); 475 476 /* ide: 0x10-20 */ 477 /* 478 * experiment shows writing ide: 0x09 changes these 479 * register behaviour. The pcicfgwrite() above writes 480 * 0x8a at ide: 0x09 to make sure legacy IDE. Then 481 * reading BAR0-3 is to return value 0s even though 482 * pcisetup() has written range assignments. Value 483 * overwrite makes no effect. Having 0x8f for native 484 * PCIIDE doesn't change register values and brings no 485 * weirdness. 486 */ 487 488 /* ide: 0x3d/3c - turn off PCI pin */ 489 val = pcicfgread(ide, 0x3c) & 0xffff00ff; 490 pcicfgwrite(ide, 0x3c, val); 491#endif 492 /* 493 * //// USBx2, audio, and modem fixup //// 494 * - disable USB #0 and #1 (pcib 0x48 and 0x85) 495 * - disable AC97 audio and MC97 modem (pcib 0x85) 496 */ 497 498 /* pcib: 0x48 - disable USB #0 at function 2 */ 499 val = pcicfgread(pcib, 0x48); 500 pcicfgwrite(pcib, 0x48, val | 04); 501 502 /* pcib: 0x85 - disable USB #1 at function 3 */ 503 /* pcib: 0x85 - disable AC97/MC97 at function 5/6 */ 504 val = pcicfgread(pcib, 0x84); 505 pcicfgwrite(pcib, 0x84, val | 0x1c00); 506 507 /* 508 * //// fxp fixup //// 509 * - use PCI pin A line 25 (fxp 0x3d/3c) 510 */ 511 /* 0x3d/3c - PCI pin/line */ 512 val = pcicfgread(net, 0x3c) & 0xffff0000; 513 val |= (('A' - '@') << 8) | 25; 514 pcicfgwrite(net, 0x3c, val); 515} 516 517void 518motsetup(struct brdprop *brd) 519{ 520 521#ifdef COSNAME 522 brd->consname = CONSNAME; 523#endif 524#ifdef CONSPORT 525 brd->consport = CONSPORT; 526#endif 527#ifdef CONSSPEED 528 brd->consspeed = CONSSPEED; 529#endif 530} 531 532void 533motbrdfix(struct brdprop *brd) 534{ 535 536/* 537 * WinBond/Symphony Lab 83C553 with PC87308 "SuperIO" 538 * 539 * 0.11.0 10ad.0565 PCI-ISA bridge 540 * 0.11.1 10ad.0105 IDE (slide) 541 */ 542} 543 544void 545motpcifix(struct brdprop *brd) 546{ 547 unsigned ide, net, pcib, steer, val; 548 int line; 549 550 pcib = pcimaketag(0, 11, 0); 551 ide = pcimaketag(0, 11, 1); 552 net = pcimaketag(0, 15, 0); 553 554 /* 555 * //// WinBond PIRQ //// 556 * 0x40 - bit 5 (0x20) indicates PIRQ presense 557 * 0x60 - PIRQ interrupt routing steer 558 */ 559 if (pcicfgread(pcib, 0x40) & 0x20) { 560 steer = pcicfgread(pcib, 0x60); 561 if ((steer & 0x80808080) == 0x80808080) 562 printf("PIRQ[0-3] disabled\n"); 563 else { 564 unsigned i, v = steer; 565 for (i = 0; i < 4; i++, v >>= 8) { 566 if ((v & 0x80) != 0 || (v & 0xf) == 0) 567 continue; 568 printf("PIRQ[%d]=%d\n", i, v & 0xf); 569 } 570 } 571 } 572#if 1 573 /* 574 * //// IDE fixup -- case A //// 575 * - "native PCI mode" (ide 0x09) 576 * - don't use ISA IRQ14/15 (pcib 0x43) 577 * - native IDE for both channels (ide 0x40) 578 * - LEGIRQ bit 11 steers interrupt to pin C (ide 0x40) 579 * - sign as PCI pin C line 11 (ide 0x3d/3c) 580 */ 581 /* ide: 0x09 - programming interface; 1000'SsPp */ 582 val = pcicfgread(ide, 0x08); 583 val &= 0xffff00ff; 584 pcicfgwrite(ide, 0x08, val | (0x8f << 8)); 585 586 /* pcib: 0x43 - IDE interrupt routing */ 587 val = pcicfgread(pcib, 0x40) & 0x00ffffff; 588 pcicfgwrite(pcib, 0x40, val); 589 590 /* pcib: 0x45/44 - PCI interrupt routing */ 591 val = pcicfgread(pcib, 0x44) & 0xffff0000; 592 pcicfgwrite(pcib, 0x44, val); 593 594 /* ide: 0x41/40 - IDE channel */ 595 val = pcicfgread(ide, 0x40) & 0xffff0000; 596 val |= (1 << 11) | 0x33; /* LEGIRQ turns on PCI interrupt */ 597 pcicfgwrite(ide, 0x40, val); 598 599 /* ide: 0x3d/3c - use PCI pin C/line 11 */ 600 val = pcicfgread(ide, 0x3c) & 0xffffff00; 601 val |= 11; /* pin designation is hardwired to pin A */ 602 pcicfgwrite(ide, 0x3c, val); 603#else 604 /* 605 * //// IDE fixup -- case B //// 606 * - "compatiblity mode" (ide 0x09) 607 * - IDE primary/secondary interrupt routing (pcib 0x43) 608 * - PCI interrupt routing (pcib 0x45/44) 609 * - no PCI pin/line assignment (ide 0x3d/3c) 610 */ 611 /* ide: 0x09 - programming interface; 1000'SsPp */ 612 val = pcicfgread(ide, 0x08); 613 val &= 0xffff00ff; 614 pcicfgwrite(ide, 0x08, val | (0x8a << 8)); 615 616 /* pcib: 0x43 - IDE interrupt routing */ 617 val = pcicfgread(pcib, 0x40) & 0x00ffffff; 618 pcicfgwrite(pcib, 0x40, val | (0xee << 24)); 619 620 /* ide: 0x45/44 - PCI interrupt routing */ 621 val = pcicfgread(ide, 0x44) & 0xffff0000; 622 pcicfgwrite(ide, 0x44, val); 623 624 /* ide: 0x3d/3c - turn off PCI pin/line */ 625 val = pcicfgread(ide, 0x3c) & 0xffff0000; 626 pcicfgwrite(ide, 0x3c, val); 627#endif 628 629 /* 630 * //// fxp fixup //// 631 * - use PCI pin A line 15 (fxp 0x3d/3c) 632 */ 633 val = pcicfgread(net, 0x3c) & 0xffff0000; 634 pcidecomposetag(net, NULL, &line, NULL); 635 val |= (('A' - '@') << 8) | line; 636 pcicfgwrite(net, 0x3c, val); 637} 638 639void 640kurosetup(struct brdprop *brd) 641{ 642 643 if (PCI_VENDOR(pcicfgread(pcimaketag(0, 11, 0), PCI_ID_REG)) == 0x10ec) 644 brd->extclk = 32768000; /* decr 2457600Hz */ 645 else 646 brd->extclk = 32521333; /* decr 2439100Hz */ 647} 648 649void 650kurobrdfix(struct brdprop *brd) 651{ 652 653 init_uart(uart2base, 9600, LCR_8BITS | LCR_PEVEN); 654 /* Stop Watchdog */ 655 send_sat("AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK"); 656} 657 658void 659synobrdfix(struct brdprop *brd) 660{ 661 662 init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE); 663 /* beep, power LED on, status LED off */ 664 send_sat("247"); 665} 666 667void 668synoreset() 669{ 670 671 send_sat("C"); 672 /*NOTREACHED*/ 673} 674 675void 676qnapbrdfix(struct brdprop *brd) 677{ 678 679 init_uart(uart2base, 19200, LCR_8BITS | LCR_PNONE); 680 /* beep, status LED red */ 681 send_sat("PW"); 682} 683 684void 685qnapreset() 686{ 687 688 send_sat("f"); 689 /*NOTREACHED*/ 690} 691 692void 693iomegabrdfix(struct brdprop *brd) 694{ 695 696 init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE); 697 /* LED flashing blue, fan auto, turn on at 60C, turn off at 50C */ 698 (void)send_iomega('b', 'd', 2, 'a', 60, 50); 699} 700 701void 702iomegareset() 703{ 704 705 (void)send_iomega('g', 0, 0, 0, 0, 0); 706 /*NOTREACHED*/ 707} 708 709void 710dlinkbrdfix(struct brdprop *brd) 711{ 712 713 init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE); 714 send_sat("SYN\n"); 715 send_sat("ZWO\n"); /* power LED solid on */ 716} 717 718void 719nhnasbrdfix(struct brdprop *brd) 720{ 721 722 /* illuminate LEDs */ 723} 724 725void 726_rtt(void) 727{ 728 uint32_t msr; 729 730 netif_shutdown_all(); 731 732 if (brdprop->reset != NULL) 733 (*brdprop->reset)(); 734 else { 735 msr = mfmsr(); 736 msr &= ~PSL_EE; 737 mtmsr(msr); 738 asm volatile ("sync; isync"); 739 asm volatile("mtspr %0,%1" : : "K"(81), "r"(0)); 740 msr &= ~(PSL_ME | PSL_DR | PSL_IR); 741 mtmsr(msr); 742 asm volatile ("sync; isync"); 743 run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */ 744 } 745 /*NOTREACHED*/ 746} 747 748satime_t 749getsecs(void) 750{ 751 u_quad_t tb = mftb(); 752 753 return (tb / ticks_per_sec); 754} 755 756/* 757 * Wait for about n microseconds (at least!). 758 */ 759void 760delay(u_int n) 761{ 762 u_quad_t tb; 763 u_long scratch, tbh, tbl; 764 765 tb = mftb(); 766 tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick; 767 tbh = tb >> 32; 768 tbl = tb; 769 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)); 770} 771 772void 773_wb(uint32_t adr, uint32_t siz) 774{ 775 uint32_t bnd; 776 777 asm volatile("eieio"); 778 for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) 779 asm volatile ("dcbst 0,%0" :: "r"(adr)); 780 asm volatile ("sync"); 781} 782 783void 784_wbinv(uint32_t adr, uint32_t siz) 785{ 786 uint32_t bnd; 787 788 asm volatile("eieio"); 789 for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) 790 asm volatile ("dcbf 0,%0" :: "r"(adr)); 791 asm volatile ("sync"); 792} 793 794void 795_inv(uint32_t adr, uint32_t siz) 796{ 797 uint32_t bnd, off; 798 799 off = adr & (dcache_line_size - 1); 800 adr -= off; 801 siz += off; 802 asm volatile ("eieio"); 803 if (off != 0) { 804 /* wbinv() leading unaligned dcache line */ 805 asm volatile ("dcbf 0,%0" :: "r"(adr)); 806 if (siz < dcache_line_size) 807 goto done; 808 adr += dcache_line_size; 809 siz -= dcache_line_size; 810 } 811 bnd = adr + siz; 812 off = bnd & (dcache_line_size - 1); 813 if (off != 0) { 814 /* wbinv() trailing unaligned dcache line */ 815 asm volatile ("dcbf 0,%0" :: "r"(bnd)); /* it's OK */ 816 if (siz < dcache_line_size) 817 goto done; 818 siz -= off; 819 } 820 for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) { 821 /* inv() intermediate dcache lines if ever */ 822 asm volatile ("dcbi 0,%0" :: "r"(adr)); 823 } 824 done: 825 asm volatile ("sync"); 826} 827 828static inline uint32_t 829mfmsr(void) 830{ 831 uint32_t msr; 832 833 asm volatile ("mfmsr %0" : "=r"(msr)); 834 return msr; 835} 836 837static inline void 838mtmsr(uint32_t msr) 839{ 840 asm volatile ("mtmsr %0" : : "r"(msr)); 841} 842 843static inline uint32_t 844cputype(void) 845{ 846 uint32_t pvr; 847 848 asm volatile ("mfpvr %0" : "=r"(pvr)); 849 return pvr >> 16; 850} 851 852static inline u_quad_t 853mftb(void) 854{ 855 u_long scratch; 856 u_quad_t tb; 857 858 asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b" 859 : "=r"(tb), "=r"(scratch)); 860 return tb; 861} 862 863static void 864init_uart(unsigned base, unsigned speed, uint8_t lcr) 865{ 866 unsigned div; 867 868 div = busclock / speed / 16; 869 UART_WRITE(base, LCR, 0x80); /* turn on DLAB bit */ 870 UART_WRITE(base, FCR, 0x00); 871 UART_WRITE(base, DMB, div >> 8); /* set speed */ 872 UART_WRITE(base, DLB, div & 0xff); 873 UART_WRITE(base, LCR, lcr); 874 UART_WRITE(base, FCR, 0x07); /* FIFO on, TXRX FIFO reset */ 875 UART_WRITE(base, IER, 0x00); /* make sure INT disabled */ 876} 877 878/* talk to satellite processor */ 879static void 880send_sat(char *msg) 881{ 882 unsigned savedbase; 883 884 savedbase = uart1base; 885 uart1base = uart2base; 886 while (*msg) 887 putchar(*msg++); 888 uart1base = savedbase; 889} 890 891#ifdef DEBUG 892static void 893iomega_debug(const char *txt, uint8_t buf[]) 894{ 895 int i; 896 897 printf("%s:", txt); 898 for (i = 0; i < IOMEGA_PACKETSIZE; i++) 899 printf(" %02x", buf[i]); 900 putchar('\n'); 901} 902#endif /* DEBUG */ 903 904static int 905send_iomega(int power, int led, int rate, int fan, int high, int low) 906{ 907 uint8_t buf[IOMEGA_PACKETSIZE]; 908 unsigned i, savedbase; 909 910 savedbase = uart1base; 911 uart1base = uart2base; 912 913 /* first flush the receive buffer */ 914 again: 915 while (tstchar()) 916 (void)getchar(); 917 delay(20000); 918 if (tstchar()) 919 goto again; 920 /* 921 * Now synchronize the transmitter by sending 0x00 922 * until we receive a status reply. 923 */ 924 do { 925 putchar(0); 926 delay(25000); 927 } while (!tstchar()); 928 929 for (i = 0; i < IOMEGA_PACKETSIZE; i++) 930 buf[i] = getchar(); 931#ifdef DEBUG 932 uart1base = savedbase; 933 iomega_debug("68HC908 status", buf); 934 uart1base = uart2base; 935#endif 936 937 /* send command */ 938 if (power >= 0) 939 buf[IOMEGA_POWER] = power; 940 if (led >= 0) 941 buf[IOMEGA_LED] = led; 942 if (rate >= 0) 943 buf[IOMEGA_FLASH_RATE] = rate; 944 if (fan >= 0) 945 buf[IOMEGA_FAN] = fan; 946 if (high >= 0) 947 buf[IOMEGA_HIGH_TEMP] = high; 948 if (low >= 0) 949 buf[IOMEGA_LOW_TEMP] = low; 950 buf[IOMEGA_ID] = 7; /* host id */ 951 buf[IOMEGA_CHECKSUM] = (buf[IOMEGA_POWER] + buf[IOMEGA_LED] + 952 buf[IOMEGA_FLASH_RATE] + buf[IOMEGA_FAN] + 953 buf[IOMEGA_HIGH_TEMP] + buf[IOMEGA_LOW_TEMP] + 954 buf[IOMEGA_ID]) & 0x7f; 955#ifdef DEBUG 956 uart1base = savedbase; 957 iomega_debug("G2 sending", buf); 958 uart1base = uart2base; 959#endif 960 for (i = 0; i < IOMEGA_PACKETSIZE; i++) 961 putchar(buf[i]); 962 963 /* receive the reply */ 964 for (i = 0; i < IOMEGA_PACKETSIZE; i++) 965 buf[i] = getchar(); 966 967 uart1base = savedbase; 968#ifdef DEBUG 969 iomega_debug("68HC908 reply", buf); 970#endif 971 return buf[0] != '#'; /* error? */ 972} 973 974void 975putchar(int c) 976{ 977 unsigned timo, lsr; 978 979 if (c == '\n') 980 putchar('\r'); 981 982 timo = 0x00100000; 983 do { 984 lsr = UART_READ(uart1base, LSR); 985 } while (timo-- > 0 && (lsr & LSR_THRE) == 0); 986 if (timo > 0) 987 UART_WRITE(uart1base, THR, c); 988} 989 990int 991getchar(void) 992{ 993 unsigned lsr; 994 995 do { 996 lsr = UART_READ(uart1base, LSR); 997 } while ((lsr & LSR_DRDY) == 0); 998 return UART_READ(uart1base, RBR); 999} 1000 1001int 1002tstchar(void) 1003{ 1004 1005 return (UART_READ(uart1base, LSR) & LSR_DRDY) != 0; 1006} 1007 1008unsigned 1009mpc107memsize() 1010{ 1011 unsigned bankn, end, n, tag, val; 1012 1013 tag = pcimaketag(0, 0, 0); 1014 1015 if (brdtype == BRD_ENCOREPP1) { 1016 /* the brd's PPCBOOT looks to have erroneous values */ 1017 unsigned tbl[] = { 1018#define MPC106_MEMSTARTADDR1 0x80 1019#define MPC106_EXTMEMSTARTADDR1 0x88 1020#define MPC106_MEMENDADDR1 0x90 1021#define MPC106_EXTMEMENDADDR1 0x98 1022#define MPC106_MEMEN 0xa0 1023#define BK0_S 0x00000000 1024#define BK0_E (128 << 20) - 1 1025#define BK1_S 0x3ff00000 1026#define BK1_E 0x3fffffff 1027#define BK2_S 0x3ff00000 1028#define BK2_E 0x3fffffff 1029#define BK3_S 0x3ff00000 1030#define BK3_E 0x3fffffff 1031#define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s)) 1032#define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s)) 1033#define SAR_MASK 0x0ff00000 1034#define SAR_SHIFT 20 1035#define EAR_MASK 0x30000000 1036#define EAR_SHIFT 28 1037 AR(BK0_S, 0) | AR(BK1_S, 8) | AR(BK2_S, 16) | AR(BK3_S, 24), 1038 XR(BK0_S, 0) | XR(BK1_S, 8) | XR(BK2_S, 16) | XR(BK3_S, 24), 1039 AR(BK0_E, 0) | AR(BK1_E, 8) | AR(BK2_E, 16) | AR(BK3_E, 24), 1040 XR(BK0_E, 0) | XR(BK1_E, 8) | XR(BK2_E, 16) | XR(BK3_E, 24), 1041 }; 1042 tag = pcimaketag(0, 0, 0); 1043 pcicfgwrite(tag, MPC106_MEMSTARTADDR1, tbl[0]); 1044 pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, tbl[1]); 1045 pcicfgwrite(tag, MPC106_MEMENDADDR1, tbl[2]); 1046 pcicfgwrite(tag, MPC106_EXTMEMENDADDR1, tbl[3]); 1047 pcicfgwrite(tag, MPC106_MEMEN, 1); 1048 } 1049 1050 bankn = 0; 1051 val = pcicfgread(tag, MPC106_MEMEN); 1052 for (n = 0; n < 4; n++) { 1053 if ((val & (1U << n)) == 0) 1054 break; 1055 bankn = n; 1056 } 1057 bankn = bankn * 8; 1058 1059 val = pcicfgread(tag, MPC106_EXTMEMENDADDR1); 1060 end = ((val >> bankn) & 0x03) << 28; 1061 val = pcicfgread(tag, MPC106_MEMENDADDR1); 1062 end |= ((val >> bankn) & 0xff) << 20; 1063 end |= 0xfffff; 1064 1065 return (end + 1); /* assume the end address matches total amount */ 1066} 1067 1068struct fis_dir_entry { 1069 char name[16]; 1070 uint32_t startaddr; 1071 uint32_t loadaddr; 1072 uint32_t flashsize; 1073 uint32_t entryaddr; 1074 uint32_t filesize; 1075 char pad[256 - (16 + 5 * sizeof(uint32_t))]; 1076}; 1077 1078#define FIS_LOWER_LIMIT 0xfff00000 1079 1080/* 1081 * Look for a Redboot-style Flash Image System FIS-directory and 1082 * return a pointer to the start address of the requested file. 1083 */ 1084static void * 1085redboot_fis_lookup(const char *filename) 1086{ 1087 static const char FISdirname[16] = { 1088 'F', 'I', 'S', ' ', 1089 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0 1090 }; 1091 struct fis_dir_entry *dir; 1092 1093 /* 1094 * The FIS directory is usually in the last sector of the flash. 1095 * But we do not know the sector size (erase size), so start 1096 * at 0xffffff00 and scan backwards in steps of the FIS directory 1097 * entry size (0x100). 1098 */ 1099 for (dir = (struct fis_dir_entry *)0xffffff00; 1100 (uint32_t)dir >= FIS_LOWER_LIMIT; dir--) 1101 if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0) 1102 break; 1103 if ((uint32_t)dir < FIS_LOWER_LIMIT) { 1104 printf("No FIS directory found!\n"); 1105 return NULL; 1106 } 1107 1108 /* Now find filename by scanning the directory from beginning. */ 1109 dir = (struct fis_dir_entry *)dir->startaddr; 1110 while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) { 1111 if (strcmp(dir->name, filename) == 0) 1112 return (void *)dir->startaddr; /* found */ 1113 dir++; 1114 } 1115 printf("\"%s\" not found in FIS directory!\n", filename); 1116 return NULL; 1117} 1118 1119static void 1120read_mac_string(uint8_t *mac, char *p) 1121{ 1122 int i; 1123 1124 for (i = 0; i < 6; i++, p += 3) 1125 *mac++ = read_hex(p); 1126} 1127 1128/* 1129 * For cost saving reasons some NAS boxes lack SEEPROM for NIC's 1130 * ethernet address and keep it in their Flash memory instead. 1131 */ 1132void 1133read_mac_from_flash(uint8_t *mac) 1134{ 1135 uint8_t *p; 1136 1137 switch (brdtype) { 1138 case BRD_SYNOLOGY: 1139 p = redboot_fis_lookup("vendor"); 1140 if (p == NULL) 1141 break; 1142 memcpy(mac, p, 6); 1143 return; 1144 case BRD_DLINKDSM: 1145 read_mac_string(mac, (char *)0xfff0ff80); 1146 return; 1147 default: 1148 printf("Warning: This board has no known method defined " 1149 "to determine its MAC address!\n"); 1150 break; 1151 } 1152 1153 /* set to 00:00:00:00:00:00 in case of error */ 1154 memset(mac, 0, 6); 1155} 1156 1157#ifdef DEBUG 1158void 1159sat_write(char *p, int len) 1160{ 1161 unsigned savedbase; 1162 1163 savedbase = uart1base; 1164 uart1base = uart2base; 1165 while (len--) 1166 putchar(*p++); 1167 uart1base = savedbase; 1168} 1169 1170int 1171sat_getch(void) 1172{ 1173 unsigned lsr; 1174 1175 do { 1176 lsr = UART_READ(uart2base, LSR); 1177 } while ((lsr & LSR_DRDY) == 0); 1178 return UART_READ(uart2base, RBR); 1179} 1180 1181int 1182sat_tstch(void) 1183{ 1184 1185 return (UART_READ(uart2base, LSR) & LSR_DRDY) != 0; 1186} 1187#endif /* DEBUG */ 1188