diff options
-rw-r--r-- | arch/powerpc/boot/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/boot/mv64x60.c | 581 | ||||
-rw-r--r-- | arch/powerpc/boot/mv64x60.h | 70 |
3 files changed, 652 insertions, 1 deletions
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 01b683987e7d..77ef7ee9cac6 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -43,7 +43,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \ | |||
43 | src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ | 43 | src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ |
44 | ns16550.c serial.c simple_alloc.c div64.S util.S \ | 44 | ns16550.c serial.c simple_alloc.c div64.S util.S \ |
45 | gunzip_util.c elf_util.c $(zlib) devtree.c \ | 45 | gunzip_util.c elf_util.c $(zlib) devtree.c \ |
46 | 44x.c ebony.c | 46 | 44x.c ebony.c mv64x60.c |
47 | src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ | 47 | src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ |
48 | cuboot-ebony.c treeboot-ebony.c | 48 | cuboot-ebony.c treeboot-ebony.c |
49 | src-boot := $(src-wlib) $(src-plat) empty.c | 49 | src-boot := $(src-wlib) $(src-plat) empty.c |
diff --git a/arch/powerpc/boot/mv64x60.c b/arch/powerpc/boot/mv64x60.c new file mode 100644 index 000000000000..b43259455d4b --- /dev/null +++ b/arch/powerpc/boot/mv64x60.c | |||
@@ -0,0 +1,581 @@ | |||
1 | /* | ||
2 | * Marvell hostbridge routines | ||
3 | * | ||
4 | * Author: Mark A. Greer <source@mvista.com> | ||
5 | * | ||
6 | * 2004, 2005, 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <stdarg.h> | ||
13 | #include <stddef.h> | ||
14 | #include "types.h" | ||
15 | #include "elf.h" | ||
16 | #include "page.h" | ||
17 | #include "string.h" | ||
18 | #include "stdio.h" | ||
19 | #include "io.h" | ||
20 | #include "ops.h" | ||
21 | #include "mv64x60.h" | ||
22 | |||
23 | #define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) | ||
24 | |||
25 | #define MV64x60_CPU2MEM_WINDOWS 4 | ||
26 | #define MV64x60_CPU2MEM_0_BASE 0x0008 | ||
27 | #define MV64x60_CPU2MEM_0_SIZE 0x0010 | ||
28 | #define MV64x60_CPU2MEM_1_BASE 0x0208 | ||
29 | #define MV64x60_CPU2MEM_1_SIZE 0x0210 | ||
30 | #define MV64x60_CPU2MEM_2_BASE 0x0018 | ||
31 | #define MV64x60_CPU2MEM_2_SIZE 0x0020 | ||
32 | #define MV64x60_CPU2MEM_3_BASE 0x0218 | ||
33 | #define MV64x60_CPU2MEM_3_SIZE 0x0220 | ||
34 | |||
35 | #define MV64x60_ENET2MEM_BAR_ENABLE 0x2290 | ||
36 | #define MV64x60_ENET2MEM_0_BASE 0x2200 | ||
37 | #define MV64x60_ENET2MEM_0_SIZE 0x2204 | ||
38 | #define MV64x60_ENET2MEM_1_BASE 0x2208 | ||
39 | #define MV64x60_ENET2MEM_1_SIZE 0x220c | ||
40 | #define MV64x60_ENET2MEM_2_BASE 0x2210 | ||
41 | #define MV64x60_ENET2MEM_2_SIZE 0x2214 | ||
42 | #define MV64x60_ENET2MEM_3_BASE 0x2218 | ||
43 | #define MV64x60_ENET2MEM_3_SIZE 0x221c | ||
44 | #define MV64x60_ENET2MEM_4_BASE 0x2220 | ||
45 | #define MV64x60_ENET2MEM_4_SIZE 0x2224 | ||
46 | #define MV64x60_ENET2MEM_5_BASE 0x2228 | ||
47 | #define MV64x60_ENET2MEM_5_SIZE 0x222c | ||
48 | #define MV64x60_ENET2MEM_ACC_PROT_0 0x2294 | ||
49 | #define MV64x60_ENET2MEM_ACC_PROT_1 0x2298 | ||
50 | #define MV64x60_ENET2MEM_ACC_PROT_2 0x229c | ||
51 | |||
52 | #define MV64x60_MPSC2MEM_BAR_ENABLE 0xf250 | ||
53 | #define MV64x60_MPSC2MEM_0_BASE 0xf200 | ||
54 | #define MV64x60_MPSC2MEM_0_SIZE 0xf204 | ||
55 | #define MV64x60_MPSC2MEM_1_BASE 0xf208 | ||
56 | #define MV64x60_MPSC2MEM_1_SIZE 0xf20c | ||
57 | #define MV64x60_MPSC2MEM_2_BASE 0xf210 | ||
58 | #define MV64x60_MPSC2MEM_2_SIZE 0xf214 | ||
59 | #define MV64x60_MPSC2MEM_3_BASE 0xf218 | ||
60 | #define MV64x60_MPSC2MEM_3_SIZE 0xf21c | ||
61 | #define MV64x60_MPSC_0_REMAP 0xf240 | ||
62 | #define MV64x60_MPSC_1_REMAP 0xf244 | ||
63 | #define MV64x60_MPSC2MEM_ACC_PROT_0 0xf254 | ||
64 | #define MV64x60_MPSC2MEM_ACC_PROT_1 0xf258 | ||
65 | #define MV64x60_MPSC2REGS_BASE 0xf25c | ||
66 | |||
67 | #define MV64x60_IDMA2MEM_BAR_ENABLE 0x0a80 | ||
68 | #define MV64x60_IDMA2MEM_0_BASE 0x0a00 | ||
69 | #define MV64x60_IDMA2MEM_0_SIZE 0x0a04 | ||
70 | #define MV64x60_IDMA2MEM_1_BASE 0x0a08 | ||
71 | #define MV64x60_IDMA2MEM_1_SIZE 0x0a0c | ||
72 | #define MV64x60_IDMA2MEM_2_BASE 0x0a10 | ||
73 | #define MV64x60_IDMA2MEM_2_SIZE 0x0a14 | ||
74 | #define MV64x60_IDMA2MEM_3_BASE 0x0a18 | ||
75 | #define MV64x60_IDMA2MEM_3_SIZE 0x0a1c | ||
76 | #define MV64x60_IDMA2MEM_4_BASE 0x0a20 | ||
77 | #define MV64x60_IDMA2MEM_4_SIZE 0x0a24 | ||
78 | #define MV64x60_IDMA2MEM_5_BASE 0x0a28 | ||
79 | #define MV64x60_IDMA2MEM_5_SIZE 0x0a2c | ||
80 | #define MV64x60_IDMA2MEM_6_BASE 0x0a30 | ||
81 | #define MV64x60_IDMA2MEM_6_SIZE 0x0a34 | ||
82 | #define MV64x60_IDMA2MEM_7_BASE 0x0a38 | ||
83 | #define MV64x60_IDMA2MEM_7_SIZE 0x0a3c | ||
84 | #define MV64x60_IDMA2MEM_ACC_PROT_0 0x0a70 | ||
85 | #define MV64x60_IDMA2MEM_ACC_PROT_1 0x0a74 | ||
86 | #define MV64x60_IDMA2MEM_ACC_PROT_2 0x0a78 | ||
87 | #define MV64x60_IDMA2MEM_ACC_PROT_3 0x0a7c | ||
88 | |||
89 | #define MV64x60_PCI_ACC_CNTL_WINDOWS 6 | ||
90 | #define MV64x60_PCI0_PCI_DECODE_CNTL 0x0d3c | ||
91 | #define MV64x60_PCI1_PCI_DECODE_CNTL 0x0dbc | ||
92 | |||
93 | #define MV64x60_PCI0_BAR_ENABLE 0x0c3c | ||
94 | #define MV64x60_PCI02MEM_0_SIZE 0x0c08 | ||
95 | #define MV64x60_PCI0_ACC_CNTL_0_BASE_LO 0x1e00 | ||
96 | #define MV64x60_PCI0_ACC_CNTL_0_BASE_HI 0x1e04 | ||
97 | #define MV64x60_PCI0_ACC_CNTL_0_SIZE 0x1e08 | ||
98 | #define MV64x60_PCI0_ACC_CNTL_1_BASE_LO 0x1e10 | ||
99 | #define MV64x60_PCI0_ACC_CNTL_1_BASE_HI 0x1e14 | ||
100 | #define MV64x60_PCI0_ACC_CNTL_1_SIZE 0x1e18 | ||
101 | #define MV64x60_PCI0_ACC_CNTL_2_BASE_LO 0x1e20 | ||
102 | #define MV64x60_PCI0_ACC_CNTL_2_BASE_HI 0x1e24 | ||
103 | #define MV64x60_PCI0_ACC_CNTL_2_SIZE 0x1e28 | ||
104 | #define MV64x60_PCI0_ACC_CNTL_3_BASE_LO 0x1e30 | ||
105 | #define MV64x60_PCI0_ACC_CNTL_3_BASE_HI 0x1e34 | ||
106 | #define MV64x60_PCI0_ACC_CNTL_3_SIZE 0x1e38 | ||
107 | #define MV64x60_PCI0_ACC_CNTL_4_BASE_LO 0x1e40 | ||
108 | #define MV64x60_PCI0_ACC_CNTL_4_BASE_HI 0x1e44 | ||
109 | #define MV64x60_PCI0_ACC_CNTL_4_SIZE 0x1e48 | ||
110 | #define MV64x60_PCI0_ACC_CNTL_5_BASE_LO 0x1e50 | ||
111 | #define MV64x60_PCI0_ACC_CNTL_5_BASE_HI 0x1e54 | ||
112 | #define MV64x60_PCI0_ACC_CNTL_5_SIZE 0x1e58 | ||
113 | |||
114 | #define MV64x60_PCI1_BAR_ENABLE 0x0cbc | ||
115 | #define MV64x60_PCI12MEM_0_SIZE 0x0c88 | ||
116 | #define MV64x60_PCI1_ACC_CNTL_0_BASE_LO 0x1e80 | ||
117 | #define MV64x60_PCI1_ACC_CNTL_0_BASE_HI 0x1e84 | ||
118 | #define MV64x60_PCI1_ACC_CNTL_0_SIZE 0x1e88 | ||
119 | #define MV64x60_PCI1_ACC_CNTL_1_BASE_LO 0x1e90 | ||
120 | #define MV64x60_PCI1_ACC_CNTL_1_BASE_HI 0x1e94 | ||
121 | #define MV64x60_PCI1_ACC_CNTL_1_SIZE 0x1e98 | ||
122 | #define MV64x60_PCI1_ACC_CNTL_2_BASE_LO 0x1ea0 | ||
123 | #define MV64x60_PCI1_ACC_CNTL_2_BASE_HI 0x1ea4 | ||
124 | #define MV64x60_PCI1_ACC_CNTL_2_SIZE 0x1ea8 | ||
125 | #define MV64x60_PCI1_ACC_CNTL_3_BASE_LO 0x1eb0 | ||
126 | #define MV64x60_PCI1_ACC_CNTL_3_BASE_HI 0x1eb4 | ||
127 | #define MV64x60_PCI1_ACC_CNTL_3_SIZE 0x1eb8 | ||
128 | #define MV64x60_PCI1_ACC_CNTL_4_BASE_LO 0x1ec0 | ||
129 | #define MV64x60_PCI1_ACC_CNTL_4_BASE_HI 0x1ec4 | ||
130 | #define MV64x60_PCI1_ACC_CNTL_4_SIZE 0x1ec8 | ||
131 | #define MV64x60_PCI1_ACC_CNTL_5_BASE_LO 0x1ed0 | ||
132 | #define MV64x60_PCI1_ACC_CNTL_5_BASE_HI 0x1ed4 | ||
133 | #define MV64x60_PCI1_ACC_CNTL_5_SIZE 0x1ed8 | ||
134 | |||
135 | #define MV64x60_CPU2PCI_SWAP_NONE 0x01000000 | ||
136 | |||
137 | #define MV64x60_CPU2PCI0_IO_BASE 0x0048 | ||
138 | #define MV64x60_CPU2PCI0_IO_SIZE 0x0050 | ||
139 | #define MV64x60_CPU2PCI0_IO_REMAP 0x00f0 | ||
140 | #define MV64x60_CPU2PCI0_MEM_0_BASE 0x0058 | ||
141 | #define MV64x60_CPU2PCI0_MEM_0_SIZE 0x0060 | ||
142 | #define MV64x60_CPU2PCI0_MEM_0_REMAP_LO 0x00f8 | ||
143 | #define MV64x60_CPU2PCI0_MEM_0_REMAP_HI 0x0320 | ||
144 | |||
145 | #define MV64x60_CPU2PCI1_IO_BASE 0x0090 | ||
146 | #define MV64x60_CPU2PCI1_IO_SIZE 0x0098 | ||
147 | #define MV64x60_CPU2PCI1_IO_REMAP 0x0108 | ||
148 | #define MV64x60_CPU2PCI1_MEM_0_BASE 0x00a0 | ||
149 | #define MV64x60_CPU2PCI1_MEM_0_SIZE 0x00a8 | ||
150 | #define MV64x60_CPU2PCI1_MEM_0_REMAP_LO 0x0110 | ||
151 | #define MV64x60_CPU2PCI1_MEM_0_REMAP_HI 0x0340 | ||
152 | |||
153 | struct mv64x60_mem_win { | ||
154 | u32 hi; | ||
155 | u32 lo; | ||
156 | u32 size; | ||
157 | }; | ||
158 | |||
159 | struct mv64x60_pci_win { | ||
160 | u32 fcn; | ||
161 | u32 hi; | ||
162 | u32 lo; | ||
163 | u32 size; | ||
164 | }; | ||
165 | |||
166 | /* PCI config access routines */ | ||
167 | struct { | ||
168 | u32 addr; | ||
169 | u32 data; | ||
170 | } static mv64x60_pci_cfgio[2] = { | ||
171 | { /* hose 0 */ | ||
172 | .addr = 0xcf8, | ||
173 | .data = 0xcfc, | ||
174 | }, | ||
175 | { /* hose 1 */ | ||
176 | .addr = 0xc78, | ||
177 | .data = 0xc7c, | ||
178 | } | ||
179 | }; | ||
180 | |||
181 | u32 mv64x60_cfg_read(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset) | ||
182 | { | ||
183 | out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), | ||
184 | (1 << 31) | (bus << 16) | (devfn << 8) | offset); | ||
185 | return in_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data)); | ||
186 | } | ||
187 | |||
188 | void mv64x60_cfg_write(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset, | ||
189 | u32 val) | ||
190 | { | ||
191 | out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), | ||
192 | (1 << 31) | (bus << 16) | (devfn << 8) | offset); | ||
193 | out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data), val); | ||
194 | } | ||
195 | |||
196 | /* I/O ctlr -> system memory setup */ | ||
197 | static struct mv64x60_mem_win mv64x60_cpu2mem[MV64x60_CPU2MEM_WINDOWS] = { | ||
198 | { | ||
199 | .lo = MV64x60_CPU2MEM_0_BASE, | ||
200 | .size = MV64x60_CPU2MEM_0_SIZE, | ||
201 | }, | ||
202 | { | ||
203 | .lo = MV64x60_CPU2MEM_1_BASE, | ||
204 | .size = MV64x60_CPU2MEM_1_SIZE, | ||
205 | }, | ||
206 | { | ||
207 | .lo = MV64x60_CPU2MEM_2_BASE, | ||
208 | .size = MV64x60_CPU2MEM_2_SIZE, | ||
209 | }, | ||
210 | { | ||
211 | .lo = MV64x60_CPU2MEM_3_BASE, | ||
212 | .size = MV64x60_CPU2MEM_3_SIZE, | ||
213 | }, | ||
214 | }; | ||
215 | |||
216 | static struct mv64x60_mem_win mv64x60_enet2mem[MV64x60_CPU2MEM_WINDOWS] = { | ||
217 | { | ||
218 | .lo = MV64x60_ENET2MEM_0_BASE, | ||
219 | .size = MV64x60_ENET2MEM_0_SIZE, | ||
220 | }, | ||
221 | { | ||
222 | .lo = MV64x60_ENET2MEM_1_BASE, | ||
223 | .size = MV64x60_ENET2MEM_1_SIZE, | ||
224 | }, | ||
225 | { | ||
226 | .lo = MV64x60_ENET2MEM_2_BASE, | ||
227 | .size = MV64x60_ENET2MEM_2_SIZE, | ||
228 | }, | ||
229 | { | ||
230 | .lo = MV64x60_ENET2MEM_3_BASE, | ||
231 | .size = MV64x60_ENET2MEM_3_SIZE, | ||
232 | }, | ||
233 | }; | ||
234 | |||
235 | static struct mv64x60_mem_win mv64x60_mpsc2mem[MV64x60_CPU2MEM_WINDOWS] = { | ||
236 | { | ||
237 | .lo = MV64x60_MPSC2MEM_0_BASE, | ||
238 | .size = MV64x60_MPSC2MEM_0_SIZE, | ||
239 | }, | ||
240 | { | ||
241 | .lo = MV64x60_MPSC2MEM_1_BASE, | ||
242 | .size = MV64x60_MPSC2MEM_1_SIZE, | ||
243 | }, | ||
244 | { | ||
245 | .lo = MV64x60_MPSC2MEM_2_BASE, | ||
246 | .size = MV64x60_MPSC2MEM_2_SIZE, | ||
247 | }, | ||
248 | { | ||
249 | .lo = MV64x60_MPSC2MEM_3_BASE, | ||
250 | .size = MV64x60_MPSC2MEM_3_SIZE, | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static struct mv64x60_mem_win mv64x60_idma2mem[MV64x60_CPU2MEM_WINDOWS] = { | ||
255 | { | ||
256 | .lo = MV64x60_IDMA2MEM_0_BASE, | ||
257 | .size = MV64x60_IDMA2MEM_0_SIZE, | ||
258 | }, | ||
259 | { | ||
260 | .lo = MV64x60_IDMA2MEM_1_BASE, | ||
261 | .size = MV64x60_IDMA2MEM_1_SIZE, | ||
262 | }, | ||
263 | { | ||
264 | .lo = MV64x60_IDMA2MEM_2_BASE, | ||
265 | .size = MV64x60_IDMA2MEM_2_SIZE, | ||
266 | }, | ||
267 | { | ||
268 | .lo = MV64x60_IDMA2MEM_3_BASE, | ||
269 | .size = MV64x60_IDMA2MEM_3_SIZE, | ||
270 | }, | ||
271 | }; | ||
272 | |||
273 | static u32 mv64x60_dram_selects[MV64x60_CPU2MEM_WINDOWS] = {0xe,0xd,0xb,0x7}; | ||
274 | |||
275 | /* | ||
276 | * ENET, MPSC, and IDMA ctlrs on the MV64x60 have separate windows that | ||
277 | * must be set up so that the respective ctlr can access system memory. | ||
278 | * Configure them to be same as cpu->memory windows. | ||
279 | */ | ||
280 | void mv64x60_config_ctlr_windows(u8 *bridge_base, u8 *bridge_pbase, | ||
281 | u8 is_coherent) | ||
282 | { | ||
283 | u32 i, base, size, enables, prot = 0, snoop_bits = 0; | ||
284 | |||
285 | /* Disable ctlr->mem windows */ | ||
286 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0x3f); | ||
287 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), 0xf); | ||
288 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0xff); | ||
289 | |||
290 | if (is_coherent) | ||
291 | snoop_bits = 0x2 << 12; /* Writeback */ | ||
292 | |||
293 | enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; | ||
294 | |||
295 | for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) { | ||
296 | if (enables & (1 << i)) /* Set means disabled */ | ||
297 | continue; | ||
298 | |||
299 | base = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].lo)) | ||
300 | << 16; | ||
301 | base |= snoop_bits | (mv64x60_dram_selects[i] << 8); | ||
302 | size = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].size)) | ||
303 | << 16; | ||
304 | prot |= (0x3 << (i << 1)); /* RW access */ | ||
305 | |||
306 | out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].lo), base); | ||
307 | out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].size), size); | ||
308 | out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].lo), base); | ||
309 | out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].size), size); | ||
310 | out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].lo), base); | ||
311 | out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].size), size); | ||
312 | } | ||
313 | |||
314 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_0), prot); | ||
315 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_1), prot); | ||
316 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_2), prot); | ||
317 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_0), prot); | ||
318 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_1), prot); | ||
319 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_0), prot); | ||
320 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_1), prot); | ||
321 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_2), prot); | ||
322 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_3), prot); | ||
323 | |||
324 | /* Set mpsc->bridge's reg window to the bridge's internal registers. */ | ||
325 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2REGS_BASE), | ||
326 | (u32)bridge_pbase); | ||
327 | |||
328 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), enables); | ||
329 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), enables); | ||
330 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_BAR_ENABLE), enables); | ||
331 | } | ||
332 | |||
333 | /* PCI MEM -> system memory, et. al. setup */ | ||
334 | static struct mv64x60_pci_win mv64x60_pci2mem[2] = { | ||
335 | { /* hose 0 */ | ||
336 | .fcn = 0, | ||
337 | .hi = 0x14, | ||
338 | .lo = 0x10, | ||
339 | .size = MV64x60_PCI02MEM_0_SIZE, | ||
340 | }, | ||
341 | { /* hose 1 */ | ||
342 | .fcn = 0, | ||
343 | .hi = 0x94, | ||
344 | .lo = 0x90, | ||
345 | .size = MV64x60_PCI12MEM_0_SIZE, | ||
346 | }, | ||
347 | }; | ||
348 | |||
349 | static struct | ||
350 | mv64x60_mem_win mv64x60_pci_acc[2][MV64x60_PCI_ACC_CNTL_WINDOWS] = { | ||
351 | { /* hose 0 */ | ||
352 | { | ||
353 | .hi = MV64x60_PCI0_ACC_CNTL_0_BASE_HI, | ||
354 | .lo = MV64x60_PCI0_ACC_CNTL_0_BASE_LO, | ||
355 | .size = MV64x60_PCI0_ACC_CNTL_0_SIZE, | ||
356 | }, | ||
357 | { | ||
358 | .hi = MV64x60_PCI0_ACC_CNTL_1_BASE_HI, | ||
359 | .lo = MV64x60_PCI0_ACC_CNTL_1_BASE_LO, | ||
360 | .size = MV64x60_PCI0_ACC_CNTL_1_SIZE, | ||
361 | }, | ||
362 | { | ||
363 | .hi = MV64x60_PCI0_ACC_CNTL_2_BASE_HI, | ||
364 | .lo = MV64x60_PCI0_ACC_CNTL_2_BASE_LO, | ||
365 | .size = MV64x60_PCI0_ACC_CNTL_2_SIZE, | ||
366 | }, | ||
367 | { | ||
368 | .hi = MV64x60_PCI0_ACC_CNTL_3_BASE_HI, | ||
369 | .lo = MV64x60_PCI0_ACC_CNTL_3_BASE_LO, | ||
370 | .size = MV64x60_PCI0_ACC_CNTL_3_SIZE, | ||
371 | }, | ||
372 | }, | ||
373 | { /* hose 1 */ | ||
374 | { | ||
375 | .hi = MV64x60_PCI1_ACC_CNTL_0_BASE_HI, | ||
376 | .lo = MV64x60_PCI1_ACC_CNTL_0_BASE_LO, | ||
377 | .size = MV64x60_PCI1_ACC_CNTL_0_SIZE, | ||
378 | }, | ||
379 | { | ||
380 | .hi = MV64x60_PCI1_ACC_CNTL_1_BASE_HI, | ||
381 | .lo = MV64x60_PCI1_ACC_CNTL_1_BASE_LO, | ||
382 | .size = MV64x60_PCI1_ACC_CNTL_1_SIZE, | ||
383 | }, | ||
384 | { | ||
385 | .hi = MV64x60_PCI1_ACC_CNTL_2_BASE_HI, | ||
386 | .lo = MV64x60_PCI1_ACC_CNTL_2_BASE_LO, | ||
387 | .size = MV64x60_PCI1_ACC_CNTL_2_SIZE, | ||
388 | }, | ||
389 | { | ||
390 | .hi = MV64x60_PCI1_ACC_CNTL_3_BASE_HI, | ||
391 | .lo = MV64x60_PCI1_ACC_CNTL_3_BASE_LO, | ||
392 | .size = MV64x60_PCI1_ACC_CNTL_3_SIZE, | ||
393 | }, | ||
394 | }, | ||
395 | }; | ||
396 | |||
397 | static struct mv64x60_mem_win mv64x60_pci2reg[2] = { | ||
398 | { | ||
399 | .hi = 0x24, | ||
400 | .lo = 0x20, | ||
401 | .size = 0, | ||
402 | }, | ||
403 | { | ||
404 | .hi = 0xa4, | ||
405 | .lo = 0xa0, | ||
406 | .size = 0, | ||
407 | }, | ||
408 | }; | ||
409 | |||
410 | /* Only need to use 1 window (per hose) to get access to all of system memory */ | ||
411 | void mv64x60_config_pci_windows(u8 *bridge_base, u8 *bridge_pbase, u8 hose, | ||
412 | u8 bus, u32 mem_size, u32 acc_bits) | ||
413 | { | ||
414 | u32 i, offset, bar_enable, enables; | ||
415 | |||
416 | /* Disable all windows but PCI MEM -> Bridge's regs window */ | ||
417 | enables = ~(1 << 9); | ||
418 | bar_enable = hose ? MV64x60_PCI1_BAR_ENABLE : MV64x60_PCI0_BAR_ENABLE; | ||
419 | out_le32((u32 *)(bridge_base + bar_enable), enables); | ||
420 | |||
421 | for (i=0; i<MV64x60_PCI_ACC_CNTL_WINDOWS; i++) | ||
422 | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][i].lo), 0); | ||
423 | |||
424 | /* If mem_size is 0, leave windows disabled */ | ||
425 | if (mem_size == 0) | ||
426 | return; | ||
427 | |||
428 | /* Cause automatic updates of PCI remap regs */ | ||
429 | offset = hose ? | ||
430 | MV64x60_PCI1_PCI_DECODE_CNTL : MV64x60_PCI0_PCI_DECODE_CNTL; | ||
431 | i = in_le32((u32 *)(bridge_base + offset)); | ||
432 | out_le32((u32 *)(bridge_base + offset), i & ~0x1); | ||
433 | |||
434 | mem_size = (mem_size - 1) & 0xfffff000; | ||
435 | |||
436 | /* Map PCI MEM addr 0 -> System Mem addr 0 */ | ||
437 | mv64x60_cfg_write(bridge_base, hose, bus, | ||
438 | PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), | ||
439 | mv64x60_pci2mem[hose].hi, 0); | ||
440 | mv64x60_cfg_write(bridge_base, hose, bus, | ||
441 | PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), | ||
442 | mv64x60_pci2mem[hose].lo, 0); | ||
443 | out_le32((u32 *)(bridge_base + mv64x60_pci2mem[hose].size),mem_size); | ||
444 | |||
445 | acc_bits |= MV64x60_PCI_ACC_CNTL_ENABLE; | ||
446 | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].hi), 0); | ||
447 | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].lo), acc_bits); | ||
448 | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].size),mem_size); | ||
449 | |||
450 | /* Set PCI MEM->bridge's reg window to where they are in CPU mem map */ | ||
451 | i = (u32)bridge_base; | ||
452 | i &= 0xffff0000; | ||
453 | i |= (0x2 << 1); | ||
454 | mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), | ||
455 | mv64x60_pci2reg[hose].hi, 0); | ||
456 | mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), | ||
457 | mv64x60_pci2reg[hose].lo, i); | ||
458 | |||
459 | enables &= ~0x1; /* Enable PCI MEM -> System Mem window 0 */ | ||
460 | out_le32((u32 *)(bridge_base + bar_enable), enables); | ||
461 | } | ||
462 | |||
463 | /* CPU -> PCI I/O & MEM setup */ | ||
464 | struct mv64x60_cpu2pci_win mv64x60_cpu2pci_io[2] = { | ||
465 | { /* hose 0 */ | ||
466 | .lo = MV64x60_CPU2PCI0_IO_BASE, | ||
467 | .size = MV64x60_CPU2PCI0_IO_SIZE, | ||
468 | .remap_hi = 0, | ||
469 | .remap_lo = MV64x60_CPU2PCI0_IO_REMAP, | ||
470 | }, | ||
471 | { /* hose 1 */ | ||
472 | .lo = MV64x60_CPU2PCI1_IO_BASE, | ||
473 | .size = MV64x60_CPU2PCI1_IO_SIZE, | ||
474 | .remap_hi = 0, | ||
475 | .remap_lo = MV64x60_CPU2PCI1_IO_REMAP, | ||
476 | }, | ||
477 | }; | ||
478 | |||
479 | struct mv64x60_cpu2pci_win mv64x60_cpu2pci_mem[2] = { | ||
480 | { /* hose 0 */ | ||
481 | .lo = MV64x60_CPU2PCI0_MEM_0_BASE, | ||
482 | .size = MV64x60_CPU2PCI0_MEM_0_SIZE, | ||
483 | .remap_hi = MV64x60_CPU2PCI0_MEM_0_REMAP_HI, | ||
484 | .remap_lo = MV64x60_CPU2PCI0_MEM_0_REMAP_LO, | ||
485 | }, | ||
486 | { /* hose 1 */ | ||
487 | .lo = MV64x60_CPU2PCI1_MEM_0_BASE, | ||
488 | .size = MV64x60_CPU2PCI1_MEM_0_SIZE, | ||
489 | .remap_hi = MV64x60_CPU2PCI1_MEM_0_REMAP_HI, | ||
490 | .remap_lo = MV64x60_CPU2PCI1_MEM_0_REMAP_LO, | ||
491 | }, | ||
492 | }; | ||
493 | |||
494 | /* Only need to set up 1 window to pci mem space */ | ||
495 | void mv64x60_config_cpu2pci_window(u8 *bridge_base, u8 hose, u32 pci_base_hi, | ||
496 | u32 pci_base_lo, u32 cpu_base, u32 size, | ||
497 | struct mv64x60_cpu2pci_win *offset_tbl) | ||
498 | { | ||
499 | cpu_base >>= 16; | ||
500 | cpu_base |= MV64x60_CPU2PCI_SWAP_NONE; | ||
501 | out_le32((u32 *)(bridge_base + offset_tbl[hose].lo), cpu_base); | ||
502 | |||
503 | if (offset_tbl[hose].remap_hi != 0) | ||
504 | out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_hi), | ||
505 | pci_base_hi); | ||
506 | out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_lo), | ||
507 | pci_base_lo >> 16); | ||
508 | |||
509 | size = (size - 1) >> 16; | ||
510 | out_le32((u32 *)(bridge_base + offset_tbl[hose].size), size); | ||
511 | } | ||
512 | |||
513 | /* Read mem ctlr to get the amount of mem in system */ | ||
514 | u32 mv64x60_get_mem_size(u8 *bridge_base) | ||
515 | { | ||
516 | u32 enables, i, v; | ||
517 | u32 mem = 0; | ||
518 | |||
519 | enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; | ||
520 | |||
521 | for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) | ||
522 | if (!(enables & (1<<i))) { | ||
523 | v = in_le32((u32*)(bridge_base | ||
524 | + mv64x60_cpu2mem[i].size)); | ||
525 | v = ((v & 0xffff) + 1) << 16; | ||
526 | mem += v; | ||
527 | } | ||
528 | |||
529 | return mem; | ||
530 | } | ||
531 | |||
532 | /* Get physical address of bridge's registers */ | ||
533 | u8 *mv64x60_get_bridge_pbase(void) | ||
534 | { | ||
535 | u32 v[2]; | ||
536 | void *devp; | ||
537 | |||
538 | devp = finddevice("/mv64x60"); | ||
539 | if (devp == NULL) | ||
540 | goto err_out; | ||
541 | if (getprop(devp, "reg", v, sizeof(v)) != sizeof(v)) | ||
542 | goto err_out; | ||
543 | |||
544 | return (u8 *)v[0]; | ||
545 | |||
546 | err_out: | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | /* Get virtual address of bridge's registers */ | ||
551 | u8 *mv64x60_get_bridge_base(void) | ||
552 | { | ||
553 | u32 v; | ||
554 | void *devp; | ||
555 | |||
556 | devp = finddevice("/mv64x60"); | ||
557 | if (devp == NULL) | ||
558 | goto err_out; | ||
559 | if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v)) | ||
560 | goto err_out; | ||
561 | |||
562 | return (u8 *)v; | ||
563 | |||
564 | err_out: | ||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | u8 mv64x60_is_coherent(void) | ||
569 | { | ||
570 | u32 v; | ||
571 | void *devp; | ||
572 | |||
573 | devp = finddevice("/"); | ||
574 | if (devp == NULL) | ||
575 | return 1; /* Assume coherency on */ | ||
576 | |||
577 | if (getprop(devp, "coherency-off", &v, sizeof(v)) < 0) | ||
578 | return 1; /* Coherency on */ | ||
579 | else | ||
580 | return 0; | ||
581 | } | ||
diff --git a/arch/powerpc/boot/mv64x60.h b/arch/powerpc/boot/mv64x60.h new file mode 100644 index 000000000000..b827105e6e54 --- /dev/null +++ b/arch/powerpc/boot/mv64x60.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Author: Mark A. Greer <source@mvista.com> | ||
3 | * | ||
4 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
5 | * the terms of the GNU General Public License version 2. This program | ||
6 | * is licensed "as is" without any warranty of any kind, whether express | ||
7 | * or implied. | ||
8 | */ | ||
9 | |||
10 | #ifndef _PPC_BOOT_MV64x60_H_ | ||
11 | #define _PPC_BOOT_MV64x60_H_ | ||
12 | |||
13 | #define MV64x60_CPU_BAR_ENABLE 0x0278 | ||
14 | |||
15 | #define MV64x60_PCI_ACC_CNTL_ENABLE (1<<0) | ||
16 | #define MV64x60_PCI_ACC_CNTL_REQ64 (1<<1) | ||
17 | #define MV64x60_PCI_ACC_CNTL_SNOOP_NONE 0x00000000 | ||
18 | #define MV64x60_PCI_ACC_CNTL_SNOOP_WT 0x00000004 | ||
19 | #define MV64x60_PCI_ACC_CNTL_SNOOP_WB 0x00000008 | ||
20 | #define MV64x60_PCI_ACC_CNTL_SNOOP_MASK 0x0000000c | ||
21 | #define MV64x60_PCI_ACC_CNTL_ACCPROT (1<<4) | ||
22 | #define MV64x60_PCI_ACC_CNTL_WRPROT (1<<5) | ||
23 | #define MV64x60_PCI_ACC_CNTL_SWAP_BYTE 0x00000000 | ||
24 | #define MV64x60_PCI_ACC_CNTL_SWAP_NONE 0x00000040 | ||
25 | #define MV64x60_PCI_ACC_CNTL_SWAP_BYTE_WORD 0x00000080 | ||
26 | #define MV64x60_PCI_ACC_CNTL_SWAP_WORD 0x000000c0 | ||
27 | #define MV64x60_PCI_ACC_CNTL_SWAP_MASK 0x000000c0 | ||
28 | #define MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES 0x00000000 | ||
29 | #define MV64x60_PCI_ACC_CNTL_MBURST_64_BYTES 0x00000100 | ||
30 | #define MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES 0x00000200 | ||
31 | #define MV64x60_PCI_ACC_CNTL_MBURST_MASK 0x00000300 | ||
32 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES 0x00000000 | ||
33 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_64_BYTES 0x00000400 | ||
34 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_128_BYTES 0x00000800 | ||
35 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES 0x00000c00 | ||
36 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_MASK 0x00000c00 | ||
37 | |||
38 | struct mv64x60_cpu2pci_win { | ||
39 | u32 lo; | ||
40 | u32 size; | ||
41 | u32 remap_hi; | ||
42 | u32 remap_lo; | ||
43 | }; | ||
44 | |||
45 | extern struct mv64x60_cpu2pci_win mv64x60_cpu2pci_io[2]; | ||
46 | extern struct mv64x60_cpu2pci_win mv64x60_cpu2pci_mem[2]; | ||
47 | |||
48 | u32 mv64x60_cfg_read(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, | ||
49 | u8 offset); | ||
50 | void mv64x60_cfg_write(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, | ||
51 | u8 offset, u32 val); | ||
52 | |||
53 | void mv64x60_config_ctlr_windows(u8 *bridge_base, u8 *bridge_pbase, | ||
54 | u8 is_coherent); | ||
55 | void mv64x60_config_pci_windows(u8 *bridge_base, u8 *bridge_pbase, u8 hose, | ||
56 | u8 bus, u32 mem_size, u32 acc_bits); | ||
57 | void mv64x60_config_cpu2pci_window(u8 *bridge_base, u8 hose, u32 pci_base_hi, | ||
58 | u32 pci_base_lo, u32 cpu_base, u32 size, | ||
59 | struct mv64x60_cpu2pci_win *offset_tbl); | ||
60 | u32 mv64x60_get_mem_size(u8 *bridge_base); | ||
61 | u8 *mv64x60_get_bridge_pbase(void); | ||
62 | u8 *mv64x60_get_bridge_base(void); | ||
63 | u8 mv64x60_is_coherent(void); | ||
64 | |||
65 | int mv64x60_i2c_open(void); | ||
66 | int mv64x60_i2c_read(u32 devaddr, u8 *buf, u32 offset, u32 offset_size, | ||
67 | u32 count); | ||
68 | void mv64x60_i2c_close(void); | ||
69 | |||
70 | #endif /* _PPC_BOOT_MV64x60_H_ */ | ||