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