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