From 56a705a48eae9c474ba7f82af5c4ff5cf306f654 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 4 Mar 2014 18:51:47 +0100 Subject: ARM: mvebu: Add a SOC bus device entry Add the SoC Family, device ID and revision to /sys/bus/soc. Signed-off-by: Andrew Lunn Link: https://lkml.kernel.org/r/1393955507-26436-1-git-send-email-andrew@lunn.ch Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/Kconfig | 1 + arch/arm/mach-mvebu/mvebu-soc-id.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 3f73eecbcfb..475cf8a6d16 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -6,6 +6,7 @@ config ARCH_MVEBU select IRQ_DOMAIN select PINCTRL select PLAT_ORION + select SOC_BUS select MVEBU_MBUS select ZONE_DMA if ARM_LPAE select ARCH_REQUIRE_GPIOLIB diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.c b/arch/arm/mach-mvebu/mvebu-soc-id.c index f3d4cf53f74..874a7504818 100644 --- a/arch/arm/mach-mvebu/mvebu-soc-id.c +++ b/arch/arm/mach-mvebu/mvebu-soc-id.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "mvebu-soc-id.h" #define PCIE_DEV_ID_OFF 0x0 @@ -118,3 +120,31 @@ clk_err: } core_initcall(mvebu_soc_id_init); +static int __init mvebu_soc_device(void) +{ + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + + /* Also protects against running on non-mvebu systems */ + if (!is_id_valid) + return 0; + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return -ENOMEM; + + soc_dev_attr->family = kasprintf(GFP_KERNEL, "Marvell"); + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", soc_rev); + soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%X", soc_dev_id); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->family); + kfree(soc_dev_attr->revision); + kfree(soc_dev_attr->soc_id); + kfree(soc_dev_attr); + } + + return 0; +} +postcore_initcall(mvebu_soc_device); -- cgit v1.2.3-70-g09d2 From 924d38f404936495b59ef7fa3ff232d978d64b18 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:46:59 +0200 Subject: ARM: mvebu: prepare coherency code to support more SOCs The code that handles the coherency fabric of Armada 370 and Armada XP in arch/arm/mach-mvebu/coherency.c made the assumption that there was only one type of coherency fabric. Unfortunately, it turns out that upcoming SoCs have a slightly different coherency unit. In preparation to the introduction of the coherency support for more SoCs, this commit: * Introduces a data associated to the compatible string in the compatible string match table, so that the code can differantiate the variant of coherency unit being used. * Separates the coherency unit initialization code into its own function. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483228-25625-2-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- .../devicetree/bindings/arm/coherency-fabric.txt | 5 ++- arch/arm/mach-mvebu/coherency.c | 47 +++++++++++++++------- 2 files changed, 37 insertions(+), 15 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt index 17d8cd10755..f0bfa37edfc 100644 --- a/Documentation/devicetree/bindings/arm/coherency-fabric.txt +++ b/Documentation/devicetree/bindings/arm/coherency-fabric.txt @@ -4,7 +4,10 @@ Available on Marvell SOCs: Armada 370 and Armada XP Required properties: -- compatible: "marvell,coherency-fabric" +- compatible: the possible values are: + + * "marvell,coherency-fabric", to be used for the coherency fabric of + the Armada 370 and Armada XP. - reg: Should contain coherency fabric registers location and length. First pair for the coherency fabric registers, second pair diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 4e9d58148ca..434cf5f90a8 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -38,8 +38,13 @@ static void __iomem *coherency_cpu_base; #define IO_SYNC_BARRIER_CTL_OFFSET 0x0 +enum { + COHERENCY_FABRIC_TYPE_ARMADA_370_XP, +}; + static struct of_device_id of_coherency_table[] = { - {.compatible = "marvell,coherency-fabric"}, + {.compatible = "marvell,coherency-fabric", + .data = (void *) COHERENCY_FABRIC_TYPE_ARMADA_370_XP }, { /* end of list */ }, }; @@ -121,26 +126,40 @@ static struct notifier_block mvebu_hwcc_platform_nb = { .notifier_call = mvebu_hwcc_platform_notifier, }; +static void __init armada_370_coherency_init(struct device_node *np) +{ + struct resource res; + + of_address_to_resource(np, 0, &res); + coherency_phys_base = res.start; + /* + * Ensure secondary CPUs will see the updated value, + * which they read before they join the coherency + * fabric, and therefore before they are coherent with + * the boot CPU cache. + */ + sync_cache_w(&coherency_phys_base); + coherency_base = of_iomap(np, 0); + coherency_cpu_base = of_iomap(np, 1); + set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); +} + int __init coherency_init(void) { struct device_node *np; np = of_find_matching_node(NULL, of_coherency_table); if (np) { - struct resource res; + const struct of_device_id *match = + of_match_node(of_coherency_table, np); + int type; + + type = (int) match->data; pr_info("Initializing Coherency fabric\n"); - of_address_to_resource(np, 0, &res); - coherency_phys_base = res.start; - /* - * Ensure secondary CPUs will see the updated value, - * which they read before they join the coherency - * fabric, and therefore before they are coherent with - * the boot CPU cache. - */ - sync_cache_w(&coherency_phys_base); - coherency_base = of_iomap(np, 0); - coherency_cpu_base = of_iomap(np, 1); - set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); + + if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) + armada_370_coherency_init(np); + of_node_put(np); } -- cgit v1.2.3-70-g09d2 From 501f928e009760f4987d4630265bb9fff28a6ecc Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:47:00 +0200 Subject: ARM: mvebu: add a coherency_available() call This commit extends the coherency fabric code to provide a coherency_available()function that the SoC code can call to be told whether coherency support is available or not. On Armada 370/XP, coherency support is available as soon as the relevant DT node is present. On some upcoming SoCs, the DT node needs to be present *and* the system running with CONFIG_SMP enabled. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483228-25625-3-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 30 ++++++++++++++++++++++-------- arch/arm/mach-mvebu/coherency.h | 1 + 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 434cf5f90a8..296cf14f08a 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -39,6 +39,7 @@ static void __iomem *coherency_cpu_base; #define IO_SYNC_BARRIER_CTL_OFFSET 0x0 enum { + COHERENCY_FABRIC_TYPE_NONE, COHERENCY_FABRIC_TYPE_ARMADA_370_XP, }; @@ -144,7 +145,7 @@ static void __init armada_370_coherency_init(struct device_node *np) set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); } -int __init coherency_init(void) +static int coherency_type(void) { struct device_node *np; @@ -155,27 +156,40 @@ int __init coherency_init(void) int type; type = (int) match->data; - pr_info("Initializing Coherency fabric\n"); + /* Armada 370/XP coherency works in both UP and SMP */ if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) - armada_370_coherency_init(np); + return type; of_node_put(np); } - return 0; + return COHERENCY_FABRIC_TYPE_NONE; } -static int __init coherency_late_init(void) +int coherency_available(void) { + return coherency_type() != COHERENCY_FABRIC_TYPE_NONE; +} + +int __init coherency_init(void) +{ + int type = coherency_type(); struct device_node *np; np = of_find_matching_node(NULL, of_coherency_table); - if (np) { + + if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) + armada_370_coherency_init(np); + + return 0; +} + +static int __init coherency_late_init(void) +{ + if (coherency_available()) bus_register_notifier(&platform_bus_type, &mvebu_hwcc_platform_nb); - of_node_put(np); - } return 0; } diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h index 760226c4135..02f7ec34ced 100644 --- a/arch/arm/mach-mvebu/coherency.h +++ b/arch/arm/mach-mvebu/coherency.h @@ -18,5 +18,6 @@ extern unsigned long coherency_phys_base; int set_cpu_coherent(unsigned int cpu_id, int smp_group_id); int coherency_init(void); +int coherency_available(void); #endif /* __MACH_370_XP_COHERENCY_H */ -- cgit v1.2.3-70-g09d2 From 5686a1e5aa436c49187a60052d5885fb1f541ce6 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:47:01 +0200 Subject: bus: mvebu: pass the coherency availability information at init time Until now, the mvebu-mbus was guessing by itself whether hardware I/O coherency was available or not by poking into the Device Tree to see if the coherency fabric Device Tree node was present or not. However, on some upcoming SoCs, the presence or absence of the coherency fabric DT node isn't sufficient: in CONFIG_SMP, the coherency can be enabled, but not in !CONFIG_SMP. In order to clean this up, the mvebu_mbus_dt_init() function is extended to get a boolean argument telling whether coherency is enabled or not. Therefore, the logic to decide whether coherency is available or not now belongs to the core SoC code instead of the mvebu-mbus driver itself, which is much better. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483228-25625-4-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-kirkwood/board-dt.c | 2 +- arch/arm/mach-mvebu/board-v7.c | 2 +- arch/arm/mach-mvebu/dove.c | 2 +- arch/arm/mach-mvebu/kirkwood.c | 2 +- drivers/bus/mvebu-mbus.c | 11 +++-------- include/linux/mbus.h | 2 +- 6 files changed, 8 insertions(+), 13 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index 2801da49e2a..ff18ff20f71 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -195,7 +195,7 @@ static void __init kirkwood_dt_init(void) { kirkwood_disable_mbus_error_propagation(); - BUG_ON(mvebu_mbus_dt_init()); + BUG_ON(mvebu_mbus_dt_init(false)); #ifdef CONFIG_CACHE_FEROCEON_L2 feroceon_of_init(); diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index 333fca8fdc4..1730e0cdb6f 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -58,7 +58,7 @@ static void __init mvebu_timer_and_clk_init(void) of_clk_init(NULL); clocksource_of_init(); coherency_init(); - BUG_ON(mvebu_mbus_dt_init()); + BUG_ON(mvebu_mbus_dt_init(coherency_available())); #ifdef CONFIG_CACHE_L2X0 l2x0_of_init(0, ~0UL); #endif diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c index 5e5a4362423..b50464ec113 100644 --- a/arch/arm/mach-mvebu/dove.c +++ b/arch/arm/mach-mvebu/dove.c @@ -23,7 +23,7 @@ static void __init dove_init(void) #ifdef CONFIG_CACHE_TAUROS2 tauros2_init(0); #endif - BUG_ON(mvebu_mbus_dt_init()); + BUG_ON(mvebu_mbus_dt_init(false)); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c index 120207fc36f..a77e0bae9c5 100644 --- a/arch/arm/mach-mvebu/kirkwood.c +++ b/arch/arm/mach-mvebu/kirkwood.c @@ -169,7 +169,7 @@ static void __init kirkwood_dt_init(void) { kirkwood_disable_mbus_error_propagation(); - BUG_ON(mvebu_mbus_dt_init()); + BUG_ON(mvebu_mbus_dt_init(false)); #ifdef CONFIG_CACHE_FEROCEON_L2 feroceon_of_init(); diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 293e2e0a0a8..ff02fc90fc2 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -694,7 +694,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, phys_addr_t sdramwins_phys_base, size_t sdramwins_size) { - struct device_node *np; int win; mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size); @@ -707,12 +706,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, return -ENOMEM; } - np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"); - if (np) { - mbus->hw_io_coherency = 1; - of_node_put(np); - } - for (win = 0; win < mbus->soc->num_wins; win++) mvebu_mbus_disable_window(mbus, win); @@ -882,7 +875,7 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np, } } -int __init mvebu_mbus_dt_init(void) +int __init mvebu_mbus_dt_init(bool is_coherent) { struct resource mbuswins_res, sdramwins_res; struct device_node *np, *controller; @@ -920,6 +913,8 @@ int __init mvebu_mbus_dt_init(void) return -EINVAL; } + mbus_state.hw_io_coherency = is_coherent; + /* Get optional pcie-{mem,io}-aperture properties */ mvebu_mbus_get_pcie_resources(np, &mbus_state.pcie_mem_aperture, &mbus_state.pcie_io_aperture); diff --git a/include/linux/mbus.h b/include/linux/mbus.h index 345b8c53b89..550c88fb026 100644 --- a/include/linux/mbus.h +++ b/include/linux/mbus.h @@ -73,6 +73,6 @@ 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); -int mvebu_mbus_dt_init(void); +int mvebu_mbus_dt_init(bool is_coherent); #endif /* __LINUX_MBUS_H */ -- cgit v1.2.3-70-g09d2 From 5fbba0805165a4883c60cf159f272dd0d7205c44 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:47:02 +0200 Subject: ARM: mvebu: ARM: mvebu: use of_find_matching_node_and_match() in coherency.c In the mach-mvebu coherency code, instead of using of_find_matching_node() and then of_match_node(), directly use the of_find_matching_node_and_match() which does both at once. We take this opportunity to also simplify the initialization of the "type" variable. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483228-25625-5-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 296cf14f08a..862100f7c83 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -148,14 +148,11 @@ static void __init armada_370_coherency_init(struct device_node *np) static int coherency_type(void) { struct device_node *np; + const struct of_device_id *match; - np = of_find_matching_node(NULL, of_coherency_table); + np = of_find_matching_node_and_match(NULL, of_coherency_table, &match); if (np) { - const struct of_device_id *match = - of_match_node(of_coherency_table, np); - int type; - - type = (int) match->data; + int type = (int) match->data; /* Armada 370/XP coherency works in both UP and SMP */ if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) -- cgit v1.2.3-70-g09d2 From 8e6ac20338228dc77c8f3538efb5a3aba712e0e5 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:47:03 +0200 Subject: ARM: mvebu: enable the ARM SCU on Armada 375 and Armada 38x Contrary to the Armada 370 and XP that used the PJ4B Marvell cores, the Armada 375 and Armada 38x use the ARM Cortex-A9. A consequence of this is that the unit responsible for the coherency between CPUs is now the ARM SCU, and not the Marvell coherency unit (which is still present to do coherency with I/O devices). Therefore this commit: * Ensures that the selection of the Armada 375 or Armada 38x SoC support enables the ARM SCU support in the kernel. * Make sure to initialize the SCU at boot time. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483228-25625-6-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/Kconfig | 2 ++ arch/arm/mach-mvebu/board-v7.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 475cf8a6d16..736bd2cbc1f 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -40,6 +40,7 @@ config MACH_ARMADA_375 select ARM_GIC select ARMADA_375_CLK select CPU_V7 + select HAVE_ARM_SCU select MACH_MVEBU_V7 select PINCTRL_ARMADA_375 help @@ -53,6 +54,7 @@ config MACH_ARMADA_38X select ARM_GIC select ARMADA_38X_CLK select CPU_V7 + select HAVE_ARM_SCU select MACH_MVEBU_V7 select PINCTRL_ARMADA_38X help diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index 1730e0cdb6f..85f964e55bf 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -27,11 +27,29 @@ #include #include #include +#include #include "armada-370-xp.h" #include "common.h" #include "coherency.h" #include "mvebu-soc-id.h" +/* + * Enables the SCU when available. Obviously, this is only useful on + * Cortex-A based SOCs, not on PJ4B based ones. + */ +static void __init mvebu_scu_enable(void) +{ + void __iomem *scu_base; + + struct device_node *np = + of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); + if (np) { + scu_base = of_iomap(np, 0); + scu_enable(scu_base); + of_node_put(np); + } +} + /* * Early versions of Armada 375 SoC have a bug where the BootROM * leaves an external data abort pending. The kernel is hit by this @@ -57,6 +75,7 @@ static void __init mvebu_timer_and_clk_init(void) { of_clk_init(NULL); clocksource_of_init(); + mvebu_scu_enable(); coherency_init(); BUG_ON(mvebu_mbus_dt_init(coherency_available())); #ifdef CONFIG_CACHE_L2X0 -- cgit v1.2.3-70-g09d2 From 77fa4b9ab0aafc0a06976814ad62aeff990dfd2c Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:47:04 +0200 Subject: ARM: mvebu: add Armada 375 support to the coherency code The Armada 375, like the Armada 370 and Armada XP, has a coherency unit. However, unlike the coherency unit of 370/XP which does both CPU and I/O coherency, the one on Armada 735 only does I/O coherency. Therefore, instead of having two sets of registers (the first one being used mainly to register each CPU in the coherency fabric, the second one being used for the I/O coherency barrier), it has only one set of register (for the I/O coherency barrier). This commit adds a new "marvell,armada-375-coherency-fabric" compatible string for this variant of the coherency fabric. The custom DMA operations, and the way of triggering an I/O barrier is the same as Armada 370/XP, so the code changes are minimal. However, the set_cpu_coherent() function is not needed on Armada 375 and will not work. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483228-25625-7-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- .../devicetree/bindings/arm/coherency-fabric.txt | 22 ++++++++++++++++++---- arch/arm/mach-mvebu/coherency.c | 14 ++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt index f0bfa37edfc..dcd80d6e047 100644 --- a/Documentation/devicetree/bindings/arm/coherency-fabric.txt +++ b/Documentation/devicetree/bindings/arm/coherency-fabric.txt @@ -1,6 +1,6 @@ Coherency fabric ---------------- -Available on Marvell SOCs: Armada 370 and Armada XP +Available on Marvell SOCs: Armada 370, Armada 375 and Armada XP Required properties: @@ -9,11 +9,20 @@ Required properties: * "marvell,coherency-fabric", to be used for the coherency fabric of the Armada 370 and Armada XP. + * "marvell,armada-375-coherency-fabric", for the Armada 375 coherency + fabric. + - reg: Should contain coherency fabric registers location and - length. First pair for the coherency fabric registers, second pair - for the per-CPU fabric registers registers. + length. + + * For "marvell,coherency-fabric", the first pair for the coherency + fabric registers, second pair for the per-CPU fabric registers. + + * For "marvell,armada-375-coherency-fabric", only one pair is needed + for the per-CPU fabric registers. -Example: + +Examples: coherency-fabric@d0020200 { compatible = "marvell,coherency-fabric"; @@ -22,3 +31,8 @@ coherency-fabric@d0020200 { }; +coherency-fabric@21810 { + compatible = "marvell,armada-375-coherency-fabric"; + reg = <0x21810 0x1c>; +}; + diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 862100f7c83..7ccaf87fd77 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -41,11 +41,14 @@ static void __iomem *coherency_cpu_base; enum { COHERENCY_FABRIC_TYPE_NONE, COHERENCY_FABRIC_TYPE_ARMADA_370_XP, + COHERENCY_FABRIC_TYPE_ARMADA_375, }; static struct of_device_id of_coherency_table[] = { {.compatible = "marvell,coherency-fabric", .data = (void *) COHERENCY_FABRIC_TYPE_ARMADA_370_XP }, + {.compatible = "marvell,armada-375-coherency-fabric", + .data = (void *) COHERENCY_FABRIC_TYPE_ARMADA_375 }, { /* end of list */ }, }; @@ -145,6 +148,11 @@ static void __init armada_370_coherency_init(struct device_node *np) set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); } +static void __init armada_375_coherency_init(struct device_node *np) +{ + coherency_cpu_base = of_iomap(np, 0); +} + static int coherency_type(void) { struct device_node *np; @@ -158,6 +166,10 @@ static int coherency_type(void) if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) return type; + /* Armada 375 coherency works only on SMP */ + else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375 && is_smp()) + return type; + of_node_put(np); } @@ -178,6 +190,8 @@ int __init coherency_init(void) if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) armada_370_coherency_init(np); + else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375) + armada_375_coherency_init(np); return 0; } -- cgit v1.2.3-70-g09d2 From 5ab5afd8ba837560f76f8ee527271d2e819bcaef Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:47:05 +0200 Subject: ARM: mvebu: implement Armada 375 coherency workaround The early revisions of Armada 375 SOCs (Z1 stepping) have a bug in the I/O coherency unit that prevents using the normal method for the I/O coherency barrier. The recommended workaround is to use a XOR memset transfer to act as the I/O coherency barrier. This involves "borrowing" a XOR engine, which gets disabled in the Device Tree so the normal XOR driver doesn't use it. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483228-25625-8-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 168 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 7ccaf87fd77..75db33ef93e 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -17,6 +17,8 @@ * supplies basic routines for configuring and controlling hardware coherency */ +#define pr_fmt(fmt) "mvebu-coherency: " fmt + #include #include #include @@ -24,6 +26,9 @@ #include #include #include +#include +#include +#include #include #include #include "armada-370-xp.h" @@ -66,8 +71,157 @@ int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id) return ll_set_cpu_coherent(coherency_base, hw_cpu_id); } +/* + * The below code implements the I/O coherency workaround on Armada + * 375. This workaround consists in using the two channels of the + * first XOR engine to trigger a XOR transaction that serves as the + * I/O coherency barrier. + */ + +static void __iomem *xor_base, *xor_high_base; +static dma_addr_t coherency_wa_buf_phys[CONFIG_NR_CPUS]; +static void *coherency_wa_buf[CONFIG_NR_CPUS]; +static bool coherency_wa_enabled; + +#define XOR_CONFIG(chan) (0x10 + (chan * 4)) +#define XOR_ACTIVATION(chan) (0x20 + (chan * 4)) +#define WINDOW_BAR_ENABLE(chan) (0x240 + ((chan) << 2)) +#define WINDOW_BASE(w) (0x250 + ((w) << 2)) +#define WINDOW_SIZE(w) (0x270 + ((w) << 2)) +#define WINDOW_REMAP_HIGH(w) (0x290 + ((w) << 2)) +#define WINDOW_OVERRIDE_CTRL(chan) (0x2A0 + ((chan) << 2)) +#define XOR_DEST_POINTER(chan) (0x2B0 + (chan * 4)) +#define XOR_BLOCK_SIZE(chan) (0x2C0 + (chan * 4)) +#define XOR_INIT_VALUE_LOW 0x2E0 +#define XOR_INIT_VALUE_HIGH 0x2E4 + +static inline void mvebu_hwcc_armada375_sync_io_barrier_wa(void) +{ + int idx = smp_processor_id(); + + /* Write '1' to the first word of the buffer */ + writel(0x1, coherency_wa_buf[idx]); + + /* Wait until the engine is idle */ + while ((readl(xor_base + XOR_ACTIVATION(idx)) >> 4) & 0x3) + ; + + dmb(); + + /* Trigger channel */ + writel(0x1, xor_base + XOR_ACTIVATION(idx)); + + /* Poll the data until it is cleared by the XOR transaction */ + while (readl(coherency_wa_buf[idx])) + ; +} + +static void __init armada_375_coherency_init_wa(void) +{ + const struct mbus_dram_target_info *dram; + struct device_node *xor_node; + struct property *xor_status; + struct clk *xor_clk; + u32 win_enable = 0; + int i; + + pr_warn("enabling coherency workaround for Armada 375 Z1, one XOR engine disabled\n"); + + /* + * Since the workaround uses one XOR engine, we grab a + * reference to its Device Tree node first. + */ + xor_node = of_find_compatible_node(NULL, NULL, "marvell,orion-xor"); + BUG_ON(!xor_node); + + /* + * Then we mark it as disabled so that the real XOR driver + * will not use it. + */ + xor_status = kzalloc(sizeof(struct property), GFP_KERNEL); + BUG_ON(!xor_status); + + xor_status->value = kstrdup("disabled", GFP_KERNEL); + BUG_ON(!xor_status->value); + + xor_status->length = 8; + xor_status->name = kstrdup("status", GFP_KERNEL); + BUG_ON(!xor_status->name); + + of_update_property(xor_node, xor_status); + + /* + * And we remap the registers, get the clock, and do the + * initial configuration of the XOR engine. + */ + xor_base = of_iomap(xor_node, 0); + xor_high_base = of_iomap(xor_node, 1); + + xor_clk = of_clk_get_by_name(xor_node, NULL); + BUG_ON(!xor_clk); + + clk_prepare_enable(xor_clk); + + dram = mv_mbus_dram_info(); + + for (i = 0; i < 8; i++) { + writel(0, xor_base + WINDOW_BASE(i)); + writel(0, xor_base + WINDOW_SIZE(i)); + if (i < 4) + writel(0, xor_base + WINDOW_REMAP_HIGH(i)); + } + + for (i = 0; i < dram->num_cs; i++) { + const struct mbus_dram_window *cs = dram->cs + i; + writel((cs->base & 0xffff0000) | + (cs->mbus_attr << 8) | + dram->mbus_dram_target_id, xor_base + WINDOW_BASE(i)); + writel((cs->size - 1) & 0xffff0000, xor_base + WINDOW_SIZE(i)); + + win_enable |= (1 << i); + win_enable |= 3 << (16 + (2 * i)); + } + + writel(win_enable, xor_base + WINDOW_BAR_ENABLE(0)); + writel(win_enable, xor_base + WINDOW_BAR_ENABLE(1)); + writel(0, xor_base + WINDOW_OVERRIDE_CTRL(0)); + writel(0, xor_base + WINDOW_OVERRIDE_CTRL(1)); + + for (i = 0; i < CONFIG_NR_CPUS; i++) { + coherency_wa_buf[i] = kzalloc(PAGE_SIZE, GFP_KERNEL); + BUG_ON(!coherency_wa_buf[i]); + + /* + * We can't use the DMA mapping API, since we don't + * have a valid 'struct device' pointer + */ + coherency_wa_buf_phys[i] = + virt_to_phys(coherency_wa_buf[i]); + BUG_ON(!coherency_wa_buf_phys[i]); + + /* + * Configure the XOR engine for memset operation, with + * a 128 bytes block size + */ + writel(0x444, xor_base + XOR_CONFIG(i)); + writel(128, xor_base + XOR_BLOCK_SIZE(i)); + writel(coherency_wa_buf_phys[i], + xor_base + XOR_DEST_POINTER(i)); + } + + writel(0x0, xor_base + XOR_INIT_VALUE_LOW); + writel(0x0, xor_base + XOR_INIT_VALUE_HIGH); + + coherency_wa_enabled = true; +} + static inline void mvebu_hwcc_sync_io_barrier(void) { + if (coherency_wa_enabled) { + mvebu_hwcc_armada375_sync_io_barrier_wa(); + return; + } + writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET); while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1); } @@ -198,9 +352,17 @@ int __init coherency_init(void) static int __init coherency_late_init(void) { - if (coherency_available()) - bus_register_notifier(&platform_bus_type, - &mvebu_hwcc_platform_nb); + int type = coherency_type(); + + if (type == COHERENCY_FABRIC_TYPE_NONE) + return 0; + + if (type == COHERENCY_FABRIC_TYPE_ARMADA_375) + armada_375_coherency_init_wa(); + + bus_register_notifier(&platform_bus_type, + &mvebu_hwcc_platform_nb); + return 0; } -- cgit v1.2.3-70-g09d2 From d0de9323822fada543f2f244eb67f520aa21ed77 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:47:06 +0200 Subject: ARM: mvebu: add Armada 38x support to the coherency code The Armada 38x has a coherency unit that is similar to the one of the Armada 375 SoC, except that it does not have the bug of the Armada 375 coherency unit that requires the XOR based workaround. This commit therefore extends the Marvell EBU coherency code with a new compatible string to support the Armada 38x coherency unit. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483228-25625-9-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- Documentation/devicetree/bindings/arm/coherency-fabric.txt | 7 ++++++- arch/arm/mach-mvebu/coherency.c | 14 +++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt index dcd80d6e047..8dd46617c88 100644 --- a/Documentation/devicetree/bindings/arm/coherency-fabric.txt +++ b/Documentation/devicetree/bindings/arm/coherency-fabric.txt @@ -1,6 +1,6 @@ Coherency fabric ---------------- -Available on Marvell SOCs: Armada 370, Armada 375 and Armada XP +Available on Marvell SOCs: Armada 370, Armada 375, Armada 38x and Armada XP Required properties: @@ -12,6 +12,9 @@ Required properties: * "marvell,armada-375-coherency-fabric", for the Armada 375 coherency fabric. + * "marvell,armada-380-coherency-fabric", for the Armada 38x coherency + fabric. + - reg: Should contain coherency fabric registers location and length. @@ -21,6 +24,8 @@ Required properties: * For "marvell,armada-375-coherency-fabric", only one pair is needed for the per-CPU fabric registers. + * For "marvell,armada-380-coherency-fabric", only one pair is needed + for the per-CPU fabric registers. Examples: diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 75db33ef93e..489edd157cf 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -47,6 +47,7 @@ enum { COHERENCY_FABRIC_TYPE_NONE, COHERENCY_FABRIC_TYPE_ARMADA_370_XP, COHERENCY_FABRIC_TYPE_ARMADA_375, + COHERENCY_FABRIC_TYPE_ARMADA_380, }; static struct of_device_id of_coherency_table[] = { @@ -54,6 +55,8 @@ static struct of_device_id of_coherency_table[] = { .data = (void *) COHERENCY_FABRIC_TYPE_ARMADA_370_XP }, {.compatible = "marvell,armada-375-coherency-fabric", .data = (void *) COHERENCY_FABRIC_TYPE_ARMADA_375 }, + {.compatible = "marvell,armada-380-coherency-fabric", + .data = (void *) COHERENCY_FABRIC_TYPE_ARMADA_380 }, { /* end of list */ }, }; @@ -302,7 +305,7 @@ static void __init armada_370_coherency_init(struct device_node *np) set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); } -static void __init armada_375_coherency_init(struct device_node *np) +static void __init armada_375_380_coherency_init(struct device_node *np) { coherency_cpu_base = of_iomap(np, 0); } @@ -324,6 +327,10 @@ static int coherency_type(void) else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375 && is_smp()) return type; + /* Armada 380 coherency works only on SMP */ + else if (type == COHERENCY_FABRIC_TYPE_ARMADA_380 && is_smp()) + return type; + of_node_put(np); } @@ -344,8 +351,9 @@ int __init coherency_init(void) if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) armada_370_coherency_init(np); - else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375) - armada_375_coherency_init(np); + else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375 || + type == COHERENCY_FABRIC_TYPE_ARMADA_380) + armada_375_380_coherency_init(np); return 0; } -- cgit v1.2.3-70-g09d2 From 3f20fb1153b374737acd40d42cb3cab2ae5dae35 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:50:28 +0200 Subject: ARM: mvebu: introduce CPU reset code The Armada 370 and Armada XP have registers that allow to reset the CPUs, which is particularly useful to take the secondary CPUs out of reset in the context of the SMP support. Unfortunately, an implementation mistake was originally made and the support for these registers was integrated into the PMSU driver, which is in fact completely unrelated. And it turns out that the Armada 375 has the same CPU reset registers, but does not have the PMSU registers. Therefore, this commit creates a small CPU reset driver. All it does is provide a simple mvebu_cpu_reset_deassert() function that the SMP support code can call to take secondary CPUs out of reset. As of this commit, the driver isn't being used, it will be used through changes in the following commits. Note that we initially planned to use the 'reset controller' framework, but it requires the addition of "resets" properties in the Device Tree, which are causing too many problems if we want to keep the Device Tree backward compatibility. Moreover, the 'reset controller' framework is mainly useful when a device driver needs to request a reset of its device from a separate reset controller. In our case, the CPU reset handling and the SMP core code are both located in arch/arm/mach-mvebu/ and are tightly linked together, so there's no real benefit in going through a separate framework. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483433-25836-2-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- .../devicetree/bindings/arm/armada-cpu-reset.txt | 14 ++++ arch/arm/mach-mvebu/Makefile | 2 +- arch/arm/mach-mvebu/common.h | 1 + arch/arm/mach-mvebu/cpu-reset.c | 82 ++++++++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/arm/armada-cpu-reset.txt create mode 100644 arch/arm/mach-mvebu/cpu-reset.c (limited to 'arch/arm/mach-mvebu') diff --git a/Documentation/devicetree/bindings/arm/armada-cpu-reset.txt b/Documentation/devicetree/bindings/arm/armada-cpu-reset.txt new file mode 100644 index 00000000000..b63a7b6ab99 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/armada-cpu-reset.txt @@ -0,0 +1,14 @@ +Marvell Armada CPU reset controller +=================================== + +Required properties: + +- compatible: Should be "marvell,armada-370-cpu-reset". + +- reg: should be register base and length as documented in the + datasheet for the CPU reset registers + +cpurst: cpurst@20800 { + compatible = "marvell,armada-370-cpu-reset"; + reg = <0x20800 0x20>; +}; diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index a63e43b6b45..f9cfab05c5f 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -3,7 +3,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ AFLAGS_coherency_ll.o := -Wa,-march=armv7-a -obj-y += system-controller.o mvebu-soc-id.o +obj-y += system-controller.o mvebu-soc-id.o cpu-reset.o obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o obj-$(CONFIG_MACH_DOVE) += dove.o obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h index 55449c487c9..cfb129b144c 100644 --- a/arch/arm/mach-mvebu/common.h +++ b/arch/arm/mach-mvebu/common.h @@ -18,6 +18,7 @@ #include void mvebu_restart(enum reboot_mode mode, const char *cmd); +int mvebu_cpu_reset_deassert(int cpu); void armada_xp_cpu_die(unsigned int cpu); diff --git a/arch/arm/mach-mvebu/cpu-reset.c b/arch/arm/mach-mvebu/cpu-reset.c new file mode 100644 index 00000000000..4ff4ce77f8b --- /dev/null +++ b/arch/arm/mach-mvebu/cpu-reset.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2014 Marvell + * + * Thomas Petazzoni + * + * 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. + */ + +#define pr_fmt(fmt) "mvebu-cpureset: " fmt + +#include +#include +#include +#include +#include +#include "armada-370-xp.h" + +static void __iomem *cpu_reset_base; +static size_t cpu_reset_size; + +#define CPU_RESET_OFFSET(cpu) (cpu * 0x8) +#define CPU_RESET_ASSERT BIT(0) + +int mvebu_cpu_reset_deassert(int cpu) +{ + u32 reg; + + if (!cpu_reset_base) + return -ENODEV; + + if (CPU_RESET_OFFSET(cpu) >= cpu_reset_size) + return -EINVAL; + + reg = readl(cpu_reset_base + CPU_RESET_OFFSET(cpu)); + reg &= ~CPU_RESET_ASSERT; + writel(reg, cpu_reset_base + CPU_RESET_OFFSET(cpu)); + + return 0; +} + +static int __init mvebu_cpu_reset_init(void) +{ + struct device_node *np; + struct resource res; + int ret = 0; + + np = of_find_compatible_node(NULL, NULL, + "marvell,armada-370-cpu-reset"); + if (!np) + return 0; + + if (of_address_to_resource(np, 0, &res)) { + pr_err("unable to get resource\n"); + ret = -ENOENT; + goto out; + } + + if (!request_mem_region(res.start, resource_size(&res), + np->full_name)) { + pr_err("unable to request region\n"); + ret = -EBUSY; + goto out; + } + + cpu_reset_base = ioremap(res.start, resource_size(&res)); + if (!cpu_reset_base) { + pr_err("unable to map registers\n"); + release_mem_region(res.start, resource_size(&res)); + ret = -ENOMEM; + goto out; + } + + cpu_reset_size = resource_size(&res); + +out: + of_node_put(np); + return ret; +} + +early_initcall(mvebu_cpu_reset_init); -- cgit v1.2.3-70-g09d2 From 49754ffef5dca1d212e5fea5957a2a164585e92c Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:50:29 +0200 Subject: ARM: mvebu: start using the CPU reset driver This commit changes the PMSU driver to no longer map itself the CPU reset registers, and instead call into the CPU reset driver to deassert the secondary CPUs for SMP booting. In order to provide Device Tree backward compatibility, the CPU reset driver is extended to not only support its official compatible string "marvell,armada-370-cpu-reset", but to also look at the PMSU compatible string "marvell,armada-370-xp-pmsu" to find the CPU reset registers address. This allows old Device Tree to work correctly with newer kernel versions. Therefore, the CPU reset driver implements the following logic: * If one of the normal compatible strings "marvell,armada-370-cpu-reset" is found, then we map its first memory resource as the CPU reset registers. * Otherwise, if none of the normal compatible strings have been found, we look for the "marvell,armada-370-xp-pmsu" compatible string, and we map the second memory as the CPU reset registers. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483433-25836-3-git-send-email-thomas.petazzoni@free-electrons.com Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/cpu-reset.c | 53 ++++++++++++++++++++++++++++------------- arch/arm/mach-mvebu/pmsu.c | 20 ++++++++-------- 2 files changed, 47 insertions(+), 26 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/cpu-reset.c b/arch/arm/mach-mvebu/cpu-reset.c index 4ff4ce77f8b..4a8f9eebebe 100644 --- a/arch/arm/mach-mvebu/cpu-reset.c +++ b/arch/arm/mach-mvebu/cpu-reset.c @@ -40,42 +40,63 @@ int mvebu_cpu_reset_deassert(int cpu) return 0; } -static int __init mvebu_cpu_reset_init(void) +static int mvebu_cpu_reset_map(struct device_node *np, int res_idx) { - struct device_node *np; struct resource res; - int ret = 0; - - np = of_find_compatible_node(NULL, NULL, - "marvell,armada-370-cpu-reset"); - if (!np) - return 0; - if (of_address_to_resource(np, 0, &res)) { + if (of_address_to_resource(np, res_idx, &res)) { pr_err("unable to get resource\n"); - ret = -ENOENT; - goto out; + return -ENOENT; } if (!request_mem_region(res.start, resource_size(&res), np->full_name)) { pr_err("unable to request region\n"); - ret = -EBUSY; - goto out; + return -EBUSY; } cpu_reset_base = ioremap(res.start, resource_size(&res)); if (!cpu_reset_base) { pr_err("unable to map registers\n"); release_mem_region(res.start, resource_size(&res)); - ret = -ENOMEM; - goto out; + return -ENOMEM; } cpu_reset_size = resource_size(&res); -out: + return 0; +} + +int __init mvebu_cpu_reset_init(void) +{ + struct device_node *np; + int res_idx; + int ret; + + np = of_find_compatible_node(NULL, NULL, + "marvell,armada-370-cpu-reset"); + if (np) { + res_idx = 0; + } else { + /* + * This code is kept for backward compatibility with + * old Device Trees. + */ + np = of_find_compatible_node(NULL, NULL, + "marvell,armada-370-xp-pmsu"); + if (np) { + pr_warn(FW_WARN "deprecated pmsu binding\n"); + res_idx = 1; + } + } + + /* No reset node found */ + if (!np) + return -ENODEV; + + ret = mvebu_cpu_reset_map(np, res_idx); of_node_put(np); + return ret; } diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index d71ef53107c..1807639173b 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -21,14 +21,14 @@ #include #include #include +#include #include +#include "common.h" #include "pmsu.h" static void __iomem *pmsu_mp_base; -static void __iomem *pmsu_reset_base; #define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x24) -#define PMSU_RESET_CTL_OFFSET(cpu) (cpu * 0x8) static struct of_device_id of_pmsu_table[] = { {.compatible = "marvell,armada-370-xp-pmsu"}, @@ -38,11 +38,11 @@ static struct of_device_id of_pmsu_table[] = { #ifdef CONFIG_SMP int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr) { - int reg, hw_cpu; + int hw_cpu, ret; - if (!pmsu_mp_base || !pmsu_reset_base) { + if (!pmsu_mp_base) { pr_warn("Can't boot CPU. PMSU is uninitialized\n"); - return 1; + return -ENODEV; } hw_cpu = cpu_logical_map(cpu_id); @@ -50,10 +50,11 @@ int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr) writel(virt_to_phys(boot_addr), pmsu_mp_base + PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu)); - /* Release CPU from reset by clearing reset bit*/ - reg = readl(pmsu_reset_base + PMSU_RESET_CTL_OFFSET(hw_cpu)); - reg &= (~0x1); - writel(reg, pmsu_reset_base + PMSU_RESET_CTL_OFFSET(hw_cpu)); + ret = mvebu_cpu_reset_deassert(hw_cpu); + if (ret) { + pr_warn("unable to boot CPU: %d\n", ret); + return ret; + } return 0; } @@ -67,7 +68,6 @@ static int __init armada_370_xp_pmsu_init(void) if (np) { pr_info("Initializing Power Management Service Unit\n"); pmsu_mp_base = of_iomap(np, 0); - pmsu_reset_base = of_iomap(np, 1); of_node_put(np); } -- cgit v1.2.3-70-g09d2 From bd045a1ebb48e5901508574188404d9bd3bdd72f Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:50:30 +0200 Subject: ARM: mvebu: improve PMSU driver to request its resource Until now, the PMSU driver was using of_iomap() to map its registers, but of_iomap() doesn't call request_mem_region(). This commit fixes the memory mapping code of the PMSU to do so, which will also be useful for a later commit since we will need to adjust the resource base address and size for Device Tree backward compatibility. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483433-25836-4-git-send-email-thomas.petazzoni@free-electrons.com Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/pmsu.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 1807639173b..b337fe56bae 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -16,6 +16,8 @@ * other SOC units */ +#define pr_fmt(fmt) "mvebu-pmsu: " fmt + #include #include #include @@ -63,15 +65,39 @@ int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr) static int __init armada_370_xp_pmsu_init(void) { struct device_node *np; + struct resource res; + int ret = 0; np = of_find_matching_node(NULL, of_pmsu_table); - if (np) { - pr_info("Initializing Power Management Service Unit\n"); - pmsu_mp_base = of_iomap(np, 0); - of_node_put(np); + if (!np) + return 0; + + pr_info("Initializing Power Management Service Unit\n"); + + if (of_address_to_resource(np, 0, &res)) { + pr_err("unable to get resource\n"); + ret = -ENOENT; + goto out; } - return 0; + if (!request_mem_region(res.start, resource_size(&res), + np->full_name)) { + pr_err("unable to request region\n"); + ret = -EBUSY; + goto out; + } + + pmsu_mp_base = ioremap(res.start, resource_size(&res)); + if (!pmsu_mp_base) { + pr_err("unable to map registers\n"); + release_mem_region(res.start, resource_size(&res)); + ret = -ENOMEM; + goto out; + } + + out: + of_node_put(np); + return ret; } early_initcall(armada_370_xp_pmsu_init); -- cgit v1.2.3-70-g09d2 From 0c3acc746d2cd84c3654b6cc07eda2411584f4af Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 15:50:31 +0200 Subject: ARM: mvebu: extend the PMSU registers The initial binding for PMSU was wrong, as it didn't take into account all the registers from the PMSU and moreover it referred to the CPU reset registers which are not part of PMSU. The Power Management Unit Service block also controls the Coherency Fabric subsystem. These registers are needed for the CPU idle implementation for the Armada 370/XP, it allows to enter a deep CPU idle state where the Coherency Fabric and the L2 cache are powered down. This commit adds support for a new compatible for the PMSU node which includes the registers related to the coherency fabric. It also keeps compatibility with the old compatible string. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397483433-25836-5-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483433-25836-5-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- .../devicetree/bindings/arm/armada-370-xp-pmsu.txt | 14 ++++++-------- arch/arm/mach-mvebu/pmsu.c | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt index 926b4d6aae7..97618877007 100644 --- a/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt +++ b/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt @@ -4,17 +4,15 @@ Available on Marvell SOCs: Armada 370 and Armada XP Required properties: -- compatible: "marvell,armada-370-xp-pmsu" +- compatible: should be "marvell,armada-370-pmsu", whereas + "marvell,armada-370-xp-pmsu" is deprecated and will be removed -- reg: Should contain PMSU registers location and length. First pair - for the per-CPU SW Reset Control registers, second pair for the - Power Management Service Unit. +- reg: Should contain PMSU registers location and length. Example: -armada-370-xp-pmsu@d0022000 { - compatible = "marvell,armada-370-xp-pmsu"; - reg = <0xd0022100 0x430>, - <0xd0020800 0x20>; +armada-370-xp-pmsu@22000 { + compatible = "marvell,armada-370-pmsu"; + reg = <0x22000 0x1000>; }; diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index b337fe56bae..4ae3ea1af7c 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -30,10 +30,14 @@ static void __iomem *pmsu_mp_base; -#define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x24) +#define PMSU_BASE_OFFSET 0x100 +#define PMSU_REG_SIZE 0x1000 + +#define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x124) static struct of_device_id of_pmsu_table[] = { - {.compatible = "marvell,armada-370-xp-pmsu"}, + { .compatible = "marvell,armada-370-pmsu", }, + { .compatible = "marvell,armada-370-xp-pmsu", }, { /* end of list */ }, }; @@ -80,6 +84,12 @@ static int __init armada_370_xp_pmsu_init(void) goto out; } + if (of_device_is_compatible(np, "marvell,armada-370-xp-pmsu")) { + pr_warn(FW_WARN "deprecated pmsu binding\n"); + res.start = res.start - PMSU_BASE_OFFSET; + res.end = res.start + PMSU_REG_SIZE - 1; + } + if (!request_mem_region(res.start, resource_size(&res), np->full_name)) { pr_err("unable to request region\n"); -- cgit v1.2.3-70-g09d2 From 02e7b06795fc129e45ed39983673efbb05d69506 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 15:50:33 +0200 Subject: ARM: mvebu: use a separate function to set the boot address of CPUs Setting the start (or boot) address of a CPU is no more used only during SMP bring up on Armada 370/XP, but it will also be used by the CPU idle function of Armada XP, and by the Armada 38x SMP support. Therefore this commit creates a separate PMSU function to set the boot address of a CPU with the PMSU. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397483433-25836-7-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483433-25836-7-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/pmsu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 4ae3ea1af7c..8361281f918 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -41,6 +41,12 @@ static struct of_device_id of_pmsu_table[] = { { /* end of list */ }, }; +static void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr) +{ + writel(virt_to_phys(boot_addr), pmsu_mp_base + + PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu)); +} + #ifdef CONFIG_SMP int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr) { @@ -53,8 +59,7 @@ int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr) hw_cpu = cpu_logical_map(cpu_id); - writel(virt_to_phys(boot_addr), pmsu_mp_base + - PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu)); + mvebu_pmsu_set_cpu_boot_addr(hw_cpu, boot_addr); ret = mvebu_cpu_reset_deassert(hw_cpu); if (ret) { -- cgit v1.2.3-70-g09d2 From ef37d337e1d37bd84ccaa5811a8d1f00f8b3677c Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:54:01 +0200 Subject: irqchip: irq-armada-370-xp: Do the set_smp_cross_call() in the driver Instead of having the SoC code in arch/arm/mach-mvebu/platsmp.c do the set_smp_cross_call() to register the IPI-triggering function, it makes more sense to do exactly what the GIC driver is doing: let the irqchip driver do it. This way, it avoids having to expose the armada_mpic_send_doorbell() function between the irqchip driver and the SoC code. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483648-26611-5-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/armada-370-xp.h | 1 - arch/arm/mach-mvebu/platsmp.c | 2 -- drivers/irqchip/irq-armada-370-xp.c | 6 +++++- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/armada-370-xp.h b/arch/arm/mach-mvebu/armada-370-xp.h index 237c86b8339..cd57c78af27 100644 --- a/arch/arm/mach-mvebu/armada-370-xp.h +++ b/arch/arm/mach-mvebu/armada-370-xp.h @@ -20,7 +20,6 @@ #define ARMADA_XP_MAX_CPUS 4 -void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq); void armada_xp_mpic_smp_cpu_init(void); void armada_xp_secondary_startup(void); extern struct smp_operations armada_xp_smp_ops; diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index a6da03f5b24..6f06f6ddb51 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -90,8 +90,6 @@ static void __init armada_xp_smp_init_cpus(void) if (ncores == 0 || ncores > ARMADA_XP_MAX_CPUS) panic("Invalid number of CPUs in DT\n"); - - set_smp_cross_call(armada_mpic_send_doorbell); } static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 41be897df8d..727566216e2 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -315,7 +315,8 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, } #ifdef CONFIG_SMP -void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq) +static void armada_mpic_send_doorbell(const struct cpumask *mask, + unsigned int irq) { int cpu; unsigned long map = 0; @@ -511,6 +512,9 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, if (parent_irq <= 0) { irq_set_default_host(armada_370_xp_mpic_domain); set_handle_irq(armada_370_xp_handle_irq); +#ifdef CONFIG_SMP + set_smp_cross_call(armada_mpic_send_doorbell); +#endif } else { irq_set_chained_handler(parent_irq, armada_370_xp_mpic_handle_cascade_irq); -- cgit v1.2.3-70-g09d2 From d7df84b3cecad4c768e4065d1d61b2f8fd02b7fa Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:54:02 +0200 Subject: irqchip: irq-armada-370-xp: Use cpu notifier to initialize secondary CPUs Some irqchip initialization must be done on secondary CPUs. On mvebu platforms, this is currently achieved by having the arch/arm/mach-mvebu/platsmp.c code directly call into a function exported by the irqchip driver, which isn't really nice. This commit changes this by using the same solution as the one used in the GIC driver: the irqchip driver registers a CPU notifier, which is used to do the secondary CPU IRQ initialization. This way, the irqchip driver is completely autonomous, and the function no longer needs to be exposed from the irqchip driver to the SoC code. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483648-26611-6-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/armada-370-xp.h | 1 - arch/arm/mach-mvebu/platsmp.c | 6 ------ drivers/irqchip/irq-armada-370-xp.c | 18 +++++++++++++++++- 3 files changed, 17 insertions(+), 8 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/armada-370-xp.h b/arch/arm/mach-mvebu/armada-370-xp.h index cd57c78af27..c3465f5b125 100644 --- a/arch/arm/mach-mvebu/armada-370-xp.h +++ b/arch/arm/mach-mvebu/armada-370-xp.h @@ -20,7 +20,6 @@ #define ARMADA_XP_MAX_CPUS 4 -void armada_xp_mpic_smp_cpu_init(void); void armada_xp_secondary_startup(void); extern struct smp_operations armada_xp_smp_ops; #endif diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index 6f06f6ddb51..e43727f391f 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -70,11 +70,6 @@ static void __init set_secondary_cpus_clock(void) } } -static void armada_xp_secondary_init(unsigned int cpu) -{ - armada_xp_mpic_smp_cpu_init(); -} - static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) { pr_info("Booting CPU %d\n", cpu); @@ -122,7 +117,6 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) struct smp_operations armada_xp_smp_ops __initdata = { .smp_init_cpus = armada_xp_smp_init_cpus, .smp_prepare_cpus = armada_xp_smp_prepare_cpus, - .smp_secondary_init = armada_xp_secondary_init, .smp_boot_secondary = armada_xp_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = armada_xp_cpu_die, diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 727566216e2..71f77848bc2 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -336,7 +337,7 @@ static void armada_mpic_send_doorbell(const struct cpumask *mask, ARMADA_370_XP_SW_TRIG_INT_OFFS); } -void armada_xp_mpic_smp_cpu_init(void) +static void armada_xp_mpic_smp_cpu_init(void) { /* Clear pending IPIs */ writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); @@ -348,6 +349,20 @@ void armada_xp_mpic_smp_cpu_init(void) /* Unmask IPI interrupt */ writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); } + +static int armada_xp_mpic_secondary_init(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) + armada_xp_mpic_smp_cpu_init(); + return NOTIFY_OK; +} + +static struct notifier_block armada_370_xp_mpic_cpu_notifier = { + .notifier_call = armada_xp_mpic_secondary_init, + .priority = 100, +}; + #endif /* CONFIG_SMP */ static struct irq_domain_ops armada_370_xp_mpic_irq_ops = { @@ -514,6 +529,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, set_handle_irq(armada_370_xp_handle_irq); #ifdef CONFIG_SMP set_smp_cross_call(armada_mpic_send_doorbell); + register_cpu_notifier(&armada_370_xp_mpic_cpu_notifier); #endif } else { irq_set_chained_handler(parent_irq, -- cgit v1.2.3-70-g09d2 From 05ad690608098b469d6052c700d96c35e697a955 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:53:58 +0200 Subject: ARM: mvebu: move Armada XP specific SMP initialization to platsmp.c The pmsu.c driver contained an armada_xp_boot_cpu() function that sets the boot address of a secondary CPUs and deasserts the reset. However, the Armada 375 needs a slightly different logic, so it makes more sense to move this code into the Armada XP specific platsmp.c. In order to achieve this, the mvebu_pmsu_set_cpu_boot_addr() function is exported. It will be needed for both the Armada XP and Armada 38x SMP implementations. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483648-26611-2-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/common.h | 1 + arch/arm/mach-mvebu/platsmp.c | 10 +++++++++- arch/arm/mach-mvebu/pmsu.c | 26 +------------------------- 3 files changed, 11 insertions(+), 26 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h index cfb129b144c..2b88eb00de8 100644 --- a/arch/arm/mach-mvebu/common.h +++ b/arch/arm/mach-mvebu/common.h @@ -19,6 +19,7 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd); int mvebu_cpu_reset_deassert(int cpu); +void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr); void armada_xp_cpu_die(unsigned int cpu); diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index a6da03f5b24..e98075f7175 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -77,9 +77,17 @@ static void armada_xp_secondary_init(unsigned int cpu) static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) { + int ret, hw_cpu; + pr_info("Booting CPU %d\n", cpu); - armada_xp_boot_cpu(cpu, armada_xp_secondary_startup); + hw_cpu = cpu_logical_map(cpu); + mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup); + ret = mvebu_cpu_reset_deassert(hw_cpu); + if (ret) { + pr_warn("unable to boot CPU: %d\n", ret); + return ret; + } return 0; } diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 8361281f918..a1508deecd2 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -41,36 +41,12 @@ static struct of_device_id of_pmsu_table[] = { { /* end of list */ }, }; -static void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr) +void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr) { writel(virt_to_phys(boot_addr), pmsu_mp_base + PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu)); } -#ifdef CONFIG_SMP -int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr) -{ - int hw_cpu, ret; - - if (!pmsu_mp_base) { - pr_warn("Can't boot CPU. PMSU is uninitialized\n"); - return -ENODEV; - } - - hw_cpu = cpu_logical_map(cpu_id); - - mvebu_pmsu_set_cpu_boot_addr(hw_cpu, boot_addr); - - ret = mvebu_cpu_reset_deassert(hw_cpu); - if (ret) { - pr_warn("unable to boot CPU: %d\n", ret); - return ret; - } - - return 0; -} -#endif - static int __init armada_370_xp_pmsu_init(void) { struct device_node *np; -- cgit v1.2.3-70-g09d2 From 2c9b2240bee340711048589023eb057f23fda356 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:53:59 +0200 Subject: ARM: mvebu: use CPU_METHOD_OF_DECLARE for SMP on Armada XP This commit adds the CPU_METHOD_OF_DECLARE declaration for the Armada XP SMP operations. Note that the .smp_ops field of Armada XP DT_MACHINE structure is kept, in order to ensure we remain compatible with older Device Trees that do not include the "enable-method" property for the CPUs. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483648-26611-3-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- Documentation/devicetree/bindings/arm/cpus.txt | 1 + arch/arm/mach-mvebu/platsmp.c | 3 +++ 2 files changed, 4 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 333f4aea302..0dc59c36ad6 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -185,6 +185,7 @@ nodes to be present and contain the properties described below. "qcom,gcc-msm8660" "qcom,kpss-acc-v1" "qcom,kpss-acc-v2" + "marvell,armada-xp-smp" - cpu-release-addr Usage: required for systems that have an "enable-method" diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index e98075f7175..e01ae51bee5 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -138,3 +138,6 @@ struct smp_operations armada_xp_smp_ops __initdata = { .cpu_die = armada_xp_cpu_die, #endif }; + +CPU_METHOD_OF_DECLARE(armada_xp_smp, "marvell,armada-xp-smp", + &armada_xp_smp_ops); -- cgit v1.2.3-70-g09d2 From 00504be42add413614bdaa943612787d6fd297f5 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 15:54:03 +0200 Subject: ARM: mvebu: add function to set the resume boot address for Armada 375 In order to boot the secondary CPUs on Armada 375, we need to set the boot address of these CPUs, through a register part of the System Controller (this deviates from the Armada XP design, where the boot address was defined using a register part of the PMSU unit). Therefore, this commit adds a new helper function in the System Controller driver to set the secondary CPU boot address. Moreover, it moves the System Controller initialization as an early_initcall(), since arch_initcall() is too late for an SMP-related initialization. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397483648-26611-7-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483648-26611-7-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/common.h | 1 + arch/arm/mach-mvebu/system-controller.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h index 2b88eb00de8..b67fb7a10d8 100644 --- a/arch/arm/mach-mvebu/common.h +++ b/arch/arm/mach-mvebu/common.h @@ -20,6 +20,7 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd); int mvebu_cpu_reset_deassert(int cpu); void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr); +void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr); void armada_xp_cpu_die(unsigned int cpu); diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c index 614ba6832ff..0c5524ac75b 100644 --- a/arch/arm/mach-mvebu/system-controller.c +++ b/arch/arm/mach-mvebu/system-controller.c @@ -37,6 +37,8 @@ struct mvebu_system_controller { u32 rstoutn_mask_reset_out_en; u32 system_soft_reset; + + u32 resume_boot_addr; }; static struct mvebu_system_controller *mvebu_sc; @@ -52,6 +54,7 @@ static const struct mvebu_system_controller armada_375_system_controller = { .system_soft_reset_offset = 0x58, .rstoutn_mask_reset_out_en = 0x1, .system_soft_reset = 0x1, + .resume_boot_addr = 0xd4, }; static const struct mvebu_system_controller orion_system_controller = { @@ -98,6 +101,16 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd) ; } +#ifdef CONFIG_SMP +void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr) +{ + BUG_ON(system_controller_base == NULL); + BUG_ON(mvebu_sc->resume_boot_addr == 0); + writel(virt_to_phys(boot_addr), system_controller_base + + mvebu_sc->resume_boot_addr); +} +#endif + static int __init mvebu_system_controller_init(void) { const struct of_device_id *match; @@ -114,4 +127,4 @@ static int __init mvebu_system_controller_init(void) return 0; } -arch_initcall(mvebu_system_controller_init); +early_initcall(mvebu_system_controller_init); -- cgit v1.2.3-70-g09d2 From 1ee89e2231a1b04dc34765edd195725ddf4ba998 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 15:54:05 +0200 Subject: ARM: mvebu: add SMP support for Armada 375 and Armada 38x This commit adds the SMP support for Armada 375 and Armada 38x. It turns out that the SMP logic for both of these SOCs are fairly similar, the only differences being: * A different method to set the secondary CPU boot address * An Armada 375 specific workaround needed for the early Z1 stepping, added by the following patch. Other than that, the patch is fairly straightforward and adds the usual platsmp and headsmp code, defining the smp_operations structure that is referenced from the DT_MACHINE structures. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397483648-26611-9-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483648-26611-9-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- Documentation/devicetree/bindings/arm/cpus.txt | 2 + arch/arm/mach-mvebu/Kconfig | 4 ++ arch/arm/mach-mvebu/Makefile | 2 +- arch/arm/mach-mvebu/headsmp-a9.S | 22 +++++++++ arch/arm/mach-mvebu/platsmp-a9.c | 68 ++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-mvebu/headsmp-a9.S create mode 100644 arch/arm/mach-mvebu/platsmp-a9.c (limited to 'arch/arm/mach-mvebu') diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 0dc59c36ad6..4bbcf4fb758 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -185,6 +185,8 @@ nodes to be present and contain the properties described below. "qcom,gcc-msm8660" "qcom,kpss-acc-v1" "qcom,kpss-acc-v2" + "marvell,armada-375-smp" + "marvell,armada-380-smp" "marvell,armada-xp-smp" - cpu-release-addr diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 736bd2cbc1f..7bb92b1a63f 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -41,6 +41,8 @@ config MACH_ARMADA_375 select ARMADA_375_CLK select CPU_V7 select HAVE_ARM_SCU + select HAVE_ARM_TWD + select HAVE_SMP select MACH_MVEBU_V7 select PINCTRL_ARMADA_375 help @@ -55,6 +57,8 @@ config MACH_ARMADA_38X select ARMADA_38X_CLK select CPU_V7 select HAVE_ARM_SCU + select HAVE_ARM_TWD + select HAVE_SMP select MACH_MVEBU_V7 select PINCTRL_ARMADA_38X help diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index f9cfab05c5f..02b5389f05f 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -7,7 +7,7 @@ obj-y += system-controller.o mvebu-soc-id.o cpu-reset.o obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o obj-$(CONFIG_MACH_DOVE) += dove.o obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o -obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o obj-$(CONFIG_MACH_T5325) += board-t5325.o diff --git a/arch/arm/mach-mvebu/headsmp-a9.S b/arch/arm/mach-mvebu/headsmp-a9.S new file mode 100644 index 00000000000..78e66c96e71 --- /dev/null +++ b/arch/arm/mach-mvebu/headsmp-a9.S @@ -0,0 +1,22 @@ +/* + * SMP support: Entry point for secondary CPUs of Marvell EBU + * Cortex-A9 based SOCs (Armada 375 and Armada 38x). + * + * Copyright (C) 2014 Marvell + * + * Gregory CLEMENT + * Thomas Petazzoni + * + * 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 +#include + + __CPUINIT +ENTRY(mvebu_cortex_a9_secondary_startup) + bl v7_invalidate_l1 + b secondary_startup +ENDPROC(mvebu_cortex_a9_secondary_startup) diff --git a/arch/arm/mach-mvebu/platsmp-a9.c b/arch/arm/mach-mvebu/platsmp-a9.c new file mode 100644 index 00000000000..27dacfc7fe9 --- /dev/null +++ b/arch/arm/mach-mvebu/platsmp-a9.c @@ -0,0 +1,68 @@ +/* + * Symmetric Multi Processing (SMP) support for Marvell EBU Cortex-A9 + * based SOCs (Armada 375/38x). + * + * Copyright (C) 2014 Marvell + * + * Gregory CLEMENT + * Thomas Petazzoni + * + * 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 +#include +#include +#include +#include +#include +#include "common.h" +#include "pmsu.h" + +extern void mvebu_cortex_a9_secondary_startup(void); + +static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + int ret, hw_cpu; + + pr_info("Booting CPU %d\n", cpu); + + /* + * Write the address of secondary startup into the system-wide + * flags register. The boot monitor waits until it receives a + * soft interrupt, and then the secondary CPU branches to this + * address. + */ + hw_cpu = cpu_logical_map(cpu); + + if (of_machine_is_compatible("marvell,armada375")) + mvebu_system_controller_set_cpu_boot_addr(mvebu_cortex_a9_secondary_startup); + else + mvebu_pmsu_set_cpu_boot_addr(hw_cpu, + mvebu_cortex_a9_secondary_startup); + + smp_wmb(); + ret = mvebu_cpu_reset_deassert(hw_cpu); + if (ret) { + pr_err("Could not start the secondary CPU: %d\n", ret); + return ret; + } + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + + return 0; +} + +static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = { + .smp_boot_secondary = mvebu_cortex_a9_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = armada_xp_cpu_die, +#endif +}; + +CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp", + &mvebu_cortex_a9_smp_ops); +CPU_METHOD_OF_DECLARE(mvebu_armada_380_smp, "marvell,armada-380-smp", + &mvebu_cortex_a9_smp_ops); -- cgit v1.2.3-70-g09d2 From 87384cc0b4bffbe26d9172d49d8b287332e9d397 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 15:54:06 +0200 Subject: ARM: mvebu: add workaround for SMP support for Armada 375 stepping Z1 Due to internal bootrom issue, CPU[1] initial jump code (four instructions) should be placed in SRAM memory of the SoC. In order to achieve this, we have to unmap the BootROM and at some specific location where the BootROM was place, create a specific MBus window for the SRAM. This SRAM is initialized with a few instructions of code that allows to jump into the real secondary CPU boot address. This workaround will most likely be disabled when newer steppings of the Armada 375 will be made available, in which case a dynamic test based on mvebu-soc-id will be added. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397483648-26611-10-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483648-26611-10-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/headsmp-a9.S | 12 ++++++++++++ arch/arm/mach-mvebu/platsmp-a9.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/headsmp-a9.S b/arch/arm/mach-mvebu/headsmp-a9.S index 78e66c96e71..5925366bc03 100644 --- a/arch/arm/mach-mvebu/headsmp-a9.S +++ b/arch/arm/mach-mvebu/headsmp-a9.S @@ -16,6 +16,18 @@ #include __CPUINIT +#define CPU_RESUME_ADDR_REG 0xf10182d4 + +.global armada_375_smp_cpu1_enable_code_start +.global armada_375_smp_cpu1_enable_code_end + +armada_375_smp_cpu1_enable_code_start: + ldr r0, [pc, #4] + ldr r1, [r0] + mov pc, r1 + .word CPU_RESUME_ADDR_REG +armada_375_smp_cpu1_enable_code_end: + ENTRY(mvebu_cortex_a9_secondary_startup) bl v7_invalidate_l1 b secondary_startup diff --git a/arch/arm/mach-mvebu/platsmp-a9.c b/arch/arm/mach-mvebu/platsmp-a9.c index 27dacfc7fe9..04d0b1847c3 100644 --- a/arch/arm/mach-mvebu/platsmp-a9.c +++ b/arch/arm/mach-mvebu/platsmp-a9.c @@ -16,11 +16,36 @@ #include #include #include +#include #include #include #include "common.h" #include "pmsu.h" +#define CRYPT0_ENG_ID 41 +#define CRYPT0_ENG_ATTR 0x1 +#define SRAM_PHYS_BASE 0xFFFF0000 + +#define BOOTROM_BASE 0xFFF00000 +#define BOOTROM_SIZE 0x100000 + +extern unsigned char armada_375_smp_cpu1_enable_code_end; +extern unsigned char armada_375_smp_cpu1_enable_code_start; + +void armada_375_smp_cpu1_enable_wa(void) +{ + void __iomem *sram_virt_base; + + mvebu_mbus_del_window(BOOTROM_BASE, BOOTROM_SIZE); + mvebu_mbus_add_window_by_id(CRYPT0_ENG_ID, CRYPT0_ENG_ATTR, + SRAM_PHYS_BASE, SZ_64K); + sram_virt_base = ioremap(SRAM_PHYS_BASE, SZ_64K); + + memcpy(sram_virt_base, &armada_375_smp_cpu1_enable_code_start, + &armada_375_smp_cpu1_enable_code_end + - &armada_375_smp_cpu1_enable_code_start); +} + extern void mvebu_cortex_a9_secondary_startup(void); static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu, @@ -55,7 +80,14 @@ static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu, return 0; } +static void __init mvebu_cortex_a9_smp_prepare_cpus(unsigned int max_cpus) +{ + if (of_machine_is_compatible("marvell,armada375")) + armada_375_smp_cpu1_enable_wa(); +} + static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = { + .smp_prepare_cpus = mvebu_cortex_a9_smp_prepare_cpus, .smp_boot_secondary = mvebu_cortex_a9_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = armada_xp_cpu_die, -- cgit v1.2.3-70-g09d2 From b4bca24957c990a09dbddde75858b24150faec89 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 14 Apr 2014 15:54:04 +0200 Subject: ARM: mvebu: add Armada 38x compatible string to pmsu Since the Armada 38x PMSU registers are slightly different than the Armada 370/XP PMSU ones, we introduce a new compatible string "armada-380-pmsu" in the PMSU driver. These differences are not visible for the current usage of the PMSU, but they might become visible in the future. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397483648-26611-8-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt | 9 ++++++--- arch/arm/mach-mvebu/pmsu.c | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt index 97618877007..26799ef562d 100644 --- a/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt +++ b/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt @@ -1,11 +1,14 @@ Power Management Service Unit(PMSU) ----------------------------------- -Available on Marvell SOCs: Armada 370 and Armada XP +Available on Marvell SOCs: Armada 370, Armada 38x and Armada XP Required properties: -- compatible: should be "marvell,armada-370-pmsu", whereas - "marvell,armada-370-xp-pmsu" is deprecated and will be removed +- compatible: should be one of: + - "marvell,armada-370-pmsu" for Armada 370 or Armada XP + - "marvell,armada-380-pmsu" for Armada 38x + - "marvell,armada-370-xp-pmsu" was used for Armada 370/XP but is now + deprecated and will be removed - reg: Should contain PMSU registers location and length. diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index a1508deecd2..a8796b832e2 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -38,6 +38,7 @@ static void __iomem *pmsu_mp_base; static struct of_device_id of_pmsu_table[] = { { .compatible = "marvell,armada-370-pmsu", }, { .compatible = "marvell,armada-370-xp-pmsu", }, + { .compatible = "marvell,armada-380-pmsu", }, { /* end of list */ }, }; -- cgit v1.2.3-70-g09d2 From ccd6a13180193700067bfdac5f7d7b436d757382 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 17:10:05 +0200 Subject: ARM: mvebu: remove the address parameter for ll_set_cpu_coherent In order to be able to deal with the MMU enabled and the MMU disabled cases, the base address of the coherency registers was passed to the function. The address by itself was not interesting as it can't change for a given SoC, the only thing we need is to have a distinction between the physical or the virtual address. This patch add a check of the MMU bit to choose the accurate address, then the calling function doesn't have to pass this information. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397488214-20685-3-git-send-email-gregory.clement@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 6 +++--- arch/arm/mach-mvebu/coherency_ll.S | 22 ++++++++++++++++++++-- arch/arm/mach-mvebu/headsmp.S | 9 --------- 3 files changed, 23 insertions(+), 14 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 489edd157cf..615dc0b6093 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -35,7 +35,7 @@ #include "coherency.h" unsigned long coherency_phys_base; -static void __iomem *coherency_base; +void __iomem *coherency_base; static void __iomem *coherency_cpu_base; /* Coherency fabric registers */ @@ -61,7 +61,7 @@ static struct of_device_id of_coherency_table[] = { }; /* Function defined in coherency_ll.S */ -int ll_set_cpu_coherent(void __iomem *base_addr, unsigned int hw_cpu_id); +int ll_set_cpu_coherent(unsigned int hw_cpu_id); int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id) { @@ -71,7 +71,7 @@ int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id) return 1; } - return ll_set_cpu_coherent(coherency_base, hw_cpu_id); + return ll_set_cpu_coherent(hw_cpu_id); } /* diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index ee7598fe75d..1f2bcd4b542 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S @@ -21,13 +21,27 @@ #define ARMADA_XP_CFB_CFG_REG_OFFSET 0x4 #include +#include .text /* - * r0: Coherency fabric base register address - * r1: HW CPU id + * r0: HW CPU id */ ENTRY(ll_set_cpu_coherent) + mrc p15, 0, r1, c1, c0, 0 + tst r1, #CR_M @ Check MMU bit enabled + bne 1f + + /* use physical address of the coherency register*/ + adr r0, 3f + ldr r3, [r0] + ldr r0, [r0, r3] + b 2f +1: + /* use virtual address of the coherency register*/ + ldr r0, =coherency_base + ldr r0, [r0] +2: /* Create bit by cpu index */ mov r3, #(1 << 24) lsl r1, r3, r1 @@ -56,3 +70,7 @@ ARM_BE8(rev r1, r1) mov r0, #0 mov pc, lr ENDPROC(ll_set_cpu_coherent) + + .align 2 +3: + .long coherency_phys_base - . diff --git a/arch/arm/mach-mvebu/headsmp.S b/arch/arm/mach-mvebu/headsmp.S index 3dd80df428f..f30bc8d7887 100644 --- a/arch/arm/mach-mvebu/headsmp.S +++ b/arch/arm/mach-mvebu/headsmp.S @@ -31,11 +31,6 @@ ENTRY(armada_xp_secondary_startup) ARM_BE8(setend be ) @ go BE8 if entered LE - /* Get coherency fabric base physical address */ - adr r0, 1f - ldr r1, [r0] - ldr r0, [r0, r1] - /* Read CPU id */ mrc p15, 0, r1, c0, c0, 5 and r1, r1, #0xF @@ -45,7 +40,3 @@ ENTRY(armada_xp_secondary_startup) b secondary_startup ENDPROC(armada_xp_secondary_startup) - - .align 2 -1: - .long coherency_phys_base - . -- cgit v1.2.3-70-g09d2 From b41375f71aceadb7d74a18aafba4da5024fc104b Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 17:10:06 +0200 Subject: ARM: mvebu: ll_set_cpu_coherent always uses the current CPU ll_set_cpu_coherent is always used on the current CPU, so instead of passing the CPU id as argument, ll_set_cpu_coherent() can find it by itself. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397488214-20685-4-git-send-email-gregory.clement@free-electrons.com Acked-by: Thomas Petazzoni Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 12 +++++------- arch/arm/mach-mvebu/coherency.h | 2 +- arch/arm/mach-mvebu/coherency_ll.S | 10 +++++----- arch/arm/mach-mvebu/headsmp.S | 4 ---- arch/arm/mach-mvebu/platsmp.c | 2 +- 5 files changed, 12 insertions(+), 18 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 615dc0b6093..2df90c99882 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -61,17 +61,17 @@ static struct of_device_id of_coherency_table[] = { }; /* Function defined in coherency_ll.S */ -int ll_set_cpu_coherent(unsigned int hw_cpu_id); +int ll_set_cpu_coherent(void); -int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id) +int set_cpu_coherent(int smp_group_id) { if (!coherency_base) { - pr_warn("Can't make CPU %d cache coherent.\n", hw_cpu_id); + pr_warn("Can't make current CPU cache coherent.\n"); pr_warn("Coherency fabric is not initialized\n"); return 1; } - return ll_set_cpu_coherent(hw_cpu_id); + return ll_set_cpu_coherent(); } /* @@ -302,7 +302,7 @@ static void __init armada_370_coherency_init(struct device_node *np) sync_cache_w(&coherency_phys_base); coherency_base = of_iomap(np, 0); coherency_cpu_base = of_iomap(np, 1); - set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); + set_cpu_coherent(0); } static void __init armada_375_380_coherency_init(struct device_node *np) @@ -330,8 +330,6 @@ static int coherency_type(void) /* Armada 380 coherency works only on SMP */ else if (type == COHERENCY_FABRIC_TYPE_ARMADA_380 && is_smp()) return type; - - of_node_put(np); } return COHERENCY_FABRIC_TYPE_NONE; diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h index 02f7ec34ced..ab594a75fef 100644 --- a/arch/arm/mach-mvebu/coherency.h +++ b/arch/arm/mach-mvebu/coherency.h @@ -16,7 +16,7 @@ extern unsigned long coherency_phys_base; -int set_cpu_coherent(unsigned int cpu_id, int smp_group_id); +int set_cpu_coherent(int smp_group_id); int coherency_init(void); int coherency_available(void); diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index 1f2bcd4b542..98a0b73f909 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S @@ -24,9 +24,7 @@ #include .text -/* - * r0: HW CPU id - */ + ENTRY(ll_set_cpu_coherent) mrc p15, 0, r1, c1, c0, 0 tst r1, #CR_M @ Check MMU bit enabled @@ -43,8 +41,10 @@ ENTRY(ll_set_cpu_coherent) ldr r0, [r0] 2: /* Create bit by cpu index */ - mov r3, #(1 << 24) - lsl r1, r3, r1 + mrc 15, 0, r1, cr0, cr0, 5 + and r1, r1, #15 + mov r2, #(1 << 24) + lsl r1, r2, r1 ARM_BE8(rev r1, r1) /* Add CPU to SMP group - Atomic */ diff --git a/arch/arm/mach-mvebu/headsmp.S b/arch/arm/mach-mvebu/headsmp.S index f30bc8d7887..cf7abe6554f 100644 --- a/arch/arm/mach-mvebu/headsmp.S +++ b/arch/arm/mach-mvebu/headsmp.S @@ -31,10 +31,6 @@ ENTRY(armada_xp_secondary_startup) ARM_BE8(setend be ) @ go BE8 if entered LE - /* Read CPU id */ - mrc p15, 0, r1, c0, c0, 5 - and r1, r1, #0xF - /* Add CPU to coherency fabric */ bl ll_set_cpu_coherent b secondary_startup diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index 32bf78e80c4..75436c0023a 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -103,7 +103,7 @@ static 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); + set_cpu_coherent(0); /* * In order to boot the secondary CPUs we need to ensure -- cgit v1.2.3-70-g09d2 From 952f4ca79b4ec7114291aa711add1b36c6ba7515 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 17:10:07 +0200 Subject: ARM: mvebu: Remove the unused argument of set_cpu_coherent() set_cpu_coherent() took the SMP group ID as parameter. But this parameter was never used, and the CPU always uses the SMP group 0. So we can remove this parameter. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397488214-20685-5-git-send-email-gregory.clement@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 4 ++-- arch/arm/mach-mvebu/coherency.h | 2 +- arch/arm/mach-mvebu/platsmp.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 2df90c99882..944372a18ed 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -63,7 +63,7 @@ static struct of_device_id of_coherency_table[] = { /* Function defined in coherency_ll.S */ int ll_set_cpu_coherent(void); -int set_cpu_coherent(int smp_group_id) +int set_cpu_coherent(void) { if (!coherency_base) { pr_warn("Can't make current CPU cache coherent.\n"); @@ -302,7 +302,7 @@ static void __init armada_370_coherency_init(struct device_node *np) sync_cache_w(&coherency_phys_base); coherency_base = of_iomap(np, 0); coherency_cpu_base = of_iomap(np, 1); - set_cpu_coherent(0); + set_cpu_coherent(); } static void __init armada_375_380_coherency_init(struct device_node *np) diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h index ab594a75fef..54cb7607b52 100644 --- a/arch/arm/mach-mvebu/coherency.h +++ b/arch/arm/mach-mvebu/coherency.h @@ -15,8 +15,8 @@ #define __MACH_370_XP_COHERENCY_H extern unsigned long coherency_phys_base; +int set_cpu_coherent(void); -int set_cpu_coherent(int smp_group_id); int coherency_init(void); int coherency_available(void); diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index 75436c0023a..88b976b3171 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -103,7 +103,7 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) set_secondary_cpus_clock(); flush_cache_all(); - set_cpu_coherent(0); + set_cpu_coherent(); /* * In order to boot the secondary CPUs we need to ensure -- cgit v1.2.3-70-g09d2 From 2e8a5942f8751c03fdd50228a02909654d13f01d Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 17:10:08 +0200 Subject: ARM: mvebu: Split low level functions to manipulate HW coherency Actually enabling coherency and adding a CPU on a SMP group are two different operations which can be done separately. This patch splits this in two functions. Moreover as they use common pattern, this patch also creates local low level functions (ll_get_coherency_base and ll_get_cpuid) to be used by the exposed functions (ll_add_cpu_to_smp_group and ll_enable_coherency) Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397488214-20685-6-git-send-email-gregory.clement@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 8 ++-- arch/arm/mach-mvebu/coherency_ll.S | 92 +++++++++++++++++++++++++------------- arch/arm/mach-mvebu/headsmp.S | 6 ++- 3 files changed, 71 insertions(+), 35 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 944372a18ed..9d5ccd37271 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -60,8 +60,9 @@ static struct of_device_id of_coherency_table[] = { { /* end of list */ }, }; -/* Function defined in coherency_ll.S */ -int ll_set_cpu_coherent(void); +/* Functions defined in coherency_ll.S */ +int ll_enable_coherency(void); +void ll_add_cpu_to_smp_group(void); int set_cpu_coherent(void) { @@ -71,7 +72,8 @@ int set_cpu_coherent(void) return 1; } - return ll_set_cpu_coherent(); + ll_add_cpu_to_smp_group(); + return ll_enable_coherency(); } /* diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index 98a0b73f909..f2e2e8677c4 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S @@ -24,52 +24,84 @@ #include .text - -ENTRY(ll_set_cpu_coherent) +/* Returns with the coherency address in r1 (r0 is untouched)*/ +ENTRY(ll_get_coherency_base) mrc p15, 0, r1, c1, c0, 0 tst r1, #CR_M @ Check MMU bit enabled bne 1f - /* use physical address of the coherency register*/ - adr r0, 3f - ldr r3, [r0] - ldr r0, [r0, r3] + /* use physical address of the coherency register */ + adr r1, 3f + ldr r3, [r1] + ldr r1, [r1, r3] b 2f 1: - /* use virtual address of the coherency register*/ - ldr r0, =coherency_base - ldr r0, [r0] + /* use virtual address of the coherency register */ + ldr r1, =coherency_base + ldr r1, [r1] 2: - /* Create bit by cpu index */ - mrc 15, 0, r1, cr0, cr0, 5 - and r1, r1, #15 + mov pc, lr +ENDPROC(ll_get_coherency_base) + +/* Returns with the CPU ID in r3 (r0 is untouched)*/ +ENTRY(ll_get_cpuid) + mrc 15, 0, r3, cr0, cr0, 5 + and r3, r3, #15 mov r2, #(1 << 24) - lsl r1, r2, r1 + lsl r3, r2, r3 ARM_BE8(rev r1, r1) + mov pc, lr +ENDPROC(ll_get_cpuid) - /* Add CPU to SMP group - Atomic */ - add r3, r0, #ARMADA_XP_CFB_CTL_REG_OFFSET -1: - ldrex r2, [r3] - orr r2, r2, r1 - strex r0, r2, [r3] - cmp r0, #0 - bne 1b +/* ll_add_cpu_to_smp_group, ll_enable_coherency and + * ll_disable_coherency use strex/ldrex whereas MMU can be off. The + * Armada XP SoC has an exclusive monitor that can track transactions + * to Device and/or SO and as such also when MMU is disabled the + * exclusive transactions will be functional + */ - /* Enable coherency on CPU - Atomic */ - add r3, r3, #ARMADA_XP_CFB_CFG_REG_OFFSET +ENTRY(ll_add_cpu_to_smp_group) + /* + * r0 being untouched in ll_get_coherency_base and + * ll_get_cpuid, we can use it to save lr modifing it with the + * following bl + */ + mov r0, lr + bl ll_get_coherency_base + bl ll_get_cpuid + mov lr, r0 + add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET 1: - ldrex r2, [r3] - orr r2, r2, r1 - strex r0, r2, [r3] - cmp r0, #0 - bne 1b + ldrex r2, [r0] + orr r2, r2, r3 + strex r1, r2, [r0] + cmp r1, #0 + bne 1b + mov pc, lr +ENDPROC(ll_add_cpu_to_smp_group) +ENTRY(ll_enable_coherency) + /* + * r0 being untouched in ll_get_coherency_base and + * ll_get_cpuid, we can use it to save lr modifing it with the + * following bl + */ + mov r0, lr + bl ll_get_coherency_base + bl ll_get_cpuid + mov lr, r0 + add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET +1: + ldrex r2, [r0] + orr r2, r2, r3 + strex r1, r2, [r0] + cmp r1, #0 + bne 1b dsb - mov r0, #0 mov pc, lr -ENDPROC(ll_set_cpu_coherent) +ENDPROC(ll_enable_coherency) + .align 2 3: diff --git a/arch/arm/mach-mvebu/headsmp.S b/arch/arm/mach-mvebu/headsmp.S index cf7abe6554f..2c4032e368b 100644 --- a/arch/arm/mach-mvebu/headsmp.S +++ b/arch/arm/mach-mvebu/headsmp.S @@ -31,8 +31,10 @@ ENTRY(armada_xp_secondary_startup) ARM_BE8(setend be ) @ go BE8 if entered LE - /* Add CPU to coherency fabric */ - bl ll_set_cpu_coherent + bl ll_add_cpu_to_smp_group + + bl ll_enable_coherency + b secondary_startup ENDPROC(armada_xp_secondary_startup) -- cgit v1.2.3-70-g09d2 From 1a6bfbc339b6a2b59a8f88fa494fe70073cdb85a Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 17:10:09 +0200 Subject: ARM: mvebu: Low level function to disable HW coherency support When going to deep idle we need to disable the SoC snooping (aka hardware coherency support). Playing with the coherency fabric requires to use assembly code to be sure that the compiler doesn't reorder the instructions nor do wrong optimization. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397488214-20685-7-git-send-email-gregory.clement@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency_ll.S | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index f2e2e8677c4..6828f9f157b 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S @@ -102,6 +102,26 @@ ENTRY(ll_enable_coherency) mov pc, lr ENDPROC(ll_enable_coherency) +ENTRY(ll_disable_coherency) + /* + * r0 being untouched in ll_get_coherency_base and + * ll_get_cpuid, we can use it to save lr modifing it with the + * following bl + */ + mov r0, lr + bl ll_get_coherency_base + bl ll_get_cpuid + mov lr, r0 + add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET +1: + ldrex r2, [r0] + bic r2, r2, r3 + strex r1, r2, [r0] + cmp r1, #0 + bne 1b + dsb + mov pc, lr +ENDPROC(ll_disable_coherency) .align 2 3: -- cgit v1.2.3-70-g09d2 From f713c7e7421d6945c977c8d8813e8089f925de41 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 17:10:10 +0200 Subject: ARM: mvebu: Allow to power down L2 cache controller in idle mode This commit adds a function which adjusts the PMSU configuration to automatically power down the L2 and coherency fabric when we enter a certain idle state. This feature is part of the Power Management Service Unit of the Armada 370 and Armada XP SoCs. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397488214-20685-8-git-send-email-gregory.clement@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/pmsu.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index a8796b832e2..7ccf14a065b 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -33,7 +33,12 @@ static void __iomem *pmsu_mp_base; #define PMSU_BASE_OFFSET 0x100 #define PMSU_REG_SIZE 0x1000 -#define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x124) +/* PMSU MP registers */ +#define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x124) + +/* PMSU fabric registers */ +#define L2C_NFABRIC_PM_CTL 0x4 +#define L2C_NFABRIC_PM_CTL_PWR_DOWN BIT(20) static struct of_device_id of_pmsu_table[] = { { .compatible = "marvell,armada-370-pmsu", }, @@ -92,4 +97,17 @@ static int __init armada_370_xp_pmsu_init(void) return ret; } +static void armada_370_xp_pmsu_enable_l2_powerdown_onidle(void) +{ + u32 reg; + + if (pmsu_mp_base == NULL) + return; + + /* Enable L2 & Fabric powerdown in Deep-Idle mode - Fabric */ + reg = readl(pmsu_mp_base + L2C_NFABRIC_PM_CTL); + reg |= L2C_NFABRIC_PM_CTL_PWR_DOWN; + writel(reg, pmsu_mp_base + L2C_NFABRIC_PM_CTL); +} + early_initcall(armada_370_xp_pmsu_init); -- cgit v1.2.3-70-g09d2 From c3e04cabb135625df8ff4b71ef4130f0ccbcc669 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 17:10:11 +0200 Subject: ARM: mvebu: Add the PMSU related part of the cpu idle functions The cpu idle support will need to access to Power Management Service Unit. This commit adds the architecture related functions that will be used in the idle path of the cpuidle driver. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397488214-20685-9-git-send-email-gregory.clement@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/pmsu.c | 132 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 7ccf14a065b..78cf0279e1a 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -24,9 +24,12 @@ #include #include #include +#include +#include #include +#include +#include #include "common.h" -#include "pmsu.h" static void __iomem *pmsu_mp_base; @@ -34,12 +37,33 @@ static void __iomem *pmsu_mp_base; #define PMSU_REG_SIZE 0x1000 /* PMSU MP registers */ +#define PMSU_CONTROL_AND_CONFIG(cpu) ((cpu * 0x100) + 0x104) +#define PMSU_CONTROL_AND_CONFIG_DFS_REQ BIT(18) +#define PMSU_CONTROL_AND_CONFIG_PWDDN_REQ BIT(16) +#define PMSU_CONTROL_AND_CONFIG_L2_PWDDN BIT(20) + +#define PMSU_CPU_POWER_DOWN_CONTROL(cpu) ((cpu * 0x100) + 0x108) + +#define PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP BIT(0) + +#define PMSU_STATUS_AND_MASK(cpu) ((cpu * 0x100) + 0x10c) +#define PMSU_STATUS_AND_MASK_CPU_IDLE_WAIT BIT(16) +#define PMSU_STATUS_AND_MASK_SNP_Q_EMPTY_WAIT BIT(17) +#define PMSU_STATUS_AND_MASK_IRQ_WAKEUP BIT(20) +#define PMSU_STATUS_AND_MASK_FIQ_WAKEUP BIT(21) +#define PMSU_STATUS_AND_MASK_DBG_WAKEUP BIT(22) +#define PMSU_STATUS_AND_MASK_IRQ_MASK BIT(24) +#define PMSU_STATUS_AND_MASK_FIQ_MASK BIT(25) + #define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x124) /* PMSU fabric registers */ #define L2C_NFABRIC_PM_CTL 0x4 #define L2C_NFABRIC_PM_CTL_PWR_DOWN BIT(20) +extern void ll_disable_coherency(void); +extern void ll_enable_coherency(void); + static struct of_device_id of_pmsu_table[] = { { .compatible = "marvell,armada-370-pmsu", }, { .compatible = "marvell,armada-370-xp-pmsu", }, @@ -110,4 +134,110 @@ static void armada_370_xp_pmsu_enable_l2_powerdown_onidle(void) writel(reg, pmsu_mp_base + L2C_NFABRIC_PM_CTL); } +static void armada_370_xp_cpu_resume(void) +{ + asm volatile("bl ll_add_cpu_to_smp_group\n\t" + "bl ll_enable_coherency\n\t" + "b cpu_resume\n\t"); +} + +/* No locking is needed because we only access per-CPU registers */ +void armada_370_xp_pmsu_idle_prepare(bool deepidle) +{ + unsigned int hw_cpu = cpu_logical_map(smp_processor_id()); + u32 reg; + + if (pmsu_mp_base == NULL) + return; + + /* + * Adjust the PMSU configuration to wait for WFI signal, enable + * IRQ and FIQ as wakeup events, set wait for snoop queue empty + * indication and mask IRQ and FIQ from CPU + */ + reg = readl(pmsu_mp_base + PMSU_STATUS_AND_MASK(hw_cpu)); + reg |= PMSU_STATUS_AND_MASK_CPU_IDLE_WAIT | + PMSU_STATUS_AND_MASK_IRQ_WAKEUP | + PMSU_STATUS_AND_MASK_FIQ_WAKEUP | + PMSU_STATUS_AND_MASK_SNP_Q_EMPTY_WAIT | + PMSU_STATUS_AND_MASK_IRQ_MASK | + PMSU_STATUS_AND_MASK_FIQ_MASK; + writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(hw_cpu)); + + reg = readl(pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu)); + /* ask HW to power down the L2 Cache if needed */ + if (deepidle) + reg |= PMSU_CONTROL_AND_CONFIG_L2_PWDDN; + + /* request power down */ + reg |= PMSU_CONTROL_AND_CONFIG_PWDDN_REQ; + writel(reg, pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu)); + + /* Disable snoop disable by HW - SW is taking care of it */ + reg = readl(pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu)); + reg |= PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP; + writel(reg, pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu)); +} + +static noinline int do_armada_370_xp_cpu_suspend(unsigned long deepidle) +{ + armada_370_xp_pmsu_idle_prepare(deepidle); + + v7_exit_coherency_flush(all); + + ll_disable_coherency(); + + dsb(); + + wfi(); + + /* If we are here, wfi failed. As processors run out of + * coherency for some time, tlbs might be stale, so flush them + */ + local_flush_tlb_all(); + + ll_enable_coherency(); + + /* Test the CR_C bit and set it if it was cleared */ + asm volatile( + "mrc p15, 0, %0, c1, c0, 0 \n\t" + "tst %0, #(1 << 2) \n\t" + "orreq %0, %0, #(1 << 2) \n\t" + "mcreq p15, 0, %0, c1, c0, 0 \n\t" + "isb " + : : "r" (0)); + + pr_warn("Failed to suspend the system\n"); + + return 0; +} + +static int armada_370_xp_cpu_suspend(unsigned long deepidle) +{ + return cpu_suspend(deepidle, do_armada_370_xp_cpu_suspend); +} + +/* No locking is needed because we only access per-CPU registers */ +static noinline void armada_370_xp_pmsu_idle_restore(void) +{ + unsigned int hw_cpu = cpu_logical_map(smp_processor_id()); + u32 reg; + + if (pmsu_mp_base == NULL) + return; + + /* cancel ask HW to power down the L2 Cache if possible */ + reg = readl(pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu)); + reg &= ~PMSU_CONTROL_AND_CONFIG_L2_PWDDN; + writel(reg, pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu)); + + /* cancel Enable wakeup events and mask interrupts */ + reg = readl(pmsu_mp_base + PMSU_STATUS_AND_MASK(hw_cpu)); + reg &= ~(PMSU_STATUS_AND_MASK_IRQ_WAKEUP | PMSU_STATUS_AND_MASK_FIQ_WAKEUP); + reg &= ~PMSU_STATUS_AND_MASK_CPU_IDLE_WAIT; + reg &= ~PMSU_STATUS_AND_MASK_SNP_Q_EMPTY_WAIT; + reg &= ~(PMSU_STATUS_AND_MASK_IRQ_MASK | PMSU_STATUS_AND_MASK_FIQ_MASK); + writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(hw_cpu)); +} + early_initcall(armada_370_xp_pmsu_init); -- cgit v1.2.3-70-g09d2 From 0041464ceeccd4718de228141438335e2d92f91b Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 28 Apr 2014 20:20:39 +0200 Subject: ARM: mvebu: refine which files are build in mach-mvebu Following the integration into mach-mvebu of the Kirkwood ARMv5 support, we need to be more careful about which files get built. For example, the pmsu.c file now calls wfi(), which only exists on ARMv7 platforms. Therefore, this commit changes mach-mvebu/Makefile to build the Armada 370/XP/375/38x specific files only when CONFIG_MACH_MVEBU_V7 is enabled. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1398709239-6126-1-git-send-email-thomas.petazzoni@free-electrons.com Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/Makefile | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 02b5389f05f..ec0b2177d99 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -3,11 +3,14 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ AFLAGS_coherency_ll.o := -Wa,-march=armv7-a -obj-y += system-controller.o mvebu-soc-id.o cpu-reset.o -obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o +obj-y += system-controller.o mvebu-soc-id.o + +ifeq ($(CONFIG_MACH_MVEBU_V7),y) +obj-y += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +endif + obj-$(CONFIG_MACH_DOVE) += dove.o -obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o -obj-$(CONFIG_SMP) += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o obj-$(CONFIG_MACH_T5325) += board-t5325.o -- cgit v1.2.3-70-g09d2 From d163ee165bd49a51f77bae632ebf37eda4899d0e Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 17:10:12 +0200 Subject: ARM: mvebu: Register notifier callback for the cpuidle transition In order to have well encapsulated code, we use notifier callbacks for CPU_PM_ENTER and CPU_PM_EXIT inside the mvebu power management code. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397488214-20685-10-git-send-email-gregory.clement@free-electrons.com Acked-by: Daniel Lezcano Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/pmsu.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 78cf0279e1a..7902d21d7d6 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -18,6 +18,7 @@ #define pr_fmt(fmt) "mvebu-pmsu: " fmt +#include #include #include #include @@ -240,4 +241,21 @@ static noinline void armada_370_xp_pmsu_idle_restore(void) writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(hw_cpu)); } +static int armada_370_xp_cpu_pm_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + if (action == CPU_PM_ENTER) { + unsigned int hw_cpu = cpu_logical_map(smp_processor_id()); + mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_370_xp_cpu_resume); + } else if (action == CPU_PM_EXIT) { + armada_370_xp_pmsu_idle_restore(); + } + + return NOTIFY_OK; +} + +static struct notifier_block armada_370_xp_cpu_pm_notifier = { + .notifier_call = armada_370_xp_cpu_pm_notify, +}; + early_initcall(armada_370_xp_pmsu_init); -- cgit v1.2.3-70-g09d2 From 8c16babc6476111efabafbb262b47f8309942403 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Mon, 14 Apr 2014 17:10:14 +0200 Subject: ARM: mvebu: register the cpuidle driver for the Armada XP SoCs The cpuidle is a platform driver so we register the device just after the initialization of the board in an arch_initcall. Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397488214-20685-12-git-send-email-gregory.clement@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/pmsu.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 7902d21d7d6..53a55c8520b 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,10 @@ static void __iomem *pmsu_mp_base; extern void ll_disable_coherency(void); extern void ll_enable_coherency(void); +static struct platform_device armada_xp_cpuidle_device = { + .name = "cpuidle-armada-370-xp", +}; + static struct of_device_id of_pmsu_table[] = { { .compatible = "marvell,armada-370-pmsu", }, { .compatible = "marvell,armada-370-xp-pmsu", }, @@ -258,4 +263,36 @@ static struct notifier_block armada_370_xp_cpu_pm_notifier = { .notifier_call = armada_370_xp_cpu_pm_notify, }; +int __init armada_370_xp_cpu_pm_init(void) +{ + struct device_node *np; + + /* + * Check that all the requirements are available to enable + * cpuidle. So far, it is only supported on Armada XP, cpuidle + * needs the coherency fabric and the PMSU enabled + */ + + if (!of_machine_is_compatible("marvell,armadaxp")) + return 0; + + np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"); + if (!np) + return 0; + of_node_put(np); + + np = of_find_matching_node(NULL, of_pmsu_table); + if (!np) + return 0; + of_node_put(np); + + armada_370_xp_pmsu_enable_l2_powerdown_onidle(); + armada_xp_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend; + platform_device_register(&armada_xp_cpuidle_device); + cpu_pm_register_notifier(&armada_370_xp_cpu_pm_notifier); + + return 0; +} + +arch_initcall(armada_370_xp_cpu_pm_init); early_initcall(armada_370_xp_pmsu_init); -- cgit v1.2.3-70-g09d2 From c42e1ffa269f098133629adf54cabe242596b647 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Sat, 19 Apr 2014 18:32:49 +0200 Subject: ARM: mvebu: remove unnecessary ifdef around l2x0_of_init l2x0_of_init function is always defined arch/arm/include/asm/hardware/cache-l2x0.h: in case of CONFIG_CACHE_L2X0 is not selected then a placeholder is defined. Then there is no need to have ifdef around l2x0_of_init. Signed-off-by: Gregory CLEMENT Reviewed-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1397925170-8202-2-git-send-email-gregory.clement@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/board-v7.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index 85f964e55bf..b674f3717cf 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -78,9 +78,7 @@ static void __init mvebu_timer_and_clk_init(void) mvebu_scu_enable(); coherency_init(); BUG_ON(mvebu_mbus_dt_init(coherency_available())); -#ifdef CONFIG_CACHE_L2X0 l2x0_of_init(0, ~0UL); -#endif if (of_machine_is_compatible("marvell,armada375")) hook_fault_code(16 + 6, armada_375_external_abort_wa, SIGBUS, 0, -- cgit v1.2.3-70-g09d2 From 8eee0f81cdaafb2fc78dcd5087a15c7f428d7751 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Sat, 19 Apr 2014 18:32:50 +0200 Subject: ARM: mvebu: fix the name of the parameter used in mvebu_get_soc_id The name of the two parameters of mvebu_get_soc_id were inverted. This patch fix it in order to have a more readable code. Reported-by: Ezequiel Garcia Signed-off-by: Gregory CLEMENT Link: https://lkml.kernel.org/r/1397925170-8202-3-git-send-email-gregory.clement@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/board-v7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index b674f3717cf..c8a90d992be 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -95,7 +95,7 @@ static void __init i2c_quirk(void) * mechanism. We can exit only if we are sure that we can * get the SoC revision and it is more recent than A0. */ - if (mvebu_get_soc_id(&rev, &dev) == 0 && dev > MV78XX0_A0_REV) + if (mvebu_get_soc_id(&dev, &rev) == 0 && rev > MV78XX0_A0_REV) return; for_each_compatible_node(np, NULL, "marvell,mv78230-i2c") { -- cgit v1.2.3-70-g09d2 From e9d3c849a8dc92e1019a6c7ced98f6ac231a2703 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 24 Apr 2014 08:34:36 -0300 Subject: ARM: mvebu: Select HAVE_ARM_TWD only if SMP is enabled HAVE_ARM_TWD depends on SMP, so we should only select it if SMP is enabled, as the others platforms do. Signed-off-by: Ezequiel Garcia Link: https://lkml.kernel.org/r/1398339276-5754-1-git-send-email-ezequiel.garcia@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 7bb92b1a63f..8c9fd60de40 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -41,7 +41,7 @@ config MACH_ARMADA_375 select ARMADA_375_CLK select CPU_V7 select HAVE_ARM_SCU - select HAVE_ARM_TWD + select HAVE_ARM_TWD if SMP select HAVE_SMP select MACH_MVEBU_V7 select PINCTRL_ARMADA_375 @@ -57,7 +57,7 @@ config MACH_ARMADA_38X select ARMADA_38X_CLK select CPU_V7 select HAVE_ARM_SCU - select HAVE_ARM_TWD + select HAVE_ARM_TWD if SMP select HAVE_SMP select MACH_MVEBU_V7 select PINCTRL_ARMADA_38X -- cgit v1.2.3-70-g09d2 From 5fd62066d2900b25a4fb3295ad13e3ee31474a51 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 24 Apr 2014 17:23:22 -0300 Subject: ARM: mvebu: Add thermal quirk for the Armada 375 DB board The initial release of the Armada 375 DB board has an Armada 375 Z1 stepping silicon. This commit introduces a quirk that allows to workaround a series of issues with the thermal sensor in this stepping, but updating the devicetree: * Updates the compatible string for the thermal, so the driver can perform a specific initialization of the sensor. * Moves the offset of the thermal control register. This quirk allows to specifiy the correct (A0 stepping) offset in the devicetree. Signed-off-by: Ezequiel Garcia Link: https://lkml.kernel.org/r/1398371004-15807-9-git-send-email-ezequiel.garcia@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/board-v7.c | 57 ++++++++++++++++++++++++++++++++++++++ arch/arm/mach-mvebu/mvebu-soc-id.h | 3 ++ 2 files changed, 60 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index c8a90d992be..bc0283f0dd8 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -113,10 +113,66 @@ static void __init i2c_quirk(void) return; } +#define A375_Z1_THERMAL_FIXUP_OFFSET 0xc + +static void __init thermal_quirk(void) +{ + struct device_node *np; + u32 dev, rev; + + if (mvebu_get_soc_id(&dev, &rev) && rev > ARMADA_375_Z1_REV) + return; + + for_each_compatible_node(np, NULL, "marvell,armada375-thermal") { + struct property *prop; + __be32 newval, *newprop, *oldprop; + int len; + + /* + * The register offset is at a wrong location. This quirk + * creates a new reg property as a clone of the previous + * one and corrects the offset. + */ + oldprop = (__be32 *)of_get_property(np, "reg", &len); + if (!oldprop) + continue; + + /* Create a duplicate of the 'reg' property */ + prop = kzalloc(sizeof(*prop), GFP_KERNEL); + prop->length = len; + prop->name = kstrdup("reg", GFP_KERNEL); + prop->value = kzalloc(len, GFP_KERNEL); + memcpy(prop->value, oldprop, len); + + /* Fixup the register offset of the second entry */ + oldprop += 2; + newprop = (__be32 *)prop->value + 2; + newval = cpu_to_be32(be32_to_cpu(*oldprop) - + A375_Z1_THERMAL_FIXUP_OFFSET); + *newprop = newval; + of_update_property(np, prop); + + /* + * The thermal controller needs some quirk too, so let's change + * the compatible string to reflect this. + */ + prop = kzalloc(sizeof(*prop), GFP_KERNEL); + prop->name = kstrdup("compatible", GFP_KERNEL); + prop->length = sizeof("marvell,armada375-z1-thermal"); + prop->value = kstrdup("marvell,armada375-z1-thermal", + GFP_KERNEL); + of_update_property(np, prop); + } + return; +} + static void __init mvebu_dt_init(void) { if (of_machine_is_compatible("plathome,openblocks-ax3-4")) i2c_quirk(); + if (of_machine_is_compatible("marvell,a375-db")) + thermal_quirk(); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } @@ -140,6 +196,7 @@ static const char * const armada_375_dt_compat[] = { DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)") .init_time = mvebu_timer_and_clk_init, + .init_machine = mvebu_dt_init, .restart = mvebu_restart, .dt_compat = armada_375_dt_compat, MACHINE_END diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.h b/arch/arm/mach-mvebu/mvebu-soc-id.h index 31654252fe3..294a443f56f 100644 --- a/arch/arm/mach-mvebu/mvebu-soc-id.h +++ b/arch/arm/mach-mvebu/mvebu-soc-id.h @@ -20,6 +20,9 @@ #define MV78XX0_A0_REV 0x1 #define MV78XX0_B0_REV 0x2 +/* Armada 375 */ +#define ARMADA_375_Z1_REV 0x0 + #ifdef CONFIG_ARCH_MVEBU int mvebu_get_soc_id(u32 *dev, u32 *rev); #else -- cgit v1.2.3-70-g09d2 From 7745b2512898e23507753513f7b5262ea1458135 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 3 May 2014 20:30:12 +0200 Subject: ARM: Kirkwood: Remove platform driver for codec Remove the platform driver and platform data for the audio codec. A DT node will replace it. Signed-off-by: Andrew Lunn Link: https://lkml.kernel.org/r/1399141819-23924-3-git-send-email-andrew@lunn.ch Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/board-t5325.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/board-t5325.c b/arch/arm/mach-mvebu/board-t5325.c index 65ace6db9f2..f2401b29821 100644 --- a/arch/arm/mach-mvebu/board-t5325.c +++ b/arch/arm/mach-mvebu/board-t5325.c @@ -11,10 +11,8 @@ */ #include -#include #include #include -#include #include "board.h" static struct platform_device hp_t5325_audio_device = { @@ -22,20 +20,7 @@ static struct platform_device hp_t5325_audio_device = { .id = -1, }; -static struct alc5623_platform_data alc5621_data = { - .add_ctrl = 0x3700, - .jack_det_ctrl = 0x4810, -}; - -static struct i2c_board_info i2c_board_info[] __initdata = { - { - I2C_BOARD_INFO("alc5621", 0x1a), - .platform_data = &alc5621_data, - }, -}; - void __init t5325_init(void) { - i2c_register_board_info(0, i2c_board_info, ARRAY_SIZE(i2c_board_info)); platform_device_register(&hp_t5325_audio_device); } -- cgit v1.2.3-70-g09d2 From efdf811d82b8001781087fd9174bb90a9530e578 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 3 May 2014 20:30:16 +0200 Subject: ARM: Kirkwood: t5325: Remove platform device to instantiate audio Remove platform device instantiating of the audio, which results in board-t5325.c being removed. A DT node will be added to take its place. Signed-off-by: Andrew Lunn Link: https://lkml.kernel.org/r/1399141819-23924-7-git-send-email-andrew@lunn.ch Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/Kconfig | 7 ------- arch/arm/mach-mvebu/Makefile | 1 - arch/arm/mach-mvebu/board-t5325.c | 26 -------------------------- arch/arm/mach-mvebu/board.h | 6 ------ arch/arm/mach-mvebu/kirkwood.c | 3 --- 5 files changed, 43 deletions(-) delete mode 100644 arch/arm/mach-mvebu/board-t5325.c (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 8c9fd60de40..d6b0a772a6d 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -104,13 +104,6 @@ config MACH_KIRKWOOD Say 'Y' here if you want your kernel to support boards based on the Marvell Kirkwood device tree. -config MACH_T5325 - bool "HP T5325 thin client" - depends on MACH_KIRKWOOD - help - Say 'Y' here if you want your kernel to support the - HP T5325 Thin client - endmenu endif diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index ec0b2177d99..854b72af9fa 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -13,4 +13,3 @@ endif obj-$(CONFIG_MACH_DOVE) += dove.o obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o -obj-$(CONFIG_MACH_T5325) += board-t5325.o diff --git a/arch/arm/mach-mvebu/board-t5325.c b/arch/arm/mach-mvebu/board-t5325.c deleted file mode 100644 index f2401b29821..00000000000 --- a/arch/arm/mach-mvebu/board-t5325.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * HP T5325 Board Setup - * - * Copyright (C) 2014 - * - * Andrew Lunn - * - * 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 -#include -#include -#include "board.h" - -static struct platform_device hp_t5325_audio_device = { - .name = "t5325-audio", - .id = -1, -}; - -void __init t5325_init(void) -{ - platform_device_register(&hp_t5325_audio_device); -} diff --git a/arch/arm/mach-mvebu/board.h b/arch/arm/mach-mvebu/board.h index de7f0a19139..9c7bb4386f8 100644 --- a/arch/arm/mach-mvebu/board.h +++ b/arch/arm/mach-mvebu/board.h @@ -13,10 +13,4 @@ #ifndef __ARCH_MVEBU_BOARD_H #define __ARCH_MVEBU_BOARD_H -#ifdef CONFIG_MACH_T5325 -void t5325_init(void); -#else -static inline void t5325_init(void) {}; -#endif - #endif diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c index a77e0bae9c5..46f105913c8 100644 --- a/arch/arm/mach-mvebu/kirkwood.c +++ b/arch/arm/mach-mvebu/kirkwood.c @@ -180,9 +180,6 @@ static void __init kirkwood_dt_init(void) kirkwood_pm_init(); kirkwood_dt_eth_fixup(); - if (of_machine_is_compatible("hp,t5325")) - t5325_init(); - of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL); } -- cgit v1.2.3-70-g09d2 From c1a01a0360f6744c9c1735e5db7b208df819156e Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 5 May 2014 17:05:22 +0200 Subject: ARM: mvebu: fix thermal quirk SoC revision check In commit 54fe26a900bc528f3df1e4235cb6b9ca5c6d4dc2 ('ARM: mvebu: Add thermal quirk for the Armada 375 DB board'), a check on the Armada SoC revision was added to decide whether a quirk for the thermal device should be applied or not. However, the quirk implementation has a bug: it assumes mvebu_get_soc_id() returns true on success, but it returns 0. Therefore, the condition: if (mvebu_get_soc_id(&dev, &rev) && rev > ARMADA_375_Z1_REV) is always false (as long as mvebu-soc-id is properly initialized). As a consequence, the quirk is always applied, even on A0 steppings, for which the quirk should not be applied. This was spotted by testing the thermal driver on Armada 375 A0, which Ezequiel could not do since he does not have access to the A0 revision of the SoC for the moment. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1399302326-6917-2-git-send-email-thomas.petazzoni@free-electrons.com Fixes: 54fe26a900bc528f3df1e4235cb6b9ca5c6d4dc2 ('ARM: mvebu: Add thermal quirk for the Armada 375 DB board') Acked-by: Ezequiel Garcia Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/board-v7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index bc0283f0dd8..01cfce6ac20 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -120,7 +120,7 @@ static void __init thermal_quirk(void) struct device_node *np; u32 dev, rev; - if (mvebu_get_soc_id(&dev, &rev) && rev > ARMADA_375_Z1_REV) + if (mvebu_get_soc_id(&dev, &rev) == 0 && rev > ARMADA_375_Z1_REV) return; for_each_compatible_node(np, NULL, "marvell,armada375-thermal") { -- cgit v1.2.3-70-g09d2 From 73c3c79137f05de2ffcfec3469e4110e40dd1522 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 5 May 2014 17:05:23 +0200 Subject: ARM: mvebu: initialize mvebu-soc-id earlier Currently, the mvebu-soc-id logic is initialized through a core_initcall(). However, we will soon need to know the SoC revision before booting secondary CPUs, because a workaround affects Armada 375 Z1 steppings, but should not be applied on Armada 375 A0 steppings. Unfortunately, core_initcall() are called way too late compared to the SMP initialization. Therefore, the mvebu-soc-id initialization is move to an early_initcall(), which is called before the SMP initialization. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1399302326-6917-3-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/mvebu-soc-id.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.c b/arch/arm/mach-mvebu/mvebu-soc-id.c index 874a7504818..e9119a99a5f 100644 --- a/arch/arm/mach-mvebu/mvebu-soc-id.c +++ b/arch/arm/mach-mvebu/mvebu-soc-id.c @@ -118,7 +118,7 @@ clk_err: return ret; } -core_initcall(mvebu_soc_id_init); +early_initcall(mvebu_soc_id_init); static int __init mvebu_soc_device(void) { -- cgit v1.2.3-70-g09d2 From 5093dcfb422d212ccdd22450bd986a2fb03cfb9f Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 5 May 2014 17:05:24 +0200 Subject: ARM: mvebu: add Armada 375 A0 revision definition Now that we have access to Armada 375 A0 platforms, we can add the corresponding revision definition in mvebu-soc-id.h. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1399302326-6917-4-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/mvebu-soc-id.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.h b/arch/arm/mach-mvebu/mvebu-soc-id.h index 294a443f56f..c16bb68ca81 100644 --- a/arch/arm/mach-mvebu/mvebu-soc-id.h +++ b/arch/arm/mach-mvebu/mvebu-soc-id.h @@ -22,6 +22,7 @@ /* Armada 375 */ #define ARMADA_375_Z1_REV 0x0 +#define ARMADA_375_A0_REV 0x3 #ifdef CONFIG_ARCH_MVEBU int mvebu_get_soc_id(u32 *dev, u32 *rev); -- cgit v1.2.3-70-g09d2 From a58d5af7d992a5e6dd8e55b3e618bd77f0368b57 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 5 May 2014 17:05:25 +0200 Subject: ARM: mvebu: conditionalize Armada 375 SMP workaround The Armada 375 SMP workaround only needs to be applied to the Z1 revision of the SoC. The A0 and later revisions have been fixed, and no longer need this workaround. Note that the initialization of the SMP workaround is delayed from ->smp_prepare_cpus() to ->smp_boot_secondary() because when ->smp_prepare_cpus() is called, the early initcalls have not be called, so the mvebu-soc-id mechanism is not operational. Since the workaround is anyway not needed before the secondary CPU is started, we can delay its implementation until the ->smp_boot_secondary() call. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1399302326-6917-5-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/platsmp-a9.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/platsmp-a9.c b/arch/arm/mach-mvebu/platsmp-a9.c index 04d0b1847c3..96c2c59e34b 100644 --- a/arch/arm/mach-mvebu/platsmp-a9.c +++ b/arch/arm/mach-mvebu/platsmp-a9.c @@ -20,6 +20,7 @@ #include #include #include "common.h" +#include "mvebu-soc-id.h" #include "pmsu.h" #define CRYPT0_ENG_ID 41 @@ -63,11 +64,19 @@ static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu, */ hw_cpu = cpu_logical_map(cpu); - if (of_machine_is_compatible("marvell,armada375")) + if (of_machine_is_compatible("marvell,armada375")) { + u32 dev, rev; + + if (mvebu_get_soc_id(&dev, &rev) == 0 && + rev == ARMADA_375_Z1_REV) + armada_375_smp_cpu1_enable_wa(); + mvebu_system_controller_set_cpu_boot_addr(mvebu_cortex_a9_secondary_startup); - else + } + else { mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cortex_a9_secondary_startup); + } smp_wmb(); ret = mvebu_cpu_reset_deassert(hw_cpu); @@ -80,14 +89,7 @@ static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu, return 0; } -static void __init mvebu_cortex_a9_smp_prepare_cpus(unsigned int max_cpus) -{ - if (of_machine_is_compatible("marvell,armada375")) - armada_375_smp_cpu1_enable_wa(); -} - static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = { - .smp_prepare_cpus = mvebu_cortex_a9_smp_prepare_cpus, .smp_boot_secondary = mvebu_cortex_a9_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = armada_xp_cpu_die, -- cgit v1.2.3-70-g09d2 From 39438567179536c9f32e85d19586a11aebe1f860 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 5 May 2014 17:05:26 +0200 Subject: ARM: mvebu: conditionalize Armada 375 coherency workaround The Armada 375 coherency workaround only needs to be applied to the Z1 revision of the SoC. The A0 and later revisions have been fixed, and no longer need this workaround. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1399302326-6917-6-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 9d5ccd37271..d5a975b6a59 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -33,6 +33,7 @@ #include #include "armada-370-xp.h" #include "coherency.h" +#include "mvebu-soc-id.h" unsigned long coherency_phys_base; void __iomem *coherency_base; @@ -365,8 +366,13 @@ static int __init coherency_late_init(void) if (type == COHERENCY_FABRIC_TYPE_NONE) return 0; - if (type == COHERENCY_FABRIC_TYPE_ARMADA_375) - armada_375_coherency_init_wa(); + if (type == COHERENCY_FABRIC_TYPE_ARMADA_375) { + u32 dev, rev; + + if (mvebu_get_soc_id(&dev, &rev) == 0 && + rev == ARMADA_375_Z1_REV) + armada_375_coherency_init_wa(); + } bus_register_notifier(&platform_bus_type, &mvebu_hwcc_platform_nb); -- cgit v1.2.3-70-g09d2 From 9f0affcf3e21fc56d8bce625bb3d5800b7a7d284 Mon Sep 17 00:00:00 2001 From: Vincent Stehlé Date: Tue, 6 May 2014 22:23:02 +0200 Subject: ARM: mvebu: Fix pmsu compilation when ARMv6 is selected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling for multiplatform for both ARMv6 and ARMv7, the default compiler flags are for ARMv6, and we will get: /tmp/ccwDEzd0.s: Assembler messages: /tmp/ccwDEzd0.s:639: Error: selected processor does not support ARM mode `isb ' /tmp/ccwDEzd0.s:645: Error: selected processor does not support ARM mode `isb ' /tmp/ccwDEzd0.s:646: Error: selected processor does not support ARM mode `dsb ' /tmp/ccwDEzd0.s:695: Error: selected processor does not support ARM mode `isb ' make[1]: *** [arch/arm/mach-mvebu/pmsu.o] Error 1 Fix this in a similar manner than done previously in commit 72533b77d30c2be02672e26b5dde1263d7b4c2be, by specifying ARMv7 flags for pmsu.o. Signed-off-by: Vincent Stehlé Link: https://lkml.kernel.org/r/1399407782-29091-1-git-send-email-vincent.stehle@laposte.net Cc: Jason Cooper Cc: Andrew Lunn Cc: Gregory Clement Cc: Sebastian Hesselbarth Cc: Russell King Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 854b72af9fa..2ecb828e4a8 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -2,6 +2,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ -I$(srctree)/arch/arm/plat-orion/include AFLAGS_coherency_ll.o := -Wa,-march=armv7-a +CFLAGS_pmsu.o := -march=armv7-a obj-y += system-controller.o mvebu-soc-id.o -- cgit v1.2.3-70-g09d2 From b0063aad5dd86308c9b9c433ac8f3ab5b49aab1b Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 13 May 2014 18:04:30 +0200 Subject: ARM: mvebu: use hardware I/O coherency also for PCI devices Since the beginning of the introduction of hardware I/O coherency support for Armada 370 and Armada XP, the special DMA operations should have applied to all DMA capable devices. Unfortunately, while the original code properly took into account platform devices, it didn't take into account PCI devices, which can also be DMA masters. This commit fixes that by registering a bus notifier on pci_bus_type, to register our custom DMA operations, like is already done for platform devices. While doing this, we also rename mvebu_hwcc_platform_notifier() to mvebu_hwcc_notifier() and mvebu_hwcc_platform_nb to mvebu_hwcc_nb because they are no longer specific to platform devices. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1399997070-11434-1-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index d5a975b6a59..5723178f658 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include "armada-370-xp.h" @@ -274,8 +275,8 @@ static struct dma_map_ops mvebu_hwcc_dma_ops = { .set_dma_mask = arm_dma_set_mask, }; -static int mvebu_hwcc_platform_notifier(struct notifier_block *nb, - unsigned long event, void *__dev) +static int mvebu_hwcc_notifier(struct notifier_block *nb, + unsigned long event, void *__dev) { struct device *dev = __dev; @@ -286,8 +287,8 @@ static int mvebu_hwcc_platform_notifier(struct notifier_block *nb, return NOTIFY_OK; } -static struct notifier_block mvebu_hwcc_platform_nb = { - .notifier_call = mvebu_hwcc_platform_notifier, +static struct notifier_block mvebu_hwcc_nb = { + .notifier_call = mvebu_hwcc_notifier, }; static void __init armada_370_coherency_init(struct device_node *np) @@ -375,9 +376,19 @@ static int __init coherency_late_init(void) } bus_register_notifier(&platform_bus_type, - &mvebu_hwcc_platform_nb); + &mvebu_hwcc_nb); return 0; } postcore_initcall(coherency_late_init); + +static int __init coherency_pci_init(void) +{ + if (coherency_available()) + bus_register_notifier(&pci_bus_type, + &mvebu_hwcc_nb); + return 0; +} + +arch_initcall(coherency_pci_init); -- cgit v1.2.3-70-g09d2 From 497a92308af8e9385fa3d135f7f416a997e4b93b Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 15 May 2014 16:59:34 +0200 Subject: ARM: mvebu: implement L2/PCIe deadlock workaround The Marvell Armada 375 and Armada 38x SOCs, which use the Cortex-A9 CPU core, the PL310 cache and the Marvell PCIe hardware block are affected a L2/PCIe deadlock caused by a system erratum when hardware I/O coherency is used. This deadlock can be avoided by mapping the PCIe memory areas as strongly-ordered (note: MT_UNCACHED is strongly-ordered), and by removing the outer cache sync done in software. This is implemented in this patch by: * Registering a custom arch_ioremap_caller function that allows to make sure PCI memory regions are mapped MT_UNCACHED. * Adding at runtime the 'arm,io-coherent' property to the PL310 cache controller. This cannot be done permanently in the DT, because the hardware I/O coherency can only be enabled when CONFIG_SMP is enabled, in the current kernel situation. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1400165974-9059-4-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 5723178f658..a2225070ac3 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "armada-370-xp.h" #include "coherency.h" #include "mvebu-soc-id.h" @@ -309,9 +310,47 @@ static void __init armada_370_coherency_init(struct device_node *np) set_cpu_coherent(); } +/* + * This ioremap hook is used on Armada 375/38x to ensure that PCIe + * memory areas are mapped as MT_UNCACHED instead of MT_DEVICE. This + * is needed as a workaround for a deadlock issue between the PCIe + * interface and the cache controller. + */ +static void __iomem * +armada_pcie_wa_ioremap_caller(phys_addr_t phys_addr, size_t size, + unsigned int mtype, void *caller) +{ + struct resource pcie_mem; + + mvebu_mbus_get_pcie_mem_aperture(&pcie_mem); + + if (pcie_mem.start <= phys_addr && (phys_addr + size) <= pcie_mem.end) + mtype = MT_UNCACHED; + + return __arm_ioremap_caller(phys_addr, size, mtype, caller); +} + static void __init armada_375_380_coherency_init(struct device_node *np) { + struct device_node *cache_dn; + coherency_cpu_base = of_iomap(np, 0); + arch_ioremap_caller = armada_pcie_wa_ioremap_caller; + + /* + * Add the PL310 property "arm,io-coherent". This makes sure the + * outer sync operation is not used, which allows to + * workaround the system erratum that causes deadlocks when + * doing PCIe in an SMP situation on Armada 375 and Armada + * 38x. + */ + for_each_compatible_node(cache_dn, NULL, "arm,pl310-cache") { + struct property *p; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + p->name = kstrdup("arm,io-coherent", GFP_KERNEL); + of_add_property(cache_dn, p); + } } static int coherency_type(void) -- cgit v1.2.3-70-g09d2 From 8828ccc3f2a8e32ddf1a0e1a80742e8482f18cea Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 20 May 2014 17:13:03 +0200 Subject: ARM: mvebu: coherency: fix registration of PCI bus notifier when !PCI Commit b0063aad5dd8 ("ARM: mvebu: use hardware I/O coherency also for PCI devices") added a reference to the pci_bus_type variable, but this variable is only available when CONFIG_PCI is enabled. Therefore, there is now a build failure in !CONFIG_PCI situations. This commit fixes that by enclosing the entire initcall into a IS_ENABLED(CONFIG_PCI) condition. Reported-by: Arnd Bergmann Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1400598783-706-1-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index a2225070ac3..477202fd39c 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -422,6 +422,7 @@ static int __init coherency_late_init(void) postcore_initcall(coherency_late_init); +#if IS_ENABLED(CONFIG_PCI) static int __init coherency_pci_init(void) { if (coherency_available()) @@ -431,3 +432,4 @@ static int __init coherency_pci_init(void) } arch_initcall(coherency_pci_init); +#endif -- cgit v1.2.3-70-g09d2 From 4fbe63937eb2a54040de58d0726d4796412fba3d Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 22 May 2014 14:47:59 +0200 Subject: ARM: mvebu: fix big endian booting after coherency code rework As part of the introduction of the cpuidle support for Armada XP, the coherency code was significantly reworked, especially in the coherency_ll.S file. However, when the ll_get_cpuid function was created, the big-endian specific code that switches the endianess of the register was not updated properly. This patch fixes this code, and therefore makes big endian systems bootable again. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1400762882-10116-2-git-send-email-thomas.petazzoni@free-electrons.com Fixes: 2e8a5942f875 ("ARM: mvebu: Split low level functions to manipulate HW coherency") Reported-by: Kevin Hilman Cc: Kevin Hilman Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency_ll.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index 6828f9f157b..a5e62c62819 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S @@ -49,7 +49,7 @@ ENTRY(ll_get_cpuid) and r3, r3, #15 mov r2, #(1 << 24) lsl r3, r2, r3 -ARM_BE8(rev r1, r1) +ARM_BE8(rev r3, r3) mov pc, lr ENDPROC(ll_get_cpuid) -- cgit v1.2.3-70-g09d2 From 90ba76f610b80d8fd33b8c36034172a98c5db05f Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 22 May 2014 14:48:00 +0200 Subject: ARM: mvebu: fix indentation of assembly instructions in coherency_ll.S This commit does not make any functional change, it only fixes the indentation of a few assembly instructions in arch/arm/mach-mvebu/coherency_ll.S. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1400762882-10116-3-git-send-email-thomas.petazzoni@free-electrons.com Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency_ll.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index a5e62c62819..7d1b5a51b65 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S @@ -66,10 +66,10 @@ ENTRY(ll_add_cpu_to_smp_group) * ll_get_cpuid, we can use it to save lr modifing it with the * following bl */ - mov r0, lr + mov r0, lr bl ll_get_coherency_base bl ll_get_cpuid - mov lr, r0 + mov lr, r0 add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET 1: ldrex r2, [r0] @@ -108,10 +108,10 @@ ENTRY(ll_disable_coherency) * ll_get_cpuid, we can use it to save lr modifing it with the * following bl */ - mov r0, lr + mov r0, lr bl ll_get_coherency_base bl ll_get_cpuid - mov lr, r0 + mov lr, r0 add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET 1: ldrex r2, [r0] -- cgit v1.2.3-70-g09d2 From 4dd1b7fa431d6b59022b3493312c6c1b52dbf547 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 22 May 2014 14:48:01 +0200 Subject: ARM: mvebu: improve comments in coherency_ll.S This commit makes no functional change, it only improves a bit the various code comments in mach-mvebu/coherency_ll.S, by fixing a few typos and adding a few more details. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1400762882-10116-4-git-send-email-thomas.petazzoni@free-electrons.com Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency_ll.S | 50 ++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 18 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index 7d1b5a51b65..311442ae128 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S @@ -24,26 +24,32 @@ #include .text -/* Returns with the coherency address in r1 (r0 is untouched)*/ +/* Returns the coherency base address in r1 (r0 is untouched) */ ENTRY(ll_get_coherency_base) mrc p15, 0, r1, c1, c0, 0 tst r1, #CR_M @ Check MMU bit enabled bne 1f - /* use physical address of the coherency register */ + /* + * MMU is disabled, use the physical address of the coherency + * base address. + */ adr r1, 3f ldr r3, [r1] ldr r1, [r1, r3] b 2f 1: - /* use virtual address of the coherency register */ + /* + * MMU is enabled, use the virtual address of the coherency + * base address. + */ ldr r1, =coherency_base ldr r1, [r1] 2: mov pc, lr ENDPROC(ll_get_coherency_base) -/* Returns with the CPU ID in r3 (r0 is untouched)*/ +/* Returns the CPU ID in r3 (r0 is untouched) */ ENTRY(ll_get_cpuid) mrc 15, 0, r3, cr0, cr0, 5 and r3, r3, #15 @@ -53,18 +59,22 @@ ARM_BE8(rev r3, r3) mov pc, lr ENDPROC(ll_get_cpuid) -/* ll_add_cpu_to_smp_group, ll_enable_coherency and - * ll_disable_coherency use strex/ldrex whereas MMU can be off. The - * Armada XP SoC has an exclusive monitor that can track transactions - * to Device and/or SO and as such also when MMU is disabled the - * exclusive transactions will be functional +/* + * ll_add_cpu_to_smp_group(), ll_enable_coherency() and + * ll_disable_coherency() use the strex/ldrex instructions while the + * MMU can be disabled. The Armada XP SoC has an exclusive monitor + * that tracks transactions to Device and/or SO memory and thanks to + * that, exclusive transactions are functional even when the MMU is + * disabled. */ ENTRY(ll_add_cpu_to_smp_group) /* - * r0 being untouched in ll_get_coherency_base and - * ll_get_cpuid, we can use it to save lr modifing it with the - * following bl + * As r0 is not modified by ll_get_coherency_base() and + * ll_get_cpuid(), we use it to temporarly save lr and avoid + * it being modified by the branch and link calls. This + * function is used very early in the secondary CPU boot, and + * no stack is available at this point. */ mov r0, lr bl ll_get_coherency_base @@ -82,9 +92,11 @@ ENDPROC(ll_add_cpu_to_smp_group) ENTRY(ll_enable_coherency) /* - * r0 being untouched in ll_get_coherency_base and - * ll_get_cpuid, we can use it to save lr modifing it with the - * following bl + * As r0 is not modified by ll_get_coherency_base() and + * ll_get_cpuid(), we use it to temporarly save lr and avoid + * it being modified by the branch and link calls. This + * function is used very early in the secondary CPU boot, and + * no stack is available at this point. */ mov r0, lr bl ll_get_coherency_base @@ -104,9 +116,11 @@ ENDPROC(ll_enable_coherency) ENTRY(ll_disable_coherency) /* - * r0 being untouched in ll_get_coherency_base and - * ll_get_cpuid, we can use it to save lr modifing it with the - * following bl + * As r0 is not modified by ll_get_coherency_base() and + * ll_get_cpuid(), we use it to temporarly save lr and avoid + * it being modified by the branch and link calls. This + * function is used very early in the secondary CPU boot, and + * no stack is available at this point. */ mov r0, lr bl ll_get_coherency_base -- cgit v1.2.3-70-g09d2 From 07ae144be1b2ac45f893bc1ed3fe1a49f7128e46 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 22 May 2014 14:48:02 +0200 Subject: ARM: mvebu: returns ll_get_cpuid() to ll_get_coherency_cpumask() In the refactoring of the coherency fabric assembly code, a function called ll_get_cpuid() was created to factorize common logic between functions adding CPU to the SMP coherency group, enabling and disabling the coherency. However, the name of the function is highly misleading: ll_get_cpuid() makes one think tat it returns the ID of the CPU, i.e 0 for CPU0, 1 for CPU1, etc. In fact, this is not at all what this function returns: it returns a CPU mask for the current CPU, usable for the coherency fabric configuration and control registers. Therefore this commit renames this function to ll_get_coherency_cpumask(), and adds additional comments on top of the function to explain in more details what it does, and also how the endianess issue is handled. Signed-off-by: Thomas Petazzoni Link: https://lkml.kernel.org/r/1400762882-10116-5-git-send-email-thomas.petazzoni@free-electrons.com Acked-by: Gregory CLEMENT Signed-off-by: Jason Cooper --- arch/arm/mach-mvebu/coherency_ll.S | 43 ++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'arch/arm/mach-mvebu') diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S index 311442ae128..510c29e079c 100644 --- a/arch/arm/mach-mvebu/coherency_ll.S +++ b/arch/arm/mach-mvebu/coherency_ll.S @@ -49,15 +49,22 @@ ENTRY(ll_get_coherency_base) mov pc, lr ENDPROC(ll_get_coherency_base) -/* Returns the CPU ID in r3 (r0 is untouched) */ -ENTRY(ll_get_cpuid) +/* + * Returns the coherency CPU mask in r3 (r0 is untouched). This + * coherency CPU mask can be used with the coherency fabric + * configuration and control registers. Note that the mask is already + * endian-swapped as appropriate so that the calling functions do not + * have to care about endianness issues while accessing the coherency + * fabric registers + */ +ENTRY(ll_get_coherency_cpumask) mrc 15, 0, r3, cr0, cr0, 5 and r3, r3, #15 mov r2, #(1 << 24) lsl r3, r2, r3 ARM_BE8(rev r3, r3) mov pc, lr -ENDPROC(ll_get_cpuid) +ENDPROC(ll_get_coherency_cpumask) /* * ll_add_cpu_to_smp_group(), ll_enable_coherency() and @@ -71,14 +78,14 @@ ENDPROC(ll_get_cpuid) ENTRY(ll_add_cpu_to_smp_group) /* * As r0 is not modified by ll_get_coherency_base() and - * ll_get_cpuid(), we use it to temporarly save lr and avoid - * it being modified by the branch and link calls. This - * function is used very early in the secondary CPU boot, and - * no stack is available at this point. + * ll_get_coherency_cpumask(), we use it to temporarly save lr + * and avoid it being modified by the branch and link + * calls. This function is used very early in the secondary + * CPU boot, and no stack is available at this point. */ mov r0, lr bl ll_get_coherency_base - bl ll_get_cpuid + bl ll_get_coherency_cpumask mov lr, r0 add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET 1: @@ -93,14 +100,14 @@ ENDPROC(ll_add_cpu_to_smp_group) ENTRY(ll_enable_coherency) /* * As r0 is not modified by ll_get_coherency_base() and - * ll_get_cpuid(), we use it to temporarly save lr and avoid - * it being modified by the branch and link calls. This - * function is used very early in the secondary CPU boot, and - * no stack is available at this point. + * ll_get_coherency_cpumask(), we use it to temporarly save lr + * and avoid it being modified by the branch and link + * calls. This function is used very early in the secondary + * CPU boot, and no stack is available at this point. */ mov r0, lr bl ll_get_coherency_base - bl ll_get_cpuid + bl ll_get_coherency_cpumask mov lr, r0 add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET 1: @@ -117,14 +124,14 @@ ENDPROC(ll_enable_coherency) ENTRY(ll_disable_coherency) /* * As r0 is not modified by ll_get_coherency_base() and - * ll_get_cpuid(), we use it to temporarly save lr and avoid - * it being modified by the branch and link calls. This - * function is used very early in the secondary CPU boot, and - * no stack is available at this point. + * ll_get_coherency_cpumask(), we use it to temporarly save lr + * and avoid it being modified by the branch and link + * calls. This function is used very early in the secondary + * CPU boot, and no stack is available at this point. */ mov r0, lr bl ll_get_coherency_base - bl ll_get_cpuid + bl ll_get_coherency_cpumask mov lr, r0 add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET 1: -- cgit v1.2.3-70-g09d2