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