aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot/mv64x60.c
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@mvista.com>2007-05-11 20:54:05 -0400
committerPaul Mackerras <paulus@samba.org>2007-05-11 21:32:49 -0400
commit0f81b11d2a14adaa9b2c944f104e13d72fedc769 (patch)
tree027a2753d7e98a131091b2699888b53eea8d6e6d /arch/powerpc/boot/mv64x60.c
parent916066d5913c37a6b3907eb6695cc9ecaaa4d8ca (diff)
[POWERPC] Add bootwrapper support for Marvell/mv64x60 hostbridge
The mv64x60 host bridge has many windows between its various components (cpu, system memory, ethernet ctlr, MPSC, DMA ctlr, PCI MEM, PCI I/O). Unfortunately, the firmware on some of mv64x60-based platforms do not properly or completely configure those windows (e.g., MPSC->system memory windows not configured or CPU->PCI MEM space not configured). So, the missing configuration needs to be done in either the bootwrapper or in the kernel. To keep the kernel as clean as possible, it is done in the bootwrapper. Note that I/O controller configuration is NOT being done, its only the windows to allow the I/O controllers and other components to access memory, etc. that is being done--drivers assume that their controllers can already access system memory). Table of routines and the windows they configure: mv64x60_config_ctlr_windows() ENET->System Memory MPSC->System Memory IDMA->System Memory mv64x60_config_pci_windows() PCI MEM->System Memory PCI I/O->Bridge's Registers mv64x60_config_cpu2pci_window() CPU->PCI MEM CPU->PCI I/O Signed-off-by: Mark A. Greer <mgreer@mvista.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/boot/mv64x60.c')
-rw-r--r--arch/powerpc/boot/mv64x60.c581
1 files changed, 581 insertions, 0 deletions
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
153struct mv64x60_mem_win {
154 u32 hi;
155 u32 lo;
156 u32 size;
157};
158
159struct mv64x60_pci_win {
160 u32 fcn;
161 u32 hi;
162 u32 lo;
163 u32 size;
164};
165
166/* PCI config access routines */
167struct {
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
181u32 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
188void 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 */
197static 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
216static 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
235static 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
254static 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
273static 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 */
280void 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 */
334static 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
349static struct
350mv64x60_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
397static 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 */
411void 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 */
464struct 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
479struct 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 */
495void 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 */
514u32 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 */
533u8 *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
546err_out:
547 return 0;
548}
549
550/* Get virtual address of bridge's registers */
551u8 *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
564err_out:
565 return 0;
566}
567
568u8 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}