diff options
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r-- | drivers/cpuidle/Kconfig.arm | 14 | ||||
-rw-r--r-- | drivers/cpuidle/Makefile | 2 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-armada-370-xp.c | 93 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-big_little.c | 12 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-exynos.c | 25 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-mvebu-v7.c | 150 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-powernv.c | 16 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 2 |
8 files changed, 182 insertions, 132 deletions
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index a186dec8e5df..38cff69ffe06 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -1,15 +1,9 @@ # # 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 + depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS depends on MCPM select ARM_CPU_SUSPEND select CPU_IDLE_MULTIPLE_DRIVERS @@ -62,3 +56,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. diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index d8bb1ff72561..11edb31c55e9 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -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 diff --git a/drivers/cpuidle/cpuidle-armada-370-xp.c b/drivers/cpuidle/cpuidle-armada-370-xp.c deleted file mode 100644 index a5fba0287bfb..000000000000 --- a/drivers/cpuidle/cpuidle-armada-370-xp.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Marvell Armada 370 and Armada XP SoC cpuidle driver - * - * Copyright (C) 2014 Marvell - * - * Nadav Haklai <nadavh@marvell.com> - * 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. - * - * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com> - */ - -#include <linux/cpu_pm.h> -#include <linux/cpuidle.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/suspend.h> -#include <linux/platform_device.h> -#include <asm/cpuidle.h> - -#define ARMADA_370_XP_MAX_STATES 3 -#define ARMADA_370_XP_FLAG_DEEP_IDLE 0x10000 - -static int (*armada_370_xp_cpu_suspend)(int); - -static int armada_370_xp_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) -{ - int ret; - bool deepidle = false; - cpu_pm_enter(); - - if (drv->states[index].flags & ARMADA_370_XP_FLAG_DEEP_IDLE) - deepidle = true; - - ret = armada_370_xp_cpu_suspend(deepidle); - if (ret) - return ret; - - cpu_pm_exit(); - - return index; -} - -static struct cpuidle_driver armada_370_xp_idle_driver = { - .name = "armada_370_xp_idle", - .states[0] = ARM_CPUIDLE_WFI_STATE, - .states[1] = { - .enter = armada_370_xp_enter_idle, - .exit_latency = 10, - .power_usage = 50, - .target_residency = 100, - .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "Idle", - .desc = "CPU power down", - }, - .states[2] = { - .enter = armada_370_xp_enter_idle, - .exit_latency = 100, - .power_usage = 5, - .target_residency = 1000, - .flags = CPUIDLE_FLAG_TIME_VALID | - ARMADA_370_XP_FLAG_DEEP_IDLE, - .name = "Deep idle", - .desc = "CPU and L2 Fabric power down", - }, - .state_count = ARMADA_370_XP_MAX_STATES, -}; - -static int armada_370_xp_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); -} - -static struct platform_driver armada_370_xp_cpuidle_plat_driver = { - .driver = { - .name = "cpuidle-armada-370-xp", - .owner = THIS_MODULE, - }, - .probe = armada_370_xp_cpuidle_probe, -}; - -module_platform_driver(armada_370_xp_cpuidle_plat_driver); - -MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>"); -MODULE_DESCRIPTION("Armada 370/XP cpu idle driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c index b45fc6249041..344d79fa3407 100644 --- a/drivers/cpuidle/cpuidle-big_little.c +++ b/drivers/cpuidle/cpuidle-big_little.c @@ -163,14 +163,24 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id) return 0; } +static const struct of_device_id compatible_machine_match[] = { + { .compatible = "arm,vexpress,v2p-ca15_a7" }, + { .compatible = "samsung,exynos5420" }, + {}, +}; + static int __init bl_idle_init(void) { int ret; + struct device_node *root = of_find_node_by_path("/"); + + if (!root) + return -ENODEV; /* * Initialize the driver just for a compliant set of machines */ - if (!of_machine_is_compatible("arm,vexpress,v2p-ca15_a7")) + if (!of_match_node(compatible_machine_match, root)) return -ENODEV; /* * For now the differentiation between little and big cores diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c index 7c0151263828..ba9b34b579f3 100644 --- a/drivers/cpuidle/cpuidle-exynos.c +++ b/drivers/cpuidle/cpuidle-exynos.c @@ -20,25 +20,6 @@ static void (*exynos_enter_aftr)(void); -static int idle_finisher(unsigned long flags) -{ - exynos_enter_aftr(); - cpu_do_idle(); - - return 1; -} - -static int exynos_enter_core0_aftr(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) -{ - cpu_pm_enter(); - cpu_suspend(0, idle_finisher); - cpu_pm_exit(); - - return index; -} - static int exynos_enter_lowpower(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -51,8 +32,10 @@ static int exynos_enter_lowpower(struct cpuidle_device *dev, if (new_index == 0) return arm_cpuidle_simple_enter(dev, drv, new_index); - else - return exynos_enter_core0_aftr(dev, drv, new_index); + + exynos_enter_aftr(); + + return new_index; } static struct cpuidle_driver exynos_idle_driver = { diff --git a/drivers/cpuidle/cpuidle-mvebu-v7.c b/drivers/cpuidle/cpuidle-mvebu-v7.c new file mode 100644 index 000000000000..45371bb16214 --- /dev/null +++ b/drivers/cpuidle/cpuidle-mvebu-v7.c @@ -0,0 +1,150 @@ +/* + * Marvell Armada 370, 38x and XP SoC cpuidle driver + * + * Copyright (C) 2014 Marvell + * + * Nadav Haklai <nadavh@marvell.com> + * 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. + * + * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com> + */ + +#include <linux/cpu_pm.h> +#include <linux/cpuidle.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/suspend.h> +#include <linux/platform_device.h> +#include <asm/cpuidle.h> + +#define MVEBU_V7_FLAG_DEEP_IDLE 0x10000 + +static int (*mvebu_v7_cpu_suspend)(int); + +static int mvebu_v7_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + 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); + if (ret) + return ret; + + cpu_pm_exit(); + + return index; +} + +static struct cpuidle_driver armadaxp_idle_driver = { + .name = "armada_xp_idle", + .states[0] = ARM_CPUIDLE_WFI_STATE, + .states[1] = { + .enter = mvebu_v7_enter_idle, + .exit_latency = 10, + .power_usage = 50, + .target_residency = 100, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "MV CPU IDLE", + .desc = "CPU power down", + }, + .states[2] = { + .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 = "MV CPU DEEP IDLE", + .desc = "CPU and L2 Fabric power down", + }, + .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 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; + + 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 if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-38x")) + return cpuidle_register(&armada38x_idle_driver, NULL); + else + return -EINVAL; +} + +static struct platform_driver armadaxp_cpuidle_plat_driver = { + .driver = { + .name = "cpuidle-armada-xp", + .owner = THIS_MODULE, + }, + .probe = mvebu_v7_cpuidle_probe, +}; + +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); + +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 <gregory.clement@free-electrons.com>"); +MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c index 74f5788d50b1..a64be578dab2 100644 --- a/drivers/cpuidle/cpuidle-powernv.c +++ b/drivers/cpuidle/cpuidle-powernv.c @@ -160,10 +160,10 @@ static int powernv_cpuidle_driver_init(void) static int powernv_add_idle_states(void) { struct device_node *power_mgt; - struct property *prop; int nr_idle_states = 1; /* Snooze */ int dt_idle_states; - u32 *flags; + const __be32 *idle_state_flags; + u32 len_flags, flags; int i; /* Currently we have snooze statically defined */ @@ -174,18 +174,18 @@ static int powernv_add_idle_states(void) return nr_idle_states; } - prop = of_find_property(power_mgt, "ibm,cpu-idle-state-flags", NULL); - if (!prop) { + idle_state_flags = of_get_property(power_mgt, "ibm,cpu-idle-state-flags", &len_flags); + if (!idle_state_flags) { pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-flags\n"); return nr_idle_states; } - dt_idle_states = prop->length / sizeof(u32); - flags = (u32 *) prop->value; + dt_idle_states = len_flags / sizeof(u32); for (i = 0; i < dt_idle_states; i++) { - if (flags[i] & IDLE_USE_INST_NAP) { + flags = be32_to_cpu(idle_state_flags[i]); + if (flags & IDLE_USE_INST_NAP) { /* Add NAP state */ strcpy(powernv_states[nr_idle_states].name, "Nap"); strcpy(powernv_states[nr_idle_states].desc, "Nap"); @@ -196,7 +196,7 @@ static int powernv_add_idle_states(void) nr_idle_states++; } - if (flags[i] & IDLE_USE_INST_SLEEP) { + if (flags & IDLE_USE_INST_SLEEP) { /* Add FASTSLEEP state */ strcpy(powernv_states[nr_idle_states].name, "FastSleep"); strcpy(powernv_states[nr_idle_states].desc, "FastSleep"); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 27702742b319..34db2fb3ef1e 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -401,7 +401,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) * * Any measured amount of time will include the exit latency. * Since we are interested in when the wakeup begun, not when it - * was completed, we must substract the exit latency. However, if + * was completed, we must subtract the exit latency. However, if * the measured amount of time is less than the exit latency, * assume the state was never reached and the exit latency is 0. */ |