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