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