Skip to contentSkip to conversation

cpuidle for Marvell Armada 370 and 38x

PATCH Superseded Thomas Petazzoni 3 participants 24 messages Jul 23, 2014 – Jul 25, 2014

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

v3 cover cpuidle for Marvell Armada 370 and 38x

Hello,

Here comes the third version of the cpuidle support for Armada 370 and Armada 38x.

We are hoping to see this patch series merged for 3.17.

Most patches are touching only arch/arm/mach-mvebu/ code so they should be handled by the mvebu maintainers. However, patches 11-13 are touching the mvebu cpuidle driver, with a possible issue on patch 11, which touches both the cpuidle driver and the mach-mvebu code in order to rename the driver without breaking functionality (if needed, we can decide to split the commits, it would break functionality temporarly, but not buildability).

Changes since v2
================

* According to the discussion with Daniel Lezcano (cpuidle maintainer) and Arnd Bergmann, changed the cpuidle-mvebu-v7 driver to actually register three separate cpuidle platform driver, one per-SoC. This way, we don't need special platform data to convey the SoC type being used, as this information is already available by looking at the driver name.

This change impacts the patches "cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7", "cpuidle: mvebu: add Armada 370 support", "cpuidle: mvebu: add Armada 38x support", "ARM: mvebu:
add cpuidle support for Armada 370" and "ARM: mvebu: add cpuidle support for Armada 38x". Other patches are unchanged. The patch "cpuidle: mvebu: make the cpuidle driver capable of handling multiple SoCs" was no longer needed, so it has been removed.

Changes since v1
================

* Series rebased on top of mvebu/fixes + mvebu/soc to take into account the conflicts with the changes already merged on the PMSU code.

* Adjusted the fix that sorts the #include statements in pmsu.c by alphabetic order to really use the alphabetic order.

* Various improvements to the implementation of the common function for the boot address workaround:

- Main function renamed from mvebu_boot_addr_wa() to mvebu_setup_boot_addr_wa().
- Both target and attribute of the crypto SRAM MBus window are now passed as arguments.
- Use appropriate types for arguments.
- Add error checking for ioremap() call.
- Use __raw_writel() instead of direct pointer dereference
- Fix the assembly code to work properly in big-endian configurations.

* Misc small fixes in the migration of the Armada 375 SMP code to use the common function for the boot address workaround: use correct types, split in a separate function to reduce the indentation level, use better naming for macros, etc.

* Re-organized the commits by grouping several patches that were separate before, to for example have a single patch to introduce the cpuidle support on Armada 370.

* Move back into the cpuidle driver the list of the cpuidle states for each SoC.

* Numerous other small typos and improvements.

Thanks,

Thomas

Gregory CLEMENT (14):
ARM: mvebu: split again armada_370_xp_pmsu_idle_enter() in PMSU code
ARM: mvebu: sort the #include of pmsu.c in alphabetic order
ARM: mvebu: add a common function for the boot address work around
ARM: mvebu: use the common function for Armada 375 SMP workaround
ARM: mvebu: rename the armada_370_xp symbols to mvebu_v7 in pmsu.c
ARM: mvebu: make the cpuidle initialization more generic
ARM: mvebu: use a local variable to store the resume address
ARM: mvebu: make the snoop disabling optional in
mvebu_v7_pmsu_idle_prepare()
ARM: mvebu: export the SCU address
ARM: mvebu: add CA9 MPcore SoC Controller node
cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7
ARM: mvebu: add cpuidle support for Armada 370
ARM: mvebu: add cpuidle support for Armada 38x
ARM: mvebu: defconfig: enable cpuidle support in mvebu_v7_defconfig

Thomas Petazzoni (2):
cpuidle: mvebu: add Armada 370 support
cpuidle: mvebu: add Armada 38x support

 .../bindings/arm/armada-380-mpcore-soc-ctrl.txt    |  14 ++
 arch/arm/boot/dts/armada-38x.dtsi                  |   5 +
 arch/arm/configs/mvebu_v7_defconfig                |   2 +
 arch/arm/mach-mvebu/armada-370-xp.h                |   1 -
 arch/arm/mach-mvebu/board-v7.c                     |   9 +-
 arch/arm/mach-mvebu/common.h                       |   2 +
 arch/arm/mach-mvebu/headsmp-a9.S                   |  15 --
 arch/arm/mach-mvebu/platsmp-a9.c                   |  42 +---
 arch/arm/mach-mvebu/platsmp.c                      |   2 +-
 arch/arm/mach-mvebu/pmsu.c                         | 273 ++++++++++++++++++---
 arch/arm/mach-mvebu/pmsu.h                         |   5 +
 arch/arm/mach-mvebu/pmsu_ll.S                      |  36 +++
 arch/arm/mach-mvebu/system-controller.c            |  31 +++
 drivers/cpuidle/Kconfig.arm                        |  12 +-
 drivers/cpuidle/Makefile                           |   2 +-
 drivers/cpuidle/cpuidle-armada-370-xp.c            |  93 -------
 drivers/cpuidle/cpuidle-mvebu-v7.c                 | 150 +++++++++++
 17 files changed, 500 insertions(+), 194 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt
 delete mode 100644 drivers/cpuidle/cpuidle-armada-370-xp.c
 create mode 100644 drivers/cpuidle/cpuidle-mvebu-v7.c
Signature · 1 line
2.0.0
#1 lore raw

PATCH v3 1/16 ARM: mvebu: split again armada_370_xp_pmsu_idle_enter() in PMSU code

From: Gregory CLEMENT <[email protected]>

do_armada_370_xp_cpu_suspend() and armada_370_xp_pmsu_idle_prepare(), have been merged into a single function called armada_370_xp_pmsu_idle_enter() by the commit "bbb92284b6c8 ARM:
mvebu: slightly refactor/rename PMSU idle related functions", in prepare for the introduction of the CPU hotplug support for Armada XP.

But for cpuidle the prepare function will be common to all the mvebu SoCs that use the PMSU, while the suspend function will be specific to each SoC. Keeping the prepare function separate will help reducing code duplication while new SoC support is added.

---
 arch/arm/mach-mvebu/pmsu.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
arch/arm/mach-mvebu/pmsu.c +12 -1
index b31a829..5fda549 100644
@@ -143,7 +143,7 @@ static void armada_370_xp_pmsu_enable_l2_powerdown_onidle(void)
 }
 
 /* No locking is needed because we only access per-CPU registers */
-int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
+static int armada_370_xp_prepare(unsigned long deepidle)
 {
 	unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
 	u32 reg;
@@ -179,6 +179,17 @@ int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
 	reg |= PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP;
 	writel(reg, pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
 
+	return 0;
+}
+
+int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
+{
+	int ret;
+
+	ret = armada_370_xp_prepare(deepidle);
+	if (ret)
+		return ret;
+
 	v7_exit_coherency_flush(all);
 
 	ll_disable_coherency();
Signature · 1 line
2.0.0
#2 lore raw

PATCH v3 2/16 ARM: mvebu: sort the #include of pmsu.c in alphabetic order

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

Sorting the headers in alphabetic order will help to reduce conflicts when adding new headers later.

---
 arch/arm/mach-mvebu/pmsu.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
arch/arm/mach-mvebu/pmsu.c +3 -3
index 5fda549..9e18cce 100644
@@ -19,13 +19,13 @@
 #define pr_fmt(fmt) "mvebu-pmsu: " fmt
 
 #include <linux/cpu_pm.h>
-#include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/of_address.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
-#include <linux/smp.h>
 #include <linux/resource.h>
+#include <linux/smp.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
 #include <asm/smp_plat.h>
Signature · 1 line
2.0.0
#3 lore raw

PATCH v3 3/16 ARM: mvebu: add a common function for the boot address work around

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

On some of the mvebu SoCs and due to internal BootROM issue, the CPU initial jump code must be placed in the 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 placed, create a dedicated MBus window for the SRAM. This SRAM is initialized with a few instructions of code that allows to jump to the real secondary CPU boot address. The SRAM used is the Crypto engine one.

This work around is currently needed for booting SMP on Armada 375 Z1 and will be needed for cpuidle support on Armada 370. Instead of duplicating the same code, this commit introduces a common function to handle it: mvebu_setup_boot_addr_wa().

---
 arch/arm/mach-mvebu/pmsu.c    | 47 +++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-mvebu/pmsu.h    |  3 +++
 arch/arm/mach-mvebu/pmsu_ll.S | 22 ++++++++++++++++++++
 3 files changed, 72 insertions(+)
arch/arm/mach-mvebu/pmsu.c +47 -0
index 9e18cce..272a9c05 100644
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/mbus.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/resource.h>
@@ -63,6 +64,10 @@ static void __iomem *pmsu_mp_base;
 #define L2C_NFABRIC_PM_CTL		    0x4
 #define L2C_NFABRIC_PM_CTL_PWR_DOWN		BIT(20)
 
+#define SRAM_PHYS_BASE  0xFFFF0000
+#define BOOTROM_BASE    0xFFF00000
+#define BOOTROM_SIZE    0x100000
+
 extern void ll_disable_coherency(void);
 extern void ll_enable_coherency(void);
 
@@ -85,6 +90,48 @@ void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr)
 		PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu));
 }
 
