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