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