+extern unsigned char mvebu_boot_wa_start;
+extern unsigned char mvebu_boot_wa_end;
+
+/*
+ * This function sets up the boot address workaround needed for SMP
+ * boot on Armada 375 Z1 and cpuidle on Armada 370. It unmaps the
+ * BootROM Mbus window, and instead remaps a crypto SRAM into which a
+ * custom piece of code is copied to replace the problematic BootROM.
+ */
+int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
+			     unsigned int crypto_eng_attribute,
+			     phys_addr_t resume_addr_reg)
+{
+	void __iomem *sram_virt_base;
+	u32 code_len = &mvebu_boot_wa_end - &mvebu_boot_wa_start;
+
+	mvebu_mbus_del_window(BOOTROM_BASE, BOOTROM_SIZE);
+	mvebu_mbus_add_window_by_id(crypto_eng_target, crypto_eng_attribute,
+				    SRAM_PHYS_BASE, SZ_64K);
+
+	sram_virt_base = ioremap(SRAM_PHYS_BASE, SZ_64K);
+	if (!sram_virt_base) {
+		pr_err("Unable to map SRAM to setup the boot address WA\n");
+		return -ENOMEM;
+	}
+
+	memcpy(sram_virt_base, &mvebu_boot_wa_start, code_len);
+
+	/*
+	 * The last word of the code copied in SRAM must contain the
+	 * physical base address of the PMSU register. We
+	 * intentionally store this address in the native endianness
+	 * of the system.
+	 */
+	__raw_writel((unsigned long)resume_addr_reg,
+		     sram_virt_base + code_len - 4);
+
+	iounmap(sram_virt_base);
+
+	return 0;
+}
+
 static int __init armada_370_xp_pmsu_init(void)
 {
 	struct device_node *np;
arch/arm/mach-mvebu/pmsu.h +3 -0
index 07a737c..ae50194 100644
@@ -12,5 +12,8 @@
 #define __MACH_MVEBU_PMSU_H
 
 int armada_xp_boot_cpu(unsigned int cpu_id, void *phys_addr);
+int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
+                             unsigned int crypto_eng_attribute,
+                             phys_addr_t resume_addr_reg);
 
 #endif	/* __MACH_370_XP_PMSU_H */
arch/arm/mach-mvebu/pmsu_ll.S +22 -0
index fc3de68..17d7f3b 100644
@@ -23,3 +23,25 @@ ARM_BE8(setend	be )			@ go BE8 if entered LE
 	b	cpu_resume
 ENDPROC(armada_370_xp_cpu_resume)
 
+.global mvebu_boot_wa_start
+.global mvebu_boot_wa_end
+
+/* The following code will be executed from SRAM */
+ENTRY(mvebu_boot_wa_start)
+mvebu_boot_wa_start:
+ARM_BE8(setend	be)
+	adr	r0, 1f
+	ldr	r0, [r0]		@ load the address of the
+					@ resume register
+	ldr	r0, [r0]		@ load the value in the
+					@ resume register
+ARM_BE8(rev	r0, r0)			@ the value is stored LE
+	mov	pc, r0			@ jump to this value
+/*
+ * the last word of this piece of code will be filled by the physical
+ * address of the boot address register just after being copied in SRAM
+ */
+1:
+	.long   .
+mvebu_boot_wa_end:
+ENDPROC(mvebu_boot_wa_end)
Signature · 1 line
2.0.0
#4 lore raw

PATCH v3 4/16 ARM: mvebu: use the common function for Armada 375 SMP workaround

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

Use the common function mvebu_setup_boot_addr_wa() introduced in the commit "ARM: mvebu: Add a common function for the boot address work around" instead of the dedicated version for Armada 375.

This commit also moves the workaround in the system-controller module. Indeed the workaround on 375 is really related to setting the boot address which is done by the system controller.

As a bonus we no longer use an harcoded value to access the register storing the boot address.

---
 arch/arm/mach-mvebu/headsmp-a9.S        | 15 ------------
 arch/arm/mach-mvebu/platsmp-a9.c        | 42 +++------------------------------
 arch/arm/mach-mvebu/system-controller.c | 31 ++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 54 deletions(-)
arch/arm/mach-mvebu/headsmp-a9.S +0 -15
index da5bb29..be51c99 100644
@@ -18,21 +18,6 @@
 #include <asm/assembler.h>
 
 	__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:
-ARM_BE8(setend	be)
-	adr     r0, 1f
-	ldr	r0, [r0]
-	ldr     r1, [r0]
-ARM_BE8(rev	r1, r1)
-	mov     pc, r1
-1:
-	.word   CPU_RESUME_ADDR_REG
-armada_375_smp_cpu1_enable_code_end:
 
 ENTRY(mvebu_cortex_a9_secondary_startup)
 ARM_BE8(setend	be)
arch/arm/mach-mvebu/platsmp-a9.c +3 -39

57 lines not on this page · raw message

arch/arm/mach-mvebu/system-controller.c +31 -0
index b2b4e3d..a068cb5 100644
@@ -28,8 +28,14 @@
 #include <linux/io.h>
 #include <linux/reboot.h>
 #include "common.h"
+#include "mvebu-soc-id.h"
+#include "pmsu.h"
+
+#define ARMADA_375_CRYPT0_ENG_TARGET 41
+#define ARMADA_375_CRYPT0_ENG_ATTR    1
 
 static void __iomem *system_controller_base;
+static phys_addr_t system_controller_phys_base;
 
 struct mvebu_system_controller {
 	u32 rstoutn_mask_offset;
@@ -121,10 +127,32 @@ int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev)
 }
 
 #ifdef CONFIG_SMP
+void mvebu_armada375_smp_wa_init(void)
+{
+	u32 dev, rev;
+	phys_addr_t resume_addr_reg;
+
+	if (mvebu_get_soc_id(&dev, &rev) != 0)
+		return;
+
+	if (rev != ARMADA_375_Z1_REV)
+		return;
+
+	resume_addr_reg = system_controller_phys_base +
+		mvebu_sc->resume_boot_addr;
+	mvebu_setup_boot_addr_wa(ARMADA_375_CRYPT0_ENG_TARGET,
+				 ARMADA_375_CRYPT0_ENG_ATTR,
+				 resume_addr_reg);
+}
+
 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);
+
+	if (of_machine_is_compatible("marvell,armada375"))
+		mvebu_armada375_smp_wa_init();
+
 	writel(virt_to_phys(boot_addr), system_controller_base +
 	       mvebu_sc->resume_boot_addr);
 }
@@ -138,7 +166,10 @@ static int __init mvebu_system_controller_init(void)
 	np = of_find_matching_node_and_match(NULL, of_system_controller_table,
 					     &match);
 	if (np) {
+		struct resource res;
 		system_controller_base = of_iomap(np, 0);
+		of_address_to_resource(np, 0, &res);
+		system_controller_phys_base = res.start;
 		mvebu_sc = (struct mvebu_system_controller *)match->data;
 		of_node_put(np);
 	}
Signature · 1 line
2.0.0
#5 lore raw

PATCH v3 5/16 ARM: mvebu: rename the armada_370_xp symbols to mvebu_v7 in pmsu.c

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

Most of the function related to the PMSU are not specific to the Armada 370 or Armada XP SoCs. They can also be used for most of the other mvebu ARMv7 SoCs, and will actually be used to support cpuidle on Armada 38x.

---
 arch/arm/mach-mvebu/armada-370-xp.h |  1 -
 arch/arm/mach-mvebu/platsmp.c       |  2 +-
 arch/arm/mach-mvebu/pmsu.c          | 34 +++++++++++++++++-----------------
 arch/arm/mach-mvebu/pmsu.h          |  2 ++
 4 files changed, 20 insertions(+), 19 deletions(-)
arch/arm/mach-mvebu/armada-370-xp.h +0 -1
index 52c1603a..84cd90d 100644
@@ -25,6 +25,5 @@ extern struct smp_operations armada_xp_smp_ops;
 #endif
 
 int armada_370_xp_pmsu_idle_enter(unsigned long deepidle);
-void armada_370_xp_pmsu_idle_exit(void);
 
 #endif /* __MACH_ARMADA_370_XP_H */
arch/arm/mach-mvebu/platsmp.c +1 -1
index b6fa9f0..6da2b72 100644
@@ -108,7 +108,7 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
  */
 static void armada_xp_secondary_init(unsigned int cpu)
 {
-	armada_370_xp_pmsu_idle_exit();
+	mvebu_v7_pmsu_idle_exit();
 }
 
 static void __init armada_xp_smp_init_cpus(void)
arch/arm/mach-mvebu/pmsu.c +17 -17
index 272a9c05..501d450 100644
@@ -73,7 +73,7 @@ extern void ll_enable_coherency(void);
 
 extern void armada_370_xp_cpu_resume(void);
 
-static struct platform_device armada_xp_cpuidle_device = {
+static struct platform_device mvebu_v7_cpuidle_device = {
 	.name = "cpuidle-armada-370-xp",
 };
 
@@ -132,7 +132,7 @@ int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
 	return 0;
 }
 
-static int __init armada_370_xp_pmsu_init(void)
+static int __init mvebu_v7_pmsu_init(void)
 {
 	struct device_node *np;
 	struct resource res;
@@ -176,7 +176,7 @@ static int __init armada_370_xp_pmsu_init(void)
 	return ret;
 }
 
-static void armada_370_xp_pmsu_enable_l2_powerdown_onidle(void)
+static void mvebu_v7_pmsu_enable_l2_powerdown_onidle(void)
 {
 	u32 reg;
 
@@ -190,7 +190,7 @@ static void armada_370_xp_pmsu_enable_l2_powerdown_onidle(void)
 }
 
 /* No locking is needed because we only access per-CPU registers */
-static int armada_370_xp_prepare(unsigned long deepidle)
+static int mvebu_v7_pmsu_idle_prepare(bool deepidle)
 {
 	unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
 	u32 reg;
@@ -233,7 +233,7 @@ int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
 {
 	int ret;
 
-	ret = armada_370_xp_prepare(deepidle);
+	ret = mvebu_v7_pmsu_idle_prepare(deepidle);
 	if (ret)
 		return ret;
 
@@ -272,7 +272,7 @@ static int armada_370_xp_cpu_suspend(unsigned long deepidle)
 }
 
 /* No locking is needed because we only access per-CPU registers */
-void armada_370_xp_pmsu_idle_exit(void)
+void mvebu_v7_pmsu_idle_exit(void)
 {
 	unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
 	u32 reg;
@@ -294,24 +294,24 @@ void armada_370_xp_pmsu_idle_exit(void)
 	writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(hw_cpu));
 }
 
