PageRenderTime 55ms CodeModel.GetById 25ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/powerpc/boot/mv64x60.c

http://github.com/mirrors/linux
C | 581 lines | 485 code | 65 blank | 31 comment | 21 complexity | 078309bc52150504895c51d827e76ae3 MD5 | raw file
  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 = 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
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 = 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
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}