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