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