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