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