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 (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 0e2cd5cab4d0..b3fb81d7cf04 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 000000000000..2c8f17d33ff4 --- /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 8767a7b3eb91..77cf767b0875 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 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 (limited to 'drivers/cpuidle') diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index bf9b6be5b180..fe1f3e26b88b 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 e0564652af35..000000000000 --- 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 2c8f17d33ff4..b3302193c15a 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 77cf767b0875..0b9d200c7e45 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 000000000000..e0564652af35 --- /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