• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
mv64x60_cfg_read(u8 * bridge_base,u8 hose,u8 bus,u8 devfn,u8 offset)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 
mv64x60_cfg_write(u8 * bridge_base,u8 hose,u8 bus,u8 devfn,u8 offset,u32 val)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  */
mv64x60_config_ctlr_windows(u8 * bridge_base,u8 * bridge_pbase,u8 is_coherent)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 */
mv64x60_config_pci_windows(u8 * bridge_base,u8 * bridge_pbase,u8 hose,u8 bus,u32 mem_size,u32 acc_bits)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 */
mv64x60_config_cpu2pci_window(u8 * bridge_base,u8 hose,u32 pci_base_hi,u32 pci_base_lo,u32 cpu_base,u32 size,struct mv64x60_cpu2pci_win * offset_tbl)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 */
mv64x60_get_mem_size(u8 * bridge_base)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 */
mv64x60_get_bridge_pbase(void)533 u8 *mv64x60_get_bridge_pbase(void)
534 {
535 	u32 v[2];
536 	void *devp;
537 
538 	devp = find_node_by_compatible(NULL, "marvell,mv64360");
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 */
mv64x60_get_bridge_base(void)551 u8 *mv64x60_get_bridge_base(void)
552 {
553 	u32 v;
554 	void *devp;
555 
556 	devp = find_node_by_compatible(NULL, "marvell,mv64360");
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 
mv64x60_is_coherent(void)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 }
582