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