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