diff options
16 files changed, 1434 insertions, 0 deletions
| diff --git a/target/linux/mvebu/config-default b/target/linux/mvebu/config-default index 1fe6b839e..f41c7c227 100644 --- a/target/linux/mvebu/config-default +++ b/target/linux/mvebu/config-default @@ -172,6 +172,7 @@ CONFIG_MACH_ARMADA_XP=y  CONFIG_MAGIC_SYSRQ=y  CONFIG_MDIO_BOARDINFO=y  CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGHT_HAVE_PCI=y  CONFIG_MODULES_USE_ELF_REL=y  # CONFIG_MPCORE_WATCHDOG is not set  CONFIG_MSDOS_FS=y @@ -210,6 +211,7 @@ CONFIG_OUTER_CACHE=y  CONFIG_OUTER_CACHE_SYNC=y  CONFIG_PAGEFLAGS_EXTENDED=y  CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PCI is not set  # CONFIG_PCI_SYSCALL is not set  CONFIG_PERCPU_RWSEM=y  CONFIG_PERF_USE_VMALLOC=y diff --git a/target/linux/mvebu/patches-3.8/028-lib_devres_dont_enclose_pcim.patch b/target/linux/mvebu/patches-3.8/028-lib_devres_dont_enclose_pcim.patch new file mode 100644 index 000000000..3872924a6 --- /dev/null +++ b/target/linux/mvebu/patches-3.8/028-lib_devres_dont_enclose_pcim.patch @@ -0,0 +1,28 @@ +The pcim_*() functions are used by the libata-sff subsystem, and this +subsystem is used for many SATA drivers on ARM platforms that do not +necessarily have I/O ports. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +Cc: Paul Gortmaker <paul.gortmaker@windriver.com> +Cc: Jesse Barnes <jbarnes@virtuousgeek.org> +Cc: Yinghai Lu <yinghai@kernel.org> +Cc: linux-kernel@vger.kernel.org +--- + lib/devres.c |    2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/lib/devres.c ++++ b/lib/devres.c +@@ -195,6 +195,7 @@ void devm_ioport_unmap(struct device *de + 			       devm_ioport_map_match, (void *)addr)); + } + EXPORT_SYMBOL(devm_ioport_unmap); ++#endif /* CONFIG_HAS_IOPORT */ +  + #ifdef CONFIG_PCI + /* +@@ -400,4 +401,3 @@ void pcim_iounmap_regions(struct pci_dev + } + EXPORT_SYMBOL(pcim_iounmap_regions); + #endif /* CONFIG_PCI */ +-#endif /* CONFIG_HAS_IOPORT */ diff --git a/target/linux/mvebu/patches-3.8/029-clk_mvebu_create_parent_child_relation.patch b/target/linux/mvebu/patches-3.8/029-clk_mvebu_create_parent_child_relation.patch new file mode 100644 index 000000000..2cccc0357 --- /dev/null +++ b/target/linux/mvebu/patches-3.8/029-clk_mvebu_create_parent_child_relation.patch @@ -0,0 +1,24 @@ +The Armada 370 has two gatable clocks for each PCIe interface, and we +want both of them to be enabled. We therefore make one of the two +clocks a child of the other, as we did for the sataX and sataXlnk +clocks on Armada XP. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +Cc: Mike Turquette <mturquette@linaro.org> +--- + drivers/clk/mvebu/clk-gating-ctrl.c |    4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/clk/mvebu/clk-gating-ctrl.c ++++ b/drivers/clk/mvebu/clk-gating-ctrl.c +@@ -119,8 +119,8 @@ static const struct mvebu_soc_descr __in + 	{ "pex1_en", NULL,  2 }, + 	{ "ge1", NULL, 3 }, + 	{ "ge0", NULL, 4 }, +-	{ "pex0", NULL, 5 }, +-	{ "pex1", NULL, 9 }, ++	{ "pex0", "pex0_en", 5 }, ++	{ "pex1", "pex1_en", 9 }, + 	{ "sata0", NULL, 15 }, + 	{ "sdio", NULL, 17 }, + 	{ "tdm", NULL, 25 }, diff --git a/target/linux/mvebu/patches-3.8/030-arm_plat_orion_introduce_win_ctrl_enable.patch b/target/linux/mvebu/patches-3.8/030-arm_plat_orion_introduce_win_ctrl_enable.patch new file mode 100644 index 000000000..9a237ec9b --- /dev/null +++ b/target/linux/mvebu/patches-3.8/030-arm_plat_orion_introduce_win_ctrl_enable.patch @@ -0,0 +1,28 @@ +Instead of hardcoding "1" as being the bit value to enable an address +decoding window, introduce and use a WIN_CTRL_ENABLE definition. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/plat-orion/addr-map.c |    4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/arch/arm/plat-orion/addr-map.c ++++ b/arch/arm/plat-orion/addr-map.c +@@ -38,6 +38,7 @@ EXPORT_SYMBOL_GPL(mv_mbus_dram_info); +  * CPU Address Decode Windows registers +  */ + #define WIN_CTRL_OFF		0x0000 ++#define   WIN_CTRL_ENABLE       BIT(0) + #define WIN_BASE_OFF		0x0004 + #define WIN_REMAP_LO_OFF	0x0008 + #define WIN_REMAP_HI_OFF	0x000c +@@ -79,7 +80,8 @@ void __init orion_setup_cpu_win(const st + 	} +  + 	base_high = base & 0xffff0000; +-	ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1; ++	ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | ++		WIN_CTRL_ENABLE; +  + 	writel(base_high, addr + WIN_BASE_OFF); + 	writel(ctrl, addr + WIN_CTRL_OFF); diff --git a/target/linux/mvebu/patches-3.8/031-arm_plat_orion_refactor.patch b/target/linux/mvebu/patches-3.8/031-arm_plat_orion_refactor.patch new file mode 100644 index 000000000..fe9f6285f --- /dev/null +++ b/target/linux/mvebu/patches-3.8/031-arm_plat_orion_refactor.patch @@ -0,0 +1,80 @@ +In the address decoding code, the orion_disable_wins() function is +used at boot time to disable all address decoding windows, before +configuring only the ones that are needed. This allows to make sure +that no configuration is left from the bootloader. + +As a preparation for the introduction of address decoding window +allocation/deallocation function, we refactor this function into an +orion_disable_cpu_win() which disables a single window. + +The orion_config_wins() function is changed to call +orion_disable_cpu_win() in a loop, to preserve an identical behavior. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/plat-orion/addr-map.c |   35 +++++++++++++++++------------------ + 1 file changed, 17 insertions(+), 18 deletions(-) + +--- a/arch/arm/plat-orion/addr-map.c ++++ b/arch/arm/plat-orion/addr-map.c +@@ -95,6 +95,19 @@ void __init orion_setup_cpu_win(const st + 	} + } +  ++static void __init orion_disable_cpu_win(const struct orion_addr_map_cfg *cfg, ++					 const int win) ++{ ++	void __iomem *addr = cfg->win_cfg_base(cfg, win); ++ ++	writel(0, addr + WIN_BASE_OFF); ++	writel(0, addr + WIN_CTRL_OFF); ++	if (cfg->cpu_win_can_remap(cfg, win)) { ++		writel(0, addr + WIN_REMAP_LO_OFF); ++		writel(0, addr + WIN_REMAP_HI_OFF); ++	} ++} ++ + /* +  * Configure a number of windows. +  */ +@@ -108,36 +121,22 @@ static void __init orion_setup_cpu_wins( + 	} + } +  +-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) + { ++	int win; ++ + 	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); ++	for (win = 0; win < cfg->num_wins; win++) ++		orion_disable_cpu_win(cfg, win); +  + 	if (info) + 		orion_setup_cpu_wins(cfg, info); diff --git a/target/linux/mvebu/patches-3.8/032-arm_plat_orion_introduce_orion_alloc_free_cpu_win.patch b/target/linux/mvebu/patches-3.8/032-arm_plat_orion_introduce_orion_alloc_free_cpu_win.patch new file mode 100644 index 000000000..91ed678b2 --- /dev/null +++ b/target/linux/mvebu/patches-3.8/032-arm_plat_orion_introduce_orion_alloc_free_cpu_win.patch @@ -0,0 +1,96 @@ +In the address decoding code, we implement two new functions: +orion_alloc_cpu_win() and orion_free_cpu_win(). The first function +finds an unused address decoding window, and configures it according +to the given arguments (in terms of base address, size, target, +attributes). The second function frees an address decoding window, +given a physical base address. + +Those two new functions will be used by the PCIe code, which needs to +dynamically register address decoding windows depending on the PCIe +devices that are detected. + +The orion_free_cpu_win() function is only here to handle error cases +in the PCIe devices initialization, in the normal case, address +decoding windows are never freed. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/plat-orion/addr-map.c              |   50 +++++++++++++++++++++++++++ + arch/arm/plat-orion/include/plat/addr-map.h |    7 ++++ + 2 files changed, 57 insertions(+) + +--- a/arch/arm/plat-orion/addr-map.c ++++ b/arch/arm/plat-orion/addr-map.c +@@ -109,6 +109,56 @@ static void __init orion_disable_cpu_win + } +  + /* ++ * Find an unused address decoding window, and enable it according to ++ * the arguments passed (base, size, target, attributes, remap). ++ */ ++int __init orion_alloc_cpu_win(const struct orion_addr_map_cfg *cfg, ++			       const u32 base, const u32 size, ++			       const u8 target, const u8 attr, const int remap) ++{ ++	int win; ++ ++	for (win = 0; win < cfg->num_wins; win++) { ++		void __iomem *addr = cfg->win_cfg_base(cfg, win); ++		u32 ctrl = readl(addr + WIN_CTRL_OFF); ++		if (!(ctrl & WIN_CTRL_ENABLE)) ++			break; ++	} ++ ++	/* No more windows available */ ++	if (win == cfg->num_wins) ++		return -ENOMEM; ++ ++	orion_setup_cpu_win(cfg, win, base, size, target, attr, remap); ++	return 0; ++} ++ ++/* ++ * Free an address decoding window, given its base address. ++ */ ++int __init orion_free_cpu_win(const struct orion_addr_map_cfg *cfg, ++			      const u32 base) ++{ ++	int win; ++ ++	for (win = 0; win < cfg->num_wins; win++) { ++		void __iomem *addr = cfg->win_cfg_base(cfg, win); ++		u32 winbase = readl(addr + WIN_BASE_OFF); ++		u32 ctrl = readl(addr + WIN_CTRL_OFF); ++ ++		if (!(ctrl & WIN_CTRL_ENABLE)) ++			continue; ++ ++		if (winbase == (base & 0xffff0000)) { ++			orion_disable_cpu_win(cfg, win); ++			return 0; ++		} ++	} ++ ++	return -EINVAL; ++} ++ ++/* +  * Configure a number of windows. +  */ + static void __init orion_setup_cpu_wins(const struct orion_addr_map_cfg * cfg, +--- a/arch/arm/plat-orion/include/plat/addr-map.h ++++ b/arch/arm/plat-orion/include/plat/addr-map.h +@@ -49,6 +49,13 @@ void __init orion_setup_cpu_win(const st + 				const u32 size, const u8 target, + 				const u8 attr, const int remap); +  ++int __init orion_alloc_cpu_win(const struct orion_addr_map_cfg *cfg, ++			       const u32 base, const u32 size, ++			       const u8 target, const u8 attr, const int remap); ++ ++int __init orion_free_cpu_win(const struct orion_addr_map_cfg *cfg, ++			      const u32 base); ++ + void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg, + 					const void __iomem *ddr_window_cpu_base); + #endif diff --git a/target/linux/mvebu/patches-3.8/033-arm_mvebu_add_functions_to_alloc_free_pcie.patch b/target/linux/mvebu/patches-3.8/033-arm_mvebu_add_functions_to_alloc_free_pcie.patch new file mode 100644 index 000000000..fd3c1af92 --- /dev/null +++ b/target/linux/mvebu/patches-3.8/033-arm_mvebu_add_functions_to_alloc_free_pcie.patch @@ -0,0 +1,201 @@ +This commit adds two functions armada_370_xp_alloc_pcie_window() and +armada_370_xp_free_pcie_window() that respectively allocate and free +an address decoding window pointing to either a memory or I/O region +of a PCIe device. + +Those functions will be used by the PCIe driver to create and remove +those regions depending on the PCIe devices that are detected. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/mach-mvebu/addr-map.c |  156 ++++++++++++++++++++++++++++++++++++++-- + arch/arm/mach-mvebu/common.h   |    4 ++ + 2 files changed, 156 insertions(+), 4 deletions(-) + +--- a/arch/arm/mach-mvebu/addr-map.c ++++ b/arch/arm/mach-mvebu/addr-map.c +@@ -24,14 +24,10 @@ + #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 +@@ -89,6 +85,158 @@ static struct __initdata orion_addr_map_ + 	.win_cfg_base = armada_cfg_base, + }; +  ++#ifdef CONFIG_PCI ++/* ++ * PCIe windows allocation code. ++ */ ++#define ARMADA_370_XP_PCIE_MEM_START 0xC0000000 ++#define ARMADA_370_XP_PCIE_MEM_END   (ARMADA_370_XP_PCIE_MEM_START + SZ_256M) ++#define ARMADA_370_XP_PCIE_IO_START  0xF2000000 ++#define ARMADA_370_XP_PCIE_IO_END    (ARMADA_370_XP_PCIE_IO_START + SZ_1M) ++ ++static unsigned long armada_370_xp_pcie_memaddr = ARMADA_370_XP_PCIE_MEM_START; ++static unsigned long armada_370_xp_pcie_ioaddr = ARMADA_370_XP_PCIE_IO_START; ++ ++/* ++ * This structure and the following arrays allow to map a PCIe (port, ++ * lane) tuple to the corresponding (target, attribute) tuple needed ++ * to configure an address decoding window for the given PCIe (port, ++ * lane). ++ */ ++struct pcie_mapping { ++	int port; ++	int lane; ++	u8  target; ++	u8  attr; ++}; ++ ++struct pcie_mapping armada_xp_pcie_mappings[] = { ++	{ .port = 0, .lane = 0, .target = 4, .attr = 0xE0 }, ++	{ .port = 0, .lane = 1, .target = 4, .attr = 0xD0 }, ++	{ .port = 0, .lane = 2, .target = 4, .attr = 0xB0 }, ++	{ .port = 0, .lane = 3, .target = 4, .attr = 0x70 }, ++	{ .port = 1, .lane = 0, .target = 8, .attr = 0xE0 }, ++	{ .port = 1, .lane = 1, .target = 8, .attr = 0xD0 }, ++	{ .port = 1, .lane = 2, .target = 8, .attr = 0xB0 }, ++	{ .port = 1, .lane = 3, .target = 8, .attr = 0x70 }, ++	{ .port = 2, .lane = 0, .target = 4, .attr = 0xF0 }, ++	{ .port = 3, .lane = 0, .target = 8, .attr = 0xF0 }, ++	{ .port = -1 }, ++}; ++ ++struct pcie_mapping armada_370_pcie_mappings[] = { ++	{ .port = 0, .lane = 0, .target = 4, .attr = 0xE0 }, ++	{ .port = 1, .lane = 0, .target = 8, .attr = 0xE0 }, ++	{ .port = -1 }, ++}; ++ ++/* ++ * This function finds an available physical address range between ++ * ARMADA_370_XP_PCIE_MEM_START and ARMADA_370_XP_PCIE_MEM_END (for ++ * PCIe memory regions) or between ARMADA_370_XP_PCIE_IO_START and ++ * ARMADA_370_XP_PCIE_IO_END (for PCIe I/O regions) and creates an ++ * address decoding window from this allocated address pointing to the ++ * right PCIe device. ++ * ++ * An error code is returned, the allocated base address is returned ++ * through the 'outbase' argument. ++ */ ++int __init armada_370_xp_alloc_pcie_window(int pcie_port, int pcie_lane, ++					   int type, u32 size, ++					   unsigned long *outbase) ++{ ++	struct pcie_mapping *mapping, *mappings; ++	u8 target, attr; ++	u32 base; ++	int ret; ++ ++	if (of_machine_is_compatible("marvell,armadaxp")) ++		mappings = armada_xp_pcie_mappings; ++	else if (of_machine_is_compatible("marvell,armada370")) ++		mappings = armada_370_pcie_mappings; ++	else ++		return -ENODEV; ++ ++	for (mapping = mappings; mapping->port != -1; mapping++) ++		if (mapping->port == pcie_port && mapping->lane == pcie_lane) ++			break; ++ ++	if (mapping->port == -1) ++		return -ENODEV; ++ ++	target = mapping->target; ++	attr = mapping->attr; ++ ++	if (type == IORESOURCE_MEM) { ++		/* ++		 * Bit 3 of the attributes indicates that it is a ++		 * memory region, as opposed to an I/O region ++		 */ ++		attr |= (1 << 3); ++ ++		if (armada_370_xp_pcie_memaddr + size > ++		    ARMADA_370_XP_PCIE_MEM_END) ++			return -ENOMEM; ++ ++		base = armada_370_xp_pcie_memaddr; ++		armada_370_xp_pcie_memaddr += size; ++ ++		ret = orion_alloc_cpu_win(&addr_map_cfg, base, size, target, ++					  attr, -1); ++		if (ret) { ++			armada_370_xp_pcie_memaddr -= size; ++			return ret; ++		} ++	} else if (type == IORESOURCE_IO) { ++		if (armada_370_xp_pcie_ioaddr + size > ++		    ARMADA_370_XP_PCIE_IO_END) ++			return -ENOMEM; ++ ++		base = armada_370_xp_pcie_ioaddr; ++		armada_370_xp_pcie_ioaddr += size; ++ ++		ret = orion_alloc_cpu_win(&addr_map_cfg, base, size, target, ++					  attr, -1); ++		if (ret) { ++			armada_370_xp_pcie_ioaddr -= size; ++			return ret; ++		} ++	} else ++		return -ENODEV; ++ ++	*outbase = base; ++	return 0; ++} ++ ++/* ++ * Frees an address decoding window previously allocated by ++ * armada_370_xp_alloc_pcie_window(). Note that only the last window ++ * allocated for a given type (MEM or IO) can be freed, due to the ++ * simplicity of the allocator. This is however sufficient to handle ++ * the error cases when initializing one PCIe device. ++ */ ++int __init armada_370_xp_free_pcie_window(int type, unsigned long base, ++					  u32 size) ++{ ++	if (type == IORESOURCE_MEM) { ++		/* We can only free the last allocated window */ ++		if (base + size != armada_370_xp_pcie_memaddr) ++			return -EINVAL; ++		orion_free_cpu_win(&addr_map_cfg, base); ++		armada_370_xp_pcie_memaddr -= size; ++	} else if (type == IORESOURCE_IO) { ++		/* We can only free the last allocated window */ ++		if (base + size != armada_370_xp_pcie_ioaddr) ++			return -EINVAL; ++		orion_free_cpu_win(&addr_map_cfg, base); ++		armada_370_xp_pcie_ioaddr -= size; ++	} else ++		return -EINVAL; ++ ++	return 0; ++} ++#endif ++ + static int __init armada_setup_cpu_mbus(void) + { + 	struct device_node *np; +--- a/arch/arm/mach-mvebu/common.h ++++ b/arch/arm/mach-mvebu/common.h +@@ -25,4 +25,8 @@ int armada_370_xp_coherency_init(void); + int armada_370_xp_pmsu_init(void); + void armada_xp_secondary_startup(void); + extern struct smp_operations armada_xp_smp_ops; ++ ++int armada_370_xp_alloc_pcie_window(int pcie_port, int pcie_lane, ++				    int type, u32 size, unsigned long *outbase); ++int armada_370_xp_free_pcie_window(int type, unsigned long base, u32 size); + #endif diff --git a/target/linux/mvebu/patches-3.8/034-arm_plat_orion_make_common_pcie.patch b/target/linux/mvebu/patches-3.8/034-arm_plat_orion_make_common_pcie.patch new file mode 100644 index 000000000..40ac714c1 --- /dev/null +++ b/target/linux/mvebu/patches-3.8/034-arm_plat_orion_make_common_pcie.patch @@ -0,0 +1,25 @@ +mvebu is a new-style Orion platform, so it only selects PLAT_ORION, +but not PLAT_ORION_LEGACY. It will however need the common PCIe code +from plat-orion, so make this code available for PLAT_ORION platforms +as a whole, and not only PLAT_ORION_LEGACY platforms. + +We also take this opportunity to build the PCIe code only when +CONFIG_PCI is enabled. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/plat-orion/Makefile |    3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/plat-orion/Makefile ++++ b/arch/arm/plat-orion/Makefile +@@ -4,7 +4,8 @@ + ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include +  + obj-y                             += addr-map.o ++obj-$(CONFIG_PCI)                 += pcie.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)   += irq.o time.o common.o mpp.o + obj-$(CONFIG_PLAT_ORION_LEGACY)   += $(orion-gpio-y) diff --git a/target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch b/target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch new file mode 100644 index 000000000..48f828344 --- /dev/null +++ b/target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch @@ -0,0 +1,474 @@ +This driver implements the hw_pci operations needed by the core ARM +PCI code to setup PCI devices and get their corresponding IRQs, and +the pci_ops operations that are used by the PCI core to read/write the +configuration space of PCI devices. + +In addition, this driver enumerates the different PCIe slots, and for +those having a device plugged in, it allocates the necessary address +decoding windows, using the new armada_370_xp_alloc_pcie_window() +function from mach-mvebu/addr-map.c. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + .../devicetree/bindings/pci/armada-370-xp-pcie.txt |  136 +++++++++ + arch/arm/mach-mvebu/Makefile                       |    1 + + arch/arm/mach-mvebu/pcie.c                         |  306 ++++++++++++++++++++ + 3 files changed, 443 insertions(+) + create mode 100644 Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt + create mode 100644 arch/arm/mach-mvebu/pcie.c + +--- /dev/null ++++ b/Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt +@@ -0,0 +1,136 @@ ++* Marvell Armada 370/XP PCIe interfaces ++ ++Mandatory properties: ++- compatible: must be "marvell,armada-370-xp-pcie" ++- status: either "disabled" or "okay" ++- #address-cells, set to <1> ++- #size-cells, set to <1> ++- ranges: describes the association between the physical addresses of ++  the PCIe registers for each PCIe interface with "virtual" addresses ++  as seen by the sub-nodes. One entry per PCIe interface. Each entry ++  must have 3 values: the "virtual" address seen by the sub-nodes, the ++  real physical address of the PCIe registers, and the size. ++ ++In addition, the Device Tree node must have sub-nodes describing each ++PCIe interface, having the following mandatory properties: ++- reg: the address and size of the PCIe registers (translated ++  addresses according to the ranges property of the parent) ++- interrupts: the interrupt number of this PCIe interface ++- clocks: the clock associated to this PCIe interface ++- marvell,pcie-port: the physical PCIe port number ++- status: either "disabled" or "okay" ++ ++and the following optional properties: ++- marvell,pcie-lane: the physical PCIe lane number, for ports having ++  multiple lanes. If this property is not found, we assume that the ++  value is 0. ++ ++Example: ++ ++pcie-controller { ++	compatible = "marvell,armada-370-xp-pcie"; ++	status = "disabled"; ++	#address-cells = <1>; ++	#size-cells = <1>; ++	ranges = <0       0xd0040000 0x2000 /* port0x1_port0 */ ++		  0x2000  0xd0042000 0x2000 /* port2x1_port0 */ ++		  0x4000  0xd0044000 0x2000 /* port0x1_port1 */ ++		  0x8000  0xd0048000 0x2000 /* port0x1_port2 */ ++		  0xC000  0xd004C000 0x2000 /* port0x1_port3 */ ++		  0x10000 0xd0080000 0x2000 /* port1x1_port0 */ ++		  0x12000 0xd0082000 0x2000 /* port3x1_port0 */ ++		  0x14000 0xd0084000 0x2000 /* port1x1_port1 */ ++		  0x18000 0xd0088000 0x2000 /* port1x1_port2 */ ++		  0x1C000 0xd008C000 0x2000 /* port1x1_port3 */>; ++ ++	pcie0.0@0xd0040000 { ++		reg = <0x0 0x2000>; ++		interrupts = <58>; ++		clocks = <&gateclk 5>; ++		marvell,pcie-port = <0>; ++		marvell,pcie-lane = <0>; ++		status = "disabled"; ++	}; ++ ++	pcie0.1@0xd0044000 { ++		reg = <0x4000 0x2000>; ++		interrupts = <59>; ++		clocks = <&gateclk 5>; ++		marvell,pcie-port = <0>; ++		marvell,pcie-lane = <1>; ++		status = "disabled"; ++	}; ++ ++	pcie0.2@0xd0048000 { ++		reg = <0x8000 0x2000>; ++		interrupts = <60>; ++		clocks = <&gateclk 5>; ++		marvell,pcie-port = <0>; ++		marvell,pcie-lane = <2>; ++		status = "disabled"; ++	}; ++ ++	pcie0.3@0xd004C000 { ++		reg = <0xC000 0x2000>; ++		interrupts = <61>; ++		clocks = <&gateclk 5>; ++		marvell,pcie-port = <0>; ++		marvell,pcie-lane = <3>; ++		status = "disabled"; ++	}; ++ ++	pcie1.0@0xd0040000 { ++		reg = <0x10000 0x2000>; ++		interrupts = <62>; ++		clocks = <&gateclk 6>; ++		marvell,pcie-port = <1>; ++		marvell,pcie-lane = <0>; ++		status = "disabled"; ++	}; ++ ++	pcie1.1@0xd0044000 { ++		reg = <0x14000 0x2000>; ++		interrupts = <63>; ++		clocks = <&gateclk 6>; ++		marvell,pcie-port = <1>; ++		marvell,pcie-lane = <1>; ++		status = "disabled"; ++	}; ++ ++	pcie1.2@0xd0048000 { ++		reg = <0x18000 0x2000>; ++		interrupts = <64>; ++		clocks = <&gateclk 6>; ++		marvell,pcie-port = <1>; ++		marvell,pcie-lane = <2>; ++		status = "disabled"; ++	}; ++ ++	pcie1.3@0xd004C000 { ++		reg = <0x1C000 0x2000>; ++		interrupts = <65>; ++		clocks = <&gateclk 6>; ++		marvell,pcie-port = <1>; ++		marvell,pcie-lane = <3>; ++		status = "disabled"; ++	}; ++ ++	pcie2@0xd0042000 { ++		reg = <0x2000 0x2000>; ++		interrupts = <99>; ++		clocks = <&gateclk 7>; ++		marvell,pcie-port = <2>; ++		marvell,pcie-lane = <0>; ++		status = "disabled"; ++	}; ++ ++	pcie3@0xd0082000 { ++		reg = <0x12000 0x2000>; ++		interrupts = <103>; ++		clocks = <&gateclk 8>; ++		marvell,pcie-port = <3>; ++		marvell,pcie-lane = <0>; ++		status = "disabled"; ++	}; ++}; ++ +--- a/arch/arm/mach-mvebu/Makefile ++++ b/arch/arm/mach-mvebu/Makefile +@@ -5,3 +5,4 @@ obj-y += system-controller.o + obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o + obj-$(CONFIG_SMP)                += platsmp.o headsmp.o + obj-$(CONFIG_HOTPLUG_CPU)        += hotplug.o ++obj-$(CONFIG_PCI)		 += pcie.o +--- /dev/null ++++ b/arch/arm/mach-mvebu/pcie.c +@@ -0,0 +1,306 @@ ++/* ++ * PCIe driver for Marvell Armada 370 and Armada XP 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/pci.h> ++#include <linux/clk.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/platform_device.h> ++#include <linux/of_address.h> ++#include <linux/of_pci.h> ++#include <linux/of_irq.h> ++#include <linux/of_platform.h> ++#include <plat/pcie.h> ++#include "common.h" ++ ++struct pcie_port { ++	u8		  root_bus_nr; ++	void __iomem	 *base; ++	spinlock_t	  conf_lock; ++	int		  irq; ++	struct resource	  res; ++	int               haslink; ++	u32               port; ++	u32               lane; ++	struct clk       *clk; ++}; ++ ++static struct pcie_port *pcie_ports; ++ ++static int pcie_valid_config(struct pcie_port *pp, int bus, int dev) ++{ ++	/* ++	 * Don't go out when trying to access -- ++	 * 1. nonexisting device on local bus ++	 * 2. where there's no device connected (no link) ++	 */ ++	if (bus == pp->root_bus_nr && dev == 0) ++		return 1; ++ ++	if (!orion_pcie_link_up(pp->base)) ++		return 0; ++ ++	if (bus == pp->root_bus_nr && dev != 1) ++		return 0; ++ ++	return 1; ++} ++ ++/* ++ * PCIe config cycles are done by programming the PCIE_CONF_ADDR register ++ * and then reading the PCIE_CONF_DATA register. Need to make sure these ++ * transactions are atomic. ++ */ ++static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, ++			int size, u32 *val) ++{ ++	struct pci_sys_data *sys = bus->sysdata; ++	struct pcie_port *pp = sys->private_data; ++	unsigned long flags; ++	int ret; ++ ++	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) { ++		*val = 0xffffffff; ++		return PCIBIOS_DEVICE_NOT_FOUND; ++	} ++ ++	spin_lock_irqsave(&pp->conf_lock, flags); ++	ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val); ++	spin_unlock_irqrestore(&pp->conf_lock, flags); ++ ++	return ret; ++} ++ ++static int pcie_wr_conf(struct pci_bus *bus, u32 devfn, ++			int where, int size, u32 val) ++{ ++	struct pci_sys_data *sys = bus->sysdata; ++	struct pcie_port *pp = sys->private_data; ++	unsigned long flags; ++	int ret; ++ ++	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) ++		return PCIBIOS_DEVICE_NOT_FOUND; ++ ++	spin_lock_irqsave(&pp->conf_lock, flags); ++	ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val); ++	spin_unlock_irqrestore(&pp->conf_lock, flags); ++ ++	return ret; ++} ++ ++static struct pci_ops pcie_ops = { ++	.read = pcie_rd_conf, ++	.write = pcie_wr_conf, ++}; ++ ++/* ++ * Returns 0 when the device could not be initialized, 1 when ++ * initialization is successful ++ */ ++static int __init armada_370_xp_pcie_setup(int nr, struct pci_sys_data *sys) ++{ ++	struct pcie_port *port = &pcie_ports[nr]; ++	unsigned long membase, iobase; ++	int ret; ++ ++	if (!port->haslink) ++		return 0; ++ ++	sys->private_data = port; ++	port->root_bus_nr = sys->busnr; ++	spin_lock_init(&port->conf_lock); ++ ++	ret = armada_370_xp_alloc_pcie_window(port->port, port->lane, ++					      IORESOURCE_MEM, SZ_64M, &membase); ++	if (ret) { ++		pr_err("PCIe%d.%d: Cannot get memory window, device disabled\n", ++		       port->port, port->lane); ++		return 0; ++	} ++ ++	ret = armada_370_xp_alloc_pcie_window(port->port, port->lane, ++					      IORESOURCE_IO, SZ_64K, &iobase); ++	if (ret) { ++		pr_err("PCIe%d.%d: Cannot get I/O window, device disabled\n", ++		       port->port, port->lane); ++		armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M); ++		return 0; ++	} ++ ++	port->res.name = kasprintf(GFP_KERNEL, "PCIe %d.%d MEM", ++				   port->port, port->lane); ++	if (!port->res.name) { ++		armada_370_xp_free_pcie_window(IORESOURCE_IO, iobase, SZ_64K); ++		armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M); ++		return 0; ++	} ++ ++	port->res.start = membase; ++	port->res.end = membase + SZ_32M - 1; ++	port->res.flags = IORESOURCE_MEM; ++ ++	pci_ioremap_io(SZ_64K * sys->busnr, iobase); ++ ++	if (request_resource(&iomem_resource, &port->res)) { ++		pr_err("PCIe%d.%d: Cannot request memory resource\n", ++		       port->port, port->lane); ++		kfree(port->res.name); ++		armada_370_xp_free_pcie_window(IORESOURCE_IO, iobase, SZ_64K); ++		armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M); ++		return 0; ++	} ++ ++	pci_add_resource_offset(&sys->resources, &port->res, sys->mem_offset); ++ ++	orion_pcie_set_local_bus_nr(port->base, sys->busnr); ++	orion_pcie_setup(port->base); ++ ++	return 1; ++} ++ ++static void __devinit rc_pci_fixup(struct pci_dev *dev) ++{ ++	/* ++	 * Prevent enumeration of root complex. ++	 */ ++	if (dev->bus->parent == NULL && dev->devfn == 0) { ++		int i; ++ ++		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { ++			dev->resource[i].start = 0; ++			dev->resource[i].end   = 0; ++			dev->resource[i].flags = 0; ++		} ++	} ++} ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); ++ ++static int __init armada_370_xp_pcie_map_irq(const struct pci_dev *dev, u8 slot, ++					     u8 pin) ++{ ++	struct pci_sys_data *sys = dev->sysdata; ++	struct pcie_port *port = sys->private_data; ++ ++	return port->irq; ++} ++ ++static struct hw_pci armada_370_xp_pci __initdata = { ++	.setup		= armada_370_xp_pcie_setup, ++	.map_irq	= armada_370_xp_pcie_map_irq, ++	.ops            = &pcie_ops, ++}; ++ ++static int __init armada_370_xp_pcie_probe(struct platform_device *pdev) ++{ ++	struct device_node *child; ++	int nports, i; ++ ++	nports = 0; ++	for_each_child_of_node(pdev->dev.of_node, child) { ++		if (!of_device_is_available(child)) ++			continue; ++		nports++; ++	} ++ ++	pcie_ports = devm_kzalloc(&pdev->dev, nports * sizeof(*pcie_ports), ++				  GFP_KERNEL); ++	if (!pcie_ports) ++		return -ENOMEM; ++ ++	i = 0; ++	for_each_child_of_node(pdev->dev.of_node, child) { ++		struct pcie_port *port = &pcie_ports[i]; ++ ++		if (!of_device_is_available(child)) ++			continue; ++ ++		if (of_property_read_u32(child, "marvell,pcie-port", ++					 &port->port)) ++			continue; ++ ++		if (of_property_read_u32(child, "marvell,pcie-lane", ++					 &port->lane)) ++			port->lane = 0; ++ ++		port->base = of_iomap(child, 0); ++		if (!port->base) { ++			dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", ++				port->port, port->lane); ++			continue; ++		} ++ ++		if (orion_pcie_link_up(port->base)) { ++			port->haslink = 1; ++			dev_info(&pdev->dev, "PCIe%d.%d: link up\n", ++				 port->port, port->lane); ++		} else { ++			port->haslink = 0; ++			dev_info(&pdev->dev, "PCIe%d.%d: link down\n", ++				 port->port, port->lane); ++			iounmap(port->base); ++			continue; ++		} ++ ++		port->irq = irq_of_parse_and_map(child, 0); ++		if (port->irq == 0) { ++			dev_err(&pdev->dev, "PCIe%d.%d: cannot parse and map IRQ\n", ++				port->port, port->lane); ++			iounmap(port->base); ++			port->haslink = 0; ++			continue; ++		} ++ ++		port->clk = of_clk_get_by_name(child, NULL); ++		if (!port->clk) { ++			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", ++			       port->port, port->lane); ++			irq_dispose_mapping(port->irq); ++			iounmap(port->base); ++			port->haslink = 0; ++			continue; ++		} ++ ++		clk_prepare_enable(port->clk); ++ ++		i++; ++	} ++ ++	armada_370_xp_pci.nr_controllers = nports; ++	pci_common_init(&armada_370_xp_pci); ++ ++	return 0; ++} ++ ++static const struct of_device_id armada_370_xp_pcie_of_match_table[] = { ++	{ .compatible = "marvell,armada-370-xp-pcie", }, ++	{}, ++}; ++MODULE_DEVICE_TABLE(of, armada_370_xp_pcie_of_match_table); ++ ++static struct platform_driver armada_370_xp_pcie_driver = { ++	.driver = { ++		.owner = THIS_MODULE, ++		.name = "armada-370-xp-pcie", ++		.of_match_table = ++		   of_match_ptr(armada_370_xp_pcie_of_match_table), ++	}, ++}; ++ ++static int armada_370_xp_pcie_init(void) ++{ ++	return platform_driver_probe(&armada_370_xp_pcie_driver, ++				     armada_370_xp_pcie_probe); ++} ++ ++subsys_initcall(armada_370_xp_pcie_init); ++ ++MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); ++MODULE_DESCRIPTION("Marvell Armada 370/XP PCIe driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/mvebu/patches-3.8/036-arm_mvebu_pcie_support_is_now_available.patch b/target/linux/mvebu/patches-3.8/036-arm_mvebu_pcie_support_is_now_available.patch new file mode 100644 index 000000000..b3c9a63d5 --- /dev/null +++ b/target/linux/mvebu/patches-3.8/036-arm_mvebu_pcie_support_is_now_available.patch @@ -0,0 +1,20 @@ +Now that the PCIe driver for mvebu has been integrated and all its +relevant dependencies, we can mark the ARCH_MVEBU platform has +MIGHT_HAVE_PCI, which allows to select the PCI bus support if needed. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/mach-mvebu/Kconfig |    2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm/mach-mvebu/Kconfig ++++ b/arch/arm/mach-mvebu/Kconfig +@@ -13,6 +13,8 @@ config ARCH_MVEBU + 	select MVEBU_CLK_CORE + 	select MVEBU_CLK_CPU + 	select MVEBU_CLK_GATING ++	select MIGHT_HAVE_PCI ++	select PCI_QUIRKS if PCI +  + if ARCH_MVEBU +  diff --git a/target/linux/mvebu/patches-3.8/037-arm_mvebu_add_pcie_dt_a370.patch b/target/linux/mvebu/patches-3.8/037-arm_mvebu_add_pcie_dt_a370.patch new file mode 100644 index 000000000..2cb8a17f0 --- /dev/null +++ b/target/linux/mvebu/patches-3.8/037-arm_mvebu_add_pcie_dt_a370.patch @@ -0,0 +1,40 @@ +The Armada 370 SoC has two 1x PCIe 2.0 interfaces, so we add the +necessary Device Tree informations to make these interfaces availabel. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/boot/dts/armada-370.dtsi |   25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +--- a/arch/arm/boot/dts/armada-370.dtsi ++++ b/arch/arm/boot/dts/armada-370.dtsi +@@ -153,5 +153,29 @@ + 			clocks = <&coreclk 0>; + 		}; +  ++		pcie-controller { ++			compatible = "marvell,armada-370-xp-pcie"; ++			status = "disabled"; ++			#address-cells = <1>; ++			#size-cells = <1>; ++			ranges = <0      0xd0040000 0x2000 ++			          0x2000 0xd0080000 0x2000>; ++ ++			pcie0@0xd0040000 { ++				reg = <0x0 0x2000>; ++				interrupts = <58>; ++				clocks = <&gateclk 5>; ++				status = "disabled"; ++				marvell,pcie-port = <0>; ++			}; ++ ++			pcie1@0xd0080000 { ++				reg = <0x2000 0x2000>; ++				interrupts = <62>; ++				clocks = <&gateclk 9>; ++				status = "disabled"; ++				marvell,pcie-port = <1>; ++			}; ++		}; + 	}; + }; diff --git a/target/linux/mvebu/patches-3.8/038-arm_mvebu_add_pcie_dt_axp.patch b/target/linux/mvebu/patches-3.8/038-arm_mvebu_add_pcie_dt_axp.patch new file mode 100644 index 000000000..647f1da5f --- /dev/null +++ b/target/linux/mvebu/patches-3.8/038-arm_mvebu_add_pcie_dt_axp.patch @@ -0,0 +1,284 @@ +The Armada XP SoCs have multiple PCIe interfaces. The MV78230 has 2 +PCIe units (one 4x or quad 1x, the other 1x only), the MV78260 has 3 +PCIe units (two 4x or quad 1x and one 4x/1x), the MV78460 has 4 PCIe +units (two 4x or quad 1x and two 4x/1x). We therefore add the +necessary Device Tree informations to make those PCIe interfaces +usable. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/boot/dts/armada-xp-mv78230.dtsi |   62 +++++++++++++++++ + arch/arm/boot/dts/armada-xp-mv78260.dtsi |   72 +++++++++++++++++++ + arch/arm/boot/dts/armada-xp-mv78460.dtsi |  112 ++++++++++++++++++++++++++++++ + 3 files changed, 246 insertions(+) + +--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi ++++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi +@@ -76,5 +76,67 @@ + 			#interrupts-cells = <2>; + 			interrupts = <87>, <88>, <89>; + 		}; ++ ++		/* ++		 * MV78230 has 2 PCIe units Gen2.0: One unit can be ++		 * configured as x4 or quad x1 lanes. One unit is ++		 * x4/x1. ++		 */ ++		pcie-controller { ++			compatible = "marvell,armada-370-xp-pcie"; ++			status = "disabled"; ++			#address-cells = <1>; ++			#size-cells = <1>; ++			ranges = <0       0xd0040000 0x2000 /* port0x1_port0 */ ++				  0x2000  0xd0042000 0x2000 /* port2x1_port0 */ ++				  0x4000  0xd0044000 0x2000 /* port0x1_port1 */ ++				  0x8000  0xd0048000 0x2000 /* port0x1_port2 */ ++				  0xC000  0xd004C000 0x2000 /* port0x1_port3 */>; ++ ++			pcie0.0@0xd0040000 { ++				reg = <0x0 0x2000>; ++				interrupts = <58>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <0>; ++				status = "disabled"; ++			}; ++ ++			pcie0.1@0xd0044000 { ++				reg = <0x4000 0x2000>; ++				interrupts = <59>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <1>; ++				status = "disabled"; ++			}; ++ ++			pcie0.2@0xd0048000 { ++				reg = <0x8000 0x2000>; ++				interrupts = <60>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <2>; ++				status = "disabled"; ++			}; ++ ++			pcie0.3@0xd004C000 { ++				reg = <0xC000 0x2000>; ++				interrupts = <61>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <3>; ++				status = "disabled"; ++			}; ++ ++			pcie2@0xd0042000 { ++				reg = <0x2000 0x2000>; ++				interrupts = <99>; ++				clocks = <&gateclk 7>; ++				marvell,pcie-port = <2>; ++				marvell,pcie-lane = <0>; ++				status = "disabled"; ++			}; ++		}; + 	}; + }; +--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi ++++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi +@@ -96,5 +96,77 @@ + 				clocks = <&gateclk 1>; + 				status = "disabled"; + 		}; ++ ++		/* ++		 * MV78260 has 3 PCIe units Gen2.0: Two units can be ++		 * configured as x4 or quad x1 lanes. One unit is ++		 * x4/x1. ++		 */ ++		pcie-controller { ++			compatible = "marvell,armada-370-xp-pcie"; ++			status = "okay"; ++			#address-cells = <1>; ++			#size-cells = <1>; ++			ranges = <0       0xd0040000 0x2000 /* port0x1_port0 */ ++				  0x2000  0xd0042000 0x2000 /* port2x1_port0 */ ++				  0x4000  0xd0044000 0x2000 /* port0x1_port1 */ ++				  0x8000  0xd0048000 0x2000 /* port0x1_port2 */ ++				  0xC000  0xd004C000 0x2000 /* port0x1_port3 */ ++				  0x12000 0xd0082000 0x2000 /* port3x1_port0 */>; ++ ++			pcie0.0@0xd0040000 { ++				reg = <0x0 0x2000>; ++				interrupts = <58>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <0>; ++				status = "disabled"; ++			}; ++ ++			pcie0.1@0xd0044000 { ++				reg = <0x4000 0x2000>; ++				interrupts = <59>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <1>; ++				status = "disabled"; ++			}; ++ ++			pcie0.2@0xd0048000 { ++				reg = <0x8000 0x2000>; ++				interrupts = <60>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <2>; ++				status = "disabled"; ++			}; ++ ++			pcie0.3@0xd004C000 { ++				reg = <0xC000 0x2000>; ++				interrupts = <61>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <3>; ++				status = "disabled"; ++			}; ++ ++			pcie2@0xd0042000 { ++				reg = <0x2000 0x2000>; ++				interrupts = <99>; ++				clocks = <&gateclk 7>; ++				marvell,pcie-port = <2>; ++				marvell,pcie-lane = <0>; ++				status = "disabled"; ++			}; ++ ++			pcie3@0xd0082000 { ++				reg = <0x12000 0x2000>; ++				interrupts = <103>; ++				clocks = <&gateclk 8>; ++				marvell,pcie-port = <3>; ++				marvell,pcie-lane = <0>; ++				status = "disabled"; ++			}; ++		}; + 	}; + }; +--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi ++++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi +@@ -111,5 +111,117 @@ + 				clocks = <&gateclk 1>; + 				status = "disabled"; + 		}; ++ ++		/* ++		 * MV78460 has 4 PCIe units Gen2.0: Two units can be ++		 * configured as x4 or quad x1 lanes. Two units are ++		 * x4/x1. ++		 */ ++		pcie-controller { ++			compatible = "marvell,armada-370-xp-pcie"; ++			status = "disabled"; ++			#address-cells = <1>; ++			#size-cells = <1>; ++			ranges = <0       0xd0040000 0x2000 /* port0x1_port0 */ ++				  0x2000  0xd0042000 0x2000 /* port2x1_port0 */ ++				  0x4000  0xd0044000 0x2000 /* port0x1_port1 */ ++				  0x8000  0xd0048000 0x2000 /* port0x1_port2 */ ++				  0xC000  0xd004C000 0x2000 /* port0x1_port3 */ ++				  0x10000 0xd0080000 0x2000 /* port1x1_port0 */ ++				  0x12000 0xd0082000 0x2000 /* port3x1_port0 */ ++				  0x14000 0xd0084000 0x2000 /* port1x1_port1 */ ++				  0x18000 0xd0088000 0x2000 /* port1x1_port2 */ ++				  0x1C000 0xd008C000 0x2000 /* port1x1_port3 */>; ++ ++			pcie0.0@0xd0040000 { ++				reg = <0x0 0x2000>; ++				interrupts = <58>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <0>; ++				status = "disabled"; ++			}; ++ ++			pcie0.1@0xd0044000 { ++				reg = <0x4000 0x2000>; ++				interrupts = <59>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <1>; ++				status = "disabled"; ++			}; ++ ++			pcie0.2@0xd0048000 { ++				reg = <0x8000 0x2000>; ++				interrupts = <60>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <2>; ++				status = "disabled"; ++			}; ++ ++			pcie0.3@0xd004C000 { ++				reg = <0xC000 0x2000>; ++				interrupts = <61>; ++				clocks = <&gateclk 5>; ++				marvell,pcie-port = <0>; ++				marvell,pcie-lane = <3>; ++				status = "disabled"; ++			}; ++ ++			pcie1.0@0xd0040000 { ++				reg = <0x10000 0x2000>; ++				interrupts = <62>; ++				clocks = <&gateclk 6>; ++				marvell,pcie-port = <1>; ++				marvell,pcie-lane = <0>; ++				status = "disabled"; ++			}; ++ ++			pcie1.1@0xd0044000 { ++				reg = <0x14000 0x2000>; ++				interrupts = <63>; ++				clocks = <&gateclk 6>; ++				marvell,pcie-port = <1>; ++				marvell,pcie-lane = <1>; ++				status = "disabled"; ++			}; ++ ++			pcie1.2@0xd0048000 { ++				reg = <0x18000 0x2000>; ++				interrupts = <64>; ++				clocks = <&gateclk 6>; ++				marvell,pcie-port = <1>; ++				marvell,pcie-lane = <2>; ++				status = "disabled"; ++			}; ++ ++			pcie1.3@0xd004C000 { ++				reg = <0x1C000 0x2000>; ++				interrupts = <65>; ++				clocks = <&gateclk 6>; ++				marvell,pcie-port = <1>; ++				marvell,pcie-lane = <3>; ++				status = "disabled"; ++			}; ++ ++			pcie2@0xd0042000 { ++				reg = <0x2000 0x2000>; ++				interrupts = <99>; ++				clocks = <&gateclk 7>; ++				marvell,pcie-port = <2>; ++				marvell,pcie-lane = <0>; ++				status = "disabled"; ++			}; ++ ++			pcie3@0xd0082000 { ++				reg = <0x12000 0x2000>; ++				interrupts = <103>; ++				clocks = <&gateclk 8>; ++				marvell,pcie-port = <3>; ++				marvell,pcie-lane = <0>; ++				status = "disabled"; ++			}; ++		}; + 	}; +  }; diff --git a/target/linux/mvebu/patches-3.8/039-arm_mvebu_add_pcie_dt_ax34.patch b/target/linux/mvebu/patches-3.8/039-arm_mvebu_add_pcie_dt_ax34.patch new file mode 100644 index 000000000..893c073eb --- /dev/null +++ b/target/linux/mvebu/patches-3.8/039-arm_mvebu_add_pcie_dt_ax34.patch @@ -0,0 +1,24 @@ +The PlatHome OpenBlocks AX3-4 has an internal mini-PCIe slot that can +be used to plug mini-PCIe devices. We therefore enable the PCIe +interface that corresponds to this slot. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts |    7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts ++++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +@@ -130,5 +130,12 @@ + 		usb@d0052000 { + 			status = "okay"; + 		}; ++		pcie-controller { ++			status = "okay"; ++			/* Internal mini-PCIe connector */ ++			pcie0.0@0xd0040000 { ++				status = "okay"; ++			}; ++		}; + 	}; + }; diff --git a/target/linux/mvebu/patches-3.8/040-arm_mvebu_add_pcie_axp_db.patch b/target/linux/mvebu/patches-3.8/040-arm_mvebu_add_pcie_axp_db.patch new file mode 100644 index 000000000..af15d4b85 --- /dev/null +++ b/target/linux/mvebu/patches-3.8/040-arm_mvebu_add_pcie_axp_db.patch @@ -0,0 +1,44 @@ +The Marvell evaluation board (DB) for the Armada XP SoC has 6 +physicals full-size PCIe slots, so we enable the corresponding PCIe +interfaces in the Device Tree. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/boot/dts/armada-xp-db.dts |   27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +--- a/arch/arm/boot/dts/armada-xp-db.dts ++++ b/arch/arm/boot/dts/armada-xp-db.dts +@@ -109,5 +109,32 @@ + 		usb@d0052000 { + 			status = "okay"; + 		}; ++ ++		pcie-controller { ++			status = "okay"; ++ ++			/* ++			 * All 6 slots are physically present as ++			 * standard PCIe slots on the board. ++			 */ ++			pcie0.0@0xd0040000 { ++				status = "okay"; ++			}; ++			pcie0.1@0xd0044000 { ++				status = "okay"; ++			}; ++			pcie0.2@0xd0048000 { ++				status = "okay"; ++			}; ++			pcie0.3@0xd004C000 { ++				status = "okay"; ++			}; ++			pcie2@0xd0042000 { ++				status = "okay"; ++			}; ++			pcie3@0xd0082000 { ++				status = "okay"; ++			}; ++		}; + 	}; + }; diff --git a/target/linux/mvebu/patches-3.8/041-arm_mvebu_add_pcie_dt_mirabox.patch b/target/linux/mvebu/patches-3.8/041-arm_mvebu_add_pcie_dt_mirabox.patch new file mode 100644 index 000000000..1b6089eef --- /dev/null +++ b/target/linux/mvebu/patches-3.8/041-arm_mvebu_add_pcie_dt_mirabox.patch @@ -0,0 +1,32 @@ +The Globalscale Mirabox platform uses one PCIe interface for an +available mini-PCIe slot, and the other PCIe interface for an internal +USB 3.0 controller. We add the necessary Device Tree informations to +enable those two interfaces. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/boot/dts/armada-370-mirabox.dts |   14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/arch/arm/boot/dts/armada-370-mirabox.dts ++++ b/arch/arm/boot/dts/armada-370-mirabox.dts +@@ -70,5 +70,19 @@ + 		usb@d0051000 { + 			status = "okay"; + 		}; ++ ++		pcie-controller { ++			status = "okay"; ++ ++			/* Internal mini-PCIe connector */ ++			pcie0@0xd0040000 { ++				status = "okay"; ++			}; ++ ++			/* Connected on the PCB to a USB 3.0 XHCI controller */ ++			pcie1@0xd0080000 { ++				status = "okay"; ++			}; ++		}; + 	}; + }; diff --git a/target/linux/mvebu/patches-3.8/042-arm_mvebu_add_pcie_dt_a370_db.patch b/target/linux/mvebu/patches-3.8/042-arm_mvebu_add_pcie_dt_a370_db.patch new file mode 100644 index 000000000..1a853f35c --- /dev/null +++ b/target/linux/mvebu/patches-3.8/042-arm_mvebu_add_pcie_dt_a370_db.patch @@ -0,0 +1,32 @@ +The Marvell evaluation board (DB) for the Armada 370 SoC has 2 +physical full-size PCIe slots, so we enable the corresponding PCIe +interfaces in the Device Tree. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + arch/arm/boot/dts/armada-370-db.dts |   15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/arch/arm/boot/dts/armada-370-db.dts ++++ b/arch/arm/boot/dts/armada-370-db.dts +@@ -82,5 +82,20 @@ + 		usb@d0051000 { + 			status = "okay"; + 		}; ++ ++		pcie-controller { ++			status = "okay"; ++			/* ++			 * The two PCIe units are accessible through ++			 * both standard PCIe slots and mini-PCIe ++			 * slots on the board. ++			 */ ++			pcie0@0xd0040000 { ++				status = "okay"; ++			}; ++			pcie1@0xd0080000 { ++				status = "okay"; ++			}; ++		}; + 	}; + }; | 