-static int armada_370_xp_cpu_pm_notify(struct notifier_block *self,
+static int mvebu_v7_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_exit();
+		mvebu_v7_pmsu_idle_exit();
 	}
 
 	return NOTIFY_OK;
 }
 
-static struct notifier_block armada_370_xp_cpu_pm_notifier = {
-	.notifier_call = armada_370_xp_cpu_pm_notify,
+static struct notifier_block mvebu_v7_cpu_pm_notifier = {
+	.notifier_call = mvebu_v7_cpu_pm_notify,
 };
 
-static int __init armada_370_xp_cpu_pm_init(void)
+static int __init mvebu_v7_cpu_pm_init(void)
 {
 	struct device_node *np;
 
@@ -334,13 +334,13 @@ static int __init armada_370_xp_cpu_pm_init(void)
 		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);
+	mvebu_v7_pmsu_enable_l2_powerdown_onidle();
+	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
+	platform_device_register(&mvebu_v7_cpuidle_device);
+	cpu_pm_register_notifier(&mvebu_v7_cpu_pm_notifier);
 
 	return 0;
 }
 
-arch_initcall(armada_370_xp_cpu_pm_init);
-early_initcall(armada_370_xp_pmsu_init);
+arch_initcall(mvebu_v7_cpu_pm_init);
+early_initcall(mvebu_v7_pmsu_init);
arch/arm/mach-mvebu/pmsu.h +2 -0
index ae50194..6b58c1f 100644
@@ -16,4 +16,6 @@ int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
                              unsigned int crypto_eng_attribute,
                              phys_addr_t resume_addr_reg);
 
+void mvebu_v7_pmsu_idle_exit(void);
+
 #endif	/* __MACH_370_XP_PMSU_H */
Signature · 1 line
2.0.0
#6 lore raw

PATCH v3 6/16 ARM: mvebu: make the cpuidle initialization more generic

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

In preparation to the addition of the cpuidle support for more SoCs, this patch moves the Armada XP specific initialization to a separate function.

---
 arch/arm/mach-mvebu/pmsu.c | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)
arch/arm/mach-mvebu/pmsu.c +20 -12
index 501d450..e976c3e 100644
@@ -311,31 +311,39 @@ static struct notifier_block mvebu_v7_cpu_pm_notifier = {
 	.notifier_call = mvebu_v7_cpu_pm_notify,
 };
 
-static int __init mvebu_v7_cpu_pm_init(void)
+static int __init armada_xp_cpuidle_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;
+		return -ENODEV;
 	of_node_put(np);
 
+	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
+
+	return 0;
+}
+
+static int __init mvebu_v7_cpu_pm_init(void)
+{
+	struct device_node *np;
+	int ret;
+
 	np = of_find_matching_node(NULL, of_pmsu_table);
 	if (!np)
 		return 0;
 	of_node_put(np);
 
+	if (of_machine_is_compatible("marvell,armadaxp"))
+		ret = armada_xp_cpuidle_init();
+	else
+		return 0;
+
+	if (ret)
+		return ret;
+
 	mvebu_v7_pmsu_enable_l2_powerdown_onidle();
-	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
 	platform_device_register(&mvebu_v7_cpuidle_device);
 	cpu_pm_register_notifier(&mvebu_v7_cpu_pm_notifier);
 
Signature · 1 line
2.0.0
#7 lore raw

PATCH v3 7/16 ARM: mvebu: use a local variable to store the resume address

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

The resume address used by the cpuidle code will not always be the same depending on the SoC. Using a local variable to store the resume address allows to keep the same function for the PM notifier but with a different address. This address will be set during the initialization of the cpuidle logic in pmsu.c.

---
 arch/arm/mach-mvebu/pmsu.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
arch/arm/mach-mvebu/pmsu.c +4 -1
index e976c3e..ab525b7 100644
@@ -73,6 +73,8 @@ extern void ll_enable_coherency(void);
 
 extern void armada_370_xp_cpu_resume(void);
 
+static void *mvebu_cpu_resume;
+
 static struct platform_device mvebu_v7_cpuidle_device = {
 	.name = "cpuidle-armada-370-xp",
 };
@@ -299,7 +301,7 @@ static int mvebu_v7_cpu_pm_notify(struct notifier_block *self,
 {
 	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);
+		mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cpu_resume);
 	} else if (action == CPU_PM_EXIT) {
 		mvebu_v7_pmsu_idle_exit();
 	}
@@ -320,6 +322,7 @@ static int __init armada_xp_cpuidle_init(void)
 		return -ENODEV;
 	of_node_put(np);
 
+	mvebu_cpu_resume = armada_370_xp_cpu_resume;
 	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
 
 	return 0;
Signature · 1 line
2.0.0
#8 lore raw

PATCH v3 8/16 ARM: mvebu: make the snoop disabling optional in mvebu_v7_pmsu_idle_prepare()

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

On some mvebu v7 SoCs (the ones using a Cortex-A9 core and not a PJ4B core), the snoop disabling feature does not exist as the hardware coherency is handled in a different way. Therefore, in preparation to the introduction of the cpuidle support for those SoCs, this commit modifies the mvebu_v7_psmu_idle_prepare() function to take several flags, which allow to decide whether snooping should be disabled, and whether we should use the deep idle mode or not.

---
 arch/arm/mach-mvebu/pmsu.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)
arch/arm/mach-mvebu/pmsu.c +19 -7
index ab525b7..15e67bf 100644
@@ -191,8 +191,14 @@ static void mvebu_v7_pmsu_enable_l2_powerdown_onidle(void)
 	writel(reg, pmsu_mp_base + L2C_NFABRIC_PM_CTL);
 }
 
+enum pmsu_idle_prepare_flags {
+	PMSU_PREPARE_NORMAL = 0,
+	PMSU_PREPARE_DEEP_IDLE = BIT(0),
+	PMSU_PREPARE_SNOOP_DISABLE = BIT(1),
+};
+
 /* No locking is needed because we only access per-CPU registers */
-static int mvebu_v7_pmsu_idle_prepare(bool deepidle)
+static int mvebu_v7_pmsu_idle_prepare(unsigned long flags)
 {
 	unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
 	u32 reg;
@@ -216,26 +222,32 @@ static int mvebu_v7_pmsu_idle_prepare(bool deepidle)
 
 	reg = readl(pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu));
 	/* ask HW to power down the L2 Cache if needed */
-	if (deepidle)
+	if (flags & PMSU_PREPARE_DEEP_IDLE)
 		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));
