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