From b98e01ad4ed9da6882b41983319361502aded307 Mon Sep 17 00:00:00 2001 From: Sahara Date: Wed, 3 Jul 2013 17:49:55 +0900 Subject: cpuidle: Add Kconfig.arm and move calxeda, kirkwood and zynq Add Kconfig.arm for ARM cpuidle drivers and moves calxeda, kirkwood and zynq to Kconfig.arm. Like in the cpufreq menu, "CPU Idle" menu is added to drivers/cpuidle/Kconfig. Signed-off-by: Sahara --- drivers/cpuidle/Kconfig | 20 +++++++------------- drivers/cpuidle/Kconfig.arm | 21 +++++++++++++++++++++ drivers/cpuidle/Makefile | 8 +++++--- 3 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 drivers/cpuidle/Kconfig.arm diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 0e2cd5cab4d..b3fb81d7cf0 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -1,5 +1,6 @@ +menu "CPU Idle" -menuconfig CPU_IDLE +config CPU_IDLE bool "CPU idle PM support" default y if ACPI || PPC_PSERIES select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE) @@ -29,20 +30,13 @@ config CPU_IDLE_GOV_MENU bool "Menu governor (for tickless system)" default y -config CPU_IDLE_CALXEDA - bool "CPU Idle Driver for Calxeda processors" - depends on ARCH_HIGHBANK - select ARM_CPU_SUSPEND - help - Select this to enable cpuidle on Calxeda processors. - -config CPU_IDLE_ZYNQ - bool "CPU Idle Driver for Xilinx Zynq processors" - depends on ARCH_ZYNQ - help - Select this to enable cpuidle on Xilinx Zynq processors. +menu "ARM CPU Idle Drivers" +depends on ARM +source "drivers/cpuidle/Kconfig.arm" +endmenu endif config ARCH_NEEDS_CPU_IDLE_COUPLED def_bool n +endmenu diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm new file mode 100644 index 00000000000..2c8f17d33ff --- /dev/null +++ b/drivers/cpuidle/Kconfig.arm @@ -0,0 +1,21 @@ +# +# ARM CPU Idle drivers +# + +config ARM_HIGHBANK_CPUIDLE + bool "CPU Idle Driver for Calxeda processors" + depends on ARCH_HIGHBANK + select ARM_CPU_SUSPEND + help + Select this to enable cpuidle on Calxeda processors. + +config ARM_KIRKWOOD_CPUIDLE + bool "CPU Idle Driver for Marvell Kirkwood SoCs" + depends on ARCH_KIRKWOOD + help + This adds the CPU Idle driver for Marvell Kirkwood SoCs. + +config ARM_ZYNQ_CPUIDLE + bool "CPU Idle Driver for Xilinx Zynq processors" + depends on ARCH_ZYNQ + help diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 8767a7b3eb9..77cf767b087 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -5,6 +5,8 @@ obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o -obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o -obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o -obj-$(CONFIG_CPU_IDLE_ZYNQ) += cpuidle-zynq.o +################################################################################## +# ARM SoC drivers +obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o +obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o +obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o -- cgit v1.2.3-70-g09d2 From 7006b8a1facc5dcafb2afa27a1209d924f99a2eb Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 28 Jun 2013 12:09:09 +0200 Subject: ARM: davinci: cpuidle: Fix target residency The commit 19976c2a88d125aec16b9255c7197c297bbdd637 changed the target residency to 100000, assuming this is a careless mistake. The same happened to the at91's cpuidle driver. Fix it by putting the initial value to 10000. Signed-off-by: Daniel Lezcano Acked-by: Sekhar Nori --- arch/arm/mach-davinci/cpuidle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 36aef3a7ded..f1ac1c94ac0 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -65,7 +65,7 @@ static struct cpuidle_driver davinci_idle_driver = { .states[1] = { .enter = davinci_enter_idle, .exit_latency = 10, - .target_residency = 100000, + .target_residency = 10000, .flags = CPUIDLE_FLAG_TIME_VALID, .name = "DDR SR", .desc = "WFI and DDR Self Refresh", -- cgit v1.2.3-70-g09d2 From 8025395f39c97e332362c24f7c33c86acdd4cd90 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 10 Jul 2013 15:35:26 +0200 Subject: ARM: ux500: cpuidle: Instantiate the driver from platform device To break the dependency on the "id.h" file we move the cpuidle driver to a platform device. Now we only call the probe() on this driver if we find a corresponding platform device (which is spawned from the PRCMU MFD driver). Signed-off-by: Linus Walleij Signed-off-by: Daniel Lezcano --- arch/arm/mach-ux500/cpuidle.c | 17 +++++++++++------ drivers/mfd/db8500-prcmu.c | 4 ++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c index a45dd09daed..c0cb37c8086 100644 --- a/arch/arm/mach-ux500/cpuidle.c +++ b/arch/arm/mach-ux500/cpuidle.c @@ -16,12 +16,12 @@ #include #include #include +#include #include #include #include "db8500-regs.h" -#include "id.h" static atomic_t master = ATOMIC_INIT(0); static DEFINE_SPINLOCK(master_lock); @@ -113,11 +113,8 @@ static struct cpuidle_driver ux500_idle_driver = { .state_count = 2, }; -int __init ux500_idle_init(void) +static int __init dbx500_cpuidle_probe(struct platform_device *pdev) { - if (!(cpu_is_u8500_family() || cpu_is_ux540_family())) - return -ENODEV; - /* Configure wake up reasons */ prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | PRCMU_WAKEUP(ABB)); @@ -125,4 +122,12 @@ int __init ux500_idle_init(void) return cpuidle_register(&ux500_idle_driver, NULL); } -device_initcall(ux500_idle_init); +static struct platform_driver dbx500_cpuidle_plat_driver = { + .driver = { + .name = "cpuidle-dbx500", + .owner = THIS_MODULE, + }, + .probe = dbx500_cpuidle_probe, +}; + +module_platform_driver(dbx500_cpuidle_plat_driver); diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 3c157faee64..0d68eb1a5ec 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3093,6 +3093,10 @@ static struct mfd_cell db8500_prcmu_devs[] = { .platform_data = &db8500_cpufreq_table, .pdata_size = sizeof(db8500_cpufreq_table), }, + { + .name = "cpuidle-dbx500", + .of_compatible = "stericsson,cpuidle-dbx500", + }, { .name = "db8500-thermal", .num_resources = ARRAY_SIZE(db8500_thsens_resources), -- cgit v1.2.3-70-g09d2 From 8457246b106cc4e53f2534309dbe35a973c7d046 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 10 Jul 2013 15:52:01 +0200 Subject: ARM: ux500: cpuidle: Remove pointless include The db8500-regs.h file does not need to be included by the cpuidle driver. Signed-off-by: Linus Walleij Signed-off-by: Daniel Lezcano --- arch/arm/mach-ux500/cpuidle.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c index c0cb37c8086..e0564652af3 100644 --- a/arch/arm/mach-ux500/cpuidle.c +++ b/arch/arm/mach-ux500/cpuidle.c @@ -21,8 +21,6 @@ #include #include -#include "db8500-regs.h" - static atomic_t master = ATOMIC_INIT(0); static DEFINE_SPINLOCK(master_lock); -- cgit v1.2.3-70-g09d2 From d3f2950f2adeea3da0317e952914b59adaa4cdb3 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 10 Jul 2013 16:02:04 +0200 Subject: ARM: ux500: cpuidle: Move ux500 cpuidle driver to drivers/cpuidle There is no more dependency with arch/arm headers, so we can safely move the driver to the drivers/cpuidle directory. Signed-off-by: Daniel Lezcano Acked-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 1 - arch/arm/mach-ux500/cpuidle.c | 131 ---------------------------------------- drivers/cpuidle/Kconfig.arm | 8 +++ drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-ux500.c | 131 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 132 deletions(-) delete mode 100644 arch/arm/mach-ux500/cpuidle.c create mode 100644 drivers/cpuidle/cpuidle-ux500.c diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index bf9b6be5b18..fe1f3e26b88 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -4,7 +4,6 @@ obj-y := cpu.o devices.o devices-common.o \ id.o usb.o timer.o pm.o -obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c deleted file mode 100644 index e0564652af3..00000000000 --- a/arch/arm/mach-ux500/cpuidle.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2012 Linaro : Daniel Lezcano (IBM) - * - * Based on the work of Rickard Andersson - * and Jonas Aaberg . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static atomic_t master = ATOMIC_INIT(0); -static DEFINE_SPINLOCK(master_lock); - -static inline int ux500_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) -{ - int this_cpu = smp_processor_id(); - bool recouple = false; - - if (atomic_inc_return(&master) == num_online_cpus()) { - - /* With this lock, we prevent the other cpu to exit and enter - * this function again and become the master */ - if (!spin_trylock(&master_lock)) - goto wfi; - - /* decouple the gic from the A9 cores */ - if (prcmu_gic_decouple()) { - spin_unlock(&master_lock); - goto out; - } - - /* If an error occur, we will have to recouple the gic - * manually */ - recouple = true; - - /* At this state, as the gic is decoupled, if the other - * cpu is in WFI, we have the guarantee it won't be wake - * up, so we can safely go to retention */ - if (!prcmu_is_cpu_in_wfi(this_cpu ? 0 : 1)) - goto out; - - /* The prcmu will be in charge of watching the interrupts - * and wake up the cpus */ - if (prcmu_copy_gic_settings()) - goto out; - - /* Check in the meantime an interrupt did - * not occur on the gic ... */ - if (prcmu_gic_pending_irq()) - goto out; - - /* ... and the prcmu */ - if (prcmu_pending_irq()) - goto out; - - /* Go to the retention state, the prcmu will wait for the - * cpu to go WFI and this is what happens after exiting this - * 'master' critical section */ - if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true)) - goto out; - - /* When we switch to retention, the prcmu is in charge - * of recoupling the gic automatically */ - recouple = false; - - spin_unlock(&master_lock); - } -wfi: - cpu_do_idle(); -out: - atomic_dec(&master); - - if (recouple) { - prcmu_gic_recouple(); - spin_unlock(&master_lock); - } - - return index; -} - -static struct cpuidle_driver ux500_idle_driver = { - .name = "ux500_idle", - .owner = THIS_MODULE, - .states = { - ARM_CPUIDLE_WFI_STATE, - { - .enter = ux500_enter_idle, - .exit_latency = 70, - .target_residency = 260, - .flags = CPUIDLE_FLAG_TIME_VALID | - CPUIDLE_FLAG_TIMER_STOP, - .name = "ApIdle", - .desc = "ARM Retention", - }, - }, - .safe_state_index = 0, - .state_count = 2, -}; - -static int __init dbx500_cpuidle_probe(struct platform_device *pdev) -{ - /* Configure wake up reasons */ - prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | - PRCMU_WAKEUP(ABB)); - - return cpuidle_register(&ux500_idle_driver, NULL); -} - -static struct platform_driver dbx500_cpuidle_plat_driver = { - .driver = { - .name = "cpuidle-dbx500", - .owner = THIS_MODULE, - }, - .probe = dbx500_cpuidle_probe, -}; - -module_platform_driver(dbx500_cpuidle_plat_driver); diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 2c8f17d33ff..b3302193c15 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -19,3 +19,11 @@ config ARM_ZYNQ_CPUIDLE bool "CPU Idle Driver for Xilinx Zynq processors" depends on ARCH_ZYNQ help + Select this to enable cpuidle on Xilinx Zynq processors. + +config ARM_U8500_CPUIDLE + bool "Cpu Idle Driver for the ST-E u8500 processors" + depends on ARCH_U8500 + help + Select this to enable cpuidle for ST-E u8500 processors + diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 77cf767b087..0b9d200c7e4 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o +obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c new file mode 100644 index 00000000000..e0564652af3 --- /dev/null +++ b/drivers/cpuidle/cpuidle-ux500.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2012 Linaro : Daniel Lezcano (IBM) + * + * Based on the work of Rickard Andersson + * and Jonas Aaberg . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static atomic_t master = ATOMIC_INIT(0); +static DEFINE_SPINLOCK(master_lock); + +static inline int ux500_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + int this_cpu = smp_processor_id(); + bool recouple = false; + + if (atomic_inc_return(&master) == num_online_cpus()) { + + /* With this lock, we prevent the other cpu to exit and enter + * this function again and become the master */ + if (!spin_trylock(&master_lock)) + goto wfi; + + /* decouple the gic from the A9 cores */ + if (prcmu_gic_decouple()) { + spin_unlock(&master_lock); + goto out; + } + + /* If an error occur, we will have to recouple the gic + * manually */ + recouple = true; + + /* At this state, as the gic is decoupled, if the other + * cpu is in WFI, we have the guarantee it won't be wake + * up, so we can safely go to retention */ + if (!prcmu_is_cpu_in_wfi(this_cpu ? 0 : 1)) + goto out; + + /* The prcmu will be in charge of watching the interrupts + * and wake up the cpus */ + if (prcmu_copy_gic_settings()) + goto out; + + /* Check in the meantime an interrupt did + * not occur on the gic ... */ + if (prcmu_gic_pending_irq()) + goto out; + + /* ... and the prcmu */ + if (prcmu_pending_irq()) + goto out; + + /* Go to the retention state, the prcmu will wait for the + * cpu to go WFI and this is what happens after exiting this + * 'master' critical section */ + if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true)) + goto out; + + /* When we switch to retention, the prcmu is in charge + * of recoupling the gic automatically */ + recouple = false; + + spin_unlock(&master_lock); + } +wfi: + cpu_do_idle(); +out: + atomic_dec(&master); + + if (recouple) { + prcmu_gic_recouple(); + spin_unlock(&master_lock); + } + + return index; +} + +static struct cpuidle_driver ux500_idle_driver = { + .name = "ux500_idle", + .owner = THIS_MODULE, + .states = { + ARM_CPUIDLE_WFI_STATE, + { + .enter = ux500_enter_idle, + .exit_latency = 70, + .target_residency = 260, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_TIMER_STOP, + .name = "ApIdle", + .desc = "ARM Retention", + }, + }, + .safe_state_index = 0, + .state_count = 2, +}; + +static int __init dbx500_cpuidle_probe(struct platform_device *pdev) +{ + /* Configure wake up reasons */ + prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | + PRCMU_WAKEUP(ABB)); + + return cpuidle_register(&ux500_idle_driver, NULL); +} + +static struct platform_driver dbx500_cpuidle_plat_driver = { + .driver = { + .name = "cpuidle-dbx500", + .owner = THIS_MODULE, + }, + .probe = dbx500_cpuidle_probe, +}; + +module_platform_driver(dbx500_cpuidle_plat_driver); -- cgit v1.2.3-70-g09d2