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