mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 17:41:44 +00:00
mvebu soc changes for v3.10
- use the mvebu-mbus driver - prep for LPAE support Depends: - mvebu/cleanup (tags/cleanup_for_v3.10) - mvebu/drivers (tags/drivers_for_v3.10) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQEcBAABAgAGBQJRbApqAAoJEAi3KVZQDZAeiUkH+gI3KNnIEmwbMANGy+zdX70Y mVj5X51MkXCawqNPLT6KYTO16Ap8STBXDxLfQfll1BuIeATgQgqs8dCcykiYQ4me 45Hj9+6uZhfPpN43u4syFPoYaLSAMT9Oe/9ntcpdnyu4fEsRmGGh2Dg8bhYcG1B2 +IVB67qSJ3vU0D2bcqsbSPuSu9MW2Qloc5+SMR74TcsyseZw10kbvL6cdwi9DpNt ru2c/bXqO88U1pmeedJ8Cxl0KGFDhocYWV6orqph+2jIxuCDYd7DjOXFKeMHwcDX lj54wMUyp8EzTs+huhnK3qL6waXTyccmMDDvgIL6WiFywvklTOJOFz0BnfHIHpk= =RK7u -----END PGP SIGNATURE----- Merge tag 'soc_for_v3.10' of git://git.infradead.org/users/jcooper/linux into next/soc2 From Jason Cooper: mvebu soc changes for v3.10 - use the mvebu-mbus driver - prep for LPAE support Depends: - mvebu/cleanup (tags/cleanup_for_v3.10) - mvebu/drivers (tags/drivers_for_v3.10) * tag 'soc_for_v3.10' of git://git.infradead.org/users/jcooper/linux: ARM: mvebu: Align the internal registers virtual base to support LPAE ARM: mvebu: Limit the DMA zone when LPAE is selected arm: plat-orion: remove addr-map code arm: mach-mv78xx0: convert to use the mvebu-mbus driver arm: mach-orion5x: convert to use mvebu-mbus driver arm: mach-dove: convert to use mvebu-mbus driver arm: mach-kirkwood: convert to use mvebu-mbus driver arm: mach-mvebu: convert to use mvebu-mbus driver bus: mvebu: fix mistake in PCIe window target attribute for Kirkwood bus: mvebu-mbus: Restore checking for coherency fabric hardware ARM: Orion: add dbg_show function to gpio-orion driver bus: introduce an Marvell EBU MBus driver arm: mach-orion5x: use mv_mbus_dram_info() in PCI code arm: plat-orion: use mv_mbus_dram_info() in PCIe code arm: plat-orion: only build addr-map.c when needed Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
8b85143e5d
@ -562,6 +562,7 @@ config ARCH_DOVE
|
||||
select PINCTRL_DOVE
|
||||
select PLAT_ORION_LEGACY
|
||||
select USB_ARCH_HAS_EHCI
|
||||
select MVEBU_MBUS
|
||||
help
|
||||
Support for the Marvell Dove SoC 88AP510
|
||||
|
||||
@ -575,6 +576,7 @@ config ARCH_KIRKWOOD
|
||||
select PINCTRL
|
||||
select PINCTRL_KIRKWOOD
|
||||
select PLAT_ORION_LEGACY
|
||||
select MVEBU_MBUS
|
||||
help
|
||||
Support for the following Marvell Kirkwood series SoCs:
|
||||
88F6180, 88F6192 and 88F6281.
|
||||
@ -586,6 +588,7 @@ config ARCH_MV78XX0
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select PCI
|
||||
select PLAT_ORION_LEGACY
|
||||
select MVEBU_MBUS
|
||||
help
|
||||
Support for the following Marvell MV78xx0 series SoCs:
|
||||
MV781x0, MV782x0.
|
||||
@ -598,6 +601,7 @@ config ARCH_ORION5X
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select PCI
|
||||
select PLAT_ORION_LEGACY
|
||||
select MVEBU_MBUS
|
||||
help
|
||||
Support for the following Marvell Orion 5x series SoCs:
|
||||
Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182),
|
||||
|
@ -73,11 +73,6 @@
|
||||
clocks = <&coreclk 2>;
|
||||
};
|
||||
|
||||
addr-decoding@d0020000 {
|
||||
compatible = "marvell,armada-addr-decoding-controller";
|
||||
reg = <0xd0020000 0x258>;
|
||||
};
|
||||
|
||||
sata@d00a0000 {
|
||||
compatible = "marvell,orion-sata";
|
||||
reg = <0xd00a0000 0x2400>;
|
||||
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
#define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000
|
||||
#define ARMADA_370_XP_REGS_VIRT_BASE 0xfeb00000
|
||||
#define ARMADA_370_XP_REGS_VIRT_BASE 0xfec00000
|
||||
|
||||
.macro addruart, rp, rv, tmp
|
||||
ldr \rp, =ARMADA_370_XP_REGS_PHYS_BASE
|
||||
|
@ -1,4 +1,4 @@
|
||||
obj-y += common.o addr-map.o irq.o
|
||||
obj-y += common.o irq.o
|
||||
obj-$(CONFIG_DOVE_LEGACY) += mpp.o
|
||||
obj-$(CONFIG_PCI) += pcie.o
|
||||
obj-$(CONFIG_MACH_DOVE_DB) += dove-db-setup.o
|
||||
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-dove/addr-map.c
|
||||
*
|
||||
* Address map functions for Marvell Dove 88AP510 SoC
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/setup.h>
|
||||
#include <mach/dove.h>
|
||||
#include <plat/addr-map.h>
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Generic Address Decode Windows bit settings
|
||||
*/
|
||||
#define TARGET_DDR 0x0
|
||||
#define TARGET_BOOTROM 0x1
|
||||
#define TARGET_CESA 0x3
|
||||
#define TARGET_PCIE0 0x4
|
||||
#define TARGET_PCIE1 0x8
|
||||
#define TARGET_SCRATCHPAD 0xd
|
||||
|
||||
#define ATTR_CESA 0x01
|
||||
#define ATTR_BOOTROM 0xfd
|
||||
#define ATTR_DEV_SPI0_ROM 0xfe
|
||||
#define ATTR_DEV_SPI1_ROM 0xfb
|
||||
#define ATTR_PCIE_IO 0xe0
|
||||
#define ATTR_PCIE_MEM 0xe8
|
||||
#define ATTR_SCRATCHPAD 0x0
|
||||
|
||||
static inline void __iomem *ddr_map_sc(int i)
|
||||
{
|
||||
return (void __iomem *)(DOVE_MC_VIRT_BASE + 0x100 + ((i) << 4));
|
||||
}
|
||||
|
||||
/*
|
||||
* Description of the windows needed by the platform code
|
||||
*/
|
||||
static struct __initdata orion_addr_map_cfg addr_map_cfg = {
|
||||
.num_wins = 8,
|
||||
.remappable_wins = 4,
|
||||
.bridge_virt_base = BRIDGE_VIRT_BASE,
|
||||
};
|
||||
|
||||
static const struct __initdata orion_addr_map_info addr_map_info[] = {
|
||||
/*
|
||||
* Windows for PCIe IO+MEM space.
|
||||
*/
|
||||
{ 0, DOVE_PCIE0_IO_PHYS_BASE, DOVE_PCIE0_IO_SIZE,
|
||||
TARGET_PCIE0, ATTR_PCIE_IO, DOVE_PCIE0_IO_BUS_BASE
|
||||
},
|
||||
{ 1, DOVE_PCIE1_IO_PHYS_BASE, DOVE_PCIE1_IO_SIZE,
|
||||
TARGET_PCIE1, ATTR_PCIE_IO, DOVE_PCIE1_IO_BUS_BASE
|
||||
},
|
||||
{ 2, DOVE_PCIE0_MEM_PHYS_BASE, DOVE_PCIE0_MEM_SIZE,
|
||||
TARGET_PCIE0, ATTR_PCIE_MEM, -1
|
||||
},
|
||||
{ 3, DOVE_PCIE1_MEM_PHYS_BASE, DOVE_PCIE1_MEM_SIZE,
|
||||
TARGET_PCIE1, ATTR_PCIE_MEM, -1
|
||||
},
|
||||
/*
|
||||
* Window for CESA engine.
|
||||
*/
|
||||
{ 4, DOVE_CESA_PHYS_BASE, DOVE_CESA_SIZE,
|
||||
TARGET_CESA, ATTR_CESA, -1
|
||||
},
|
||||
/*
|
||||
* Window to the BootROM for Standby and Sleep Resume
|
||||
*/
|
||||
{ 5, DOVE_BOOTROM_PHYS_BASE, DOVE_BOOTROM_SIZE,
|
||||
TARGET_BOOTROM, ATTR_BOOTROM, -1
|
||||
},
|
||||
/*
|
||||
* Window to the PMU Scratch Pad space
|
||||
*/
|
||||
{ 6, DOVE_SCRATCHPAD_PHYS_BASE, DOVE_SCRATCHPAD_SIZE,
|
||||
TARGET_SCRATCHPAD, ATTR_SCRATCHPAD, -1
|
||||
},
|
||||
/* End marker */
|
||||
{ -1, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
void __init dove_setup_cpu_mbus(void)
|
||||
{
|
||||
int i;
|
||||
int cs;
|
||||
|
||||
/*
|
||||
* Disable, clear and configure windows.
|
||||
*/
|
||||
orion_config_wins(&addr_map_cfg, addr_map_info);
|
||||
|
||||
/*
|
||||
* Setup MBUS dram target info.
|
||||
*/
|
||||
orion_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
|
||||
|
||||
for (i = 0, cs = 0; i < 2; i++) {
|
||||
u32 map = readl(ddr_map_sc(i));
|
||||
|
||||
/*
|
||||
* Chip select enabled?
|
||||
*/
|
||||
if (map & 1) {
|
||||
struct mbus_dram_window *w;
|
||||
|
||||
w = &orion_mbus_dram_info.cs[cs++];
|
||||
w->cs_index = i;
|
||||
w->mbus_attr = 0; /* CS address decoding done inside */
|
||||
/* the DDR controller, no need to */
|
||||
/* provide attributes */
|
||||
w->base = map & 0xff800000;
|
||||
w->size = 0x100000 << (((map & 0x000f0000) >> 16) - 4);
|
||||
}
|
||||
}
|
||||
orion_mbus_dram_info.num_cs = cs;
|
||||
}
|
@ -64,7 +64,7 @@ static void __init dove_dt_init(void)
|
||||
#ifdef CONFIG_CACHE_TAUROS2
|
||||
tauros2_init(0);
|
||||
#endif
|
||||
dove_setup_cpu_mbus();
|
||||
dove_setup_cpu_wins();
|
||||
|
||||
/* Setup root of clk tree */
|
||||
dove_of_clk_init();
|
||||
|
@ -224,6 +224,9 @@ void __init dove_i2c_init(void)
|
||||
void __init dove_init_early(void)
|
||||
{
|
||||
orion_time_set_base(TIMER_VIRT_BASE);
|
||||
mvebu_mbus_init("marvell,dove-mbus",
|
||||
BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
|
||||
DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ);
|
||||
}
|
||||
|
||||
static int __init dove_find_tclk(void)
|
||||
@ -326,6 +329,40 @@ void __init dove_sdio1_init(void)
|
||||
platform_device_register(&dove_sdio1);
|
||||
}
|
||||
|
||||
void __init dove_setup_cpu_wins(void)
|
||||
{
|
||||
/*
|
||||
* The PCIe windows will no longer be statically allocated
|
||||
* here once Dove is migrated to the pci-mvebu driver.
|
||||
*/
|
||||
mvebu_mbus_add_window_remap_flags("pcie0.0",
|
||||
DOVE_PCIE0_IO_PHYS_BASE,
|
||||
DOVE_PCIE0_IO_SIZE,
|
||||
DOVE_PCIE0_IO_BUS_BASE,
|
||||
MVEBU_MBUS_PCI_IO);
|
||||
mvebu_mbus_add_window_remap_flags("pcie1.0",
|
||||
DOVE_PCIE1_IO_PHYS_BASE,
|
||||
DOVE_PCIE1_IO_SIZE,
|
||||
DOVE_PCIE1_IO_BUS_BASE,
|
||||
MVEBU_MBUS_PCI_IO);
|
||||
mvebu_mbus_add_window_remap_flags("pcie0.0",
|
||||
DOVE_PCIE0_MEM_PHYS_BASE,
|
||||
DOVE_PCIE0_MEM_SIZE,
|
||||
MVEBU_MBUS_NO_REMAP,
|
||||
MVEBU_MBUS_PCI_MEM);
|
||||
mvebu_mbus_add_window_remap_flags("pcie1.0",
|
||||
DOVE_PCIE1_MEM_PHYS_BASE,
|
||||
DOVE_PCIE1_MEM_SIZE,
|
||||
MVEBU_MBUS_NO_REMAP,
|
||||
MVEBU_MBUS_PCI_MEM);
|
||||
mvebu_mbus_add_window("cesa", DOVE_CESA_PHYS_BASE,
|
||||
DOVE_CESA_SIZE);
|
||||
mvebu_mbus_add_window("bootrom", DOVE_BOOTROM_PHYS_BASE,
|
||||
DOVE_BOOTROM_SIZE);
|
||||
mvebu_mbus_add_window("scratchpad", DOVE_SCRATCHPAD_PHYS_BASE,
|
||||
DOVE_SCRATCHPAD_SIZE);
|
||||
}
|
||||
|
||||
void __init dove_init(void)
|
||||
{
|
||||
pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n",
|
||||
@ -334,7 +371,7 @@ void __init dove_init(void)
|
||||
#ifdef CONFIG_CACHE_TAUROS2
|
||||
tauros2_init(0);
|
||||
#endif
|
||||
dove_setup_cpu_mbus();
|
||||
dove_setup_cpu_wins();
|
||||
|
||||
/* Setup root of clk tree */
|
||||
dove_clk_init();
|
||||
|
@ -23,7 +23,7 @@ void dove_map_io(void);
|
||||
void dove_init(void);
|
||||
void dove_init_early(void);
|
||||
void dove_init_irq(void);
|
||||
void dove_setup_cpu_mbus(void);
|
||||
void dove_setup_cpu_wins(void);
|
||||
void dove_ge00_init(struct mv643xx_eth_platform_data *eth_data);
|
||||
void dove_sata_init(struct mv_sata_platform_data *sata_data);
|
||||
#ifdef CONFIG_PCI
|
||||
|
@ -77,6 +77,8 @@
|
||||
/* North-South Bridge */
|
||||
#define BRIDGE_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0x20000)
|
||||
#define BRIDGE_PHYS_BASE (DOVE_SB_REGS_PHYS_BASE + 0x20000)
|
||||
#define BRIDGE_WINS_BASE (BRIDGE_PHYS_BASE)
|
||||
#define BRIDGE_WINS_SZ (0x80)
|
||||
|
||||
/* Cryptographic Engine */
|
||||
#define DOVE_CRYPT_PHYS_BASE (DOVE_SB_REGS_PHYS_BASE + 0x30000)
|
||||
@ -168,6 +170,9 @@
|
||||
#define DOVE_SSP_CLOCK_ENABLE (1 << 1)
|
||||
#define DOVE_SSP_BPB_CLOCK_SRC_SSP (1 << 11)
|
||||
/* Memory Controller */
|
||||
#define DOVE_MC_PHYS_BASE (DOVE_NB_REGS_PHYS_BASE + 0x00000)
|
||||
#define DOVE_MC_WINS_BASE (DOVE_MC_PHYS_BASE + 0x100)
|
||||
#define DOVE_MC_WINS_SZ (0x8)
|
||||
#define DOVE_MC_VIRT_BASE (DOVE_NB_REGS_VIRT_BASE + 0x00000)
|
||||
|
||||
/* LCD Controller */
|
||||
|
@ -1,4 +1,4 @@
|
||||
obj-y += common.o addr-map.o irq.o pcie.o mpp.o
|
||||
obj-y += common.o irq.o pcie.o mpp.o
|
||||
|
||||
obj-$(CONFIG_MACH_DB88F6281_BP) += db88f6281-bp-setup.o
|
||||
obj-$(CONFIG_MACH_RD88F6192_NAS) += rd88f6192-nas-setup.o
|
||||
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-kirkwood/addr-map.c
|
||||
*
|
||||
* Address map functions for Marvell Kirkwood SoCs
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <linux/io.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <plat/addr-map.h>
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Generic Address Decode Windows bit settings
|
||||
*/
|
||||
#define TARGET_DEV_BUS 1
|
||||
#define TARGET_SRAM 3
|
||||
#define TARGET_PCIE 4
|
||||
#define ATTR_DEV_SPI_ROM 0x1e
|
||||
#define ATTR_DEV_BOOT 0x1d
|
||||
#define ATTR_DEV_NAND 0x2f
|
||||
#define ATTR_DEV_CS3 0x37
|
||||
#define ATTR_DEV_CS2 0x3b
|
||||
#define ATTR_DEV_CS1 0x3d
|
||||
#define ATTR_DEV_CS0 0x3e
|
||||
#define ATTR_PCIE_IO 0xe0
|
||||
#define ATTR_PCIE_MEM 0xe8
|
||||
#define ATTR_PCIE1_IO 0xd0
|
||||
#define ATTR_PCIE1_MEM 0xd8
|
||||
#define ATTR_SRAM 0x01
|
||||
|
||||
/*
|
||||
* Description of the windows needed by the platform code
|
||||
*/
|
||||
static struct __initdata orion_addr_map_cfg addr_map_cfg = {
|
||||
.num_wins = 8,
|
||||
.remappable_wins = 4,
|
||||
.bridge_virt_base = BRIDGE_VIRT_BASE,
|
||||
};
|
||||
|
||||
static const struct __initdata orion_addr_map_info addr_map_info[] = {
|
||||
/*
|
||||
* Windows for PCIe IO+MEM space.
|
||||
*/
|
||||
{ 0, KIRKWOOD_PCIE_IO_PHYS_BASE, KIRKWOOD_PCIE_IO_SIZE,
|
||||
TARGET_PCIE, ATTR_PCIE_IO, KIRKWOOD_PCIE_IO_BUS_BASE
|
||||
},
|
||||
{ 1, KIRKWOOD_PCIE_MEM_PHYS_BASE, KIRKWOOD_PCIE_MEM_SIZE,
|
||||
TARGET_PCIE, ATTR_PCIE_MEM, KIRKWOOD_PCIE_MEM_BUS_BASE
|
||||
},
|
||||
{ 2, KIRKWOOD_PCIE1_IO_PHYS_BASE, KIRKWOOD_PCIE1_IO_SIZE,
|
||||
TARGET_PCIE, ATTR_PCIE1_IO, KIRKWOOD_PCIE1_IO_BUS_BASE
|
||||
},
|
||||
{ 3, KIRKWOOD_PCIE1_MEM_PHYS_BASE, KIRKWOOD_PCIE1_MEM_SIZE,
|
||||
TARGET_PCIE, ATTR_PCIE1_MEM, KIRKWOOD_PCIE1_MEM_BUS_BASE
|
||||
},
|
||||
/*
|
||||
* Window for NAND controller.
|
||||
*/
|
||||
{ 4, KIRKWOOD_NAND_MEM_PHYS_BASE, KIRKWOOD_NAND_MEM_SIZE,
|
||||
TARGET_DEV_BUS, ATTR_DEV_NAND, -1
|
||||
},
|
||||
/*
|
||||
* Window for SRAM.
|
||||
*/
|
||||
{ 5, KIRKWOOD_SRAM_PHYS_BASE, KIRKWOOD_SRAM_SIZE,
|
||||
TARGET_SRAM, ATTR_SRAM, -1
|
||||
},
|
||||
/* End marker */
|
||||
{ -1, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
void __init kirkwood_setup_cpu_mbus(void)
|
||||
{
|
||||
/*
|
||||
* Disable, clear and configure windows.
|
||||
*/
|
||||
orion_config_wins(&addr_map_cfg, addr_map_info);
|
||||
|
||||
/*
|
||||
* Setup MBUS dram target info.
|
||||
*/
|
||||
orion_setup_cpu_mbus_target(&addr_map_cfg,
|
||||
(void __iomem *) DDR_WINDOW_CPU_BASE);
|
||||
}
|
@ -93,7 +93,7 @@ static void __init kirkwood_dt_init(void)
|
||||
*/
|
||||
writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
|
||||
|
||||
kirkwood_setup_cpu_mbus();
|
||||
kirkwood_setup_wins();
|
||||
|
||||
kirkwood_l2_init();
|
||||
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include <linux/platform_data/usb-ehci-orion.h>
|
||||
#include <plat/common.h>
|
||||
#include <plat/time.h>
|
||||
#include <plat/addr-map.h>
|
||||
#include <linux/platform_data/dma-mv_xor.h>
|
||||
#include "common.h"
|
||||
|
||||
@ -535,6 +534,9 @@ void __init kirkwood_init_early(void)
|
||||
* the allocations won't fail.
|
||||
*/
|
||||
init_dma_coherent_pool_size(SZ_1M);
|
||||
mvebu_mbus_init("marvell,kirkwood-mbus",
|
||||
BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
|
||||
DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ);
|
||||
}
|
||||
|
||||
int kirkwood_tclk;
|
||||
@ -650,6 +652,38 @@ char * __init kirkwood_id(void)
|
||||
}
|
||||
}
|
||||
|
||||
void __init kirkwood_setup_wins(void)
|
||||
{
|
||||
/*
|
||||
* The PCIe windows will no longer be statically allocated
|
||||
* here once Kirkwood is migrated to the pci-mvebu driver.
|
||||
*/
|
||||
mvebu_mbus_add_window_remap_flags("pcie0.0",
|
||||
KIRKWOOD_PCIE_IO_PHYS_BASE,
|
||||
KIRKWOOD_PCIE_IO_SIZE,
|
||||
KIRKWOOD_PCIE_IO_BUS_BASE,
|
||||
MVEBU_MBUS_PCI_IO);
|
||||
mvebu_mbus_add_window_remap_flags("pcie0.0",
|
||||
KIRKWOOD_PCIE_MEM_PHYS_BASE,
|
||||
KIRKWOOD_PCIE_MEM_SIZE,
|
||||
MVEBU_MBUS_NO_REMAP,
|
||||
MVEBU_MBUS_PCI_MEM);
|
||||
mvebu_mbus_add_window_remap_flags("pcie1.0",
|
||||
KIRKWOOD_PCIE1_IO_PHYS_BASE,
|
||||
KIRKWOOD_PCIE1_IO_SIZE,
|
||||
KIRKWOOD_PCIE1_IO_BUS_BASE,
|
||||
MVEBU_MBUS_PCI_IO);
|
||||
mvebu_mbus_add_window_remap_flags("pcie1.0",
|
||||
KIRKWOOD_PCIE1_MEM_PHYS_BASE,
|
||||
KIRKWOOD_PCIE1_MEM_SIZE,
|
||||
MVEBU_MBUS_NO_REMAP,
|
||||
MVEBU_MBUS_PCI_MEM);
|
||||
mvebu_mbus_add_window("nand", KIRKWOOD_NAND_MEM_PHYS_BASE,
|
||||
KIRKWOOD_NAND_MEM_SIZE);
|
||||
mvebu_mbus_add_window("sram", KIRKWOOD_SRAM_PHYS_BASE,
|
||||
KIRKWOOD_SRAM_SIZE);
|
||||
}
|
||||
|
||||
void __init kirkwood_l2_init(void)
|
||||
{
|
||||
#ifdef CONFIG_CACHE_FEROCEON_L2
|
||||
@ -675,7 +709,7 @@ void __init kirkwood_init(void)
|
||||
*/
|
||||
writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
|
||||
|
||||
kirkwood_setup_cpu_mbus();
|
||||
kirkwood_setup_wins();
|
||||
|
||||
kirkwood_l2_init();
|
||||
|
||||
|
@ -30,7 +30,7 @@ void kirkwood_init(void);
|
||||
void kirkwood_init_early(void);
|
||||
void kirkwood_init_irq(void);
|
||||
|
||||
void kirkwood_setup_cpu_mbus(void);
|
||||
void kirkwood_setup_wins(void);
|
||||
|
||||
void kirkwood_enable_pcie(void);
|
||||
void kirkwood_pcie_id(u32 *dev, u32 *rev);
|
||||
|
@ -60,8 +60,9 @@
|
||||
* Register Map
|
||||
*/
|
||||
#define DDR_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x00000)
|
||||
#define DDR_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x00000)
|
||||
#define DDR_WINDOW_CPU_BASE (DDR_VIRT_BASE + 0x1500)
|
||||
#define DDR_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x00000)
|
||||
#define DDR_WINDOW_CPU_BASE (DDR_PHYS_BASE + 0x1500)
|
||||
#define DDR_WINDOW_CPU_SZ (0x20)
|
||||
#define DDR_OPERATION_BASE (DDR_PHYS_BASE + 0x1418)
|
||||
|
||||
#define DEV_BUS_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x10000)
|
||||
@ -80,6 +81,8 @@
|
||||
|
||||
#define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x20000)
|
||||
#define BRIDGE_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x20000)
|
||||
#define BRIDGE_WINS_BASE (BRIDGE_PHYS_BASE)
|
||||
#define BRIDGE_WINS_SZ (0x80)
|
||||
|
||||
#define CRYPTO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x30000)
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <asm/mach/pci.h>
|
||||
#include <plat/pcie.h>
|
||||
#include <mach/bridge-regs.h>
|
||||
#include <plat/addr-map.h>
|
||||
#include "common.h"
|
||||
|
||||
static void kirkwood_enable_pcie_clk(const char *port)
|
||||
|
@ -1,4 +1,4 @@
|
||||
obj-y += common.o addr-map.o mpp.o irq.o pcie.o
|
||||
obj-y += common.o mpp.o irq.o pcie.o
|
||||
obj-$(CONFIG_MACH_DB78X00_BP) += db78x00-bp-setup.o
|
||||
obj-$(CONFIG_MACH_RD78X00_MASA) += rd78x00-masa-setup.o
|
||||
obj-$(CONFIG_MACH_TERASTATION_WXL) += buffalo-wxl-setup.o
|
||||
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-mv78xx0/addr-map.c
|
||||
*
|
||||
* Address map functions for Marvell MV78xx0 SoCs
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <linux/io.h>
|
||||
#include <plat/addr-map.h>
|
||||
#include <mach/mv78xx0.h>
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Generic Address Decode Windows bit settings
|
||||
*/
|
||||
#define TARGET_DEV_BUS 1
|
||||
#define TARGET_PCIE0 4
|
||||
#define TARGET_PCIE1 8
|
||||
#define TARGET_PCIE(i) ((i) ? TARGET_PCIE1 : TARGET_PCIE0)
|
||||
#define ATTR_DEV_SPI_ROM 0x1f
|
||||
#define ATTR_DEV_BOOT 0x2f
|
||||
#define ATTR_DEV_CS3 0x37
|
||||
#define ATTR_DEV_CS2 0x3b
|
||||
#define ATTR_DEV_CS1 0x3d
|
||||
#define ATTR_DEV_CS0 0x3e
|
||||
#define ATTR_PCIE_IO(l) (0xf0 & ~(0x10 << (l)))
|
||||
#define ATTR_PCIE_MEM(l) (0xf8 & ~(0x10 << (l)))
|
||||
|
||||
/*
|
||||
* CPU Address Decode Windows registers
|
||||
*/
|
||||
#define WIN0_OFF(n) (BRIDGE_VIRT_BASE + 0x0000 + ((n) << 4))
|
||||
#define WIN8_OFF(n) (BRIDGE_VIRT_BASE + 0x0900 + (((n) - 8) << 4))
|
||||
|
||||
static void __init __iomem *win_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
|
||||
{
|
||||
/*
|
||||
* Find the control register base address for this window.
|
||||
*
|
||||
* BRIDGE_VIRT_BASE points to the right (CPU0's or CPU1's)
|
||||
* MBUS bridge depending on which CPU core we're running on,
|
||||
* so we don't need to take that into account here.
|
||||
*/
|
||||
|
||||
return (win < 8) ? WIN0_OFF(win) : WIN8_OFF(win);
|
||||
}
|
||||
|
||||
/*
|
||||
* Description of the windows needed by the platform code
|
||||
*/
|
||||
static struct orion_addr_map_cfg addr_map_cfg __initdata = {
|
||||
.num_wins = 14,
|
||||
.remappable_wins = 8,
|
||||
.win_cfg_base = win_cfg_base,
|
||||
};
|
||||
|
||||
void __init mv78xx0_setup_cpu_mbus(void)
|
||||
{
|
||||
/*
|
||||
* Disable, clear and configure windows.
|
||||
*/
|
||||
orion_config_wins(&addr_map_cfg, NULL);
|
||||
|
||||
/*
|
||||
* Setup MBUS dram target info.
|
||||
*/
|
||||
if (mv78xx0_core_index() == 0)
|
||||
orion_setup_cpu_mbus_target(&addr_map_cfg,
|
||||
(void __iomem *) DDR_WINDOW_CPU0_BASE);
|
||||
else
|
||||
orion_setup_cpu_mbus_target(&addr_map_cfg,
|
||||
(void __iomem *) DDR_WINDOW_CPU1_BASE);
|
||||
}
|
||||
|
||||
void __init mv78xx0_setup_pcie_io_win(int window, u32 base, u32 size,
|
||||
int maj, int min)
|
||||
{
|
||||
orion_setup_cpu_win(&addr_map_cfg, window, base, size,
|
||||
TARGET_PCIE(maj), ATTR_PCIE_IO(min), 0);
|
||||
}
|
||||
|
||||
void __init mv78xx0_setup_pcie_mem_win(int window, u32 base, u32 size,
|
||||
int maj, int min)
|
||||
{
|
||||
orion_setup_cpu_win(&addr_map_cfg, window, base, size,
|
||||
TARGET_PCIE(maj), ATTR_PCIE_MEM(min), -1);
|
||||
}
|
@ -334,6 +334,14 @@ void __init mv78xx0_uart3_init(void)
|
||||
void __init mv78xx0_init_early(void)
|
||||
{
|
||||
orion_time_set_base(TIMER_VIRT_BASE);
|
||||
if (mv78xx0_core_index() == 0)
|
||||
mvebu_mbus_init("marvell,mv78xx0-mbus",
|
||||
BRIDGE_WINS_CPU0_BASE, BRIDGE_WINS_SZ,
|
||||
DDR_WINDOW_CPU0_BASE, DDR_WINDOW_CPU_SZ);
|
||||
else
|
||||
mvebu_mbus_init("marvell,mv78xx0-mbus",
|
||||
BRIDGE_WINS_CPU1_BASE, BRIDGE_WINS_SZ,
|
||||
DDR_WINDOW_CPU1_BASE, DDR_WINDOW_CPU_SZ);
|
||||
}
|
||||
|
||||
void __init_refok mv78xx0_timer_init(void)
|
||||
@ -397,8 +405,6 @@ void __init mv78xx0_init(void)
|
||||
printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000);
|
||||
printk("TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000);
|
||||
|
||||
mv78xx0_setup_cpu_mbus();
|
||||
|
||||
#ifdef CONFIG_CACHE_FEROCEON_L2
|
||||
feroceon_l2_init(is_l2_writethrough());
|
||||
#endif
|
||||
|
@ -60,13 +60,18 @@
|
||||
*/
|
||||
#define BRIDGE_VIRT_BASE (MV78XX0_CORE_REGS_VIRT_BASE)
|
||||
#define BRIDGE_PHYS_BASE (MV78XX0_CORE_REGS_PHYS_BASE)
|
||||
#define BRIDGE_WINS_CPU0_BASE (MV78XX0_CORE0_REGS_PHYS_BASE)
|
||||
#define BRIDGE_WINS_CPU1_BASE (MV78XX0_CORE1_REGS_PHYS_BASE)
|
||||
#define BRIDGE_WINS_SZ (0xA000)
|
||||
|
||||
/*
|
||||
* Register Map
|
||||
*/
|
||||
#define DDR_VIRT_BASE (MV78XX0_REGS_VIRT_BASE + 0x00000)
|
||||
#define DDR_WINDOW_CPU0_BASE (DDR_VIRT_BASE + 0x1500)
|
||||
#define DDR_WINDOW_CPU1_BASE (DDR_VIRT_BASE + 0x1570)
|
||||
#define DDR_PHYS_BASE (MV78XX0_REGS_PHYS_BASE + 0x00000)
|
||||
#define DDR_WINDOW_CPU0_BASE (DDR_PHYS_BASE + 0x1500)
|
||||
#define DDR_WINDOW_CPU1_BASE (DDR_PHYS_BASE + 0x1570)
|
||||
#define DDR_WINDOW_CPU_SZ (0x20)
|
||||
|
||||
#define DEV_BUS_PHYS_BASE (MV78XX0_REGS_PHYS_BASE + 0x10000)
|
||||
#define DEV_BUS_VIRT_BASE (MV78XX0_REGS_VIRT_BASE + 0x10000)
|
||||
|
@ -10,11 +10,11 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <video/vga.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach/pci.h>
|
||||
#include <plat/pcie.h>
|
||||
#include <plat/addr-map.h>
|
||||
#include <mach/mv78xx0.h>
|
||||
#include "common.h"
|
||||
|
||||
@ -54,7 +54,6 @@ static void __init mv78xx0_pcie_preinit(void)
|
||||
int i;
|
||||
u32 size_each;
|
||||
u32 start;
|
||||
int win = 0;
|
||||
|
||||
pcie_io_space.name = "PCIe I/O Space";
|
||||
pcie_io_space.start = MV78XX0_PCIE_IO_PHYS_BASE(0);
|
||||
@ -72,6 +71,7 @@ static void __init mv78xx0_pcie_preinit(void)
|
||||
start = MV78XX0_PCIE_MEM_PHYS_BASE;
|
||||
for (i = 0; i < num_pcie_ports; i++) {
|
||||
struct pcie_port *pp = pcie_port + i;
|
||||
char winname[MVEBU_MBUS_MAX_WINNAME_SZ];
|
||||
|
||||
snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
|
||||
"PCIe %d.%d MEM", pp->maj, pp->min);
|
||||
@ -85,12 +85,17 @@ static void __init mv78xx0_pcie_preinit(void)
|
||||
if (request_resource(&iomem_resource, &pp->res))
|
||||
panic("can't allocate PCIe MEM sub-space");
|
||||
|
||||
mv78xx0_setup_pcie_mem_win(win + i + 8, pp->res.start,
|
||||
resource_size(&pp->res),
|
||||
pp->maj, pp->min);
|
||||
snprintf(winname, sizeof(winname), "pcie%d.%d",
|
||||
pp->maj, pp->min);
|
||||
|
||||
mv78xx0_setup_pcie_io_win(win + i, i * SZ_64K, SZ_64K,
|
||||
pp->maj, pp->min);
|
||||
mvebu_mbus_add_window_remap_flags(winname,
|
||||
pp->res.start,
|
||||
resource_size(&pp->res),
|
||||
MVEBU_MBUS_NO_REMAP,
|
||||
MVEBU_MBUS_PCI_MEM);
|
||||
mvebu_mbus_add_window_remap_flags(winname,
|
||||
i * SZ_64K, SZ_64K,
|
||||
0, MVEBU_MBUS_PCI_IO);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,8 @@ config ARCH_MVEBU
|
||||
select MVEBU_CLK_CORE
|
||||
select MVEBU_CLK_CPU
|
||||
select MVEBU_CLK_GATING
|
||||
select MVEBU_MBUS
|
||||
select ZONE_DMA if ARM_LPAE
|
||||
|
||||
if ARCH_MVEBU
|
||||
|
||||
|
@ -5,6 +5,6 @@ AFLAGS_coherency_ll.o := -Wa,-march=armv7-a
|
||||
|
||||
obj-y += system-controller.o
|
||||
obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o
|
||||
obj-$(CONFIG_ARCH_MVEBU) += addr-map.o coherency.o coherency_ll.o pmsu.o irq-armada-370-xp.o
|
||||
obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o irq-armada-370-xp.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
|
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Address map functions for Marvell 370 / XP SoCs
|
||||
*
|
||||
* Copyright (C) 2012 Marvell
|
||||
*
|
||||
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <plat/addr-map.h>
|
||||
|
||||
/*
|
||||
* Generic Address Decode Windows bit settings
|
||||
*/
|
||||
#define ARMADA_XP_TARGET_DEV_BUS 1
|
||||
#define ARMADA_XP_ATTR_DEV_BOOTROM 0x1D
|
||||
#define ARMADA_XP_TARGET_ETH1 3
|
||||
#define ARMADA_XP_TARGET_PCIE_0_2 4
|
||||
#define ARMADA_XP_TARGET_ETH0 7
|
||||
#define ARMADA_XP_TARGET_PCIE_1_3 8
|
||||
|
||||
#define ARMADA_370_TARGET_DEV_BUS 1
|
||||
#define ARMADA_370_ATTR_DEV_BOOTROM 0x1D
|
||||
#define ARMADA_370_TARGET_PCIE_0 4
|
||||
#define ARMADA_370_TARGET_PCIE_1 8
|
||||
|
||||
#define ARMADA_WINDOW_8_PLUS_OFFSET 0x90
|
||||
#define ARMADA_SDRAM_ADDR_DECODING_OFFSET 0x180
|
||||
|
||||
static const struct __initdata orion_addr_map_info
|
||||
armada_xp_addr_map_info[] = {
|
||||
/*
|
||||
* Window for the BootROM, needed for SMP on Armada XP
|
||||
*/
|
||||
{ 0, 0xfff00000, SZ_1M, ARMADA_XP_TARGET_DEV_BUS,
|
||||
ARMADA_XP_ATTR_DEV_BOOTROM, -1 },
|
||||
/* End marker */
|
||||
{ -1, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const struct __initdata orion_addr_map_info
|
||||
armada_370_addr_map_info[] = {
|
||||
/* End marker */
|
||||
{ -1, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct of_device_id of_addr_decoding_controller_table[] = {
|
||||
{ .compatible = "marvell,armada-addr-decoding-controller" },
|
||||
{ /* end of list */ },
|
||||
};
|
||||
|
||||
static void __iomem *
|
||||
armada_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
|
||||
{
|
||||
unsigned int offset;
|
||||
|
||||
/* The register layout is a bit annoying and the below code
|
||||
* tries to cope with it.
|
||||
* - At offset 0x0, there are the registers for the first 8
|
||||
* windows, with 4 registers of 32 bits per window (ctrl,
|
||||
* base, remap low, remap high)
|
||||
* - Then at offset 0x80, there is a hole of 0x10 bytes for
|
||||
* the internal registers base address and internal units
|
||||
* sync barrier register.
|
||||
* - Then at offset 0x90, there the registers for 12
|
||||
* windows, with only 2 registers of 32 bits per window
|
||||
* (ctrl, base).
|
||||
*/
|
||||
if (win < 8)
|
||||
offset = (win << 4);
|
||||
else
|
||||
offset = ARMADA_WINDOW_8_PLUS_OFFSET + ((win - 8) << 3);
|
||||
|
||||
return cfg->bridge_virt_base + offset;
|
||||
}
|
||||
|
||||
static struct __initdata orion_addr_map_cfg addr_map_cfg = {
|
||||
.num_wins = 20,
|
||||
.remappable_wins = 8,
|
||||
.win_cfg_base = armada_cfg_base,
|
||||
};
|
||||
|
||||
static int __init armada_setup_cpu_mbus(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
void __iomem *mbus_unit_addr_decoding_base;
|
||||
void __iomem *sdram_addr_decoding_base;
|
||||
|
||||
np = of_find_matching_node(NULL, of_addr_decoding_controller_table);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
mbus_unit_addr_decoding_base = of_iomap(np, 0);
|
||||
BUG_ON(!mbus_unit_addr_decoding_base);
|
||||
|
||||
sdram_addr_decoding_base =
|
||||
mbus_unit_addr_decoding_base +
|
||||
ARMADA_SDRAM_ADDR_DECODING_OFFSET;
|
||||
|
||||
addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base;
|
||||
|
||||
if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
|
||||
addr_map_cfg.hw_io_coherency = 1;
|
||||
|
||||
/*
|
||||
* Disable, clear and configure windows.
|
||||
*/
|
||||
if (of_machine_is_compatible("marvell,armadaxp"))
|
||||
orion_config_wins(&addr_map_cfg, armada_xp_addr_map_info);
|
||||
else if (of_machine_is_compatible("marvell,armada370"))
|
||||
orion_config_wins(&addr_map_cfg, armada_370_addr_map_info);
|
||||
else {
|
||||
pr_err("Unsupported SoC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup MBUS dram target info.
|
||||
*/
|
||||
orion_setup_cpu_mbus_target(&addr_map_cfg,
|
||||
sdram_addr_decoding_base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Using a early_initcall is needed so that this initialization gets
|
||||
* done before the SMP initialization, which requires the BootROM to
|
||||
* be remapped. */
|
||||
early_initcall(armada_setup_cpu_mbus);
|
@ -19,6 +19,7 @@
|
||||
#include <linux/time-armada-370-xp.h>
|
||||
#include <linux/clk/mvebu.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/time.h>
|
||||
@ -48,12 +49,29 @@ void __init armada_370_xp_timer_and_clk_init(void)
|
||||
|
||||
void __init armada_370_xp_init_early(void)
|
||||
{
|
||||
char *mbus_soc_name;
|
||||
|
||||
/*
|
||||
* Some Armada 370/XP devices allocate their coherent buffers
|
||||
* from atomic context. Increase size of atomic coherent pool
|
||||
* to make sure such the allocations won't fail.
|
||||
*/
|
||||
init_dma_coherent_pool_size(SZ_1M);
|
||||
|
||||
/*
|
||||
* This initialization will be replaced by a DT-based
|
||||
* initialization once the mvebu-mbus driver gains DT support.
|
||||
*/
|
||||
if (of_machine_is_compatible("marvell,armada370"))
|
||||
mbus_soc_name = "marvell,armada370-mbus";
|
||||
else
|
||||
mbus_soc_name = "marvell,armadaxp-mbus";
|
||||
|
||||
mvebu_mbus_init(mbus_soc_name,
|
||||
ARMADA_370_XP_MBUS_WINS_BASE,
|
||||
ARMADA_370_XP_MBUS_WINS_SIZE,
|
||||
ARMADA_370_XP_SDRAM_WINS_BASE,
|
||||
ARMADA_370_XP_SDRAM_WINS_SIZE);
|
||||
}
|
||||
|
||||
static void __init armada_370_xp_dt_init(void)
|
||||
|
@ -16,9 +16,15 @@
|
||||
#define __MACH_ARMADA_370_XP_H
|
||||
|
||||
#define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000
|
||||
#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfeb00000)
|
||||
#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfec00000)
|
||||
#define ARMADA_370_XP_REGS_SIZE SZ_1M
|
||||
|
||||
/* These defines can go away once mvebu-mbus has a DT binding */
|
||||
#define ARMADA_370_XP_MBUS_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20000)
|
||||
#define ARMADA_370_XP_MBUS_WINS_SIZE 0x100
|
||||
#define ARMADA_370_XP_SDRAM_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20180)
|
||||
#define ARMADA_370_XP_SDRAM_WINS_SIZE 0x20
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/smp.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include "common.h"
|
||||
@ -109,6 +110,7 @@ void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
|
||||
set_secondary_cpus_clock();
|
||||
flush_cache_all();
|
||||
set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
|
||||
mvebu_mbus_add_window("bootrom", 0xfff00000, SZ_1M);
|
||||
}
|
||||
|
||||
struct smp_operations armada_xp_smp_ops __initdata = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
obj-y += common.o addr-map.o pci.o irq.o mpp.o
|
||||
obj-y += common.o pci.o irq.o mpp.o
|
||||
obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o
|
||||
obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o
|
||||
obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o
|
||||
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-orion5x/addr-map.c
|
||||
*
|
||||
* Address map functions for Marvell Orion 5x SoCs
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <linux/io.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <plat/addr-map.h>
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* The Orion has fully programmable address map. There's a separate address
|
||||
* map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIe, USB,
|
||||
* Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
|
||||
* address decode windows that allow it to access any of the Orion resources.
|
||||
*
|
||||
* CPU address decoding --
|
||||
* Linux assumes that it is the boot loader that already setup the access to
|
||||
* DDR and internal registers.
|
||||
* Setup access to PCI and PCIe IO/MEM space is issued by this file.
|
||||
* Setup access to various devices located on the device bus interface (e.g.
|
||||
* flashes, RTC, etc) should be issued by machine-setup.c according to
|
||||
* specific board population (by using orion5x_setup_*_win()).
|
||||
*
|
||||
* Non-CPU Masters address decoding --
|
||||
* Unlike the CPU, we setup the access from Orion's master interfaces to DDR
|
||||
* banks only (the typical use case).
|
||||
* Setup access for each master to DDR is issued by platform device setup.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic Address Decode Windows bit settings
|
||||
*/
|
||||
#define TARGET_DEV_BUS 1
|
||||
#define TARGET_PCI 3
|
||||
#define TARGET_PCIE 4
|
||||
#define TARGET_SRAM 9
|
||||
#define ATTR_PCIE_MEM 0x59
|
||||
#define ATTR_PCIE_IO 0x51
|
||||
#define ATTR_PCIE_WA 0x79
|
||||
#define ATTR_PCI_MEM 0x59
|
||||
#define ATTR_PCI_IO 0x51
|
||||
#define ATTR_DEV_CS0 0x1e
|
||||
#define ATTR_DEV_CS1 0x1d
|
||||
#define ATTR_DEV_CS2 0x1b
|
||||
#define ATTR_DEV_BOOT 0xf
|
||||
#define ATTR_SRAM 0x0
|
||||
|
||||
static int __initdata win_alloc_count;
|
||||
|
||||
static int __init cpu_win_can_remap(const struct orion_addr_map_cfg *cfg,
|
||||
const int win)
|
||||
{
|
||||
u32 dev, rev;
|
||||
|
||||
orion5x_pcie_id(&dev, &rev);
|
||||
if ((dev == MV88F5281_DEV_ID && win < 4)
|
||||
|| (dev == MV88F5182_DEV_ID && win < 2)
|
||||
|| (dev == MV88F5181_DEV_ID && win < 2)
|
||||
|| (dev == MV88F6183_DEV_ID && win < 4))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Description of the windows needed by the platform code
|
||||
*/
|
||||
static struct orion_addr_map_cfg addr_map_cfg __initdata = {
|
||||
.num_wins = 8,
|
||||
.cpu_win_can_remap = cpu_win_can_remap,
|
||||
.bridge_virt_base = ORION5X_BRIDGE_VIRT_BASE,
|
||||
};
|
||||
|
||||
static const struct __initdata orion_addr_map_info addr_map_info[] = {
|
||||
/*
|
||||
* Setup windows for PCI+PCIe IO+MEM space.
|
||||
*/
|
||||
{ 0, ORION5X_PCIE_IO_PHYS_BASE, ORION5X_PCIE_IO_SIZE,
|
||||
TARGET_PCIE, ATTR_PCIE_IO, ORION5X_PCIE_IO_BUS_BASE
|
||||
},
|
||||
{ 1, ORION5X_PCI_IO_PHYS_BASE, ORION5X_PCI_IO_SIZE,
|
||||
TARGET_PCI, ATTR_PCI_IO, ORION5X_PCI_IO_BUS_BASE
|
||||
},
|
||||
{ 2, ORION5X_PCIE_MEM_PHYS_BASE, ORION5X_PCIE_MEM_SIZE,
|
||||
TARGET_PCIE, ATTR_PCIE_MEM, -1
|
||||
},
|
||||
{ 3, ORION5X_PCI_MEM_PHYS_BASE, ORION5X_PCI_MEM_SIZE,
|
||||
TARGET_PCI, ATTR_PCI_MEM, -1
|
||||
},
|
||||
/* End marker */
|
||||
{ -1, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
void __init orion5x_setup_cpu_mbus_bridge(void)
|
||||
{
|
||||
/*
|
||||
* Disable, clear and configure windows.
|
||||
*/
|
||||
orion_config_wins(&addr_map_cfg, addr_map_info);
|
||||
win_alloc_count = 4;
|
||||
|
||||
/*
|
||||
* Setup MBUS dram target info.
|
||||
*/
|
||||
orion_setup_cpu_mbus_target(&addr_map_cfg,
|
||||
(void __iomem *) ORION5X_DDR_WINDOW_CPU_BASE);
|
||||
}
|
||||
|
||||
void __init orion5x_setup_dev_boot_win(u32 base, u32 size)
|
||||
{
|
||||
orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size,
|
||||
TARGET_DEV_BUS, ATTR_DEV_BOOT, -1);
|
||||
}
|
||||
|
||||
void __init orion5x_setup_dev0_win(u32 base, u32 size)
|
||||
{
|
||||
orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size,
|
||||
TARGET_DEV_BUS, ATTR_DEV_CS0, -1);
|
||||
}
|
||||
|
||||
void __init orion5x_setup_dev1_win(u32 base, u32 size)
|
||||
{
|
||||
orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size,
|
||||
TARGET_DEV_BUS, ATTR_DEV_CS1, -1);
|
||||
}
|
||||
|
||||
void __init orion5x_setup_dev2_win(u32 base, u32 size)
|
||||
{
|
||||
orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size,
|
||||
TARGET_DEV_BUS, ATTR_DEV_CS2, -1);
|
||||
}
|
||||
|
||||
void __init orion5x_setup_pcie_wa_win(u32 base, u32 size)
|
||||
{
|
||||
orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size,
|
||||
TARGET_PCIE, ATTR_PCIE_WA, -1);
|
||||
}
|
||||
|
||||
void __init orion5x_setup_sram_win(void)
|
||||
{
|
||||
orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++,
|
||||
ORION5X_SRAM_PHYS_BASE, ORION5X_SRAM_SIZE,
|
||||
TARGET_SRAM, ATTR_SRAM, -1);
|
||||
}
|
@ -41,7 +41,7 @@ static void __init orion5x_dt_init(void)
|
||||
/*
|
||||
* Setup Orion address map
|
||||
*/
|
||||
orion5x_setup_cpu_mbus_bridge();
|
||||
orion5x_setup_wins();
|
||||
|
||||
/* Setup root of clk tree */
|
||||
clk_init();
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include <linux/platform_data/usb-ehci-orion.h>
|
||||
#include <plat/time.h>
|
||||
#include <plat/common.h>
|
||||
#include <plat/addr-map.h>
|
||||
#include "common.h"
|
||||
|
||||
/*****************************************************************************
|
||||
@ -174,7 +173,8 @@ void __init orion5x_xor_init(void)
|
||||
****************************************************************************/
|
||||
static void __init orion5x_crypto_init(void)
|
||||
{
|
||||
orion5x_setup_sram_win();
|
||||
mvebu_mbus_add_window("sram", ORION5X_SRAM_PHYS_BASE,
|
||||
ORION5X_SRAM_SIZE);
|
||||
orion_crypto_init(ORION5X_CRYPTO_PHYS_BASE, ORION5X_SRAM_PHYS_BASE,
|
||||
SZ_8K, IRQ_ORION5X_CESA);
|
||||
}
|
||||
@ -193,6 +193,9 @@ void __init orion5x_wdt_init(void)
|
||||
****************************************************************************/
|
||||
void __init orion5x_init_early(void)
|
||||
{
|
||||
u32 rev, dev;
|
||||
const char *mbus_soc_name;
|
||||
|
||||
orion_time_set_base(TIMER_VIRT_BASE);
|
||||
|
||||
/*
|
||||
@ -201,6 +204,46 @@ void __init orion5x_init_early(void)
|
||||
* the allocations won't fail.
|
||||
*/
|
||||
init_dma_coherent_pool_size(SZ_1M);
|
||||
|
||||
/* Initialize the MBUS driver */
|
||||
orion5x_pcie_id(&dev, &rev);
|
||||
if (dev == MV88F5281_DEV_ID)
|
||||
mbus_soc_name = "marvell,orion5x-88f5281-mbus";
|
||||
else if (dev == MV88F5182_DEV_ID)
|
||||
mbus_soc_name = "marvell,orion5x-88f5182-mbus";
|
||||
else if (dev == MV88F5181_DEV_ID)
|
||||
mbus_soc_name = "marvell,orion5x-88f5181-mbus";
|
||||
else if (dev == MV88F6183_DEV_ID)
|
||||
mbus_soc_name = "marvell,orion5x-88f6183-mbus";
|
||||
else
|
||||
mbus_soc_name = NULL;
|
||||
mvebu_mbus_init(mbus_soc_name, ORION5X_BRIDGE_WINS_BASE,
|
||||
ORION5X_BRIDGE_WINS_SZ,
|
||||
ORION5X_DDR_WINS_BASE, ORION5X_DDR_WINS_SZ);
|
||||
}
|
||||
|
||||
void orion5x_setup_wins(void)
|
||||
{
|
||||
/*
|
||||
* The PCIe windows will no longer be statically allocated
|
||||
* here once Orion5x is migrated to the pci-mvebu driver.
|
||||
*/
|
||||
mvebu_mbus_add_window_remap_flags("pcie0.0", ORION5X_PCIE_IO_PHYS_BASE,
|
||||
ORION5X_PCIE_IO_SIZE,
|
||||
ORION5X_PCIE_IO_BUS_BASE,
|
||||
MVEBU_MBUS_PCI_IO);
|
||||
mvebu_mbus_add_window_remap_flags("pcie0.0", ORION5X_PCIE_MEM_PHYS_BASE,
|
||||
ORION5X_PCIE_MEM_SIZE,
|
||||
MVEBU_MBUS_NO_REMAP,
|
||||
MVEBU_MBUS_PCI_MEM);
|
||||
mvebu_mbus_add_window_remap_flags("pci0.0", ORION5X_PCI_IO_PHYS_BASE,
|
||||
ORION5X_PCI_IO_SIZE,
|
||||
ORION5X_PCI_IO_BUS_BASE,
|
||||
MVEBU_MBUS_PCI_IO);
|
||||
mvebu_mbus_add_window_remap_flags("pci0.0", ORION5X_PCI_MEM_PHYS_BASE,
|
||||
ORION5X_PCI_MEM_SIZE,
|
||||
MVEBU_MBUS_NO_REMAP,
|
||||
MVEBU_MBUS_PCI_MEM);
|
||||
}
|
||||
|
||||
int orion5x_tclk;
|
||||
@ -282,7 +325,7 @@ void __init orion5x_init(void)
|
||||
/*
|
||||
* Setup Orion address map
|
||||
*/
|
||||
orion5x_setup_cpu_mbus_bridge();
|
||||
orion5x_setup_wins();
|
||||
|
||||
/* Setup root of clk tree */
|
||||
clk_init();
|
||||
|
@ -17,18 +17,7 @@ void clk_init(void);
|
||||
extern int orion5x_tclk;
|
||||
extern void orion5x_timer_init(void);
|
||||
|
||||
/*
|
||||
* Enumerations and functions for Orion windows mapping. Used by Orion core
|
||||
* functions to map its interfaces and by the machine-setup to map its on-
|
||||
* board devices. Details in /mach-orion/addr-map.c
|
||||
*/
|
||||
void orion5x_setup_cpu_mbus_bridge(void);
|
||||
void orion5x_setup_dev_boot_win(u32 base, u32 size);
|
||||
void orion5x_setup_dev0_win(u32 base, u32 size);
|
||||
void orion5x_setup_dev1_win(u32 base, u32 size);
|
||||
void orion5x_setup_dev2_win(u32 base, u32 size);
|
||||
void orion5x_setup_pcie_wa_win(u32 base, u32 size);
|
||||
void orion5x_setup_sram_win(void);
|
||||
void orion5x_setup_wins(void);
|
||||
|
||||
void orion5x_ehci0_init(void);
|
||||
void orion5x_ehci1_init(void);
|
||||
|
@ -317,8 +317,8 @@ static void __init d2net_init(void)
|
||||
d2net_sata_power_init();
|
||||
orion5x_sata_init(&d2net_sata_data);
|
||||
|
||||
orion5x_setup_dev_boot_win(D2NET_NOR_BOOT_BASE,
|
||||
D2NET_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", D2NET_NOR_BOOT_BASE,
|
||||
D2NET_NOR_BOOT_SIZE);
|
||||
platform_device_register(&d2net_nor_flash);
|
||||
|
||||
platform_device_register(&d2net_gpio_buttons);
|
||||
|
@ -340,16 +340,19 @@ static void __init db88f5281_init(void)
|
||||
orion5x_uart0_init();
|
||||
orion5x_uart1_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(DB88F5281_NOR_BOOT_BASE,
|
||||
DB88F5281_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", DB88F5281_NOR_BOOT_BASE,
|
||||
DB88F5281_NOR_BOOT_SIZE);
|
||||
platform_device_register(&db88f5281_boot_flash);
|
||||
|
||||
orion5x_setup_dev0_win(DB88F5281_7SEG_BASE, DB88F5281_7SEG_SIZE);
|
||||
mvebu_mbus_add_window("devbus-cs0", DB88F5281_7SEG_BASE,
|
||||
DB88F5281_7SEG_SIZE);
|
||||
|
||||
orion5x_setup_dev1_win(DB88F5281_NOR_BASE, DB88F5281_NOR_SIZE);
|
||||
mvebu_mbus_add_window("devbus-cs1", DB88F5281_NOR_BASE,
|
||||
DB88F5281_NOR_SIZE);
|
||||
platform_device_register(&db88f5281_nor_flash);
|
||||
|
||||
orion5x_setup_dev2_win(DB88F5281_NAND_BASE, DB88F5281_NAND_SIZE);
|
||||
mvebu_mbus_add_window("devbus-cs2", DB88F5281_NAND_BASE,
|
||||
DB88F5281_NAND_SIZE);
|
||||
platform_device_register(&db88f5281_nand_flash);
|
||||
|
||||
i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
|
||||
|
@ -611,7 +611,8 @@ static void __init dns323_init(void)
|
||||
/* setup flash mapping
|
||||
* CS3 holds a 8 MB Spansion S29GL064M90TFIR4
|
||||
*/
|
||||
orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", DNS323_NOR_BOOT_BASE,
|
||||
DNS323_NOR_BOOT_SIZE);
|
||||
platform_device_register(&dns323_nor_flash);
|
||||
|
||||
/* Sort out LEDs, Buttons and i2c devices */
|
||||
|
@ -154,8 +154,8 @@ void __init edmini_v2_init(void)
|
||||
orion5x_ehci0_init();
|
||||
orion5x_eth_init(&edmini_v2_eth_data);
|
||||
|
||||
orion5x_setup_dev_boot_win(EDMINI_V2_NOR_BOOT_BASE,
|
||||
EDMINI_V2_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", EDMINI_V2_NOR_BOOT_BASE,
|
||||
EDMINI_V2_NOR_BOOT_SIZE);
|
||||
platform_device_register(&edmini_v2_nor_flash);
|
||||
|
||||
pr_notice("edmini_v2: USB device port, flash write and power-off "
|
||||
|
@ -66,8 +66,10 @@
|
||||
* Orion Registers Map
|
||||
******************************************************************************/
|
||||
|
||||
#define ORION5X_DDR_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x00000)
|
||||
#define ORION5X_DDR_WINS_BASE (ORION5X_DDR_PHYS_BASE + 0x1500)
|
||||
#define ORION5X_DDR_WINS_SZ (0x10)
|
||||
#define ORION5X_DDR_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x00000)
|
||||
#define ORION5X_DDR_WINDOW_CPU_BASE (ORION5X_DDR_VIRT_BASE + 0x1500)
|
||||
#define ORION5X_DEV_BUS_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x10000)
|
||||
#define ORION5X_DEV_BUS_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x10000)
|
||||
#define ORION5X_DEV_BUS_REG(x) (ORION5X_DEV_BUS_VIRT_BASE + (x))
|
||||
@ -81,6 +83,8 @@
|
||||
|
||||
#define ORION5X_BRIDGE_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x20000)
|
||||
#define ORION5X_BRIDGE_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x20000)
|
||||
#define ORION5X_BRIDGE_WINS_BASE (ORION5X_BRIDGE_PHYS_BASE)
|
||||
#define ORION5X_BRIDGE_WINS_SZ (0x80)
|
||||
|
||||
#define ORION5X_PCI_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x30000)
|
||||
|
||||
|
@ -359,13 +359,13 @@ static void __init kurobox_pro_init(void)
|
||||
orion5x_uart1_init();
|
||||
orion5x_xor_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE,
|
||||
KUROBOX_PRO_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", KUROBOX_PRO_NOR_BOOT_BASE,
|
||||
KUROBOX_PRO_NOR_BOOT_SIZE);
|
||||
platform_device_register(&kurobox_pro_nor_flash);
|
||||
|
||||
if (machine_is_kurobox_pro()) {
|
||||
orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE,
|
||||
KUROBOX_PRO_NAND_SIZE);
|
||||
mvebu_mbus_add_window("devbus-cs0", KUROBOX_PRO_NAND_BASE,
|
||||
KUROBOX_PRO_NAND_SIZE);
|
||||
platform_device_register(&kurobox_pro_nand_flash);
|
||||
}
|
||||
|
||||
|
@ -294,8 +294,8 @@ static void __init lschl_init(void)
|
||||
orion5x_uart0_init();
|
||||
orion5x_xor_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(LSCHL_NOR_BOOT_BASE,
|
||||
LSCHL_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", LSCHL_NOR_BOOT_BASE,
|
||||
LSCHL_NOR_BOOT_SIZE);
|
||||
platform_device_register(&lschl_nor_flash);
|
||||
|
||||
platform_device_register(&lschl_leds);
|
||||
|
@ -243,8 +243,8 @@ static void __init ls_hgl_init(void)
|
||||
orion5x_uart0_init();
|
||||
orion5x_xor_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(LS_HGL_NOR_BOOT_BASE,
|
||||
LS_HGL_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", LS_HGL_NOR_BOOT_BASE,
|
||||
LS_HGL_NOR_BOOT_SIZE);
|
||||
platform_device_register(&ls_hgl_nor_flash);
|
||||
|
||||
platform_device_register(&ls_hgl_button_device);
|
||||
|
@ -244,8 +244,8 @@ static void __init lsmini_init(void)
|
||||
orion5x_uart0_init();
|
||||
orion5x_xor_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(LSMINI_NOR_BOOT_BASE,
|
||||
LSMINI_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", LSMINI_NOR_BOOT_BASE,
|
||||
LSMINI_NOR_BOOT_SIZE);
|
||||
platform_device_register(&lsmini_nor_flash);
|
||||
|
||||
platform_device_register(&lsmini_button_device);
|
||||
|
@ -241,7 +241,8 @@ static void __init mss2_init(void)
|
||||
orion5x_uart0_init();
|
||||
orion5x_xor_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(MSS2_NOR_BOOT_BASE, MSS2_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", MSS2_NOR_BOOT_BASE,
|
||||
MSS2_NOR_BOOT_SIZE);
|
||||
platform_device_register(&mss2_nor_flash);
|
||||
|
||||
platform_device_register(&mss2_button_device);
|
||||
|
@ -204,7 +204,8 @@ static void __init mv2120_init(void)
|
||||
orion5x_uart0_init();
|
||||
orion5x_xor_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(MV2120_NOR_BOOT_BASE, MV2120_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", MV2120_NOR_BOOT_BASE,
|
||||
MV2120_NOR_BOOT_SIZE);
|
||||
platform_device_register(&mv2120_nor_flash);
|
||||
|
||||
platform_device_register(&mv2120_button_device);
|
||||
|
@ -397,8 +397,8 @@ static void __init net2big_init(void)
|
||||
net2big_sata_power_init();
|
||||
orion5x_sata_init(&net2big_sata_data);
|
||||
|
||||
orion5x_setup_dev_boot_win(NET2BIG_NOR_BOOT_BASE,
|
||||
NET2BIG_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", NET2BIG_NOR_BOOT_BASE,
|
||||
NET2BIG_NOR_BOOT_SIZE);
|
||||
platform_device_register(&net2big_nor_flash);
|
||||
|
||||
platform_device_register(&net2big_gpio_buttons);
|
||||
|
@ -157,8 +157,11 @@ static int __init pcie_setup(struct pci_sys_data *sys)
|
||||
if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
|
||||
printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config "
|
||||
"read transaction workaround\n");
|
||||
orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
|
||||
ORION5X_PCIE_WA_SIZE);
|
||||
mvebu_mbus_add_window_remap_flags("pcie0.0",
|
||||
ORION5X_PCIE_WA_PHYS_BASE,
|
||||
ORION5X_PCIE_WA_SIZE,
|
||||
MVEBU_MBUS_NO_REMAP,
|
||||
MVEBU_MBUS_PCI_WA);
|
||||
pcie_ops.read = pcie_rd_conf_wa;
|
||||
}
|
||||
|
||||
@ -402,8 +405,9 @@ static void __init orion5x_pci_master_slave_enable(void)
|
||||
orion5x_pci_hw_wr_conf(bus_nr, 0, func, reg, 4, val | 0x7);
|
||||
}
|
||||
|
||||
static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram)
|
||||
static void __init orion5x_setup_pci_wins(void)
|
||||
{
|
||||
const struct mbus_dram_target_info *dram = mv_mbus_dram_info();
|
||||
u32 win_enable;
|
||||
int bus;
|
||||
int i;
|
||||
@ -420,7 +424,7 @@ static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram)
|
||||
bus = orion5x_pci_local_bus_nr();
|
||||
|
||||
for (i = 0; i < dram->num_cs; i++) {
|
||||
struct mbus_dram_window *cs = dram->cs + i;
|
||||
const struct mbus_dram_window *cs = dram->cs + i;
|
||||
u32 func = PCI_CONF_FUNC_BAR_CS(cs->cs_index);
|
||||
u32 reg;
|
||||
u32 val;
|
||||
@ -467,7 +471,7 @@ static int __init pci_setup(struct pci_sys_data *sys)
|
||||
/*
|
||||
* Point PCI unit MBUS decode windows to DRAM space.
|
||||
*/
|
||||
orion5x_setup_pci_wins(&orion_mbus_dram_info);
|
||||
orion5x_setup_pci_wins();
|
||||
|
||||
/*
|
||||
* Master + Slave enable
|
||||
|
@ -123,8 +123,8 @@ static void __init rd88f5181l_fxo_init(void)
|
||||
orion5x_eth_switch_init(&rd88f5181l_fxo_switch_plat_data, NO_IRQ);
|
||||
orion5x_uart0_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(RD88F5181L_FXO_NOR_BOOT_BASE,
|
||||
RD88F5181L_FXO_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", RD88F5181L_FXO_NOR_BOOT_BASE,
|
||||
RD88F5181L_FXO_NOR_BOOT_SIZE);
|
||||
platform_device_register(&rd88f5181l_fxo_nor_boot_flash);
|
||||
}
|
||||
|
||||
|
@ -130,8 +130,8 @@ static void __init rd88f5181l_ge_init(void)
|
||||
orion5x_i2c_init();
|
||||
orion5x_uart0_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(RD88F5181L_GE_NOR_BOOT_BASE,
|
||||
RD88F5181L_GE_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", RD88F5181L_GE_NOR_BOOT_BASE,
|
||||
RD88F5181L_GE_NOR_BOOT_SIZE);
|
||||
platform_device_register(&rd88f5181l_ge_nor_boot_flash);
|
||||
|
||||
i2c_register_board_info(0, &rd88f5181l_ge_i2c_rtc, 1);
|
||||
|
@ -264,10 +264,11 @@ static void __init rd88f5182_init(void)
|
||||
orion5x_uart0_init();
|
||||
orion5x_xor_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(RD88F5182_NOR_BOOT_BASE,
|
||||
RD88F5182_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", RD88F5182_NOR_BOOT_BASE,
|
||||
RD88F5182_NOR_BOOT_SIZE);
|
||||
|
||||
orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);
|
||||
mvebu_mbus_add_window("devbus-cs1", RD88F5182_NOR_BASE,
|
||||
RD88F5182_NOR_SIZE);
|
||||
platform_device_register(&rd88f5182_nor_flash);
|
||||
platform_device_register(&rd88f5182_gpio_leds);
|
||||
|
||||
|
@ -329,8 +329,8 @@ static void __init tsp2_init(void)
|
||||
/*
|
||||
* Configure peripherals.
|
||||
*/
|
||||
orion5x_setup_dev_boot_win(TSP2_NOR_BOOT_BASE,
|
||||
TSP2_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", TSP2_NOR_BOOT_BASE,
|
||||
TSP2_NOR_BOOT_SIZE);
|
||||
platform_device_register(&tsp2_nor_flash);
|
||||
|
||||
orion5x_ehci0_init();
|
||||
|
@ -286,8 +286,8 @@ static void __init qnap_ts209_init(void)
|
||||
/*
|
||||
* Configure peripherals.
|
||||
*/
|
||||
orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE,
|
||||
QNAP_TS209_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", QNAP_TS209_NOR_BOOT_BASE,
|
||||
QNAP_TS209_NOR_BOOT_SIZE);
|
||||
platform_device_register(&qnap_ts209_nor_flash);
|
||||
|
||||
orion5x_ehci0_init();
|
||||
|
@ -277,8 +277,8 @@ static void __init qnap_ts409_init(void)
|
||||
/*
|
||||
* Configure peripherals.
|
||||
*/
|
||||
orion5x_setup_dev_boot_win(QNAP_TS409_NOR_BOOT_BASE,
|
||||
QNAP_TS409_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", QNAP_TS409_NOR_BOOT_BASE,
|
||||
QNAP_TS409_NOR_BOOT_SIZE);
|
||||
platform_device_register(&qnap_ts409_nor_flash);
|
||||
|
||||
orion5x_ehci0_init();
|
||||
|
@ -127,8 +127,8 @@ static void __init wnr854t_init(void)
|
||||
orion5x_eth_switch_init(&wnr854t_switch_plat_data, NO_IRQ);
|
||||
orion5x_uart0_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(WNR854T_NOR_BOOT_BASE,
|
||||
WNR854T_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", WNR854T_NOR_BOOT_BASE,
|
||||
WNR854T_NOR_BOOT_SIZE);
|
||||
platform_device_register(&wnr854t_nor_flash);
|
||||
}
|
||||
|
||||
|
@ -213,8 +213,8 @@ static void __init wrt350n_v2_init(void)
|
||||
orion5x_eth_switch_init(&wrt350n_v2_switch_plat_data, NO_IRQ);
|
||||
orion5x_uart0_init();
|
||||
|
||||
orion5x_setup_dev_boot_win(WRT350N_V2_NOR_BOOT_BASE,
|
||||
WRT350N_V2_NOR_BOOT_SIZE);
|
||||
mvebu_mbus_add_window("devbus-boot", WRT350N_V2_NOR_BOOT_BASE,
|
||||
WRT350N_V2_NOR_BOOT_SIZE);
|
||||
platform_device_register(&wrt350n_v2_nor_flash);
|
||||
platform_device_register(&wrt350n_v2_leds);
|
||||
platform_device_register(&wrt350n_v2_button_device);
|
||||
|
@ -3,8 +3,6 @@
|
||||
#
|
||||
ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
|
||||
|
||||
obj-y += addr-map.o
|
||||
|
||||
orion-gpio-$(CONFIG_GENERIC_GPIO) += gpio.o
|
||||
obj-$(CONFIG_PLAT_ORION_LEGACY) += irq.o pcie.o time.o common.o mpp.o
|
||||
obj-$(CONFIG_PLAT_ORION_LEGACY) += $(orion-gpio-y)
|
||||
|
@ -1,178 +0,0 @@
|
||||
/*
|
||||
* arch/arm/plat-orion/addr-map.c
|
||||
*
|
||||
* Address map functions for Marvell Orion based SoCs
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <linux/io.h>
|
||||
#include <plat/addr-map.h>
|
||||
|
||||
struct mbus_dram_target_info orion_mbus_dram_info;
|
||||
|
||||
const struct mbus_dram_target_info *mv_mbus_dram_info(void)
|
||||
{
|
||||
return &orion_mbus_dram_info;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
|
||||
|
||||
/*
|
||||
* DDR target is the same on all Orion platforms.
|
||||
*/
|
||||
#define TARGET_DDR 0
|
||||
|
||||
/*
|
||||
* Helpers to get DDR bank info
|
||||
*/
|
||||
#define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3))
|
||||
#define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3))
|
||||
|
||||
/*
|
||||
* CPU Address Decode Windows registers
|
||||
*/
|
||||
#define WIN_CTRL_OFF 0x0000
|
||||
#define WIN_BASE_OFF 0x0004
|
||||
#define WIN_REMAP_LO_OFF 0x0008
|
||||
#define WIN_REMAP_HI_OFF 0x000c
|
||||
|
||||
#define ATTR_HW_COHERENCY (0x1 << 4)
|
||||
|
||||
/*
|
||||
* Default implementation
|
||||
*/
|
||||
static void __init __iomem *
|
||||
orion_win_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
|
||||
{
|
||||
return cfg->bridge_virt_base + (win << 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Default implementation
|
||||
*/
|
||||
static int __init orion_cpu_win_can_remap(const struct orion_addr_map_cfg *cfg,
|
||||
const int win)
|
||||
{
|
||||
if (win < cfg->remappable_wins)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg,
|
||||
const int win, const u32 base,
|
||||
const u32 size, const u8 target,
|
||||
const u8 attr, const int remap)
|
||||
{
|
||||
void __iomem *addr = cfg->win_cfg_base(cfg, win);
|
||||
u32 ctrl, base_high, remap_addr;
|
||||
|
||||
if (win >= cfg->num_wins) {
|
||||
printk(KERN_ERR "setup_cpu_win: trying to allocate window "
|
||||
"%d when only %d allowed\n", win, cfg->num_wins);
|
||||
}
|
||||
|
||||
base_high = base & 0xffff0000;
|
||||
ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1;
|
||||
|
||||
writel(base_high, addr + WIN_BASE_OFF);
|
||||
writel(ctrl, addr + WIN_CTRL_OFF);
|
||||
if (cfg->cpu_win_can_remap(cfg, win)) {
|
||||
if (remap < 0)
|
||||
remap_addr = base;
|
||||
else
|
||||
remap_addr = remap;
|
||||
writel(remap_addr & 0xffff0000, addr + WIN_REMAP_LO_OFF);
|
||||
writel(0, addr + WIN_REMAP_HI_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure a number of windows.
|
||||
*/
|
||||
static void __init orion_setup_cpu_wins(const struct orion_addr_map_cfg * cfg,
|
||||
const struct orion_addr_map_info *info)
|
||||
{
|
||||
while (info->win != -1) {
|
||||
orion_setup_cpu_win(cfg, info->win, info->base, info->size,
|
||||
info->target, info->attr, info->remap);
|
||||
info++;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init orion_disable_wins(const struct orion_addr_map_cfg * cfg)
|
||||
{
|
||||
void __iomem *addr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cfg->num_wins; i++) {
|
||||
addr = cfg->win_cfg_base(cfg, i);
|
||||
|
||||
writel(0, addr + WIN_BASE_OFF);
|
||||
writel(0, addr + WIN_CTRL_OFF);
|
||||
if (cfg->cpu_win_can_remap(cfg, i)) {
|
||||
writel(0, addr + WIN_REMAP_LO_OFF);
|
||||
writel(0, addr + WIN_REMAP_HI_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable, clear and configure windows.
|
||||
*/
|
||||
void __init orion_config_wins(struct orion_addr_map_cfg * cfg,
|
||||
const struct orion_addr_map_info *info)
|
||||
{
|
||||
if (!cfg->cpu_win_can_remap)
|
||||
cfg->cpu_win_can_remap = orion_cpu_win_can_remap;
|
||||
|
||||
if (!cfg->win_cfg_base)
|
||||
cfg->win_cfg_base = orion_win_cfg_base;
|
||||
|
||||
orion_disable_wins(cfg);
|
||||
|
||||
if (info)
|
||||
orion_setup_cpu_wins(cfg, info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup MBUS dram target info.
|
||||
*/
|
||||
void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
|
||||
const void __iomem *ddr_window_cpu_base)
|
||||
{
|
||||
int i;
|
||||
int cs;
|
||||
|
||||
orion_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
|
||||
|
||||
for (i = 0, cs = 0; i < 4; i++) {
|
||||
u32 base = readl(ddr_window_cpu_base + DDR_BASE_CS_OFF(i));
|
||||
u32 size = readl(ddr_window_cpu_base + DDR_SIZE_CS_OFF(i));
|
||||
|
||||
/*
|
||||
* We only take care of entries for which the chip
|
||||
* select is enabled, and that don't have high base
|
||||
* address bits set (devices can only access the first
|
||||
* 32 bits of the memory).
|
||||
*/
|
||||
if ((size & 1) && !(base & 0xF)) {
|
||||
struct mbus_dram_window *w;
|
||||
|
||||
w = &orion_mbus_dram_info.cs[cs++];
|
||||
w->cs_index = i;
|
||||
w->mbus_attr = 0xf & ~(1 << i);
|
||||
if (cfg->hw_io_coherency)
|
||||
w->mbus_attr |= ATTR_HW_COHERENCY;
|
||||
w->base = base & 0xffff0000;
|
||||
w->size = (size | 0x0000ffff) + 1;
|
||||
}
|
||||
}
|
||||
orion_mbus_dram_info.num_cs = cs;
|
||||
}
|
@ -439,6 +439,64 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
static void orion_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
struct orion_gpio_chip *ochip =
|
||||
container_of(chip, struct orion_gpio_chip, chip);
|
||||
u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk;
|
||||
int i;
|
||||
|
||||
out = readl_relaxed(GPIO_OUT(ochip));
|
||||
io_conf = readl_relaxed(GPIO_IO_CONF(ochip));
|
||||
blink = readl_relaxed(GPIO_BLINK_EN(ochip));
|
||||
in_pol = readl_relaxed(GPIO_IN_POL(ochip));
|
||||
data_in = readl_relaxed(GPIO_DATA_IN(ochip));
|
||||
cause = readl_relaxed(GPIO_EDGE_CAUSE(ochip));
|
||||
edg_msk = readl_relaxed(GPIO_EDGE_MASK(ochip));
|
||||
lvl_msk = readl_relaxed(GPIO_LEVEL_MASK(ochip));
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++) {
|
||||
const char *label;
|
||||
u32 msk;
|
||||
bool is_out;
|
||||
|
||||
label = gpiochip_is_requested(chip, i);
|
||||
if (!label)
|
||||
continue;
|
||||
|
||||
msk = 1 << i;
|
||||
is_out = !(io_conf & msk);
|
||||
|
||||
seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label);
|
||||
|
||||
if (is_out) {
|
||||
seq_printf(s, " out %s %s\n",
|
||||
out & msk ? "hi" : "lo",
|
||||
blink & msk ? "(blink )" : "");
|
||||
continue;
|
||||
}
|
||||
|
||||
seq_printf(s, " in %s (act %s) - IRQ",
|
||||
(data_in ^ in_pol) & msk ? "hi" : "lo",
|
||||
in_pol & msk ? "lo" : "hi");
|
||||
if (!((edg_msk | lvl_msk) & msk)) {
|
||||
seq_printf(s, " disabled\n");
|
||||
continue;
|
||||
}
|
||||
if (edg_msk & msk)
|
||||
seq_printf(s, " edge ");
|
||||
if (lvl_msk & msk)
|
||||
seq_printf(s, " level");
|
||||
seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear ");
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define orion_gpio_dbg_show NULL
|
||||
#endif
|
||||
|
||||
void __init orion_gpio_init(struct device_node *np,
|
||||
int gpio_base, int ngpio,
|
||||
void __iomem *base, int mask_offset,
|
||||
@ -471,6 +529,7 @@ void __init orion_gpio_init(struct device_node *np,
|
||||
#ifdef CONFIG_OF
|
||||
ochip->chip.of_node = np;
|
||||
#endif
|
||||
ochip->chip.dbg_show = orion_gpio_dbg_show;
|
||||
|
||||
spin_lock_init(&ochip->lock);
|
||||
ochip->base = (void __iomem *)base;
|
||||
|
@ -120,12 +120,14 @@ void __init orion_pcie_reset(void __iomem *base)
|
||||
* BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
|
||||
* WIN[0-3] -> DRAM bank[0-3]
|
||||
*/
|
||||
static void __init orion_pcie_setup_wins(void __iomem *base,
|
||||
struct mbus_dram_target_info *dram)
|
||||
static void __init orion_pcie_setup_wins(void __iomem *base)
|
||||
{
|
||||
const struct mbus_dram_target_info *dram;
|
||||
u32 size;
|
||||
int i;
|
||||
|
||||
dram = mv_mbus_dram_info();
|
||||
|
||||
/*
|
||||
* First, disable and clear BARs and windows.
|
||||
*/
|
||||
@ -150,7 +152,7 @@ static void __init orion_pcie_setup_wins(void __iomem *base,
|
||||
*/
|
||||
size = 0;
|
||||
for (i = 0; i < dram->num_cs; i++) {
|
||||
struct mbus_dram_window *cs = dram->cs + i;
|
||||
const struct mbus_dram_window *cs = dram->cs + i;
|
||||
|
||||
writel(cs->base & 0xffff0000, base + PCIE_WIN04_BASE_OFF(i));
|
||||
writel(0, base + PCIE_WIN04_REMAP_OFF(i));
|
||||
@ -184,7 +186,7 @@ void __init orion_pcie_setup(void __iomem *base)
|
||||
/*
|
||||
* Point PCIe unit MBUS decode windows to DRAM space.
|
||||
*/
|
||||
orion_pcie_setup_wins(base, &orion_mbus_dram_info);
|
||||
orion_pcie_setup_wins(base);
|
||||
|
||||
/*
|
||||
* Master + slave enable.
|
||||
|
@ -4,6 +4,13 @@
|
||||
|
||||
menu "Bus devices"
|
||||
|
||||
config MVEBU_MBUS
|
||||
bool
|
||||
depends on PLAT_ORION
|
||||
help
|
||||
Driver needed for the MBus configuration on Marvell EBU SoCs
|
||||
(Kirkwood, Dove, Orion5x, MV78XX0 and Armada 370/XP).
|
||||
|
||||
config OMAP_OCP2SCP
|
||||
tristate "OMAP OCP2SCP DRIVER"
|
||||
depends on ARCH_OMAP2PLUS
|
||||
|
@ -2,6 +2,7 @@
|
||||
# Makefile for the bus drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
|
||||
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
|
||||
|
||||
# Interconnect bus driver for OMAP SoCs.
|
||||
|
870
drivers/bus/mvebu-mbus.c
Normal file
870
drivers/bus/mvebu-mbus.c
Normal file
@ -0,0 +1,870 @@
|
||||
/*
|
||||
* Address map functions for Marvell EBU SoCs (Kirkwood, Armada
|
||||
* 370/XP, Dove, Orion5x and MV78xx0)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Marvell EBU SoCs have a configurable physical address space:
|
||||
* the physical address at which certain devices (PCIe, NOR, NAND,
|
||||
* etc.) sit can be configured. The configuration takes place through
|
||||
* two sets of registers:
|
||||
*
|
||||
* - One to configure the access of the CPU to the devices. Depending
|
||||
* on the families, there are between 8 and 20 configurable windows,
|
||||
* each can be use to create a physical memory window that maps to a
|
||||
* specific device. Devices are identified by a tuple (target,
|
||||
* attribute).
|
||||
*
|
||||
* - One to configure the access to the CPU to the SDRAM. There are
|
||||
* either 2 (for Dove) or 4 (for other families) windows to map the
|
||||
* SDRAM into the physical address space.
|
||||
*
|
||||
* This driver:
|
||||
*
|
||||
* - Reads out the SDRAM address decoding windows at initialization
|
||||
* time, and fills the mvebu_mbus_dram_info structure with these
|
||||
* informations. The exported function mv_mbus_dram_info() allow
|
||||
* device drivers to get those informations related to the SDRAM
|
||||
* address decoding windows. This is because devices also have their
|
||||
* own windows (configured through registers that are part of each
|
||||
* device register space), and therefore the drivers for Marvell
|
||||
* devices have to configure those device -> SDRAM windows to ensure
|
||||
* that DMA works properly.
|
||||
*
|
||||
* - Provides an API for platform code or device drivers to
|
||||
* dynamically add or remove address decoding windows for the CPU ->
|
||||
* device accesses. This API is mvebu_mbus_add_window(),
|
||||
* mvebu_mbus_add_window_remap_flags() and
|
||||
* mvebu_mbus_del_window(). Since the (target, attribute) values
|
||||
* differ from one SoC family to another, the API uses a 'const char
|
||||
* *' string to identify devices, and this driver is responsible for
|
||||
* knowing the mapping between the name of a device and its
|
||||
* corresponding (target, attribute) in the current SoC family.
|
||||
*
|
||||
* - Provides a debugfs interface in /sys/kernel/debug/mvebu-mbus/ to
|
||||
* see the list of CPU -> SDRAM windows and their configuration
|
||||
* (file 'sdram') and the list of CPU -> devices windows and their
|
||||
* configuration (file 'devices').
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
/*
|
||||
* DDR target is the same on all platforms.
|
||||
*/
|
||||
#define TARGET_DDR 0
|
||||
|
||||
/*
|
||||
* CPU Address Decode Windows registers
|
||||
*/
|
||||
#define WIN_CTRL_OFF 0x0000
|
||||
#define WIN_CTRL_ENABLE BIT(0)
|
||||
#define WIN_CTRL_TGT_MASK 0xf0
|
||||
#define WIN_CTRL_TGT_SHIFT 4
|
||||
#define WIN_CTRL_ATTR_MASK 0xff00
|
||||
#define WIN_CTRL_ATTR_SHIFT 8
|
||||
#define WIN_CTRL_SIZE_MASK 0xffff0000
|
||||
#define WIN_CTRL_SIZE_SHIFT 16
|
||||
#define WIN_BASE_OFF 0x0004
|
||||
#define WIN_BASE_LOW 0xffff0000
|
||||
#define WIN_BASE_HIGH 0xf
|
||||
#define WIN_REMAP_LO_OFF 0x0008
|
||||
#define WIN_REMAP_LOW 0xffff0000
|
||||
#define WIN_REMAP_HI_OFF 0x000c
|
||||
|
||||
#define ATTR_HW_COHERENCY (0x1 << 4)
|
||||
|
||||
#define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3))
|
||||
#define DDR_BASE_CS_HIGH_MASK 0xf
|
||||
#define DDR_BASE_CS_LOW_MASK 0xff000000
|
||||
#define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3))
|
||||
#define DDR_SIZE_ENABLED BIT(0)
|
||||
#define DDR_SIZE_CS_MASK 0x1c
|
||||
#define DDR_SIZE_CS_SHIFT 2
|
||||
#define DDR_SIZE_MASK 0xff000000
|
||||
|
||||
#define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4)
|
||||
|
||||
struct mvebu_mbus_mapping {
|
||||
const char *name;
|
||||
u8 target;
|
||||
u8 attr;
|
||||
u8 attrmask;
|
||||
};
|
||||
|
||||
/*
|
||||
* Masks used for the 'attrmask' field of mvebu_mbus_mapping. They
|
||||
* allow to get the real attribute value, discarding the special bits
|
||||
* used to select a PCI MEM region or a PCI WA region. This allows the
|
||||
* debugfs code to reverse-match the name of a device from its
|
||||
* target/attr values.
|
||||
*
|
||||
* For all devices except PCI, all bits of 'attr' must be
|
||||
* considered. For most SoCs, only bit 3 should be ignored (it allows
|
||||
* to select between PCI MEM and PCI I/O). On Orion5x however, there
|
||||
* is the special bit 5 to select a PCI WA region.
|
||||
*/
|
||||
#define MAPDEF_NOMASK 0xff
|
||||
#define MAPDEF_PCIMASK 0xf7
|
||||
#define MAPDEF_ORIONPCIMASK 0xd7
|
||||
|
||||
/* Macro used to define one mvebu_mbus_mapping entry */
|
||||
#define MAPDEF(__n, __t, __a, __m) \
|
||||
{ .name = __n, .target = __t, .attr = __a, .attrmask = __m }
|
||||
|
||||
struct mvebu_mbus_state;
|
||||
|
||||
struct mvebu_mbus_soc_data {
|
||||
unsigned int num_wins;
|
||||
unsigned int num_remappable_wins;
|
||||
unsigned int (*win_cfg_offset)(const int win);
|
||||
void (*setup_cpu_target)(struct mvebu_mbus_state *s);
|
||||
int (*show_cpu_target)(struct mvebu_mbus_state *s,
|
||||
struct seq_file *seq, void *v);
|
||||
const struct mvebu_mbus_mapping *map;
|
||||
};
|
||||
|
||||
struct mvebu_mbus_state {
|
||||
void __iomem *mbuswins_base;
|
||||
void __iomem *sdramwins_base;
|
||||
struct dentry *debugfs_root;
|
||||
struct dentry *debugfs_sdram;
|
||||
struct dentry *debugfs_devs;
|
||||
const struct mvebu_mbus_soc_data *soc;
|
||||
int hw_io_coherency;
|
||||
};
|
||||
|
||||
static struct mvebu_mbus_state mbus_state;
|
||||
|
||||
static struct mbus_dram_target_info mvebu_mbus_dram_info;
|
||||
const struct mbus_dram_target_info *mv_mbus_dram_info(void)
|
||||
{
|
||||
return &mvebu_mbus_dram_info;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
|
||||
|
||||
/*
|
||||
* Functions to manipulate the address decoding windows
|
||||
*/
|
||||
|
||||
static void mvebu_mbus_read_window(struct mvebu_mbus_state *mbus,
|
||||
int win, int *enabled, u64 *base,
|
||||
u32 *size, u8 *target, u8 *attr,
|
||||
u64 *remap)
|
||||
{
|
||||
void __iomem *addr = mbus->mbuswins_base +
|
||||
mbus->soc->win_cfg_offset(win);
|
||||
u32 basereg = readl(addr + WIN_BASE_OFF);
|
||||
u32 ctrlreg = readl(addr + WIN_CTRL_OFF);
|
||||
|
||||
if (!(ctrlreg & WIN_CTRL_ENABLE)) {
|
||||
*enabled = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*enabled = 1;
|
||||
*base = ((u64)basereg & WIN_BASE_HIGH) << 32;
|
||||
*base |= (basereg & WIN_BASE_LOW);
|
||||
*size = (ctrlreg | ~WIN_CTRL_SIZE_MASK) + 1;
|
||||
|
||||
if (target)
|
||||
*target = (ctrlreg & WIN_CTRL_TGT_MASK) >> WIN_CTRL_TGT_SHIFT;
|
||||
|
||||
if (attr)
|
||||
*attr = (ctrlreg & WIN_CTRL_ATTR_MASK) >> WIN_CTRL_ATTR_SHIFT;
|
||||
|
||||
if (remap) {
|
||||
if (win < mbus->soc->num_remappable_wins) {
|
||||
u32 remap_low = readl(addr + WIN_REMAP_LO_OFF);
|
||||
u32 remap_hi = readl(addr + WIN_REMAP_HI_OFF);
|
||||
*remap = ((u64)remap_hi << 32) | remap_low;
|
||||
} else
|
||||
*remap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus,
|
||||
int win)
|
||||
{
|
||||
void __iomem *addr;
|
||||
|
||||
addr = mbus->mbuswins_base + mbus->soc->win_cfg_offset(win);
|
||||
|
||||
writel(0, addr + WIN_BASE_OFF);
|
||||
writel(0, addr + WIN_CTRL_OFF);
|
||||
if (win < mbus->soc->num_remappable_wins) {
|
||||
writel(0, addr + WIN_REMAP_LO_OFF);
|
||||
writel(0, addr + WIN_REMAP_HI_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks whether the given window number is available */
|
||||
static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus,
|
||||
const int win)
|
||||
{
|
||||
void __iomem *addr = mbus->mbuswins_base +
|
||||
mbus->soc->win_cfg_offset(win);
|
||||
u32 ctrl = readl(addr + WIN_CTRL_OFF);
|
||||
return !(ctrl & WIN_CTRL_ENABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether the given (base, base+size) area doesn't overlap an
|
||||
* existing region
|
||||
*/
|
||||
static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
|
||||
phys_addr_t base, size_t size,
|
||||
u8 target, u8 attr)
|
||||
{
|
||||
u64 end = (u64)base + size;
|
||||
int win;
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++) {
|
||||
u64 wbase, wend;
|
||||
u32 wsize;
|
||||
u8 wtarget, wattr;
|
||||
int enabled;
|
||||
|
||||
mvebu_mbus_read_window(mbus, win,
|
||||
&enabled, &wbase, &wsize,
|
||||
&wtarget, &wattr, NULL);
|
||||
|
||||
if (!enabled)
|
||||
continue;
|
||||
|
||||
wend = wbase + wsize;
|
||||
|
||||
/*
|
||||
* Check if the current window overlaps with the
|
||||
* proposed physical range
|
||||
*/
|
||||
if ((u64)base < wend && end > wbase)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check if target/attribute conflicts
|
||||
*/
|
||||
if (target == wtarget && attr == wattr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mvebu_mbus_find_window(struct mvebu_mbus_state *mbus,
|
||||
phys_addr_t base, size_t size)
|
||||
{
|
||||
int win;
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++) {
|
||||
u64 wbase;
|
||||
u32 wsize;
|
||||
int enabled;
|
||||
|
||||
mvebu_mbus_read_window(mbus, win,
|
||||
&enabled, &wbase, &wsize,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (!enabled)
|
||||
continue;
|
||||
|
||||
if (base == wbase && size == wsize)
|
||||
return win;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus,
|
||||
int win, phys_addr_t base, size_t size,
|
||||
phys_addr_t remap, u8 target,
|
||||
u8 attr)
|
||||
{
|
||||
void __iomem *addr = mbus->mbuswins_base +
|
||||
mbus->soc->win_cfg_offset(win);
|
||||
u32 ctrl, remap_addr;
|
||||
|
||||
ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) |
|
||||
(attr << WIN_CTRL_ATTR_SHIFT) |
|
||||
(target << WIN_CTRL_TGT_SHIFT) |
|
||||
WIN_CTRL_ENABLE;
|
||||
|
||||
writel(base & WIN_BASE_LOW, addr + WIN_BASE_OFF);
|
||||
writel(ctrl, addr + WIN_CTRL_OFF);
|
||||
if (win < mbus->soc->num_remappable_wins) {
|
||||
if (remap == MVEBU_MBUS_NO_REMAP)
|
||||
remap_addr = base;
|
||||
else
|
||||
remap_addr = remap;
|
||||
writel(remap_addr & WIN_REMAP_LOW, addr + WIN_REMAP_LO_OFF);
|
||||
writel(0, addr + WIN_REMAP_HI_OFF);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_mbus_alloc_window(struct mvebu_mbus_state *mbus,
|
||||
phys_addr_t base, size_t size,
|
||||
phys_addr_t remap, u8 target,
|
||||
u8 attr)
|
||||
{
|
||||
int win;
|
||||
|
||||
if (remap == MVEBU_MBUS_NO_REMAP) {
|
||||
for (win = mbus->soc->num_remappable_wins;
|
||||
win < mbus->soc->num_wins; win++)
|
||||
if (mvebu_mbus_window_is_free(mbus, win))
|
||||
return mvebu_mbus_setup_window(mbus, win, base,
|
||||
size, remap,
|
||||
target, attr);
|
||||
}
|
||||
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++)
|
||||
if (mvebu_mbus_window_is_free(mbus, win))
|
||||
return mvebu_mbus_setup_window(mbus, win, base, size,
|
||||
remap, target, attr);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugfs debugging
|
||||
*/
|
||||
|
||||
/* Common function used for Dove, Kirkwood, Armada 370/XP and Orion 5x */
|
||||
static int mvebu_sdram_debug_show_orion(struct mvebu_mbus_state *mbus,
|
||||
struct seq_file *seq, void *v)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
u32 basereg = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
|
||||
u32 sizereg = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
|
||||
u64 base;
|
||||
u32 size;
|
||||
|
||||
if (!(sizereg & DDR_SIZE_ENABLED)) {
|
||||
seq_printf(seq, "[%d] disabled\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
base = ((u64)basereg & DDR_BASE_CS_HIGH_MASK) << 32;
|
||||
base |= basereg & DDR_BASE_CS_LOW_MASK;
|
||||
size = (sizereg | ~DDR_SIZE_MASK);
|
||||
|
||||
seq_printf(seq, "[%d] %016llx - %016llx : cs%d\n",
|
||||
i, (unsigned long long)base,
|
||||
(unsigned long long)base + size + 1,
|
||||
(sizereg & DDR_SIZE_CS_MASK) >> DDR_SIZE_CS_SHIFT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Special function for Dove */
|
||||
static int mvebu_sdram_debug_show_dove(struct mvebu_mbus_state *mbus,
|
||||
struct seq_file *seq, void *v)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
u32 map = readl(mbus->sdramwins_base + DOVE_DDR_BASE_CS_OFF(i));
|
||||
u64 base;
|
||||
u32 size;
|
||||
|
||||
if (!(map & 1)) {
|
||||
seq_printf(seq, "[%d] disabled\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
base = map & 0xff800000;
|
||||
size = 0x100000 << (((map & 0x000f0000) >> 16) - 4);
|
||||
|
||||
seq_printf(seq, "[%d] %016llx - %016llx : cs%d\n",
|
||||
i, (unsigned long long)base,
|
||||
(unsigned long long)base + size, i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_sdram_debug_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct mvebu_mbus_state *mbus = &mbus_state;
|
||||
return mbus->soc->show_cpu_target(mbus, seq, v);
|
||||
}
|
||||
|
||||
static int mvebu_sdram_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, mvebu_sdram_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations mvebu_sdram_debug_fops = {
|
||||
.open = mvebu_sdram_debug_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int mvebu_devs_debug_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct mvebu_mbus_state *mbus = &mbus_state;
|
||||
int win;
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++) {
|
||||
u64 wbase, wremap;
|
||||
u32 wsize;
|
||||
u8 wtarget, wattr;
|
||||
int enabled, i;
|
||||
const char *name;
|
||||
|
||||
mvebu_mbus_read_window(mbus, win,
|
||||
&enabled, &wbase, &wsize,
|
||||
&wtarget, &wattr, &wremap);
|
||||
|
||||
if (!enabled) {
|
||||
seq_printf(seq, "[%02d] disabled\n", win);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; mbus->soc->map[i].name; i++)
|
||||
if (mbus->soc->map[i].target == wtarget &&
|
||||
mbus->soc->map[i].attr ==
|
||||
(wattr & mbus->soc->map[i].attrmask))
|
||||
break;
|
||||
|
||||
name = mbus->soc->map[i].name ?: "unknown";
|
||||
|
||||
seq_printf(seq, "[%02d] %016llx - %016llx : %s",
|
||||
win, (unsigned long long)wbase,
|
||||
(unsigned long long)(wbase + wsize), name);
|
||||
|
||||
if (win < mbus->soc->num_remappable_wins) {
|
||||
seq_printf(seq, " (remap %016llx)\n",
|
||||
(unsigned long long)wremap);
|
||||
} else
|
||||
seq_printf(seq, "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_devs_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, mvebu_devs_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations mvebu_devs_debug_fops = {
|
||||
.open = mvebu_devs_debug_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
/*
|
||||
* SoC-specific functions and definitions
|
||||
*/
|
||||
|
||||
static unsigned int orion_mbus_win_offset(int win)
|
||||
{
|
||||
return win << 4;
|
||||
}
|
||||
|
||||
static unsigned int armada_370_xp_mbus_win_offset(int win)
|
||||
{
|
||||
/* The register layout is a bit annoying and the below code
|
||||
* tries to cope with it.
|
||||
* - At offset 0x0, there are the registers for the first 8
|
||||
* windows, with 4 registers of 32 bits per window (ctrl,
|
||||
* base, remap low, remap high)
|
||||
* - Then at offset 0x80, there is a hole of 0x10 bytes for
|
||||
* the internal registers base address and internal units
|
||||
* sync barrier register.
|
||||
* - Then at offset 0x90, there the registers for 12
|
||||
* windows, with only 2 registers of 32 bits per window
|
||||
* (ctrl, base).
|
||||
*/
|
||||
if (win < 8)
|
||||
return win << 4;
|
||||
else
|
||||
return 0x90 + ((win - 8) << 3);
|
||||
}
|
||||
|
||||
static unsigned int mv78xx0_mbus_win_offset(int win)
|
||||
{
|
||||
if (win < 8)
|
||||
return win << 4;
|
||||
else
|
||||
return 0x900 + ((win - 8) << 4);
|
||||
}
|
||||
|
||||
static void __init
|
||||
mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
||||
{
|
||||
int i;
|
||||
int cs;
|
||||
|
||||
mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
|
||||
|
||||
for (i = 0, cs = 0; i < 4; i++) {
|
||||
u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
|
||||
u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
|
||||
|
||||
/*
|
||||
* We only take care of entries for which the chip
|
||||
* select is enabled, and that don't have high base
|
||||
* address bits set (devices can only access the first
|
||||
* 32 bits of the memory).
|
||||
*/
|
||||
if ((size & DDR_SIZE_ENABLED) &&
|
||||
!(base & DDR_BASE_CS_HIGH_MASK)) {
|
||||
struct mbus_dram_window *w;
|
||||
|
||||
w = &mvebu_mbus_dram_info.cs[cs++];
|
||||
w->cs_index = i;
|
||||
w->mbus_attr = 0xf & ~(1 << i);
|
||||
if (mbus->hw_io_coherency)
|
||||
w->mbus_attr |= ATTR_HW_COHERENCY;
|
||||
w->base = base & DDR_BASE_CS_LOW_MASK;
|
||||
w->size = (size | ~DDR_SIZE_MASK) + 1;
|
||||
}
|
||||
}
|
||||
mvebu_mbus_dram_info.num_cs = cs;
|
||||
}
|
||||
|
||||
static void __init
|
||||
mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
||||
{
|
||||
int i;
|
||||
int cs;
|
||||
|
||||
mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
|
||||
|
||||
for (i = 0, cs = 0; i < 2; i++) {
|
||||
u32 map = readl(mbus->sdramwins_base + DOVE_DDR_BASE_CS_OFF(i));
|
||||
|
||||
/*
|
||||
* Chip select enabled?
|
||||
*/
|
||||
if (map & 1) {
|
||||
struct mbus_dram_window *w;
|
||||
|
||||
w = &mvebu_mbus_dram_info.cs[cs++];
|
||||
w->cs_index = i;
|
||||
w->mbus_attr = 0; /* CS address decoding done inside */
|
||||
/* the DDR controller, no need to */
|
||||
/* provide attributes */
|
||||
w->base = map & 0xff800000;
|
||||
w->size = 0x100000 << (((map & 0x000f0000) >> 16) - 4);
|
||||
}
|
||||
}
|
||||
|
||||
mvebu_mbus_dram_info.num_cs = cs;
|
||||
}
|
||||
|
||||
static const struct mvebu_mbus_mapping armada_370_map[] = {
|
||||
MAPDEF("bootrom", 1, 0xe0, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-boot", 1, 0x2f, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs0", 1, 0x3e, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs1", 1, 0x3d, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs2", 1, 0x3b, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs3", 1, 0x37, MAPDEF_NOMASK),
|
||||
MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK),
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_soc_data armada_370_mbus_data = {
|
||||
.num_wins = 20,
|
||||
.num_remappable_wins = 8,
|
||||
.win_cfg_offset = armada_370_xp_mbus_win_offset,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
.map = armada_370_map,
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_mapping armada_xp_map[] = {
|
||||
MAPDEF("bootrom", 1, 0x1d, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-boot", 1, 0x2f, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs0", 1, 0x3e, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs1", 1, 0x3d, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs2", 1, 0x3b, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs3", 1, 0x37, MAPDEF_NOMASK),
|
||||
MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie0.1", 4, 0xd0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie0.2", 4, 0xb0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie0.3", 4, 0x70, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.1", 8, 0xd0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.2", 8, 0xb0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.3", 8, 0x70, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie2.0", 4, 0xf0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie3.0", 8, 0xf0, MAPDEF_PCIMASK),
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_soc_data armada_xp_mbus_data = {
|
||||
.num_wins = 20,
|
||||
.num_remappable_wins = 8,
|
||||
.win_cfg_offset = armada_370_xp_mbus_win_offset,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
.map = armada_xp_map,
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_mapping kirkwood_map[] = {
|
||||
MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.0", 4, 0xd0, MAPDEF_PCIMASK),
|
||||
MAPDEF("sram", 3, 0x01, MAPDEF_NOMASK),
|
||||
MAPDEF("nand", 1, 0x2f, MAPDEF_NOMASK),
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
|
||||
.num_wins = 8,
|
||||
.num_remappable_wins = 4,
|
||||
.win_cfg_offset = orion_mbus_win_offset,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
.map = kirkwood_map,
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_mapping dove_map[] = {
|
||||
MAPDEF("pcie0.0", 0x4, 0xe0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.0", 0x8, 0xe0, MAPDEF_PCIMASK),
|
||||
MAPDEF("cesa", 0x3, 0x01, MAPDEF_NOMASK),
|
||||
MAPDEF("bootrom", 0x1, 0xfd, MAPDEF_NOMASK),
|
||||
MAPDEF("scratchpad", 0xd, 0x0, MAPDEF_NOMASK),
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_soc_data dove_mbus_data = {
|
||||
.num_wins = 8,
|
||||
.num_remappable_wins = 4,
|
||||
.win_cfg_offset = orion_mbus_win_offset,
|
||||
.setup_cpu_target = mvebu_mbus_dove_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_dove,
|
||||
.map = dove_map,
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_mapping orion5x_map[] = {
|
||||
MAPDEF("pcie0.0", 4, 0x51, MAPDEF_ORIONPCIMASK),
|
||||
MAPDEF("pci0.0", 3, 0x51, MAPDEF_ORIONPCIMASK),
|
||||
MAPDEF("devbus-boot", 1, 0x0f, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs0", 1, 0x1e, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs1", 1, 0x1d, MAPDEF_NOMASK),
|
||||
MAPDEF("devbus-cs2", 1, 0x1b, MAPDEF_NOMASK),
|
||||
MAPDEF("sram", 0, 0x00, MAPDEF_NOMASK),
|
||||
{},
|
||||
};
|
||||
|
||||
/*
|
||||
* Some variants of Orion5x have 4 remappable windows, some other have
|
||||
* only two of them.
|
||||
*/
|
||||
static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = {
|
||||
.num_wins = 8,
|
||||
.num_remappable_wins = 4,
|
||||
.win_cfg_offset = orion_mbus_win_offset,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
.map = orion5x_map,
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
|
||||
.num_wins = 8,
|
||||
.num_remappable_wins = 2,
|
||||
.win_cfg_offset = orion_mbus_win_offset,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
.map = orion5x_map,
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_mapping mv78xx0_map[] = {
|
||||
MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie0.1", 4, 0xd0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie0.2", 4, 0xb0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie0.3", 4, 0x70, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.1", 8, 0xd0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.2", 8, 0xb0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie1.3", 8, 0x70, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie2.0", 4, 0xf0, MAPDEF_PCIMASK),
|
||||
MAPDEF("pcie3.0", 8, 0xf0, MAPDEF_PCIMASK),
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
|
||||
.num_wins = 14,
|
||||
.num_remappable_wins = 8,
|
||||
.win_cfg_offset = mv78xx0_mbus_win_offset,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
.show_cpu_target = mvebu_sdram_debug_show_orion,
|
||||
.map = mv78xx0_map,
|
||||
};
|
||||
|
||||
/*
|
||||
* The driver doesn't yet have a DT binding because the details of
|
||||
* this DT binding still need to be sorted out. However, as a
|
||||
* preparation, we already use of_device_id to match a SoC description
|
||||
* string against the SoC specific details of this driver.
|
||||
*/
|
||||
static const struct of_device_id of_mvebu_mbus_ids[] = {
|
||||
{ .compatible = "marvell,armada370-mbus",
|
||||
.data = &armada_370_mbus_data, },
|
||||
{ .compatible = "marvell,armadaxp-mbus",
|
||||
.data = &armada_xp_mbus_data, },
|
||||
{ .compatible = "marvell,kirkwood-mbus",
|
||||
.data = &kirkwood_mbus_data, },
|
||||
{ .compatible = "marvell,dove-mbus",
|
||||
.data = &dove_mbus_data, },
|
||||
{ .compatible = "marvell,orion5x-88f5281-mbus",
|
||||
.data = &orion5x_4win_mbus_data, },
|
||||
{ .compatible = "marvell,orion5x-88f5182-mbus",
|
||||
.data = &orion5x_2win_mbus_data, },
|
||||
{ .compatible = "marvell,orion5x-88f5181-mbus",
|
||||
.data = &orion5x_2win_mbus_data, },
|
||||
{ .compatible = "marvell,orion5x-88f6183-mbus",
|
||||
.data = &orion5x_4win_mbus_data, },
|
||||
{ .compatible = "marvell,mv78xx0-mbus",
|
||||
.data = &mv78xx0_mbus_data, },
|
||||
{ },
|
||||
};
|
||||
|
||||
/*
|
||||
* Public API of the driver
|
||||
*/
|
||||
int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base,
|
||||
size_t size, phys_addr_t remap,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct mvebu_mbus_state *s = &mbus_state;
|
||||
u8 target, attr;
|
||||
int i;
|
||||
|
||||
if (!s->soc->map)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; s->soc->map[i].name; i++)
|
||||
if (!strcmp(s->soc->map[i].name, devname))
|
||||
break;
|
||||
|
||||
if (!s->soc->map[i].name) {
|
||||
pr_err("mvebu-mbus: unknown device '%s'\n", devname);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
target = s->soc->map[i].target;
|
||||
attr = s->soc->map[i].attr;
|
||||
|
||||
if (flags == MVEBU_MBUS_PCI_MEM)
|
||||
attr |= 0x8;
|
||||
else if (flags == MVEBU_MBUS_PCI_WA)
|
||||
attr |= 0x28;
|
||||
|
||||
if (!mvebu_mbus_window_conflicts(s, base, size, target, attr)) {
|
||||
pr_err("mvebu-mbus: cannot add window '%s', conflicts with another window\n",
|
||||
devname);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mvebu_mbus_alloc_window(s, base, size, remap, target, attr);
|
||||
|
||||
}
|
||||
|
||||
int mvebu_mbus_add_window(const char *devname, phys_addr_t base, size_t size)
|
||||
{
|
||||
return mvebu_mbus_add_window_remap_flags(devname, base, size,
|
||||
MVEBU_MBUS_NO_REMAP, 0);
|
||||
}
|
||||
|
||||
int mvebu_mbus_del_window(phys_addr_t base, size_t size)
|
||||
{
|
||||
int win;
|
||||
|
||||
win = mvebu_mbus_find_window(&mbus_state, base, size);
|
||||
if (win < 0)
|
||||
return win;
|
||||
|
||||
mvebu_mbus_disable_window(&mbus_state, win);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __init int mvebu_mbus_debugfs_init(void)
|
||||
{
|
||||
struct mvebu_mbus_state *s = &mbus_state;
|
||||
|
||||
/*
|
||||
* If no base has been initialized, doesn't make sense to
|
||||
* register the debugfs entries. We may be on a multiplatform
|
||||
* kernel that isn't running a Marvell EBU SoC.
|
||||
*/
|
||||
if (!s->mbuswins_base)
|
||||
return 0;
|
||||
|
||||
s->debugfs_root = debugfs_create_dir("mvebu-mbus", NULL);
|
||||
if (s->debugfs_root) {
|
||||
s->debugfs_sdram = debugfs_create_file("sdram", S_IRUGO,
|
||||
s->debugfs_root, NULL,
|
||||
&mvebu_sdram_debug_fops);
|
||||
s->debugfs_devs = debugfs_create_file("devices", S_IRUGO,
|
||||
s->debugfs_root, NULL,
|
||||
&mvebu_devs_debug_fops);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
fs_initcall(mvebu_mbus_debugfs_init);
|
||||
|
||||
int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
|
||||
size_t mbuswins_size,
|
||||
phys_addr_t sdramwins_phys_base,
|
||||
size_t sdramwins_size)
|
||||
{
|
||||
struct mvebu_mbus_state *mbus = &mbus_state;
|
||||
const struct of_device_id *of_id;
|
||||
int win;
|
||||
|
||||
for (of_id = of_mvebu_mbus_ids; of_id->compatible; of_id++)
|
||||
if (!strcmp(of_id->compatible, soc))
|
||||
break;
|
||||
|
||||
if (!of_id->compatible) {
|
||||
pr_err("mvebu-mbus: could not find a matching SoC family\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mbus->soc = of_id->data;
|
||||
|
||||
mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size);
|
||||
if (!mbus->mbuswins_base)
|
||||
return -ENOMEM;
|
||||
|
||||
mbus->sdramwins_base = ioremap(sdramwins_phys_base, sdramwins_size);
|
||||
if (!mbus->sdramwins_base) {
|
||||
iounmap(mbus_state.mbuswins_base);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
|
||||
mbus->hw_io_coherency = 1;
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++)
|
||||
mvebu_mbus_disable_window(mbus, win);
|
||||
|
||||
mbus->soc->setup_cpu_target(mbus);
|
||||
|
||||
return 0;
|
||||
}
|
@ -32,6 +32,20 @@ struct mbus_dram_target_info
|
||||
} cs[4];
|
||||
};
|
||||
|
||||
/* Flags for PCI/PCIe address decoding regions */
|
||||
#define MVEBU_MBUS_PCI_IO 0x1
|
||||
#define MVEBU_MBUS_PCI_MEM 0x2
|
||||
#define MVEBU_MBUS_PCI_WA 0x3
|
||||
|
||||
/*
|
||||
* Magic value that explicits that we don't need a remapping-capable
|
||||
* address decoding window.
|
||||
*/
|
||||
#define MVEBU_MBUS_NO_REMAP (0xffffffff)
|
||||
|
||||
/* Maximum size of a mbus window name */
|
||||
#define MVEBU_MBUS_MAX_WINNAME_SZ 32
|
||||
|
||||
/*
|
||||
* The Marvell mbus is to be found only on SOCs from the Orion family
|
||||
* at the moment. Provide a dummy stub for other architectures.
|
||||
@ -44,4 +58,15 @@ static inline const struct mbus_dram_target_info *mv_mbus_dram_info(void)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base,
|
||||
size_t size, phys_addr_t remap,
|
||||
unsigned int flags);
|
||||
int mvebu_mbus_add_window(const char *devname, phys_addr_t base,
|
||||
size_t size);
|
||||
int mvebu_mbus_del_window(phys_addr_t base, size_t size);
|
||||
int mvebu_mbus_init(const char *soc, phys_addr_t mbus_phys_base,
|
||||
size_t mbus_size, phys_addr_t sdram_phys_base,
|
||||
size_t sdram_size);
|
||||
|
||||
#endif /* __LINUX_MBUS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user