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