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