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