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