blob: d9bb302b91d28bda1fb6d139ac82714e34220e9b [file] [log] [blame]
Mark A. Greer0f81b112007-05-12 10:54:05 +10001/*
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
Dale Farnswortha05ce882008-04-08 08:09:51 +1000538 devp = find_node_by_compatible(NULL, "marvell,mv64360");
Mark A. Greer0f81b112007-05-12 10:54:05 +1000539 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
Dale Farnswortha05ce882008-04-08 08:09:51 +1000556 devp = find_node_by_compatible(NULL, "marvell,mv64360");
Mark A. Greer0f81b112007-05-12 10:54:05 +1000557 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}