ARM: S3C64XX: Add basic cpuidle driver
Subsystems (3)
PATCH 1/1 ARM: S3C64XX: Add basic cpuidle driver
Add a very basic cpuidle driver for S3C64xx which merely drives the CPU into IDLE mode. We could do this with pm_idle but the more modern idiom is to use cpuidle and the intention is to go further and support STOP and DEEP-STOP states in conjunction with the pm_domain framework.
The actual state entry code was lifted from Tomasz Figa's work on spica.
--- arch/arm/mach-s3c64xx/Makefile | 1 + arch/arm/mach-s3c64xx/cpuidle.c | 91 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-s3c64xx/cpuidle.c
arch/arm/mach-s3c64xx/Makefile +1 -0
@@ -40,6 +40,7 @@ obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM) += sleep.o obj-$(CONFIG_PM) += irq-pm.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o # Machine support
arch/arm/mach-s3c64xx/cpuidle.c new file +91 -0
91 lines not on this page · raw message
Signature · 1 line
1.7.7.3
PATCH 1/1 ARM: S3C64XX: Add basic cpuidle driver
Am Montag, 5. Dezember 2011, 21:32:49 schrieb Mark Brown:
Quoted 4 lines
Add a very basic cpuidle driver for S3C64xx which merely drives the CPU into IDLE mode. We could do this with
pm_idlebut the more modern idiom is to use cpuidle and the intention is to go further and support STOP and DEEP-STOP states in conjunction with thepm_domainframework.
cool :-)
My S3C2416 playground is quite similar in its low power modes and their wakeup sources and I've got a idle driver for it in a similar state sitting here.
So I'm really looking forward to seeing a possible example on how to support the STOP and DEEP-STOP modes best.
Quoted 3 lines
The actual state entry code was lifted from Tomasz Figa's work on spica.
Signed-off-by Mark Brown <[email protected]>
Quoted 116 lines
--- arch/arm/mach-s3c64xx/Makefile | 1 + arch/arm/mach-s3c64xx/cpuidle.c | 91 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-s3c64xx/cpuidle.c(quoted diff) +0
-0b/arch/arm/mach-s3c64xx/Makefile index e32093c..8f5574b 100644
arch/arm/mach-s3c64xx/Makefile +0
-0@@ -40,6 +40,7 @@ obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) +=setup-sdhci-gpio.o obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_PM) += sleep.o
obj-$(CONFIG_PM) += irq-pm.oarch/arm/mach-s3c64xx/Makefile +1
-0+obj-$(CONFIG_CPU_IDLE) += cpuidle.o # Machine support(quoted diff) +0
-0
b/arch/arm/mach-s3c64xx/cpuidle.cnew file mode 100644 index 0000000..625d2c7arch/arm/mach-s3c64xx/cpuidle.c new file +91
-0@@ -0,0 +1,91 @@ +/* linux/arch/arm/mach-s3c64xx/cpuidle.c +* +* Copyright (c) 2011 Wolfson Microelectronics, plc +* Copyright (c) 2011 Samsung Electronics Co., Ltd. +* http://www.samsung.com +* +* 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 <linux/kernel.h> +#include <linux/init.h> +#include <linux/cpuidle.h> +#include <linux/io.h> +#include <linux/export.h> +#include <linux/time.h> + +#include <asm/proc-fns.h> + +#include <mach/map.h> + +#include <mach/regs-sys.h> +#include <mach/regs-syscon-power.h> + +static int s3c64xx_enter_idle (struct cpuidle_device *dev, +struct cpuidle_driver *drv, +int index) +{ +struct timeval before, after; +unsigned long tmp; +int idle_time; + +local_irq_disable (); +do_gettimeofday (&before); + +/* Setup PWRCFG to enter idle mode */ + tmp =__raw_readl (S3C64XX_PWR_CFG ); + tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK ; + tmp |=S3C64XX_PWRCFG_CFG_WFI_IDLE ; +__raw_writel (tmp,S3C64XX_PWR_CFG ); + +cpu_do_idle (); + +do_gettimeofday (&after); +local_irq_enable (); + idle_time = (after.tv_sec - before.tv_sec) *USEC_PER_SEC + + (after.tv_usec - before.tv_usec); + + dev->last_residency = idle_time; +return index; +} + +static struct cpuidle_state s3c64xx_cpuidle_set[] = { + [0 ] = { + .enter = s3c64xx_enter_idle, + .exit_latency =1 , + .target_residency =100000 , + .flags =CPUIDLE_FLAG_TIME_VALID , + .name ="IDLE" , + .desc ="System active, ARM gated" , + }, +}; + +static struct cpuidle_driver s3c64xx_cpuidle_driver = { + .name ="s3c64xx_cpuidle" , + .owner =THIS_MODULE , + .state_count =ARRAY_SIZE (s3c64xx_cpuidle_set), +}; + +static struct cpuidle_device s3c64xx_cpuidle_device = { + .state_count =ARRAY_SIZE (s3c64xx_cpuidle_set), +}; + +static int __init s3c64xx_init_cpuidle (void ) +{ +int ret; + +memcpy (s3c64xx_cpuidle_driver.states, s3c64xx_cpuidle_set, +sizeof (s3c64xx_cpuidle_set)); +cpuidle_register_driver (&s3c64xx_cpuidle_driver); + + ret =cpuidle_register_device (&s3c64xx_cpuidle_device); +if (ret) { +pr_err ("Failed to register cpuidle device: %d\n" , ret); +return ret; + } + +return 0 ; +} +device_initcall (s3c64xx_init_cpuidle);
PATCH 1/1 ARM: S3C64XX: Add basic cpuidle driver
Quoted 2 lines · Heiko St?bner
My S3C2416 playground is quite similar in its low power modes and their wakeup sources and I've got a idle driver for it in a similar state sitting here.
Yeah, there's a lot of ARM systems look like this.
Quoted 2 lines
So I'm really looking forward to seeing a possible example on how to support the STOP and DEEP-STOP modes best.
My plan there for the s3c64xx was to use pm_domain to figure out if the system is idle enough to drop down, I've been adding some pm_runtime support to provide the information to the core to let it figure this out.
PATCH 1/1 ARM: S3C64XX: Add basic cpuidle driver
Hi Mark,
Am Donnerstag, 22. Dezember 2011, 19:13:59 schrieb Mark Brown:
Quoted 7 lines · Heiko St?bner
Quoted 2 lines
So I'm really looking forward to seeing a possible example on how to support the STOP and DEEP-STOP modes best.
My plan there for the s3c64xx was to use
pm_domainto figure out if the system is idle enough to drop down, I've been adding somepm_runtimesupport to provide the information to the core to let it figure this out.
sorry for digging this up again, but do you happen to have some preliminary code laying around for this, that I could "borrow"?
Thanks
Heiko
PATCH 1/1 ARM: S3C64XX: Add basic cpuidle driver
Quoted 8 lines · Heiko St?bner
Am Donnerstag, 22. Dezember 2011, 19:13:59 schrieb Mark Brown:
Quoted 3 lines
My plan there for the s3c64xx was to use
pm_domainto figure out if the system is idle enough to drop down, I've been adding somepm_runtimesupport to provide the information to the core to let it figure this out.sorry for digging this up again, but do you happen to have some preliminary code laying around for this, that I could "borrow"?
No, sorry. The big problem is putting all the devices in power domains
since the Samsung port always has every single machine driver directly
register devices. Until that problem is solved it's not possible to
figure out if we're idle.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120330/75918690/attachment-0001.sig>
PATCH 1/1 ARM: S3C64XX: Add basic cpuidle driver
In reply to Mark BrownQuoted 129 lines · Mark Brown
Add a very basic cpuidle driver for S3C64xx which merely drives the CPU into IDLE mode. We could do this with
pm_idlebut the more modern idiom is to use cpuidle and the intention is to go further and support STOP and DEEP-STOP states in conjunction with thepm_domainframework.The actual state entry code was lifted from Tomasz Figa's work on spica.
Signed-off-by Mark Brown <[email protected]>--- arch/arm/mach-s3c64xx/Makefile | 1 + arch/arm/mach-s3c64xx/cpuidle.c | 91 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-s3c64xx/cpuidle.carch/arm/mach- renamed from arch/arm/mach-s3c64xx/Makefile +0
-0s3c64xx/Makefile
index e32093c..8f5574b 100644arch/arm/mach-s3c64xx/Makefile +0
-0@@ -40,6 +40,7 @@ obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_PM) += sleep.o
obj-$(CONFIG_PM) += irq-pm.oarch/arm/mach-s3c64xx/Makefile +1
-0+obj-$(CONFIG_CPU_IDLE) += cpuidle.o # Machine supportarch/arm/mach- renamed from arch/arm/mach-s3c64xx/cpuidle.c +0
-0
s3c64xx/cpuidle.c
new file mode 100644
index 0000000..625d2c7arch/arm/mach-s3c64xx/cpuidle.c new file +91
-1@@ -0,0 +1,91 @@ +/* linux/arch/arm/mach-s3c64xx/cpuidle.c +* +* Copyright (c) 2011 Wolfson Microelectronics, plc +* Copyright (c) 2011 Samsung Electronics Co., Ltd. +* http://www.samsung.com +* +* 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 <linux/kernel.h> +#include <linux/init.h> +#include <linux/cpuidle.h> +#include <linux/io.h> +#include <linux/export.h> +#include <linux/time.h> + +#include <asm/proc-fns.h> + +#include <mach/map.h> + +#include <mach/regs-sys.h> +#include <mach/regs-syscon-power.h> + +static int s3c64xx_enter_idle (struct cpuidle_device *dev, +struct cpuidle_driver *drv, +int index) +{ +struct timeval before, after; +unsigned long tmp; +int idle_time; + +local_irq_disable (); +do_gettimeofday (&before); + +/* Setup PWRCFG to enter idle mode */ + tmp =__raw_readl (S3C64XX_PWR_CFG ); + tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK ; + tmp |=S3C64XX_PWRCFG_CFG_WFI_IDLE ; +__raw_writel (tmp,S3C64XX_PWR_CFG ); + +cpu_do_idle (); + +do_gettimeofday (&after); +local_irq_enable (); + idle_time = (after.tv_sec - before.tv_sec) *USEC_PER_SEC + + (after.tv_usec - before.tv_usec); + + dev->last_residency = idle_time; +return index; +} + +static struct cpuidle_state s3c64xx_cpuidle_set[] = { + [0 ] = { + .enter = s3c64xx_enter_idle, + .exit_latency =1 , + .target_residency =100000 , + .flags =CPUIDLE_FLAG_TIME_VALID , + .name ="IDLE" , + .desc ="System active, ARM gated" , + }, +}; + +static struct cpuidle_driver s3c64xx_cpuidle_driver = { + .name ="s3c64xx_cpuidle" , + .owner =THIS_MODULE , + .state_count =ARRAY_SIZE (s3c64xx_cpuidle_set), +}; + +static struct cpuidle_device s3c64xx_cpuidle_device = { + .state_count =ARRAY_SIZE (s3c64xx_cpuidle_set), +}; + +static int __init s3c64xx_init_cpuidle (void ) +{ +int ret; + +memcpy (s3c64xx_cpuidle_driver.states, s3c64xx_cpuidle_set, +sizeof (s3c64xx_cpuidle_set)); +cpuidle_register_driver (&s3c64xx_cpuidle_driver); + + ret =cpuidle_register_device (&s3c64xx_cpuidle_device); +if (ret) { +pr_err ("Failed to register cpuidle device: %d\n" , ret); +return ret; + } + +return 0 ; +} +device_initcall (s3c64xx_init_cpuidle); --
Quoted 1 line
1.7.7.3
Hi Mark,
Looks ok to me, will apply.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.