+	if (flags & PMSU_PREPARE_SNOOP_DISABLE) {
+		/* 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));
+	}
 
 	return 0;
 }
 
 int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
 {
+	unsigned long flags = PMSU_PREPARE_SNOOP_DISABLE;
 	int ret;
 
-	ret = mvebu_v7_pmsu_idle_prepare(deepidle);
+	if (deepidle)
+		flags |= PMSU_PREPARE_DEEP_IDLE;
+
+	ret = mvebu_v7_pmsu_idle_prepare(flags);
 	if (ret)
 		return ret;
 
Signature · 1 line
2.0.0
#9 lore raw

PATCH v3 9/16 ARM: mvebu: export the SCU address

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

The SCU address will be needed in other files than board-v7.c, especially in pmsu.c for cpuidle related activities. So this patch adds a function that allows to retrieve the virtual address at which the SCU has been mapped.

---
 arch/arm/mach-mvebu/board-v7.c | 9 +++++++--
 arch/arm/mach-mvebu/common.h   | 2 ++
 2 files changed, 9 insertions(+), 2 deletions(-)
arch/arm/mach-mvebu/board-v7.c +7 -2
index f244622..6478626 100644
@@ -34,14 +34,14 @@
 #include "coherency.h"
 #include "mvebu-soc-id.h"
 
+static void __iomem *scu_base;
+
 /*
  * 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) {
@@ -51,6 +51,11 @@ static void __init mvebu_scu_enable(void)
 	}
 }
 
+void __iomem *mvebu_get_scu_base(void)
+{
+	return scu_base;
+}
+
 /*
  * Early versions of Armada 375 SoC have a bug where the BootROM
  * leaves an external data abort pending. The kernel is hit by this
arch/arm/mach-mvebu/common.h +2 -0
index a97778e..3ccb40c 100644
@@ -23,4 +23,6 @@ void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr);
 void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr);
 int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
 
+void __iomem *mvebu_get_scu_base(void);
+
 #endif
Signature · 1 line
2.0.0
#10 lore raw

PATCH v3 10/16 ARM: mvebu: add CA9 MPcore SoC Controller node

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

The CA9 MPcore SoC Control block is a set of registers that allows to configure certain internal aspects of the core blocks of the SoC (Cortex-A9, L2 cache controller, etc.). In most cases, the default values are fine so they aren't many reasons to touch those registers, but there is one exception: to support cpuidle on Armada 38x, we need to modify the value of the CA9 MPcore Reset Control register.

Therefore, this commit adds a new Device Tree binding for this hardware block, and uses this new binding for the Armada 38x Device Tree file.

Cc devicetree at vger.kernel.org
---
 .../devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt | 14 ++++++++++++++
 arch/arm/boot/dts/armada-38x.dtsi                          |  5 +++++
 2 files changed, 19 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt
Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt new file +14 -0
new file mode 100644
index 0000000..8781073
@@ -0,0 +1,14 @@
+Marvell Armada 38x CA9 MPcore SoC Controller
+============================================
+
+Required properties:
+
+- compatible: Should be "marvell,armada-380-mpcore-soc-ctrl".
+
+- reg: should be the register base and length as documented in the
+  datasheet for the CA9 MPcore SoC Control registers
+
+mpcore-soc-ctrl at 20d20 {
+	compatible = "marvell,armada-380-mpcore-soc-ctrl";
+	reg = <0x20d20 0x6c>;
+};
arch/arm/boot/dts/armada-38x.dtsi +5 -0
index 689fa1a..242d0ec 100644
@@ -286,6 +286,11 @@
 				reg = <0x20800 0x10>;
 			};
 
+			mpcore-soc-ctrl at 20d20 {
+				compatible = "marvell,armada-380-mpcore-soc-ctrl";
+				reg = <0x20d20 0x6c>;
+			};
+
 			coherency-fabric at 21010 {
 				compatible = "marvell,armada-380-coherency-fabric";
 				reg = <0x21010 0x1c>;
Signature · 1 line
2.0.0
#11 lore raw

PATCH v3 11/16 cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

This driver will be able to manage the cpuidle for more SoCs than just Armada 370 and XP. It will also support Armada 38x and potentially other SoC of the Marvell Armada EBU family. To take this into account, this patch renames the driver and its symbols.

It also changes the driver name from cpuidle-armada-370-xp to cpuidle-armada-xp, because separate platform drivers will be registered for the other SoC types. This change must be done simultaneously in the cpuidle driver and in the PMSU code in order to remain bisectable.

---
 arch/arm/mach-mvebu/pmsu.c                         |  2 +-
 drivers/cpuidle/Kconfig.arm                        | 12 +++----
 drivers/cpuidle/Makefile                           |  2 +-
 ...{cpuidle-armada-370-xp.c => cpuidle-mvebu-v7.c} | 39 +++++++++++-----------
 4 files changed, 27 insertions(+), 28 deletions(-)
 rename drivers/cpuidle/{cpuidle-armada-370-xp.c => cpuidle-mvebu-v7.c} (58%)
arch/arm/mach-mvebu/pmsu.c +1 -1
index 15e67bf..0cd2d09 100644
@@ -76,7 +76,7 @@ extern void armada_370_xp_cpu_resume(void);
 static void *mvebu_cpu_resume;
 
 static struct platform_device mvebu_v7_cpuidle_device = {
-	.name = "cpuidle-armada-370-xp",
+	.name = "cpuidle-armada-xp",
 };
 
 static struct of_device_id of_pmsu_table[] = {
drivers/cpuidle/Kconfig.arm +6 -6
index b6d69e8..a563427 100644
@@ -1,12 +1,6 @@
 #
 # ARM CPU Idle drivers
 #
-config ARM_ARMADA_370_XP_CPUIDLE
-	bool "CPU Idle Driver for Armada 370/XP family processors"
-	depends on ARCH_MVEBU
-	help
-	  Select this to enable cpuidle on Armada 370/XP processors.
-
 config ARM_BIG_LITTLE_CPUIDLE
 	bool "Support for ARM big.LITTLE processors"
 	depends on ARCH_VEXPRESS_TC2_PM
@@ -61,3 +55,9 @@ config ARM_EXYNOS_CPUIDLE
 	depends on ARCH_EXYNOS
 	help
 	  Select this to enable cpuidle for Exynos processors
+
+config ARM_MVEBU_V7_CPUIDLE
+	bool "CPU Idle Driver for mvebu v7 family processors"
+	depends on ARCH_MVEBU
+	help
+	  Select this to enable cpuidle on Armada 370, 38x and XP processors.
drivers/cpuidle/Makefile +1 -1
index d8bb1ff..11edb31 100644
@@ -7,7 +7,7 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
 
 ##################################################################################
 # ARM SoC drivers
-obj-$(CONFIG_ARM_ARMADA_370_XP_CPUIDLE) += cpuidle-armada-370-xp.o
+obj-$(CONFIG_ARM_MVEBU_V7_CPUIDLE) += cpuidle-mvebu-v7.o
 obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE)	+= cpuidle-big_little.o
 obj-$(CONFIG_ARM_CLPS711X_CPUIDLE)	+= cpuidle-clps711x.o
 obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE)	+= cpuidle-calxeda.o
drivers/cpuidle/cpuidle-mvebu-v7.c renamed from drivers/cpuidle/cpuidle-armada-370-xp.c +19 -20
similarity index 58%
rename from drivers/cpuidle/cpuidle-armada-370-xp.c
rename to drivers/cpuidle/cpuidle-mvebu-v7.c
index 28587d0..7252fd8 100644
@@ -21,12 +21,11 @@
 #include <linux/platform_device.h>
 #include <asm/cpuidle.h>
 
-#define ARMADA_370_XP_MAX_STATES	3
-#define ARMADA_370_XP_FLAG_DEEP_IDLE	0x10000
+#define MVEBU_V7_FLAG_DEEP_IDLE	0x10000
 
-static int (*armada_370_xp_cpu_suspend)(int);
+static int (*mvebu_v7_cpu_suspend)(int);
 
-static int armada_370_xp_enter_idle(struct cpuidle_device *dev,
+static int mvebu_v7_enter_idle(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index)
 {
@@ -34,10 +33,10 @@ static int armada_370_xp_enter_idle(struct cpuidle_device *dev,
 	bool deepidle = false;
 	cpu_pm_enter();
 
-	if (drv->states[index].flags & ARMADA_370_XP_FLAG_DEEP_IDLE)
+	if (drv->states[index].flags & MVEBU_V7_FLAG_DEEP_IDLE)
 		deepidle = true;
 
-	ret = armada_370_xp_cpu_suspend(deepidle);
+	ret = mvebu_v7_cpu_suspend(deepidle);
 	if (ret)
 		return ret;
 
@@ -46,11 +45,11 @@ static int armada_370_xp_enter_idle(struct cpuidle_device *dev,
 	return index;
 }
 
-static struct cpuidle_driver armada_370_xp_idle_driver = {
-	.name			= "armada_370_xp_idle",
+static struct cpuidle_driver armadaxp_idle_driver = {
+	.name			= "armada_xp_idle",
 	.states[0]		= ARM_CPUIDLE_WFI_STATE,
 	.states[1]		= {
-		.enter			= armada_370_xp_enter_idle,
+		.enter			= mvebu_v7_enter_idle,
 		.exit_latency		= 10,
 		.power_usage		= 50,
 		.target_residency	= 100,
@@ -59,35 +58,35 @@ static struct cpuidle_driver armada_370_xp_idle_driver = {
 		.desc			= "CPU power down",
 	},
 	.states[2]		= {
-		.enter			= armada_370_xp_enter_idle,
+		.enter			= mvebu_v7_enter_idle,
 		.exit_latency		= 100,
 		.power_usage		= 5,
 		.target_residency	= 1000,
 		.flags			= CPUIDLE_FLAG_TIME_VALID |
-						ARMADA_370_XP_FLAG_DEEP_IDLE,
+						MVEBU_V7_FLAG_DEEP_IDLE,
 		.name			= "MV CPU DEEP IDLE",
 		.desc			= "CPU and L2 Fabric power down",
 	},
-	.state_count = ARMADA_370_XP_MAX_STATES,
+	.state_count = 3,
 };
 
-static int armada_370_xp_cpuidle_probe(struct platform_device *pdev)
+static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
 {
 
-	armada_370_xp_cpu_suspend = (void *)(pdev->dev.platform_data);
-	return cpuidle_register(&armada_370_xp_idle_driver, NULL);
+	mvebu_v7_cpu_suspend = pdev->dev.platform_data;
+	return cpuidle_register(&armadaxp_idle_driver, NULL);
 }
 
-static struct platform_driver armada_370_xp_cpuidle_plat_driver = {
+static struct platform_driver armadaxp_cpuidle_plat_driver = {
 	.driver = {
-		.name = "cpuidle-armada-370-xp",
+		.name = "cpuidle-armada-xp",
 		.owner = THIS_MODULE,
 	},
-	.probe = armada_370_xp_cpuidle_probe,
+	.probe = mvebu_v7_cpuidle_probe,
 };
 
-module_platform_driver(armada_370_xp_cpuidle_plat_driver);
+module_platform_driver(armadaxp_cpuidle_plat_driver);
 
 MODULE_AUTHOR("Gregory CLEMENT <[email protected]>");
-MODULE_DESCRIPTION("Armada 370/XP cpu idle driver");
+MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
 MODULE_LICENSE("GPL");
Signature · 1 line
2.0.0
#12 lore raw

PATCH v3 11/16 cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7

Quoted 7 lines · Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

This driver will be able to manage the cpuidle for more SoCs than just Armada 370 and XP. It will also support Armada 38x and potentially other SoC of the Marvell Armada EBU family. To take this into account, this patch renames the driver and its symbols.

Quoted 8 lines

It also changes the driver name from cpuidle-armada-370-xp to cpuidle-armada-xp, because separate platform drivers will be registered for the other SoC types. This change must be done simultaneously in the cpuidle driver and in the PMSU code in order to remain bisectable.

Quoted 160 lines
---
  arch/arm/mach-mvebu/pmsu.c                         |  2 +-
  drivers/cpuidle/Kconfig.arm                        | 12 +++----
  drivers/cpuidle/Makefile                           |  2 +-
  ...{cpuidle-armada-370-xp.c => cpuidle-mvebu-v7.c} | 39 +++++++++++-----------
  4 files changed, 27 insertions(+), 28 deletions(-)

rename drivers/cpuidle/{cpuidle-armada-370-xp.c => cpuidle-mvebu-v7.c} (58%)

arch/arm/mach-mvebu/pmsu.c +1 -1
index 15e67bf..0cd2d09 100644
@@ -76,7 +76,7 @@ extern void armada_370_xp_cpu_resume(void);
  static void *mvebu_cpu_resume;
 
  static struct platform_device mvebu_v7_cpuidle_device = {
-	.name = "cpuidle-armada-370-xp",
+	.name = "cpuidle-armada-xp",
  };
 
  static struct of_device_id of_pmsu_table[] = {
drivers/cpuidle/Kconfig.arm +6 -6
index b6d69e8..a563427 100644
@@ -1,12 +1,6 @@
  #
  # ARM CPU Idle drivers
  #
-config ARM_ARMADA_370_XP_CPUIDLE
-	bool "CPU Idle Driver for Armada 370/XP family processors"
-	depends on ARCH_MVEBU
-	help
-	  Select this to enable cpuidle on Armada 370/XP processors.
-
  config ARM_BIG_LITTLE_CPUIDLE
  	bool "Support for ARM big.LITTLE processors"
  	depends on ARCH_VEXPRESS_TC2_PM
@@ -61,3 +55,9 @@ config ARM_EXYNOS_CPUIDLE
  	depends on ARCH_EXYNOS
  	help
  	  Select this to enable cpuidle for Exynos processors
+
+config ARM_MVEBU_V7_CPUIDLE
+	bool "CPU Idle Driver for mvebu v7 family processors"
+	depends on ARCH_MVEBU
+	help
+	  Select this to enable cpuidle on Armada 370, 38x and XP processors.
drivers/cpuidle/Makefile +1 -1
index d8bb1ff..11edb31 100644
@@ -7,7 +7,7 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
 
  ##################################################################################
  # ARM SoC drivers
-obj-$(CONFIG_ARM_ARMADA_370_XP_CPUIDLE) += cpuidle-armada-370-xp.o
+obj-$(CONFIG_ARM_MVEBU_V7_CPUIDLE) += cpuidle-mvebu-v7.o
  obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE)	+= cpuidle-big_little.o
  obj-$(CONFIG_ARM_CLPS711X_CPUIDLE)	+= cpuidle-clps711x.o
  obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE)	+= cpuidle-calxeda.o
drivers/cpuidle/cpuidle-mvebu-v7.c renamed from drivers/cpuidle/cpuidle-armada-370-xp.c +19 -20
similarity index 58%
rename from drivers/cpuidle/cpuidle-armada-370-xp.c
rename to drivers/cpuidle/cpuidle-mvebu-v7.c
index 28587d0..7252fd8 100644
@@ -21,12 +21,11 @@
  #include <linux/platform_device.h>
  #include <asm/cpuidle.h>
 
-#define ARMADA_370_XP_MAX_STATES	3
-#define ARMADA_370_XP_FLAG_DEEP_IDLE	0x10000
+#define MVEBU_V7_FLAG_DEEP_IDLE	0x10000
 
-static int (*armada_370_xp_cpu_suspend)(int);
+static int (*mvebu_v7_cpu_suspend)(int);
 
-static int armada_370_xp_enter_idle(struct cpuidle_device *dev,
+static int mvebu_v7_enter_idle(struct cpuidle_device *dev,
  				struct cpuidle_driver *drv,
  				int index)
  {
@@ -34,10 +33,10 @@ static int armada_370_xp_enter_idle(struct cpuidle_device *dev,
  	bool deepidle = false;
  	cpu_pm_enter();
 
-	if (drv->states[index].flags & ARMADA_370_XP_FLAG_DEEP_IDLE)
+	if (drv->states[index].flags & MVEBU_V7_FLAG_DEEP_IDLE)
  		deepidle = true;
 
-	ret = armada_370_xp_cpu_suspend(deepidle);
+	ret = mvebu_v7_cpu_suspend(deepidle);
  	if (ret)
  		return ret;
 
@@ -46,11 +45,11 @@ static int armada_370_xp_enter_idle(struct cpuidle_device *dev,
  	return index;
  }
 
-static struct cpuidle_driver armada_370_xp_idle_driver = {
-	.name			= "armada_370_xp_idle",
+static struct cpuidle_driver armadaxp_idle_driver = {
+	.name			= "armada_xp_idle",
  	.states[0]		= ARM_CPUIDLE_WFI_STATE,
  	.states[1]		= {
-		.enter			= armada_370_xp_enter_idle,
+		.enter			= mvebu_v7_enter_idle,
  		.exit_latency		= 10,
  		.power_usage		= 50,
  		.target_residency	= 100,
@@ -59,35 +58,35 @@ static struct cpuidle_driver armada_370_xp_idle_driver = {
  		.desc			= "CPU power down",
  	},
  	.states[2]		= {
-		.enter			= armada_370_xp_enter_idle,
+		.enter			= mvebu_v7_enter_idle,
  		.exit_latency		= 100,
  		.power_usage		= 5,
  		.target_residency	= 1000,
  		.flags			= CPUIDLE_FLAG_TIME_VALID |
-						ARMADA_370_XP_FLAG_DEEP_IDLE,
+						MVEBU_V7_FLAG_DEEP_IDLE,
  		.name			= "MV CPU DEEP IDLE",
  		.desc			= "CPU and L2 Fabric power down",
  	},
-	.state_count = ARMADA_370_XP_MAX_STATES,
+	.state_count = 3,
  };
 
-static int armada_370_xp_cpuidle_probe(struct platform_device *pdev)
+static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
  {
 
-	armada_370_xp_cpu_suspend = (void *)(pdev->dev.platform_data);
-	return cpuidle_register(&armada_370_xp_idle_driver, NULL);
+	mvebu_v7_cpu_suspend = pdev->dev.platform_data;
+	return cpuidle_register(&armadaxp_idle_driver, NULL);
  }
 
-static struct platform_driver armada_370_xp_cpuidle_plat_driver = {
+static struct platform_driver armadaxp_cpuidle_plat_driver = {
  	.driver = {
-		.name = "cpuidle-armada-370-xp",
+		.name = "cpuidle-armada-xp",
  		.owner = THIS_MODULE,
  	},
-	.probe = armada_370_xp_cpuidle_probe,
+	.probe = mvebu_v7_cpuidle_probe,
  };
 
-module_platform_driver(armada_370_xp_cpuidle_plat_driver);
+module_platform_driver(armadaxp_cpuidle_plat_driver);
 
  MODULE_AUTHOR("Gregory CLEMENT <[email protected]>");
-MODULE_DESCRIPTION("Armada 370/XP cpu idle driver");
+MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
  MODULE_LICENSE("GPL");
Signature · 5 lines
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
#13 lore raw

PATCH v3 11/16 cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7

Quoted 14 lines · Daniel Lezcano
Quoted 13 lines · Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

This driver will be able to manage the cpuidle for more SoCs than just Armada 370 and XP. It will also support Armada 38x and potentially other SoC of the Marvell Armada EBU family. To take this into account, this patch renames the driver and its symbols.

It also changes the driver name from cpuidle-armada-370-xp to cpuidle-armada-xp, because separate platform drivers will be registered for the other SoC types. This change must be done simultaneously in the cpuidle driver and in the PMSU code in order to remain bisectable.

Quoted 4 lines
Quoted 2 lines

Thanks for getting on top of this so quickly after returning from vacation!

thx,

Jason.

#14 lore raw

PATCH v3 12/16 cpuidle: mvebu: add Armada 370 support

In reply to Thomas Petazzoni

This commit adds the list of cpuidle states supported by the Armada 370 SoC in the cpuidle-mvebu-v7 driver, as well as the necessary logic around it to support this SoC.

---
 drivers/cpuidle/cpuidle-mvebu-v7.c | 35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)
drivers/cpuidle/cpuidle-mvebu-v7.c +33 -2
index 7252fd8..d23597f 100644
@@ -70,11 +70,32 @@ static struct cpuidle_driver armadaxp_idle_driver = {
 	.state_count = 3,
 };
 
+static struct cpuidle_driver armada370_idle_driver = {
+	.name			= "armada_370_idle",
+	.states[0]		= ARM_CPUIDLE_WFI_STATE,
+	.states[1]		= {
+		.enter			= mvebu_v7_enter_idle,
+		.exit_latency		= 100,
+		.power_usage		= 5,
+		.target_residency	= 1000,
+		.flags			= (CPUIDLE_FLAG_TIME_VALID |
+					   MVEBU_V7_FLAG_DEEP_IDLE),
+		.name			= "Deep Idle",
+		.desc			= "CPU and L2 Fabric power down",
+	},
+	.state_count = 2,
+};
+
 static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
 {
-
 	mvebu_v7_cpu_suspend = pdev->dev.platform_data;
-	return cpuidle_register(&armadaxp_idle_driver, NULL);
+
+	if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-xp"))
+		return cpuidle_register(&armadaxp_idle_driver, NULL);
+	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-370"))
+		return cpuidle_register(&armada370_idle_driver, NULL);
+	else
+		return -EINVAL;
 }
 
 static struct platform_driver armadaxp_cpuidle_plat_driver = {
@@ -87,6 +108,16 @@ static struct platform_driver armadaxp_cpuidle_plat_driver = {
 
 module_platform_driver(armadaxp_cpuidle_plat_driver);
 
+static struct platform_driver armada370_cpuidle_plat_driver = {
+	.driver = {
+		.name = "cpuidle-armada-370",
+		.owner = THIS_MODULE,
+	},
+	.probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armada370_cpuidle_plat_driver);
+
 MODULE_AUTHOR("Gregory CLEMENT <[email protected]>");
 MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
 MODULE_LICENSE("GPL");
Signature · 1 line
2.0.0
#15 lore raw

PATCH v3 12/16 cpuidle: mvebu: add Armada 370 support

Quoted 5 lines · Thomas Petazzoni

This commit adds the list of cpuidle states supported by the Armada 370 SoC in the cpuidle-mvebu-v7 driver, as well as the necessary logic around it to support this SoC.

Quoted 61 lines
---
  drivers/cpuidle/cpuidle-mvebu-v7.c | 35 +++++++++++++++++++++++++++++++++--
  1 file changed, 33 insertions(+), 2 deletions(-)
drivers/cpuidle/cpuidle-mvebu-v7.c +33 -2
index 7252fd8..d23597f 100644
@@ -70,11 +70,32 @@ static struct cpuidle_driver armadaxp_idle_driver = {
  	.state_count = 3,
  };
 
+static struct cpuidle_driver armada370_idle_driver = {
+	.name			= "armada_370_idle",
+	.states[0]		= ARM_CPUIDLE_WFI_STATE,
+	.states[1]		= {
+		.enter			= mvebu_v7_enter_idle,
+		.exit_latency		= 100,
+		.power_usage		= 5,
+		.target_residency	= 1000,
+		.flags			= (CPUIDLE_FLAG_TIME_VALID |
+					   MVEBU_V7_FLAG_DEEP_IDLE),
+		.name			= "Deep Idle",
+		.desc			= "CPU and L2 Fabric power down",
+	},
+	.state_count = 2,
+};
+
  static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
  {
-
  	mvebu_v7_cpu_suspend = pdev->dev.platform_data;
-	return cpuidle_register(&armadaxp_idle_driver, NULL);
+
+	if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-xp"))
+		return cpuidle_register(&armadaxp_idle_driver, NULL);
+	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-370"))
+		return cpuidle_register(&armada370_idle_driver, NULL);
+	else
+		return -EINVAL;
  }
 
  static struct platform_driver armadaxp_cpuidle_plat_driver = {
@@ -87,6 +108,16 @@ static struct platform_driver armadaxp_cpuidle_plat_driver = {
 
  module_platform_driver(armadaxp_cpuidle_plat_driver);
 
+static struct platform_driver armada370_cpuidle_plat_driver = {
+	.driver = {
+		.name = "cpuidle-armada-370",
+		.owner = THIS_MODULE,
+	},
+	.probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armada370_cpuidle_plat_driver);
+
  MODULE_AUTHOR("Gregory CLEMENT <[email protected]>");
  MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
  MODULE_LICENSE("GPL");
Signature · 5 lines
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
#16 lore raw

PATCH v3 13/16 cpuidle: mvebu: add Armada 38x support

In reply to Thomas Petazzoni

This commit adds the list of cpuidle states supported by the Armada 38x SoC in the cpuidle-mvebu-v7 driver, as well as the necessary logic around it to support this SoC.

---
 drivers/cpuidle/cpuidle-mvebu-v7.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)
drivers/cpuidle/cpuidle-mvebu-v7.c +28 -1
index d23597f..45371bb 100644
@@ -1,5 +1,5 @@
 /*
- * Marvell Armada 370 and Armada XP SoC cpuidle driver
+ * Marvell Armada 370, 38x and XP SoC cpuidle driver
  *
  * Copyright (C) 2014 Marvell
  *
@@ -86,6 +86,21 @@ static struct cpuidle_driver armada370_idle_driver = {
 	.state_count = 2,
 };
 
+static struct cpuidle_driver armada38x_idle_driver = {
+	.name			= "armada_38x_idle",
+	.states[0]		= ARM_CPUIDLE_WFI_STATE,
+	.states[1]		= {
+		.enter			= mvebu_v7_enter_idle,
+		.exit_latency		= 10,
+		.power_usage		= 5,
+		.target_residency	= 100,
+		.flags			= CPUIDLE_FLAG_TIME_VALID,
+		.name			= "Idle",
+		.desc			= "CPU and SCU power down",
+	},
+	.state_count = 2,
+};
+
 static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
 {
 	mvebu_v7_cpu_suspend = pdev->dev.platform_data;
@@ -94,6 +109,8 @@ static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
 		return cpuidle_register(&armadaxp_idle_driver, NULL);
 	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-370"))
 		return cpuidle_register(&armada370_idle_driver, NULL);
+	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-38x"))
+		return cpuidle_register(&armada38x_idle_driver, NULL);
 	else
 		return -EINVAL;
 }
@@ -118,6 +135,16 @@ static struct platform_driver armada370_cpuidle_plat_driver = {
 
 module_platform_driver(armada370_cpuidle_plat_driver);
 
+static struct platform_driver armada38x_cpuidle_plat_driver = {
+	.driver = {
+		.name = "cpuidle-armada-38x",
+		.owner = THIS_MODULE,
+	},
+	.probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armada38x_cpuidle_plat_driver);
+
 MODULE_AUTHOR("Gregory CLEMENT <[email protected]>");
 MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
 MODULE_LICENSE("GPL");
Signature · 1 line
2.0.0
#17 lore raw

PATCH v3 13/16 cpuidle: mvebu: add Armada 38x support

Quoted 5 lines · Thomas Petazzoni

This commit adds the list of cpuidle states supported by the Armada 38x SoC in the cpuidle-mvebu-v7 driver, as well as the necessary logic around it to support this SoC.

Quoted 64 lines
---
  drivers/cpuidle/cpuidle-mvebu-v7.c | 29 ++++++++++++++++++++++++++++-
  1 file changed, 28 insertions(+), 1 deletion(-)
drivers/cpuidle/cpuidle-mvebu-v7.c +28 -1
index d23597f..45371bb 100644
@@ -1,5 +1,5 @@
  /*
- * Marvell Armada 370 and Armada XP SoC cpuidle driver
+ * Marvell Armada 370, 38x and XP SoC cpuidle driver
   *
   * Copyright (C) 2014 Marvell
   *
@@ -86,6 +86,21 @@ static struct cpuidle_driver armada370_idle_driver = {
  	.state_count = 2,
  };
 
+static struct cpuidle_driver armada38x_idle_driver = {
+	.name			= "armada_38x_idle",
+	.states[0]		= ARM_CPUIDLE_WFI_STATE,
+	.states[1]		= {
+		.enter			= mvebu_v7_enter_idle,
+		.exit_latency		= 10,
+		.power_usage		= 5,
+		.target_residency	= 100,
+		.flags			= CPUIDLE_FLAG_TIME_VALID,
+		.name			= "Idle",
+		.desc			= "CPU and SCU power down",
+	},
+	.state_count = 2,
+};
+
  static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
  {
  	mvebu_v7_cpu_suspend = pdev->dev.platform_data;
@@ -94,6 +109,8 @@ static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
  		return cpuidle_register(&armadaxp_idle_driver, NULL);
  	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-370"))
  		return cpuidle_register(&armada370_idle_driver, NULL);
+	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-38x"))
+		return cpuidle_register(&armada38x_idle_driver, NULL);
  	else
  		return -EINVAL;
  }
@@ -118,6 +135,16 @@ static struct platform_driver armada370_cpuidle_plat_driver = {
 
  module_platform_driver(armada370_cpuidle_plat_driver);
 
+static struct platform_driver armada38x_cpuidle_plat_driver = {
+	.driver = {
+		.name = "cpuidle-armada-38x",
+		.owner = THIS_MODULE,
+	},
+	.probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armada38x_cpuidle_plat_driver);
+
  MODULE_AUTHOR("Gregory CLEMENT <[email protected]>");
  MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
  MODULE_LICENSE("GPL");
Signature · 5 lines
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
#18 lore raw

PATCH v3 14/16 ARM: mvebu: add cpuidle support for Armada 370

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

This commit introduces the cpuidle support for Armada 370. The main difference compared to the already supported Armada XP is that the Armada 370 has an issue caused by "a slow exit process from the deep idle state due to heavy L1/L2 cache cleanup operations performed by the BootROM software" (cf errata GL-BootROM-10).

To work around this issue, we replace the restart code of the BootROM by some custom code located in an internal SRAM. For this purpose, we use the common function mvebu_boot_addr_wa() introduced in the commit "ARM: mvebu: Add a common function for the boot address work around".

The message in case of failure to suspend the system was switched from the warn level to the debug level. Indeed due to the "slow exit process from the deep idle state" in Armada 370, this situation happens quite often. Using the debug level avoids spamming the kernel logs, but still allows to enable it if needed.

---
 arch/arm/mach-mvebu/pmsu.c | 51 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 7 deletions(-)
arch/arm/mach-mvebu/pmsu.c +44 -7
index 0cd2d09..9190ae8 100644
@@ -34,7 +34,6 @@
 #include <asm/tlbflush.h>
 #include "common.h"
 
-static void __iomem *pmsu_mp_base;
 
 #define PMSU_BASE_OFFSET    0x100
 #define PMSU_REG_SIZE	    0x1000
@@ -68,17 +67,18 @@ static void __iomem *pmsu_mp_base;
 #define BOOTROM_BASE    0xFFF00000
 #define BOOTROM_SIZE    0x100000
 
+#define ARMADA_370_CRYPT0_ENG_TARGET   0x9
+#define ARMADA_370_CRYPT0_ENG_ATTR     0x1
+
 extern void ll_disable_coherency(void);
 extern void ll_enable_coherency(void);
 
 extern void armada_370_xp_cpu_resume(void);
+static phys_addr_t pmsu_mp_phys_base;
+static void __iomem *pmsu_mp_base;
 
 static void *mvebu_cpu_resume;
 
-static struct platform_device mvebu_v7_cpuidle_device = {
-	.name = "cpuidle-armada-xp",
-};
-
 static struct of_device_id of_pmsu_table[] = {
 	{ .compatible = "marvell,armada-370-pmsu", },
 	{ .compatible = "marvell,armada-370-xp-pmsu", },
@@ -165,6 +165,8 @@ static int __init mvebu_v7_pmsu_init(void)
 		goto out;
 	}
 
+	pmsu_mp_phys_base = res.start;
+
 	pmsu_mp_base = ioremap(res.start, resource_size(&res));
 	if (!pmsu_mp_base) {
 		pr_err("unable to map registers\n");
@@ -275,7 +277,7 @@ int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
 	"isb	"
 	: : : "r0");
 
-	pr_warn("Failed to suspend the system\n");
+	pr_debug("Failed to suspend the system\n");
 
 	return 0;
 }
@@ -325,7 +327,39 @@ static struct notifier_block mvebu_v7_cpu_pm_notifier = {
 	.notifier_call = mvebu_v7_cpu_pm_notify,
 };
 
-static int __init armada_xp_cpuidle_init(void)
+static struct platform_device mvebu_v7_cpuidle_device;
+
+static __init int armada_370_cpuidle_init(void)
+{
+	struct device_node *np;
+	phys_addr_t redirect_reg;
+
+	np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
+	if (!np)
+		return -ENODEV;
+	of_node_put(np);
+
+	/*
+	 * On Armada 370, there is "a slow exit process from the deep
+	 * idle state due to heavy L1/L2 cache cleanup operations
+	 * performed by the BootROM software". To avoid this, we
+	 * replace the restart code of the bootrom by a a simple jump
+	 * to the boot address. Then the code located at this boot
+	 * address will take care of the initialization.
+	 */
+	redirect_reg = pmsu_mp_phys_base + PMSU_BOOT_ADDR_REDIRECT_OFFSET(0);
+	mvebu_setup_boot_addr_wa(ARMADA_370_CRYPT0_ENG_TARGET,
+				 ARMADA_370_CRYPT0_ENG_ATTR,
+				 redirect_reg);
+
+	mvebu_cpu_resume = armada_370_xp_cpu_resume;
+	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
+	mvebu_v7_cpuidle_device.name = "cpuidle-armada-370";
+
+	return 0;
+}
+
+static __init int armada_xp_cpuidle_init(void)
 {
 	struct device_node *np;
 
@@ -336,6 +370,7 @@ static int __init armada_xp_cpuidle_init(void)
 
 	mvebu_cpu_resume = armada_370_xp_cpu_resume;
 	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
+	mvebu_v7_cpuidle_device.name = "cpuidle-armada-xp";
 
 	return 0;
 }
