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