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