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