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