|  | /* | 
|  | * Marvell hostbridge routines | 
|  | * | 
|  | * Author: Mark A. Greer <source@mvista.com> | 
|  | * | 
|  | * 2004, 2005, 2007 (c) MontaVista Software, Inc. This file is licensed under | 
|  | * the terms of the GNU General Public License version 2. This program | 
|  | * is licensed "as is" without any warranty of any kind, whether express | 
|  | * or implied. | 
|  | */ | 
|  |  | 
|  | #include <stdarg.h> | 
|  | #include <stddef.h> | 
|  | #include "types.h" | 
|  | #include "elf.h" | 
|  | #include "page.h" | 
|  | #include "string.h" | 
|  | #include "stdio.h" | 
|  | #include "io.h" | 
|  | #include "ops.h" | 
|  | #include "mv64x60.h" | 
|  |  | 
|  | #define PCI_DEVFN(slot,func)	((((slot) & 0x1f) << 3) | ((func) & 0x07)) | 
|  |  | 
|  | #define MV64x60_CPU2MEM_WINDOWS			4 | 
|  | #define MV64x60_CPU2MEM_0_BASE			0x0008 | 
|  | #define MV64x60_CPU2MEM_0_SIZE			0x0010 | 
|  | #define MV64x60_CPU2MEM_1_BASE			0x0208 | 
|  | #define MV64x60_CPU2MEM_1_SIZE			0x0210 | 
|  | #define MV64x60_CPU2MEM_2_BASE			0x0018 | 
|  | #define MV64x60_CPU2MEM_2_SIZE			0x0020 | 
|  | #define MV64x60_CPU2MEM_3_BASE			0x0218 | 
|  | #define MV64x60_CPU2MEM_3_SIZE			0x0220 | 
|  |  | 
|  | #define MV64x60_ENET2MEM_BAR_ENABLE		0x2290 | 
|  | #define MV64x60_ENET2MEM_0_BASE			0x2200 | 
|  | #define MV64x60_ENET2MEM_0_SIZE			0x2204 | 
|  | #define MV64x60_ENET2MEM_1_BASE			0x2208 | 
|  | #define MV64x60_ENET2MEM_1_SIZE			0x220c | 
|  | #define MV64x60_ENET2MEM_2_BASE			0x2210 | 
|  | #define MV64x60_ENET2MEM_2_SIZE			0x2214 | 
|  | #define MV64x60_ENET2MEM_3_BASE			0x2218 | 
|  | #define MV64x60_ENET2MEM_3_SIZE			0x221c | 
|  | #define MV64x60_ENET2MEM_4_BASE			0x2220 | 
|  | #define MV64x60_ENET2MEM_4_SIZE			0x2224 | 
|  | #define MV64x60_ENET2MEM_5_BASE			0x2228 | 
|  | #define MV64x60_ENET2MEM_5_SIZE			0x222c | 
|  | #define MV64x60_ENET2MEM_ACC_PROT_0		0x2294 | 
|  | #define MV64x60_ENET2MEM_ACC_PROT_1		0x2298 | 
|  | #define MV64x60_ENET2MEM_ACC_PROT_2		0x229c | 
|  |  | 
|  | #define MV64x60_MPSC2MEM_BAR_ENABLE		0xf250 | 
|  | #define MV64x60_MPSC2MEM_0_BASE			0xf200 | 
|  | #define MV64x60_MPSC2MEM_0_SIZE			0xf204 | 
|  | #define MV64x60_MPSC2MEM_1_BASE			0xf208 | 
|  | #define MV64x60_MPSC2MEM_1_SIZE			0xf20c | 
|  | #define MV64x60_MPSC2MEM_2_BASE			0xf210 | 
|  | #define MV64x60_MPSC2MEM_2_SIZE			0xf214 | 
|  | #define MV64x60_MPSC2MEM_3_BASE			0xf218 | 
|  | #define MV64x60_MPSC2MEM_3_SIZE			0xf21c | 
|  | #define MV64x60_MPSC_0_REMAP			0xf240 | 
|  | #define MV64x60_MPSC_1_REMAP			0xf244 | 
|  | #define MV64x60_MPSC2MEM_ACC_PROT_0		0xf254 | 
|  | #define MV64x60_MPSC2MEM_ACC_PROT_1		0xf258 | 
|  | #define MV64x60_MPSC2REGS_BASE			0xf25c | 
|  |  | 
|  | #define MV64x60_IDMA2MEM_BAR_ENABLE		0x0a80 | 
|  | #define MV64x60_IDMA2MEM_0_BASE			0x0a00 | 
|  | #define MV64x60_IDMA2MEM_0_SIZE			0x0a04 | 
|  | #define MV64x60_IDMA2MEM_1_BASE			0x0a08 | 
|  | #define MV64x60_IDMA2MEM_1_SIZE			0x0a0c | 
|  | #define MV64x60_IDMA2MEM_2_BASE			0x0a10 | 
|  | #define MV64x60_IDMA2MEM_2_SIZE			0x0a14 | 
|  | #define MV64x60_IDMA2MEM_3_BASE			0x0a18 | 
|  | #define MV64x60_IDMA2MEM_3_SIZE			0x0a1c | 
|  | #define MV64x60_IDMA2MEM_4_BASE			0x0a20 | 
|  | #define MV64x60_IDMA2MEM_4_SIZE			0x0a24 | 
|  | #define MV64x60_IDMA2MEM_5_BASE			0x0a28 | 
|  | #define MV64x60_IDMA2MEM_5_SIZE			0x0a2c | 
|  | #define MV64x60_IDMA2MEM_6_BASE			0x0a30 | 
|  | #define MV64x60_IDMA2MEM_6_SIZE			0x0a34 | 
|  | #define MV64x60_IDMA2MEM_7_BASE			0x0a38 | 
|  | #define MV64x60_IDMA2MEM_7_SIZE			0x0a3c | 
|  | #define MV64x60_IDMA2MEM_ACC_PROT_0		0x0a70 | 
|  | #define MV64x60_IDMA2MEM_ACC_PROT_1		0x0a74 | 
|  | #define MV64x60_IDMA2MEM_ACC_PROT_2		0x0a78 | 
|  | #define MV64x60_IDMA2MEM_ACC_PROT_3		0x0a7c | 
|  |  | 
|  | #define MV64x60_PCI_ACC_CNTL_WINDOWS		6 | 
|  | #define MV64x60_PCI0_PCI_DECODE_CNTL		0x0d3c | 
|  | #define MV64x60_PCI1_PCI_DECODE_CNTL		0x0dbc | 
|  |  | 
|  | #define MV64x60_PCI0_BAR_ENABLE			0x0c3c | 
|  | #define MV64x60_PCI02MEM_0_SIZE			0x0c08 | 
|  | #define MV64x60_PCI0_ACC_CNTL_0_BASE_LO		0x1e00 | 
|  | #define MV64x60_PCI0_ACC_CNTL_0_BASE_HI		0x1e04 | 
|  | #define MV64x60_PCI0_ACC_CNTL_0_SIZE		0x1e08 | 
|  | #define MV64x60_PCI0_ACC_CNTL_1_BASE_LO		0x1e10 | 
|  | #define MV64x60_PCI0_ACC_CNTL_1_BASE_HI		0x1e14 | 
|  | #define MV64x60_PCI0_ACC_CNTL_1_SIZE		0x1e18 | 
|  | #define MV64x60_PCI0_ACC_CNTL_2_BASE_LO		0x1e20 | 
|  | #define MV64x60_PCI0_ACC_CNTL_2_BASE_HI		0x1e24 | 
|  | #define MV64x60_PCI0_ACC_CNTL_2_SIZE		0x1e28 | 
|  | #define MV64x60_PCI0_ACC_CNTL_3_BASE_LO		0x1e30 | 
|  | #define MV64x60_PCI0_ACC_CNTL_3_BASE_HI		0x1e34 | 
|  | #define MV64x60_PCI0_ACC_CNTL_3_SIZE		0x1e38 | 
|  | #define MV64x60_PCI0_ACC_CNTL_4_BASE_LO		0x1e40 | 
|  | #define MV64x60_PCI0_ACC_CNTL_4_BASE_HI		0x1e44 | 
|  | #define MV64x60_PCI0_ACC_CNTL_4_SIZE		0x1e48 | 
|  | #define MV64x60_PCI0_ACC_CNTL_5_BASE_LO		0x1e50 | 
|  | #define MV64x60_PCI0_ACC_CNTL_5_BASE_HI		0x1e54 | 
|  | #define MV64x60_PCI0_ACC_CNTL_5_SIZE		0x1e58 | 
|  |  | 
|  | #define MV64x60_PCI1_BAR_ENABLE			0x0cbc | 
|  | #define MV64x60_PCI12MEM_0_SIZE			0x0c88 | 
|  | #define MV64x60_PCI1_ACC_CNTL_0_BASE_LO		0x1e80 | 
|  | #define MV64x60_PCI1_ACC_CNTL_0_BASE_HI		0x1e84 | 
|  | #define MV64x60_PCI1_ACC_CNTL_0_SIZE		0x1e88 | 
|  | #define MV64x60_PCI1_ACC_CNTL_1_BASE_LO		0x1e90 | 
|  | #define MV64x60_PCI1_ACC_CNTL_1_BASE_HI		0x1e94 | 
|  | #define MV64x60_PCI1_ACC_CNTL_1_SIZE		0x1e98 | 
|  | #define MV64x60_PCI1_ACC_CNTL_2_BASE_LO		0x1ea0 | 
|  | #define MV64x60_PCI1_ACC_CNTL_2_BASE_HI		0x1ea4 | 
|  | #define MV64x60_PCI1_ACC_CNTL_2_SIZE		0x1ea8 | 
|  | #define MV64x60_PCI1_ACC_CNTL_3_BASE_LO		0x1eb0 | 
|  | #define MV64x60_PCI1_ACC_CNTL_3_BASE_HI		0x1eb4 | 
|  | #define MV64x60_PCI1_ACC_CNTL_3_SIZE		0x1eb8 | 
|  | #define MV64x60_PCI1_ACC_CNTL_4_BASE_LO		0x1ec0 | 
|  | #define MV64x60_PCI1_ACC_CNTL_4_BASE_HI		0x1ec4 | 
|  | #define MV64x60_PCI1_ACC_CNTL_4_SIZE		0x1ec8 | 
|  | #define MV64x60_PCI1_ACC_CNTL_5_BASE_LO		0x1ed0 | 
|  | #define MV64x60_PCI1_ACC_CNTL_5_BASE_HI		0x1ed4 | 
|  | #define MV64x60_PCI1_ACC_CNTL_5_SIZE		0x1ed8 | 
|  |  | 
|  | #define MV64x60_CPU2PCI_SWAP_NONE		0x01000000 | 
|  |  | 
|  | #define MV64x60_CPU2PCI0_IO_BASE		0x0048 | 
|  | #define MV64x60_CPU2PCI0_IO_SIZE		0x0050 | 
|  | #define MV64x60_CPU2PCI0_IO_REMAP		0x00f0 | 
|  | #define MV64x60_CPU2PCI0_MEM_0_BASE		0x0058 | 
|  | #define MV64x60_CPU2PCI0_MEM_0_SIZE		0x0060 | 
|  | #define MV64x60_CPU2PCI0_MEM_0_REMAP_LO		0x00f8 | 
|  | #define MV64x60_CPU2PCI0_MEM_0_REMAP_HI		0x0320 | 
|  |  | 
|  | #define MV64x60_CPU2PCI1_IO_BASE		0x0090 | 
|  | #define MV64x60_CPU2PCI1_IO_SIZE		0x0098 | 
|  | #define MV64x60_CPU2PCI1_IO_REMAP		0x0108 | 
|  | #define MV64x60_CPU2PCI1_MEM_0_BASE		0x00a0 | 
|  | #define MV64x60_CPU2PCI1_MEM_0_SIZE		0x00a8 | 
|  | #define MV64x60_CPU2PCI1_MEM_0_REMAP_LO		0x0110 | 
|  | #define MV64x60_CPU2PCI1_MEM_0_REMAP_HI		0x0340 | 
|  |  | 
|  | struct mv64x60_mem_win { | 
|  | u32 hi; | 
|  | u32 lo; | 
|  | u32 size; | 
|  | }; | 
|  |  | 
|  | struct mv64x60_pci_win { | 
|  | u32 fcn; | 
|  | u32 hi; | 
|  | u32 lo; | 
|  | u32 size; | 
|  | }; | 
|  |  | 
|  | /* PCI config access routines */ | 
|  | struct { | 
|  | u32 addr; | 
|  | u32 data; | 
|  | } static mv64x60_pci_cfgio[2] = { | 
|  | { /* hose 0 */ | 
|  | .addr	= 0xcf8, | 
|  | .data	= 0xcfc, | 
|  | }, | 
|  | { /* hose 1 */ | 
|  | .addr	= 0xc78, | 
|  | .data	= 0xc7c, | 
|  | } | 
|  | }; | 
|  |  | 
|  | u32 mv64x60_cfg_read(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset) | 
|  | { | 
|  | out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), | 
|  | (1 << 31) | (bus << 16) | (devfn << 8) | offset); | 
|  | return in_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data)); | 
|  | } | 
|  |  | 
|  | void mv64x60_cfg_write(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset, | 
|  | u32 val) | 
|  | { | 
|  | out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), | 
|  | (1 << 31) | (bus << 16) | (devfn << 8) | offset); | 
|  | out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data), val); | 
|  | } | 
|  |  | 
|  | /* I/O ctlr -> system memory setup */ | 
|  | static struct mv64x60_mem_win mv64x60_cpu2mem[MV64x60_CPU2MEM_WINDOWS] = { | 
|  | { | 
|  | .lo	= MV64x60_CPU2MEM_0_BASE, | 
|  | .size	= MV64x60_CPU2MEM_0_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_CPU2MEM_1_BASE, | 
|  | .size	= MV64x60_CPU2MEM_1_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_CPU2MEM_2_BASE, | 
|  | .size	= MV64x60_CPU2MEM_2_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_CPU2MEM_3_BASE, | 
|  | .size	= MV64x60_CPU2MEM_3_SIZE, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static struct mv64x60_mem_win mv64x60_enet2mem[MV64x60_CPU2MEM_WINDOWS] = { | 
|  | { | 
|  | .lo	= MV64x60_ENET2MEM_0_BASE, | 
|  | .size	= MV64x60_ENET2MEM_0_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_ENET2MEM_1_BASE, | 
|  | .size	= MV64x60_ENET2MEM_1_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_ENET2MEM_2_BASE, | 
|  | .size	= MV64x60_ENET2MEM_2_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_ENET2MEM_3_BASE, | 
|  | .size	= MV64x60_ENET2MEM_3_SIZE, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static struct mv64x60_mem_win mv64x60_mpsc2mem[MV64x60_CPU2MEM_WINDOWS] = { | 
|  | { | 
|  | .lo	= MV64x60_MPSC2MEM_0_BASE, | 
|  | .size	= MV64x60_MPSC2MEM_0_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_MPSC2MEM_1_BASE, | 
|  | .size	= MV64x60_MPSC2MEM_1_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_MPSC2MEM_2_BASE, | 
|  | .size	= MV64x60_MPSC2MEM_2_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_MPSC2MEM_3_BASE, | 
|  | .size	= MV64x60_MPSC2MEM_3_SIZE, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static struct mv64x60_mem_win mv64x60_idma2mem[MV64x60_CPU2MEM_WINDOWS] = { | 
|  | { | 
|  | .lo	= MV64x60_IDMA2MEM_0_BASE, | 
|  | .size	= MV64x60_IDMA2MEM_0_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_IDMA2MEM_1_BASE, | 
|  | .size	= MV64x60_IDMA2MEM_1_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_IDMA2MEM_2_BASE, | 
|  | .size	= MV64x60_IDMA2MEM_2_SIZE, | 
|  | }, | 
|  | { | 
|  | .lo	= MV64x60_IDMA2MEM_3_BASE, | 
|  | .size	= MV64x60_IDMA2MEM_3_SIZE, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static u32 mv64x60_dram_selects[MV64x60_CPU2MEM_WINDOWS] = {0xe,0xd,0xb,0x7}; | 
|  |  | 
|  | /* | 
|  | * ENET, MPSC, and IDMA ctlrs on the MV64x60 have separate windows that | 
|  | * must be set up so that the respective ctlr can access system memory. | 
|  | * Configure them to be same as cpu->memory windows. | 
|  | */ | 
|  | void mv64x60_config_ctlr_windows(u8 *bridge_base, u8 *bridge_pbase, | 
|  | u8 is_coherent) | 
|  | { | 
|  | u32 i, base, size, enables, prot = 0, snoop_bits = 0; | 
|  |  | 
|  | /* Disable ctlr->mem windows */ | 
|  | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0x3f); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), 0xf); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0xff); | 
|  |  | 
|  | if (is_coherent) | 
|  | snoop_bits = 0x2 << 12; /* Writeback */ | 
|  |  | 
|  | enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; | 
|  |  | 
|  | for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) { | 
|  | if (enables & (1 << i)) /* Set means disabled */ | 
|  | continue; | 
|  |  | 
|  | base = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].lo)) | 
|  | << 16; | 
|  | base |= snoop_bits | (mv64x60_dram_selects[i] << 8); | 
|  | size = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].size)) | 
|  | << 16; | 
|  | prot |= (0x3 << (i << 1)); /* RW access */ | 
|  |  | 
|  | out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].lo), base); | 
|  | out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].size), size); | 
|  | out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].lo), base); | 
|  | out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].size), size); | 
|  | out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].lo), base); | 
|  | out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].size), size); | 
|  | } | 
|  |  | 
|  | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_0), prot); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_1), prot); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_2), prot); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_0), prot); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_1), prot); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_0), prot); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_1), prot); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_2), prot); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_3), prot); | 
|  |  | 
|  | /* Set mpsc->bridge's reg window to the bridge's internal registers. */ | 
|  | out_le32((u32 *)(bridge_base + MV64x60_MPSC2REGS_BASE), | 
|  | (u32)bridge_pbase); | 
|  |  | 
|  | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), enables); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), enables); | 
|  | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_BAR_ENABLE), enables); | 
|  | } | 
|  |  | 
|  | /* PCI MEM -> system memory, et. al. setup */ | 
|  | static struct mv64x60_pci_win mv64x60_pci2mem[2] = { | 
|  | { /* hose 0 */ | 
|  | .fcn	= 0, | 
|  | .hi	= 0x14, | 
|  | .lo	= 0x10, | 
|  | .size	= MV64x60_PCI02MEM_0_SIZE, | 
|  | }, | 
|  | { /* hose 1 */ | 
|  | .fcn	= 0, | 
|  | .hi	= 0x94, | 
|  | .lo	= 0x90, | 
|  | .size	= MV64x60_PCI12MEM_0_SIZE, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static struct | 
|  | mv64x60_mem_win mv64x60_pci_acc[2][MV64x60_PCI_ACC_CNTL_WINDOWS] = { | 
|  | { /* hose 0 */ | 
|  | { | 
|  | .hi	= MV64x60_PCI0_ACC_CNTL_0_BASE_HI, | 
|  | .lo	= MV64x60_PCI0_ACC_CNTL_0_BASE_LO, | 
|  | .size	= MV64x60_PCI0_ACC_CNTL_0_SIZE, | 
|  | }, | 
|  | { | 
|  | .hi	= MV64x60_PCI0_ACC_CNTL_1_BASE_HI, | 
|  | .lo	= MV64x60_PCI0_ACC_CNTL_1_BASE_LO, | 
|  | .size	= MV64x60_PCI0_ACC_CNTL_1_SIZE, | 
|  | }, | 
|  | { | 
|  | .hi	= MV64x60_PCI0_ACC_CNTL_2_BASE_HI, | 
|  | .lo	= MV64x60_PCI0_ACC_CNTL_2_BASE_LO, | 
|  | .size	= MV64x60_PCI0_ACC_CNTL_2_SIZE, | 
|  | }, | 
|  | { | 
|  | .hi	= MV64x60_PCI0_ACC_CNTL_3_BASE_HI, | 
|  | .lo	= MV64x60_PCI0_ACC_CNTL_3_BASE_LO, | 
|  | .size	= MV64x60_PCI0_ACC_CNTL_3_SIZE, | 
|  | }, | 
|  | }, | 
|  | { /* hose 1 */ | 
|  | { | 
|  | .hi	= MV64x60_PCI1_ACC_CNTL_0_BASE_HI, | 
|  | .lo	= MV64x60_PCI1_ACC_CNTL_0_BASE_LO, | 
|  | .size	= MV64x60_PCI1_ACC_CNTL_0_SIZE, | 
|  | }, | 
|  | { | 
|  | .hi	= MV64x60_PCI1_ACC_CNTL_1_BASE_HI, | 
|  | .lo	= MV64x60_PCI1_ACC_CNTL_1_BASE_LO, | 
|  | .size	= MV64x60_PCI1_ACC_CNTL_1_SIZE, | 
|  | }, | 
|  | { | 
|  | .hi	= MV64x60_PCI1_ACC_CNTL_2_BASE_HI, | 
|  | .lo	= MV64x60_PCI1_ACC_CNTL_2_BASE_LO, | 
|  | .size	= MV64x60_PCI1_ACC_CNTL_2_SIZE, | 
|  | }, | 
|  | { | 
|  | .hi	= MV64x60_PCI1_ACC_CNTL_3_BASE_HI, | 
|  | .lo	= MV64x60_PCI1_ACC_CNTL_3_BASE_LO, | 
|  | .size	= MV64x60_PCI1_ACC_CNTL_3_SIZE, | 
|  | }, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static struct mv64x60_mem_win mv64x60_pci2reg[2] = { | 
|  | { | 
|  | .hi	= 0x24, | 
|  | .lo	= 0x20, | 
|  | .size	= 0, | 
|  | }, | 
|  | { | 
|  | .hi	= 0xa4, | 
|  | .lo	= 0xa0, | 
|  | .size	= 0, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | /* Only need to use 1 window (per hose) to get access to all of system memory */ | 
|  | void mv64x60_config_pci_windows(u8 *bridge_base, u8 *bridge_pbase, u8 hose, | 
|  | u8 bus, u32 mem_size, u32 acc_bits) | 
|  | { | 
|  | u32 i, offset, bar_enable, enables; | 
|  |  | 
|  | /* Disable all windows but PCI MEM -> Bridge's regs window */ | 
|  | enables = ~(1 << 9); | 
|  | bar_enable = hose ? MV64x60_PCI1_BAR_ENABLE : MV64x60_PCI0_BAR_ENABLE; | 
|  | out_le32((u32 *)(bridge_base + bar_enable), enables); | 
|  |  | 
|  | for (i=0; i<MV64x60_PCI_ACC_CNTL_WINDOWS; i++) | 
|  | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][i].lo), 0); | 
|  |  | 
|  | /* If mem_size is 0, leave windows disabled */ | 
|  | if (mem_size == 0) | 
|  | return; | 
|  |  | 
|  | /* Cause automatic updates of PCI remap regs */ | 
|  | offset = hose ? | 
|  | MV64x60_PCI1_PCI_DECODE_CNTL : MV64x60_PCI0_PCI_DECODE_CNTL; | 
|  | i = in_le32((u32 *)(bridge_base + offset)); | 
|  | out_le32((u32 *)(bridge_base + offset), i & ~0x1); | 
|  |  | 
|  | mem_size = (mem_size - 1) & 0xfffff000; | 
|  |  | 
|  | /* Map PCI MEM addr 0 -> System Mem addr 0 */ | 
|  | mv64x60_cfg_write(bridge_base, hose, bus, | 
|  | PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), | 
|  | mv64x60_pci2mem[hose].hi, 0); | 
|  | mv64x60_cfg_write(bridge_base, hose, bus, | 
|  | PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), | 
|  | mv64x60_pci2mem[hose].lo, 0); | 
|  | out_le32((u32 *)(bridge_base + mv64x60_pci2mem[hose].size),mem_size); | 
|  |  | 
|  | acc_bits |= MV64x60_PCI_ACC_CNTL_ENABLE; | 
|  | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].hi), 0); | 
|  | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].lo), acc_bits); | 
|  | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].size),mem_size); | 
|  |  | 
|  | /* Set PCI MEM->bridge's reg window to where they are in CPU mem map */ | 
|  | i = (u32)bridge_base; | 
|  | i &= 0xffff0000; | 
|  | i |= (0x2 << 1); | 
|  | mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), | 
|  | mv64x60_pci2reg[hose].hi, 0); | 
|  | mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), | 
|  | mv64x60_pci2reg[hose].lo, i); | 
|  |  | 
|  | enables &= ~0x1; /* Enable PCI MEM -> System Mem window 0 */ | 
|  | out_le32((u32 *)(bridge_base + bar_enable), enables); | 
|  | } | 
|  |  | 
|  | /* CPU -> PCI I/O & MEM setup */ | 
|  | struct mv64x60_cpu2pci_win mv64x60_cpu2pci_io[2] = { | 
|  | { /* hose 0 */ | 
|  | .lo		= MV64x60_CPU2PCI0_IO_BASE, | 
|  | .size		= MV64x60_CPU2PCI0_IO_SIZE, | 
|  | .remap_hi	= 0, | 
|  | .remap_lo	= MV64x60_CPU2PCI0_IO_REMAP, | 
|  | }, | 
|  | { /* hose 1 */ | 
|  | .lo		= MV64x60_CPU2PCI1_IO_BASE, | 
|  | .size		= MV64x60_CPU2PCI1_IO_SIZE, | 
|  | .remap_hi	= 0, | 
|  | .remap_lo	= MV64x60_CPU2PCI1_IO_REMAP, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | struct mv64x60_cpu2pci_win mv64x60_cpu2pci_mem[2] = { | 
|  | { /* hose 0 */ | 
|  | .lo		= MV64x60_CPU2PCI0_MEM_0_BASE, | 
|  | .size		= MV64x60_CPU2PCI0_MEM_0_SIZE, | 
|  | .remap_hi	= MV64x60_CPU2PCI0_MEM_0_REMAP_HI, | 
|  | .remap_lo	= MV64x60_CPU2PCI0_MEM_0_REMAP_LO, | 
|  | }, | 
|  | { /* hose 1 */ | 
|  | .lo		= MV64x60_CPU2PCI1_MEM_0_BASE, | 
|  | .size		= MV64x60_CPU2PCI1_MEM_0_SIZE, | 
|  | .remap_hi	= MV64x60_CPU2PCI1_MEM_0_REMAP_HI, | 
|  | .remap_lo	= MV64x60_CPU2PCI1_MEM_0_REMAP_LO, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | /* Only need to set up 1 window to pci mem space */ | 
|  | void 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) | 
|  | { | 
|  | cpu_base >>= 16; | 
|  | cpu_base |= MV64x60_CPU2PCI_SWAP_NONE; | 
|  | out_le32((u32 *)(bridge_base + offset_tbl[hose].lo), cpu_base); | 
|  |  | 
|  | if (offset_tbl[hose].remap_hi != 0) | 
|  | out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_hi), | 
|  | pci_base_hi); | 
|  | out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_lo), | 
|  | pci_base_lo >> 16); | 
|  |  | 
|  | size = (size - 1) >> 16; | 
|  | out_le32((u32 *)(bridge_base + offset_tbl[hose].size), size); | 
|  | } | 
|  |  | 
|  | /* Read mem ctlr to get the amount of mem in system */ | 
|  | u32 mv64x60_get_mem_size(u8 *bridge_base) | 
|  | { | 
|  | u32 enables, i, v; | 
|  | u32 mem = 0; | 
|  |  | 
|  | enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; | 
|  |  | 
|  | for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) | 
|  | if (!(enables & (1<<i))) { | 
|  | v = in_le32((u32*)(bridge_base | 
|  | + mv64x60_cpu2mem[i].size)); | 
|  | v = ((v & 0xffff) + 1) << 16; | 
|  | mem += v; | 
|  | } | 
|  |  | 
|  | return mem; | 
|  | } | 
|  |  | 
|  | /* Get physical address of bridge's registers */ | 
|  | u8 *mv64x60_get_bridge_pbase(void) | 
|  | { | 
|  | u32 v[2]; | 
|  | void *devp; | 
|  |  | 
|  | devp = find_node_by_compatible(NULL, "marvell,mv64360"); | 
|  | if (devp == NULL) | 
|  | goto err_out; | 
|  | if (getprop(devp, "reg", v, sizeof(v)) != sizeof(v)) | 
|  | goto err_out; | 
|  |  | 
|  | return (u8 *)v[0]; | 
|  |  | 
|  | err_out: | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Get virtual address of bridge's registers */ | 
|  | u8 *mv64x60_get_bridge_base(void) | 
|  | { | 
|  | u32 v; | 
|  | void *devp; | 
|  |  | 
|  | devp = find_node_by_compatible(NULL, "marvell,mv64360"); | 
|  | if (devp == NULL) | 
|  | goto err_out; | 
|  | if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v)) | 
|  | goto err_out; | 
|  |  | 
|  | return (u8 *)v; | 
|  |  | 
|  | err_out: | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | u8 mv64x60_is_coherent(void) | 
|  | { | 
|  | u32 v; | 
|  | void *devp; | 
|  |  | 
|  | devp = finddevice("/"); | 
|  | if (devp == NULL) | 
|  | return 1; /* Assume coherency on */ | 
|  |  | 
|  | if (getprop(devp, "coherency-off", &v, sizeof(v)) < 0) | 
|  | return 1; /* Coherency on */ | 
|  | else | 
|  | return 0; | 
|  | } |