[PATCHv2 12/17] cpuidle: mvebu: make the cpuidle driver capable of handling multiple SoCs
From: Thomas Petazzoni <hidden>
Date: 2014-07-09 13:40:16
Also in:
linux-pm
Subsystem:
arm port, arm/marvell kirkwood and armada 370, 375, 38x, 39x, xp, 3700, 7k/8k, cn9130 soc support, cpu idle time management framework, the rest · Maintainers:
Russell King, Andrew Lunn, Gregory Clement, Sebastian Hesselbarth, "Rafael J. Wysocki", Daniel Lezcano, Linus Torvalds
From: Gregory CLEMENT <redacted> In order to prepare the add of new SoCs supports for this cpuidle driver, this patch extends the platform_data understood by the cpuidle-mvebu-v7 driver to contain a "type" identifying which specific SoC the cpuidle driver is being probed for. It will be used by the cpuidle driver to know the list of states for the current SoC. Signed-off-by: Gregory CLEMENT <redacted> Signed-off-by: Thomas Petazzoni <redacted> --- arch/arm/mach-mvebu/pmsu.c | 20 +++++++++++++------- drivers/cpuidle/cpuidle-mvebu-v7.c | 32 ++++++++++++++++++++------------ include/linux/mvebu-v7-cpuidle.h | 26 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 include/linux/mvebu-v7-cpuidle.h
diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c
index 802edc8..0a24073 100644
--- a/arch/arm/mach-mvebu/pmsu.c
+++ b/arch/arm/mach-mvebu/pmsu.c@@ -19,10 +19,12 @@ #define pr_fmt(fmt) "mvebu-pmsu: " fmt #include <linux/cpu_pm.h> +#include <linux/cpuidle.h> #include <linux/init.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/mbus.h> +#include <linux/mvebu-v7-cpuidle.h> #include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/resource.h>
@@ -75,10 +77,6 @@ extern void armada_370_xp_cpu_resume(void); static void *mvebu_cpu_resume; -static struct platform_device mvebu_v7_cpuidle_device = { - .name = "cpuidle-mvebu-v7", -}; - static struct of_device_id of_pmsu_table[] = { { .compatible = "marvell,armada-370-pmsu", }, { .compatible = "marvell,armada-370-xp-pmsu", },
@@ -325,17 +323,25 @@ 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 mvebu_v7_cpuidle armada_xp_cpuidle = { + .type = CPUIDLE_ARMADA_XP, + .cpu_suspend = armada_370_xp_cpu_suspend, +}; + +static struct platform_device mvebu_v7_cpuidle_device = { + .name = "cpuidle-mvebu-v7", +}; + +static __init int armada_xp_cpuidle_init(void) { struct device_node *np; - np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"); if (!np) 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; + mvebu_v7_cpuidle_device.dev.platform_data = &armada_xp_cpuidle; return 0; }
diff --git a/drivers/cpuidle/cpuidle-mvebu-v7.c b/drivers/cpuidle/cpuidle-mvebu-v7.c
index 302596e..82c545bb 100644
--- a/drivers/cpuidle/cpuidle-mvebu-v7.c
+++ b/drivers/cpuidle/cpuidle-mvebu-v7.c@@ -16,15 +16,15 @@ #include <linux/cpu_pm.h> #include <linux/cpuidle.h> #include <linux/module.h> +#include <linux/mvebu-v7-cpuidle.h> #include <linux/of.h> #include <linux/suspend.h> #include <linux/platform_device.h> #include <asm/cpuidle.h> -#define MVEBU_V7_MAX_STATES 3 #define MVEBU_V7_FLAG_DEEP_IDLE 0x10000 -static int (*mvebu_v7_cpu_suspend)(int); +static struct mvebu_v7_cpuidle *pcpuidle; static int mvebu_v7_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv,
@@ -32,12 +32,13 @@ static int mvebu_v7_enter_idle(struct cpuidle_device *dev, { int ret; bool deepidle = false; + cpu_pm_enter(); if (drv->states[index].flags & MVEBU_V7_FLAG_DEEP_IDLE) deepidle = true; - ret = mvebu_v7_cpu_suspend(deepidle); + ret = pcpuidle->cpu_suspend(deepidle); if (ret) return ret;
@@ -46,8 +47,8 @@ static int mvebu_v7_enter_idle(struct cpuidle_device *dev, return index; } -static struct cpuidle_driver mvebu_v7_idle_driver = { - .name = "mvebu_v7_idle", +static struct cpuidle_driver armadaxp_cpuidle_driver = { + .name = "armada_xp_idle", .states[0] = ARM_CPUIDLE_WFI_STATE, .states[1] = { .enter = mvebu_v7_enter_idle,
@@ -55,7 +56,7 @@ static struct cpuidle_driver mvebu_v7_idle_driver = { .power_usage = 50, .target_residency = 100, .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "MV CPU IDLE", + .name = "Idle", .desc = "CPU power down", }, .states[2] = {
@@ -63,19 +64,26 @@ static struct cpuidle_driver mvebu_v7_idle_driver = { .exit_latency = 100, .power_usage = 5, .target_residency = 1000, - .flags = CPUIDLE_FLAG_TIME_VALID | - MVEBU_V7_FLAG_DEEP_IDLE, - .name = "MV CPU DEEP IDLE", + .flags = (CPUIDLE_FLAG_TIME_VALID | + MVEBU_V7_FLAG_DEEP_IDLE), + .name = "Deep idle", .desc = "CPU and L2 Fabric power down", }, - .state_count = MVEBU_V7_MAX_STATES, + .state_count = 3, }; static int mvebu_v7_cpuidle_probe(struct platform_device *pdev) { + struct cpuidle_driver *drv; + + pcpuidle = pdev->dev.platform_data; + + if (pcpuidle->type == CPUIDLE_ARMADA_XP) + drv = &armadaxp_cpuidle_driver; + else + return -EINVAL; - mvebu_v7_cpu_suspend = (void *)(pdev->dev.platform_data); - return cpuidle_register(&mvebu_v7_idle_driver, NULL); + return cpuidle_register(drv, NULL); } static struct platform_driver mvebu_v7_cpuidle_plat_driver = {
diff --git a/include/linux/mvebu-v7-cpuidle.h b/include/linux/mvebu-v7-cpuidle.h
new file mode 100644
index 0000000..00fde86
--- /dev/null
+++ b/include/linux/mvebu-v7-cpuidle.h@@ -0,0 +1,26 @@ +/* + * Marvell EBU cpuidle defintion + * + * Copyright (C) 2014 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + */ + +#ifndef __LINUX_MVEBU_V7_CPUIDLE_H__ +#define __LINUX_MVEBU_V7_CPUIDLE_H__ + +enum mvebu_v7_cpuidle_types { + CPUIDLE_ARMADA_XP, +}; + +struct mvebu_v7_cpuidle { + int type; + int (*cpu_suspend)(unsigned long deepidle); +}; + +#endif
--
2.0.0