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