@@ -352,6 +387,8 @@ static int __init mvebu_v7_cpu_pm_init(void)
 
 	if (of_machine_is_compatible("marvell,armadaxp"))
 		ret = armada_xp_cpuidle_init();
+	else if (of_machine_is_compatible("marvell,armada370"))
+		ret = armada_370_cpuidle_init();
 	else
 		return 0;
 
Signature · 1 line
2.0.0
#19 lore raw

PATCH v3 15/16 ARM: mvebu: add cpuidle support for Armada 38x

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

Unlike the Armada XP and the Armada 370, this SoC uses a Cortex A9 core. Consequently, the procedure to enter the idle state is
different: interaction with the SCU, not disabling snooping, etc.

---
 arch/arm/mach-mvebu/pmsu.c    | 85 ++++++++++++++++++++++++++++++++++++++++++-
 arch/arm/mach-mvebu/pmsu_ll.S | 14 +++++++
 2 files changed, 98 insertions(+), 1 deletion(-)
arch/arm/mach-mvebu/pmsu.c +84 -1
index 9190ae8..bd7c66a 100644
@@ -29,6 +29,7 @@
 #include <linux/smp.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
+#include <asm/smp_scu.h>
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 #include <asm/tlbflush.h>
@@ -63,6 +64,18 @@
 #define L2C_NFABRIC_PM_CTL		    0x4
 #define L2C_NFABRIC_PM_CTL_PWR_DOWN		BIT(20)
 
