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