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