+/* PMSU delay registers */
+#define PMSU_POWERDOWN_DELAY		    0xF04
+#define PMSU_POWERDOWN_DELAY_PMU		BIT(1)
+#define PMSU_POWERDOWN_DELAY_MASK		0xFFFE
+#define PMSU_DFLT_ARMADA38X_DELAY	        0x64
+
+/* CA9 MPcore SoC Control registers */
+
+#define MPCORE_RESET_CTL		    0x64
+#define MPCORE_RESET_CTL_L2			BIT(0)
+#define MPCORE_RESET_CTL_DEBUG			BIT(16)
+
 #define SRAM_PHYS_BASE  0xFFFF0000
 #define BOOTROM_BASE    0xFFF00000
 #define BOOTROM_SIZE    0x100000
@@ -74,6 +87,8 @@ extern void ll_disable_coherency(void);
 extern void ll_enable_coherency(void);
 
 extern void armada_370_xp_cpu_resume(void);
+extern void armada_38x_cpu_resume(void);
+
 static phys_addr_t pmsu_mp_phys_base;
 static void __iomem *pmsu_mp_base;
 
@@ -287,6 +302,32 @@ static int armada_370_xp_cpu_suspend(unsigned long deepidle)
 	return cpu_suspend(deepidle, armada_370_xp_pmsu_idle_enter);
 }
 
+static int armada_38x_do_cpu_suspend(unsigned long deepidle)
+{
+	unsigned long flags = 0;
+
+	if (deepidle)
+		flags |= PMSU_PREPARE_DEEP_IDLE;
+
+	mvebu_v7_pmsu_idle_prepare(flags);
+	/*
+	 * Already flushed cache, but do it again as the outer cache
+	 * functions dirty the cache with spinlocks
+	 */
+	v7_exit_coherency_flush(louis);
+
+	scu_power_mode(mvebu_get_scu_base(), SCU_PM_POWEROFF);
+
+	cpu_do_idle();
+
+	return 1;
+}
+
+static int armada_38x_cpu_suspend(unsigned long deepidle)
+{
+	return cpu_suspend(false, armada_38x_do_cpu_suspend);
+}
+
 /* No locking is needed because we only access per-CPU registers */
 void mvebu_v7_pmsu_idle_exit(void)
 {
@@ -295,7 +336,6 @@ void mvebu_v7_pmsu_idle_exit(void)
 
 	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;
@@ -359,6 +399,47 @@ static __init int armada_370_cpuidle_init(void)
 	return 0;
 }
 
+static __init int armada_38x_cpuidle_init(void)
+{
+	struct device_node *np;
+	void __iomem *mpsoc_base;
+	u32 reg;
+
+	np = of_find_compatible_node(NULL, NULL,
+				     "marvell,armada-380-coherency-fabric");
+	if (!np)
+		return -ENODEV;
+	of_node_put(np);
+
+	np = of_find_compatible_node(NULL, NULL,
+				     "marvell,armada-380-mpcore-soc-ctrl");
+	if (!np)
+		return -ENODEV;
+	mpsoc_base = of_iomap(np, 0);
+	BUG_ON(!mpsoc_base);
+	of_node_put(np);
+
+	/* Set up reset mask when powering down the cpus */
+	reg = readl(mpsoc_base + MPCORE_RESET_CTL);
+	reg |= MPCORE_RESET_CTL_L2;
+	reg |= MPCORE_RESET_CTL_DEBUG;
+	writel(reg, mpsoc_base + MPCORE_RESET_CTL);
+	iounmap(mpsoc_base);
+
+	/* Set up delay */
+	reg = readl(pmsu_mp_base + PMSU_POWERDOWN_DELAY);
+	reg &= ~PMSU_POWERDOWN_DELAY_MASK;
+	reg |= PMSU_DFLT_ARMADA38X_DELAY;
+	reg |= PMSU_POWERDOWN_DELAY_PMU;
+	writel(reg, pmsu_mp_base + PMSU_POWERDOWN_DELAY);
+
+	mvebu_cpu_resume = armada_38x_cpu_resume;
+	mvebu_v7_cpuidle_device.dev.platform_data = armada_38x_cpu_suspend;
+	mvebu_v7_cpuidle_device.name = "cpuidle-armada-38x";
+
+	return 0;
+}
+
 static __init int armada_xp_cpuidle_init(void)
 {
 	struct device_node *np;
@@ -389,6 +470,8 @@ static int __init mvebu_v7_cpu_pm_init(void)
 		ret = armada_xp_cpuidle_init();
 	else if (of_machine_is_compatible("marvell,armada370"))
 		ret = armada_370_cpuidle_init();
+	else if (of_machine_is_compatible("marvell,armada380"))
+		ret = armada_38x_cpuidle_init();
 	else
 		return 0;
 
arch/arm/mach-mvebu/pmsu_ll.S +14 -0
index 17d7f3b..a945756 100644
@@ -23,6 +23,20 @@ ARM_BE8(setend	be )			@ go BE8 if entered LE
 	b	cpu_resume
 ENDPROC(armada_370_xp_cpu_resume)
 
+ENTRY(armada_38x_cpu_resume)
+	/* do we need it for Armada 38x*/
+ARM_BE8(setend	be )			@ go BE8 if entered LE
+	bl	v7_invalidate_l1
+	mrc     p15, 4, r1, c15, c0	@ get SCU base address
+	orr	r1, r1, #0x8		@ SCU CPU Power Status Register
+	mrc	15, 0, r0, cr0, cr0, 5	@ get the CPU ID
+	and	r0, r0, #15
+	add	r1, r1, r0
+	mov	r0, #0x0
+	strb	r0, [r1]		@ switch SCU power state to Normal mode
+	b	cpu_resume
+ENDPROC(armada_38x_cpu_resume)
+
 .global mvebu_boot_wa_start
 .global mvebu_boot_wa_end
 
Signature · 1 line
2.0.0
#20 lore raw

PATCH v3 16/16 ARM: mvebu: defconfig: enable cpuidle support in mvebu_v7_defconfig

In reply to Thomas Petazzoni

From: Gregory CLEMENT <[email protected]>

The Marvell EBU SoCs such as Armada 370, Armada XP or Armada 38x now support cpuidle, so this commit enables the appropriate Kconfig options in mvebu_v7_defconfig.

---
 arch/arm/configs/mvebu_v7_defconfig | 2 ++
 1 file changed, 2 insertions(+)
arch/arm/configs/mvebu_v7_defconfig +2 -0
index e11170e..b174072 100644
@@ -28,6 +28,8 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_MVEBU_V7_CPUIDLE=y
 CONFIG_VFP=y
 CONFIG_NET=y
 CONFIG_INET=y
Signature · 1 line
2.0.0
#21 lore raw

v3 cover cpuidle for Marvell Armada 370 and 38x

In reply to Thomas Petazzoni

Thomas, all,

Quoted 33 lines · Thomas Petazzoni

Hello,

Here comes the third version of the cpuidle support for Armada 370 and Armada 38x.

We are hoping to see this patch series merged for 3.17.

Most patches are touching only arch/arm/mach-mvebu/ code so they should be handled by the mvebu maintainers. However, patches 11-13 are touching the mvebu cpuidle driver, with a possible issue on patch 11, which touches both the cpuidle driver and the mach-mvebu code in order to rename the driver without breaking functionality (if needed, we can decide to split the commits, it would break functionality temporarly, but not buildability).

Changes since v2
================

* According to the discussion with Daniel Lezcano (cpuidle maintainer) and Arnd Bergmann, changed the cpuidle-mvebu-v7 driver to actually register three separate cpuidle platform driver, one per-SoC. This way, we don't need special platform data to convey the SoC type being used, as this information is already available by looking at the driver name.

This change impacts the patches "cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7", "cpuidle: mvebu: add Armada 370 support", "cpuidle: mvebu: add Armada 38x support", "ARM: mvebu:
add cpuidle support for Armada 370" and "ARM: mvebu: add cpuidle support for Armada 38x". Other patches are unchanged. The patch "cpuidle: mvebu: make the cpuidle driver capable of handling multiple SoCs" was no longer needed, so it has been removed.

...

Quoted 34 lines

Gregory CLEMENT (14):
ARM: mvebu: split again armada_370_xp_pmsu_idle_enter() in PMSU code
ARM: mvebu: sort the #include of pmsu.c in alphabetic order
ARM: mvebu: add a common function for the boot address work around
ARM: mvebu: use the common function for Armada 375 SMP workaround
ARM: mvebu: rename the armada_370_xp symbols to mvebu_v7 in pmsu.c
ARM: mvebu: make the cpuidle initialization more generic
ARM: mvebu: use a local variable to store the resume address
ARM: mvebu: make the snoop disabling optional in
mvebu_v7_pmsu_idle_prepare()
ARM: mvebu: export the SCU address
ARM: mvebu: add CA9 MPcore SoC Controller node
cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7
ARM: mvebu: add cpuidle support for Armada 370
ARM: mvebu: add cpuidle support for Armada 38x
ARM: mvebu: defconfig: enable cpuidle support in mvebu_v7_defconfig

Thomas Petazzoni (2):
cpuidle: mvebu: add Armada 370 support
cpuidle: mvebu: add Armada 38x support

 .../bindings/arm/armada-380-mpcore-soc-ctrl.txt    |  14 ++
 arch/arm/boot/dts/armada-38x.dtsi                  |   5 +
 arch/arm/configs/mvebu_v7_defconfig                |   2 +
 arch/arm/mach-mvebu/armada-370-xp.h                |   1 -
 arch/arm/mach-mvebu/board-v7.c                     |   9 +-
 arch/arm/mach-mvebu/common.h                       |   2 +
 arch/arm/mach-mvebu/headsmp-a9.S                   |  15 --
 arch/arm/mach-mvebu/platsmp-a9.c                   |  42 +---
 arch/arm/mach-mvebu/platsmp.c                      |   2 +-
 arch/arm/mach-mvebu/pmsu.c                         | 273 ++++++++++++++++++---
 arch/arm/mach-mvebu/pmsu.h                         |   5 +
 arch/arm/mach-mvebu/pmsu_ll.S                      |  36 +++
 arch/arm/mach-mvebu/system-controller.c            |  31 +++
Quoted 8 lines
 drivers/cpuidle/Kconfig.arm                        |  12 +-
 drivers/cpuidle/Makefile                           |   2 +-
 drivers/cpuidle/cpuidle-armada-370-xp.c            |  93 -------
 drivers/cpuidle/cpuidle-mvebu-v7.c                 | 150 +++++++++++
 17 files changed, 500 insertions(+), 194 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt
 delete mode 100644 drivers/cpuidle/cpuidle-armada-370-xp.c
 create mode 100644 drivers/cpuidle/cpuidle-mvebu-v7.c

Whole series, except 10 (went to mvebu/dt), and 16 (went to mvebu/defconfig) applied to mvebu/soc-cpuidle. Patches 11 to 13 applied with Daniel's Ack.

It'll be in -next tonight.

thx,

Jason.

#22 lore raw

v3 cover cpuidle for Marvell Armada 370 and 38x

Dear Jason Cooper,

Quoted 22 lines · Jason Cooper
Quoted 13 lines
 .../bindings/arm/armada-380-mpcore-soc-ctrl.txt    |  14 ++
 arch/arm/boot/dts/armada-38x.dtsi                  |   5 +
 arch/arm/configs/mvebu_v7_defconfig                |   2 +
 arch/arm/mach-mvebu/armada-370-xp.h                |   1 -
 arch/arm/mach-mvebu/board-v7.c                     |   9 +-
 arch/arm/mach-mvebu/common.h                       |   2 +
 arch/arm/mach-mvebu/headsmp-a9.S                   |  15 --
 arch/arm/mach-mvebu/platsmp-a9.c                   |  42 +---
 arch/arm/mach-mvebu/platsmp.c                      |   2 +-
 arch/arm/mach-mvebu/pmsu.c                         | 273 ++++++++++++++++++---
 arch/arm/mach-mvebu/pmsu.h                         |   5 +
 arch/arm/mach-mvebu/pmsu_ll.S                      |  36 +++
 arch/arm/mach-mvebu/system-controller.c            |  31 +++
Quoted 8 lines
 drivers/cpuidle/Kconfig.arm                        |  12 +-
 drivers/cpuidle/Makefile                           |   2 +-
 drivers/cpuidle/cpuidle-armada-370-xp.c            |  93 -------
 drivers/cpuidle/cpuidle-mvebu-v7.c                 | 150 +++++++++++
 17 files changed, 500 insertions(+), 194 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt
 delete mode 100644 drivers/cpuidle/cpuidle-armada-370-xp.c
 create mode 100644 drivers/cpuidle/cpuidle-mvebu-v7.c
Quoted 5 lines

Whole series, except 10 (went to mvebu/dt), and 16 (went to mvebu/defconfig) applied to mvebu/soc-cpuidle. Patches 11 to 13 applied with Daniel's Ack.

It'll be in -next tonight.

Great, thanks a lot!

Thomas

Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
#23 lore raw

v3 cover cpuidle for Marvell Armada 370 and 38x

In reply to Jason Cooper
Quoted 80 lines · Jason Cooper

Thomas, all,

Quoted 33 lines · Thomas Petazzoni

Hello,

Here comes the third version of the cpuidle support for Armada 370 and Armada 38x.

We are hoping to see this patch series merged for 3.17.

Most patches are touching only arch/arm/mach-mvebu/ code so they should be handled by the mvebu maintainers. However, patches 11-13 are touching the mvebu cpuidle driver, with a possible issue on patch 11, which touches both the cpuidle driver and the mach-mvebu code in order to rename the driver without breaking functionality (if needed, we can decide to split the commits, it would break functionality temporarly, but not buildability).

Changes since v2
================

* According to the discussion with Daniel Lezcano (cpuidle maintainer) and Arnd Bergmann, changed the cpuidle-mvebu-v7 driver to actually register three separate cpuidle platform driver, one per-SoC. This way, we don't need special platform data to convey the SoC type being used, as this information is already available by looking at the driver name.

This change impacts the patches "cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7", "cpuidle: mvebu: add Armada 370 support", "cpuidle: mvebu: add Armada 38x support", "ARM: mvebu:
add cpuidle support for Armada 370" and "ARM: mvebu: add cpuidle support for Armada 38x". Other patches are unchanged. The patch "cpuidle: mvebu: make the cpuidle driver capable of handling multiple SoCs" was no longer needed, so it has been removed.

...

Quoted 34 lines

Gregory CLEMENT (14):
ARM: mvebu: split again armada_370_xp_pmsu_idle_enter() in PMSU code
ARM: mvebu: sort the #include of pmsu.c in alphabetic order
ARM: mvebu: add a common function for the boot address work around
ARM: mvebu: use the common function for Armada 375 SMP workaround
ARM: mvebu: rename the armada_370_xp symbols to mvebu_v7 in pmsu.c
ARM: mvebu: make the cpuidle initialization more generic
ARM: mvebu: use a local variable to store the resume address
ARM: mvebu: make the snoop disabling optional in
mvebu_v7_pmsu_idle_prepare()
ARM: mvebu: export the SCU address
ARM: mvebu: add CA9 MPcore SoC Controller node
cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7
ARM: mvebu: add cpuidle support for Armada 370
ARM: mvebu: add cpuidle support for Armada 38x
ARM: mvebu: defconfig: enable cpuidle support in mvebu_v7_defconfig

Thomas Petazzoni (2):
cpuidle: mvebu: add Armada 370 support
cpuidle: mvebu: add Armada 38x support

 .../bindings/arm/armada-380-mpcore-soc-ctrl.txt    |  14 ++
 arch/arm/boot/dts/armada-38x.dtsi                  |   5 +
 arch/arm/configs/mvebu_v7_defconfig                |   2 +
 arch/arm/mach-mvebu/armada-370-xp.h                |   1 -
 arch/arm/mach-mvebu/board-v7.c                     |   9 +-
 arch/arm/mach-mvebu/common.h                       |   2 +
 arch/arm/mach-mvebu/headsmp-a9.S                   |  15 --
 arch/arm/mach-mvebu/platsmp-a9.c                   |  42 +---
 arch/arm/mach-mvebu/platsmp.c                      |   2 +-
 arch/arm/mach-mvebu/pmsu.c                         | 273 ++++++++++++++++++---
 arch/arm/mach-mvebu/pmsu.h                         |   5 +
 arch/arm/mach-mvebu/pmsu_ll.S                      |  36 +++
 arch/arm/mach-mvebu/system-controller.c            |  31 +++
Quoted 8 lines
 drivers/cpuidle/Kconfig.arm                        |  12 +-
 drivers/cpuidle/Makefile                           |   2 +-
 drivers/cpuidle/cpuidle-armada-370-xp.c            |  93 -------
 drivers/cpuidle/cpuidle-mvebu-v7.c                 | 150 +++++++++++
 17 files changed, 500 insertions(+), 194 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt
 delete mode 100644 drivers/cpuidle/cpuidle-armada-370-xp.c
 create mode 100644 drivers/cpuidle/cpuidle-mvebu-v7.c
Quoted 3 lines

Whole series, except 10 (went to mvebu/dt), and 16 (went to mvebu/defconfig) applied to mvebu/soc-cpuidle. Patches 11 to 13 applied with Daniel's Ack.

Now merged into mvebu/soc.

It's getting really close. I'll try to send out the pull request tomorrow am.

thx,

Jason.