S3C64xx updates
cover S3C64xx updates
This set of patches has all been previously posted prior to the 3.0-rc1 release, some of them are really quite old now. Kukjin, I seem to recall you said were OK with several of these patches already?
Ben Dooks (2):
ARM: SAMSUNG: Add support for pre-sleep/post-restore gpio control
ARM: S3C64XX: Ensure VIC based IRQs can be resumed from
Mark Brown (3):
CPUFREQ/S3C64xx: Move S3C64xx CPUfreq driver into drivers/cpufreq
ARM: S3C6410: Support 800MHz operation in cpufreq
ARM: S3C6410: Add some lower frequencies for 800MHz base clock operation
PATCH 1/5 CPUFREQ/S3C64xx: Move S3C64xx CPUfreq driver into drivers/cpufreq
This is a straight code motion patch, there are no changes to the driver itself. The Kconfig is left untouched as the ARM CPUfreq Kconfig is all in one big block in arm/Kconfig and should be moved en masse rather than being done piecemeal.
--- arch/arm/mach-s3c64xx/Makefile | 4 - arch/arm/mach-s3c64xx/cpufreq.c | 270 --------------------------------------- drivers/cpufreq/Makefile | 1 + drivers/cpufreq/s3c64xx.c | 269 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 270 insertions(+), 274 deletions(-) delete mode 100644 arch/arm/mach-s3c64xx/cpufreq.c create mode 100644 drivers/cpufreq/s3c64xx.c
arch/arm/mach-s3c64xx/Makefile +0 -4
@@ -23,10 +23,6 @@ obj-$(CONFIG_CPU_S3C6410) += s3c6410.o obj-y += irq.o obj-y += irq-eint.o -# CPU frequency scaling - -obj-$(CONFIG_CPU_FREQ_S3C64XX) += cpufreq.o - # DMA support obj-$(CONFIG_S3C64XX_DMA) += dma.o
arch/arm/mach-s3c64xx/cpufreq.c deleted +0 -270
270 lines not on this page · raw message
drivers/cpufreq/Makefile +1 -0
@@ -40,4 +40,5 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o ##################################################################################d # ARM SoC drivers +obj-$(CONFIG_CPU_FREQ_S3C64XX) += s3c64xx.o obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
drivers/cpufreq/s3c64xx.c new file +269 -0
269 lines not on this page · raw message
Signature · 1 line
1.7.5.3
PATCH 2/5 ARM: SAMSUNG: Add support for pre-sleep/post-restore gpio control
From: Ben Dooks <[email protected]>
Add a callback so that per-arch can do pre-sleep and post-resume gpio configuration so that for the S3C64XX, the GPIO configuration is restored before the sleep mode is cleared.
For the S3C64XX case, it means that the GPIOs get set back to normal operation after the restore code puts the original configurations back in after the
--- arch/arm/mach-s3c2410/include/mach/pm-core.h | 3 +++ arch/arm/mach-s3c64xx/include/mach/pm-core.h | 17 +++++++++++++++++ arch/arm/mach-s5pv210/include/mach/pm-core.h | 3 +++ arch/arm/plat-samsung/pm.c | 2 ++ 4 files changed, 25 insertions(+), 0 deletions(-)
arch/arm/mach-s3c2410/include/mach/pm-core.h +3 -0
@@ -62,3 +62,6 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs, struct pm_uart_save *save) { } + +static inline void s3c_pm_restored_gpios (void ) { } +static inline void s3c_pm_saved_gpios (void ) { }
arch/arm/mach-s3c64xx/include/mach/pm-core.h +17 -0
@@ -96,3 +96,20 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs, save->ucon = new_ucon; } } + +static inline void s3c_pm_restored_gpios (void ) +{ +/* ensure sleep mode has been cleared from the system */ + +__raw_writel (0 ,S3C64XX_SLPEN ); +} + +static inline void s3c_pm_saved_gpios (void ) +{ +/* turn on the sleep mode and keep it there, as it seems that during +* suspend the xCON registers get re-set and thus you can end up with +* problems between going to sleep and resuming. +*/ + +__raw_writel (S3C64XX_SLPEN_USE_xSLP,S3C64XX_SLPEN ); +}
arch/arm/mach-s5pv210/include/mach/pm-core.h +3 -0
@@ -41,3 +41,6 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs, {/* nothing here yet */ } + +static inline void s3c_pm_restored_gpios (void ) { } +static inline void s3c_pm_saved_gpios (void ) { }
arch/arm/plat-samsung/pm.c +2 -0
@@ -268,6 +268,7 @@ static int s3c_pm_enter(suspend_state_t state)/* save all necessary core registers not covered by the drivers */ s3c_pm_save_gpios (); +s3c_pm_saved_gpios ();s3c_pm_save_uarts ();s3c_pm_save_core ();
@@ -309,6 +310,7 @@ static int s3c_pm_enter(suspend_state_t state)s3c_pm_restore_core ();s3c_pm_restore_uarts ();s3c_pm_restore_gpios (); +s3c_pm_restored_gpios ();s3c_pm_debug_init ();
Signature · 1 line
1.7.5.3
PATCH 3/5 ARM: S3C64XX: Ensure VIC based IRQs can be resumed from
In reply to Mark BrownFrom: Ben Dooks <[email protected]>
Any interrupts based off either of the onboard VICs cannot be resumed from any more as it seems set_irq_wake() is now checking the error code returned from the low level handlers and not setting the wake-state on the interrupt if this fails.
Ensure that we make the interrupts we can resume from available on the VIC and then do a pre-sleep mask of all the VIC interrupts as the wakeup is handled by a seperate block.
--- arch/arm/mach-s3c64xx/include/mach/pm-core.h | 2 +- arch/arm/mach-s3c64xx/irq.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-)
arch/arm/mach-s3c64xx/include/mach/pm-core.h +1 -1
@@ -53,7 +53,7 @@ static inline void s3c_pm_arch_show_resume_irqs(void)* the IRQ wake controls depending on the CPU we are running on */ #define s3c_irqwake_eintallow ((1 << 28) - 1) -#define s3c_irqwake_intallow (0) +#define s3c_irqwake_intallow (~0)static inline void s3c_pm_arch_update_uart (void __iomem *regs,struct pm_uart_save *save)
arch/arm/mach-s3c64xx/irq.c +10 -2
@@ -48,14 +48,22 @@ static struct s3c_uart_irq uart_irqs[] = { }, }; +/* setup the sources the vic should advertise resume for, even though it +* is not doing the wake (set_irq_wake needs to be valid) */ +#define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE)) +#define IRQ_VIC1_RESUME (1 << (IRQ_RTC_ALARM - IRQ_VIC1_BASE) | \ + 1 << (IRQ_PENDN - IRQ_VIC1_BASE) | \ + 1 << (IRQ_HSMMC0 - IRQ_VIC1_BASE) | \ + 1 << (IRQ_HSMMC1 - IRQ_VIC1_BASE) | \ + 1 << (IRQ_HSMMC2 - IRQ_VIC1_BASE))void __init s3c64xx_init_irq (u32 vic0_valid,u32 vic1_valid) {printk (KERN_DEBUG "%s: initialising interrupts\n" , __func__);/* initialise the pair of VICs */ -vic_init (VA_VIC0 ,IRQ_VIC0_BASE , vic0_valid,0 ); -vic_init (VA_VIC1 ,IRQ_VIC1_BASE , vic1_valid,0 ); +vic_init (VA_VIC0 ,IRQ_VIC0_BASE , vic0_valid,IRQ_VIC0_RESUME ); +vic_init (VA_VIC1 ,IRQ_VIC1_BASE , vic1_valid,IRQ_VIC1_RESUME );/* add the timer sub-irqs */ s3c_init_vic_timer_irq (5 ,IRQ_TIMER0 );
Signature · 1 line
1.7.5.3
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
In reply to Mark BrownAt least some newer S3C6410 silicon supports operation up to 800MHz rather than just 667MHz. Unfortunately I don't have access to any of documentation of this other than some running systems, add a new cpufreq table entry for this based on the behaviour of those systems.
--- drivers/cpufreq/s3c64xx.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/cpufreq/s3c64xx.c +2 -0
@@ -31,6 +31,7 @@ static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = { [1] = { 1050000, 1150000 }, [2] = { 1100000, 1150000 }, [3] = { 1200000, 1350000 }, + [4] = { 1300000, 1350000 }, };static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
@@ -43,6 +44,7 @@ static struct cpufreq_frequency_table s3c64xx_freq_table[] = { { 2, 532000 }, { 2, 533000 }, { 3, 667000 }, + { 4, 800000 }, { 0, CPUFREQ_TABLE_END }, }; #endif
Signature · 1 line
1.7.5.3
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
Hi, Mark
800Mhz S3C6410 is only supplied by customer request. 800Mhz dvfs operation should be controlled carefully. (Stable VDD_ARM should be supplied)
To optimize s3c6410 dvfs operation, not only ARMCLK
But also HCLK should do dvfs.
In other words, VDD_INT, as well as VDD_ARM should be controlled.
Thanks and regards,
SB Kim
On Wed, Jun 1, 2011 at 6:45 PM, Mark Brown
Quoted 40 lines
At least some newer S3C6410 silicon supports operation up to 800MHz rather than just 667MHz. Unfortunately I don't have access to any of documentation
of this other than some running systems, add a new cpufreq table entry for this based on the behaviour of those systems.Signed-off-by Mark Brown <[email protected]>--- drivers/cpufreq/s3c64xx.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)drivers/cpufreq/s3c64xx.c +2
-0@@ -31,6 +31,7 @@ static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = { [1] = { 1050000, 1150000 }, [2] = { 1100000, 1150000 }, [3] = { 1200000, 1350000 }, + [4] = { 1300000, 1350000 }, };static struct cpufreq_frequency_table s3c64xx_freq_table[] = {@@ -43,6 +44,7 @@ static struct cpufreq_frequency_table s3c64xx_freq_table[] = { {2 ,532000 }, {2 ,533000 }, {3 ,667000 }, + {4 ,800000 }, {0 ,CPUFREQ_TABLE_END }, };#endif
--
1.7.5.3_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
Quoted 1 line · Sangbeom Kim
Hi, Mark
Don't top post.
Quoted 3 lines
800Mhz S3C6410 is only supplied by customer request. 800Mhz dvfs operation should be controlled carefully. (Stable
VDD_ARMshould be supplied)
The fact that the chip is only on limited distribution isn't really an issue for supporting it in mainline - many CPUs currently supported in Linux, including some Samsung ones, are only available to certain customers.
Similarly, stable power supplies are a basic system design thing that we shouldn't be worrying about here.
Quoted 3 lines
To optimize s3c6410 dvfs operation, not only ARMCLK
But also HCLK should do dvfs.
In other words,VDD_INT, as well asVDD_ARMshould be controlled.
I don't have any access to documentation on this part here and in any case we've already got code in mainline which is doing DVFS on S3C6410 without varying VDD_INT so that's a bit of a moot point. We need to add the 800MHz support in order to have the existing code understand the state the device boots up in on the system I'm currently working with, never mind actually change anything at runtime.
As things stand the system will boot and then immediately scale the voltage down to 400MHz as it's the only supported rate for 800MHz (we're only doing scaling by division of the ARM clock) so adding the operating point for 800MHz at least means that the performance governor will do the right thing.
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
On Wed, Jun 1, 2011 at 7:41 PM, Mark Brown
Quoted 4 lines
The fact that the chip is only on limited distribution isn't really an issue for supporting it in mainline - many CPUs currently supported in Linux, including some Samsung ones, are only available to certain customers.
As you said, limited distribution isn't issue,
Issue is that all s3c6410 can't support 800Mhz.
Even if some s3c6410 processor unable to support 800Mhz,
In some cases, It seems to work on 800Mhz.
But System suddenly can be dead after few days working.(system hang up) So, If some developer want use 800Mhz, They should exactly know that their s3c6410 can support 800Mhz or not.
I just want to say this.
800Mhz s3c6410 can be distinguished by checking laser mark.
Quoted 2 lines
Similarly, stable power supplies are a basic system design thing that we shouldn't be worrying about here.
Even if 6410 can support 800Mhz, If power is unstable, system can be dead. It is not 6410 problem. It is board problem.
When system hang up happened, In the most cases, regulator give unstable VDD_ARM
(Even if regulator register setting is right)
You can just say that I don't care about that.
But System hang up isn't simple problem.
I want developer to know that If They try to develop 800Mhz 6410, They should consider many things like board design,
selecting regulator, support 800Mhz etc.
So It is more desirable to add some comment for using 800Mhz
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
Quoted 2 lines · Sangbeom Kim
I just want to say this.
800Mhz s3c6410 can be distinguished by checking laser mark.
It's really unfortunate that there's no software visible method I'm aware of :/
Quoted 7 lines
Quoted 2 lines
Similarly, stable power supplies are a basic system design thing that we shouldn't be worrying about here.
Even if 6410 can support 800Mhz, If power is unstable, system can be dead. It is not 6410 problem. It is board problem.
When system hang up happened, In the most cases, regulator give unstableVDD_ARM
Yes, this is very much the case with any board design - the regulators need to be able to both sustain the full rate current draw and rapidly respond to changes in load and voltage in order to make a viable system. In the case of voltage changes we've got some support in the regulator API for ramp delays which should allow us to cope with regulators that are slow to implement voltage changes but for transient response there's really nothing doing except for good hardware design.
I'm not sure it's a particular concern for the 800MHz part above others simply because it's such a universal issue.
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
On Wed, Jun 2, 2011 at 9:11 AM, Mark Brown
Quoted 3 lines
It's really unfortunate that there's no software visible method I'm aware of :/
Unfortunately, There is no method to detect 800Mhz s3c6410 by software.
Quoted 2 lines
I'm not sure it's a particular concern for the 800MHz part above others simply because it's such a universal issue.
Because Voltage margin(VDD_ARM) of s3c6410 800Mhz is particularly weak. Under 667Mhz, There is no issue for dvfs.
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
Quoted 5 lines · Sangbeom Kim
On Wed, Jun 2, 2011 at 9:11 AM, Mark Brown
Quoted 3 lines
It's really unfortunate that there's no software visible method I'm aware of :/
Unfortunately, There is no method to detect 800Mhz s3c6410 by software.
Then how about to introduce the software flags. and set it at each board. It can support the 800MHz.
Also this flags are handled at cpufreq drivers properly.
How do you think?
Quoted 14 lines
Quoted 4 lines
I'm not sure it's a particular concern for the 800MHz part above others simply because it's such a universal issue.
Because Voltage
margin(VDD_ARM)of s3c6410 800Mhz is particularly weak. Under 667Mhz, There is no issue for dvfs._______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
Quoted 10 lines · Kyungmin Park
Quoted 4 lines
Quoted 3 lines
It's really unfortunate that there's no software visible method I'm aware of :/
Unfortunately, There is no method to detect 800Mhz s3c6410 by software.
Then how about to introduce the software flags. and set it at each board. It can support the 800MHz.
Also this flags are handled at cpufreq drivers properly.How do you think?
Two SMDKs may have different versions of s3c6410.
Which file do we want to set the flags in ?
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
Quoted 6 lines · On Thursday 02 June 2011 12:50:56 Jassi Brar wrote:
Quoted 5 lines · Kyungmin Park
Quoted 4 lines
Quoted 2 lines
It's really unfortunate that there's no software visible method I'm aware of :/
Unfortunately, There is no method to detect 800Mhz s3c6410 by software.
Quoted 8 lines
Quoted 5 lines
Then how about to introduce the software flags. and set it at each board. It can support the 800MHz.
Also this flags are handled at cpufreq drivers properly.How do you think?
Two SMDKs may have different versions of s3c6410.
Which file do we want to set the flags in ?
What about adding cmdline arg like 's3c6410_maxfreq', and defaulting it to 667 MHz?
Regards
Vasily
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
In reply to Jassi BrarQuoted 10 lines · Jassi Brar
Quoted 5 lines · Kyungmin Park
Then how about to introduce the software flags. and set it at each board. It can support the 800MHz.
Also this flags are handled at cpufreq drivers properly.How do you think?
Two SMDKs may have different versions of s3c6410.
Which file do we want to set the flags in ?
In this case the board can effectively eliminate 800MHz operation through the regulation constraints as it requires 1.3V rather than 1.2V.
IIRC the device always comes up at full speed so the boot state also constrains things with the current system - there's no code to reclock the PLLs so if we boot up at 667MHz then 800MHz is inaccessible.
PATCH 4/5 ARM: S3C6410: Support 800MHz operation in cpufreq
In reply to Jassi BrarQuoted 6 lines · Jassi Brar
Quoted 5 lines · Kyungmin Park
Quoted 4 lines
Quoted 3 lines
It's really unfortunate that there's no software visible method I'm aware of :/
Unfortunately, There is no method to detect 800Mhz s3c6410 by software.
Quoted 8 lines
Quoted 5 lines
Then how about to introduce the software flags. and set it at each board. It can support the 800MHz.
Also this flags are handled at cpufreq drivers properly.How do you think?
Two SMDKs may have different versions of s3c6410.
Which file do we want to set the flags in ?
Does it general case in real? As SMDK is development board. If make a real board, it usually uses the same revision chip.
Quoted 1 line
PATCH 5/5 ARM: S3C6410: Add some lower frequencies for 800MHz base clock operation
In reply to Mark BrownBy extension from the 667MHz based clocks currently supported add 100MHz and 200MHz operating points. Due to a lack of documentation these have not been confirmed as supported but by extension from the existing frequencies they should be OK and there is less risk than with the previuus patch for 800MHz operation.
--- drivers/cpufreq/s3c64xx.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/cpufreq/s3c64xx.c +2 -0
@@ -36,7 +36,9 @@ static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = {static struct cpufreq_frequency_table s3c64xx_freq_table[] = { {0 ,66000 }, + {0 ,100000 }, {0 ,133000 }, + {1 ,200000 }, {1 ,222000 }, {1 ,266000 }, {2 ,333000 },
Signature · 1 line
1.7.5.3
Re: [PATCH 1/5] CPUFREQ/S3C64xx: Move S3C64xx CPUfreq driver into drivers/cpufreq
In reply to Mark BrownHi Mark,
Instead of samsung tree, it should be handled at cpufreq tree. CCed the cpufreq maintainer.
Thank you,
Kyungmin Park
Quoted 600 lines · Mark Brown
This is a straight code motion patch, there are no changes to the driver itself. The
Kconfigis left untouched as the ARM CPUfreqKconfigis all in one big block in arm/Kconfig and should be moved en masse rather than being done piecemeal.Signed-off-by Mark Brown <[email protected]>---
arch/arm/mach-s3c64xx/Makefile | 4 -arch/arm/mach-s3c64xx/cpufreq.c| 270 ---------------------------------------drivers/cpufreq/Makefile| 1 +drivers/cpufreq/s3c64xx.c| 269 ++++++++++++++++++++++++++++++++++++++4 files changed, 270 insertions(+), 274 deletions(-)delete mode 100644
arch/arm/mach-s3c64xx/cpufreq.ccreate mode 100644drivers/cpufreq/s3c64xx.carch/arm/mach-s3c64xx/Makefile +0
-0@@ -23,10 +23,6 @@ obj-$(CONFIG_CPU_S3C6410) += s3c6410.oobj-y += irq.o
obj-y += irq-eint.oarch/arm/mach-s3c64xx/Makefile +0
-4-# CPU frequency scaling - -obj-$(CONFIG_CPU_FREQ_S3C64XX) += cpufreq.o -# DMA support
obj-$(CONFIG_S3C64XX_DMA) += dma.o
arch/arm/mach-s3c64xx/cpufreq.c deleted +0
-270@@ -1,270 +0,0 @@ -/* linux/arch/arm/plat-s3c64xx/cpufreq.c -* -* Copyright 2009 Wolfson Microelectronics plc -* -* S3C64xx CPUfreq Support -* -* 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/types.h> -#include <linux/init.h> -#include <linux/cpufreq.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/regulator/consumer.h> - -static struct clk *armclk; -static struct regulator *vddarm; -static unsigned long regulator_latency; - -#ifdef CONFIG_CPU_S3C6410 -struct s3c64xx_dvfs { - unsigned int vddarm_min; - unsigned int vddarm_max; -}; - -static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = { - [0] = { 1000000, 1150000 }, - [1] = { 1050000, 1150000 }, - [2] = { 1100000, 1150000 }, - [3] = { 1200000, 1350000 }, -}; - -static struct cpufreq_frequency_table s3c64xx_freq_table[] = { - { 0, 66000 }, - { 0, 133000 }, - { 1, 222000 }, - { 1, 266000 }, - { 2, 333000 }, - { 2, 400000 }, - { 2, 532000 }, - { 2, 533000 }, - { 3, 667000 }, - { 0, CPUFREQ_TABLE_END }, -}; -#endif - -static int s3c64xx_cpufreq_verify_speed (struct cpufreq_policy *policy) -{ - if (policy->cpu != 0) - return -EINVAL; - - return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table); -} - -static unsigned int s3c64xx_cpufreq_get_speed (unsigned int cpu) -{ - if (cpu != 0) - return 0; - - return clk_get_rate(armclk) / 1000; -} - -static int s3c64xx_cpufreq_set_target (struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - int ret; - unsigned int i; - struct cpufreq_freqs freqs; - struct s3c64xx_dvfs *dvfs; - - ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table, - target_freq, relation, &i); - if (ret != 0) - return ret; - - freqs.cpu = 0; - freqs.old = clk_get_rate(armclk) / 1000; - freqs.new = s3c64xx_freq_table[i].frequency; - freqs.flags = 0; - dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].index]; - - if (freqs.old == freqs.new) - return 0; - - pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new); - - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - -#ifdef CONFIG_REGULATOR - if (vddarm && freqs.new > freqs.old) { - ret = regulator_set_voltage(vddarm, - dvfs->vddarm_min, - dvfs->vddarm_max); - if (ret != 0) { - pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n", - freqs.new, ret); - goto err; - } - } -#endif - - ret = clk_set_rate(armclk, freqs.new * 1000); - if (ret < 0) { - pr_err("cpufreq: Failed to set rate %dkHz: %d\n", - freqs.new, ret); - goto err; - } - -#ifdef CONFIG_REGULATOR - if (vddarm && freqs.new < freqs.old) { - ret = regulator_set_voltage(vddarm, - dvfs->vddarm_min, - dvfs->vddarm_max); - if (ret != 0) { - pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n", - freqs.new, ret); - goto err_clk; - } - } -#endif - - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - - pr_debug("cpufreq: Set actual frequency %lukHz\n", - clk_get_rate(armclk) / 1000); - - return 0; - -err_clk: - if (clk_set_rate(armclk, freqs.old * 1000) < 0) - pr_err("Failed to restore original clock rate\n"); -err: - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - - return ret; -} - -#ifdef CONFIG_REGULATOR -static void __init s3c64xx_cpufreq_config_regulator (void ) -{ - int count, v, i, found; - struct cpufreq_frequency_table *freq; - struct s3c64xx_dvfs *dvfs; - - count = regulator_count_voltages(vddarm); - if (count < 0) { - pr_err("cpufreq: Unable to check supported voltages\n"); - } - - freq = s3c64xx_freq_table; - while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) { - if (freq->frequency == CPUFREQ_ENTRY_INVALID) - continue; - - dvfs = &s3c64xx_dvfs_table[freq->index]; - found = 0; - - for (i = 0; i < count; i++) { - v = regulator_list_voltage(vddarm, i); - if (v >= dvfs->vddarm_min && v <= dvfs->vddarm_max) - found = 1; - } - - if (!found) { - pr_debug("cpufreq: %dkHz unsupported by regulator\n", - freq->frequency); - freq->frequency = CPUFREQ_ENTRY_INVALID; - } - - freq++; - } - - /* Guess based on having to do an I2C/SPI write; in future we - * will be able to query the regulator performance here. */ - regulator_latency = 1 * 1000 * 1000; -} -#endif - -static int s3c64xx_cpufreq_driver_init (struct cpufreq_policy *policy) -{ - int ret; - struct cpufreq_frequency_table *freq; - - if (policy->cpu != 0) - return -EINVAL; - - if (s3c64xx_freq_table == NULL) { - pr_err("cpufreq: No frequency information for this CPU\n"); - return -ENODEV; - } - - armclk = clk_get(NULL, "armclk"); - if (IS_ERR(armclk)) { - pr_err("cpufreq: Unable to obtain ARMCLK: %ld\n", - PTR_ERR(armclk)); - return PTR_ERR(armclk); - } - -#ifdef CONFIG_REGULATOR - vddarm = regulator_get(NULL, "vddarm"); - if (IS_ERR(vddarm)) { - ret = PTR_ERR(vddarm); - pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret); - pr_err("cpufreq: Only frequency scaling available\n"); - vddarm = NULL; - } else { - s3c64xx_cpufreq_config_regulator(); - } -#endif - - freq = s3c64xx_freq_table; - while (freq->frequency != CPUFREQ_TABLE_END) { - unsigned long r; - - /* Check for frequencies we can generate */ - r = clk_round_rate(armclk, freq->frequency * 1000); - r /= 1000; - if (r != freq->frequency) { - pr_debug("cpufreq: %dkHz unsupported by clock\n", - freq->frequency); - freq->frequency = CPUFREQ_ENTRY_INVALID; - } - - /* If we have no regulator then assume startup - * frequency is the maximum we can support. */ - if (!vddarm && freq->frequency > s3c64xx_cpufreq_get_speed(0)) - freq->frequency = CPUFREQ_ENTRY_INVALID; - - freq++; - } - - policy->cur = clk_get_rate(armclk) / 1000; - - /* Datasheet says PLL stabalisation time (if we were to use - * the PLLs, which we don't currently) is ~300us worst case, - * but add some fudge. - */ - policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency; - - ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table); - if (ret != 0) { - pr_err("cpufreq: Failed to configure frequency table: %d\n", - ret); - regulator_put(vddarm); - clk_put(armclk); - } - - return ret; -} - -static struct cpufreq_driver s3c64xx_cpufreq_driver = { - .owner = THIS_MODULE, - .flags = 0, - .verify = s3c64xx_cpufreq_verify_speed, - .target = s3c64xx_cpufreq_set_target, - .get = s3c64xx_cpufreq_get_speed, - .init = s3c64xx_cpufreq_driver_init, - .name = "s3c", -}; - -static int __init s3c64xx_cpufreq_init (void ) -{ - return cpufreq_register_driver(&s3c64xx_cpufreq_driver); -} -module_init (s3c64xx_cpufreq_init);drivers/cpufreq/Makefile +1
-0@@ -40,4 +40,5 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o ##################################################################################d # ARM SoC drivers +obj-$(CONFIG_CPU_FREQ_S3C64XX) += s3c64xx.oobj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
drivers/cpufreq/s3c64xx.c new file +269
-1@@ -0,0 +1,269 @@ +/* +* Copyright 2009 Wolfson Microelectronics plc +* +* S3C64xx CPUfreq Support +* +* 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/types.h> +#include <linux/init.h> +#include <linux/cpufreq.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/regulator/consumer.h> + +static struct clk *armclk; +static struct regulator *vddarm; +static unsigned long regulator_latency; + +#ifdef CONFIG_CPU_S3C6410 +struct s3c64xx_dvfs { + unsigned int vddarm_min; + unsigned int vddarm_max; +}; + +static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = { + [0] = { 1000000, 1150000 }, + [1] = { 1050000, 1150000 }, + [2] = { 1100000, 1150000 }, + [3] = { 1200000, 1350000 }, +}; + +static struct cpufreq_frequency_table s3c64xx_freq_table[] = { + { 0, 66000 }, + { 0, 133000 }, + { 1, 222000 }, + { 1, 266000 }, + { 2, 333000 }, + { 2, 400000 }, + { 2, 532000 }, + { 2, 533000 }, + { 3, 667000 }, + { 0, CPUFREQ_TABLE_END }, +}; +#endif + +static int s3c64xx_cpufreq_verify_speed (struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -EINVAL; + + return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table); +} + +static unsigned int s3c64xx_cpufreq_get_speed (unsigned int cpu) +{ + if (cpu != 0) + return 0; + + return clk_get_rate(armclk) / 1000; +} + +static int s3c64xx_cpufreq_set_target (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + int ret; + unsigned int i; + struct cpufreq_freqs freqs; + struct s3c64xx_dvfs *dvfs; + + ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table, + target_freq, relation, &i); + if (ret != 0) + return ret; + + freqs.cpu = 0; + freqs.old = clk_get_rate(armclk) / 1000; + freqs.new = s3c64xx_freq_table[i].frequency; + freqs.flags = 0; + dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].index]; + + if (freqs.old == freqs.new) + return 0; + + pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new); + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + +#ifdef CONFIG_REGULATOR + if (vddarm && freqs.new > freqs.old) { + ret = regulator_set_voltage(vddarm, + dvfs->vddarm_min, + dvfs->vddarm_max); + if (ret != 0) { + pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n", + freqs.new, ret); + goto err; + } + } +#endif + + ret = clk_set_rate(armclk, freqs.new * 1000); + if (ret < 0) { + pr_err("cpufreq: Failed to set rate %dkHz: %d\n", + freqs.new, ret); + goto err; + } + +#ifdef CONFIG_REGULATOR + if (vddarm && freqs.new < freqs.old) { + ret = regulator_set_voltage(vddarm, + dvfs->vddarm_min, + dvfs->vddarm_max); + if (ret != 0) { + pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n", + freqs.new, ret); + goto err_clk; + } + } +#endif + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + pr_debug("cpufreq: Set actual frequency %lukHz\n", + clk_get_rate(armclk) / 1000); + + return 0; + +err_clk: + if (clk_set_rate(armclk, freqs.old * 1000) < 0) + pr_err("Failed to restore original clock rate\n"); +err: + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return ret; +} + +#ifdef CONFIG_REGULATOR +static void __init s3c64xx_cpufreq_config_regulator (void ) +{ + int count, v, i, found; + struct cpufreq_frequency_table *freq; + struct s3c64xx_dvfs *dvfs; + + count = regulator_count_voltages(vddarm); + if (count < 0) { + pr_err("cpufreq: Unable to check supported voltages\n"); + } + + freq = s3c64xx_freq_table; + while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) { + if (freq->frequency == CPUFREQ_ENTRY_INVALID) + continue; + + dvfs = &s3c64xx_dvfs_table[freq->index]; + found = 0; + + for (i = 0; i < count; i++) { + v = regulator_list_voltage(vddarm, i); + if (v >= dvfs->vddarm_min && v <= dvfs->vddarm_max) + found = 1; + } + + if (!found) { + pr_debug("cpufreq: %dkHz unsupported by regulator\n", + freq->frequency); + freq->frequency = CPUFREQ_ENTRY_INVALID; + } + + freq++; + } + + /* Guess based on having to do an I2C/SPI write; in future we + * will be able to query the regulator performance here. */ + regulator_latency = 1 * 1000 * 1000; +} +#endif + +static int s3c64xx_cpufreq_driver_init (struct cpufreq_policy *policy) +{ + int ret; + struct cpufreq_frequency_table *freq; + + if (policy->cpu != 0) + return -EINVAL; + + if (s3c64xx_freq_table == NULL) { + pr_err("cpufreq: No frequency information for this CPU\n"); + return -ENODEV; + } + + armclk = clk_get(NULL, "armclk"); + if (IS_ERR(armclk)) { + pr_err("cpufreq: Unable to obtain ARMCLK: %ld\n", + PTR_ERR(armclk)); + return PTR_ERR(armclk); + } + +#ifdef CONFIG_REGULATOR + vddarm = regulator_get(NULL, "vddarm"); + if (IS_ERR(vddarm)) { + ret = PTR_ERR(vddarm); + pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret); + pr_err("cpufreq: Only frequency scaling available\n"); + vddarm = NULL; + } else { + s3c64xx_cpufreq_config_regulator(); + } +#endif + + freq = s3c64xx_freq_table; + while (freq->frequency != CPUFREQ_TABLE_END) { + unsigned long r; + + /* Check for frequencies we can generate */ + r = clk_round_rate(armclk, freq->frequency * 1000); + r /= 1000; + if (r != freq->frequency) { + pr_debug("cpufreq: %dkHz unsupported by clock\n", + freq->frequency); + freq->frequency = CPUFREQ_ENTRY_INVALID; + } + + /* If we have no regulator then assume startup + * frequency is the maximum we can support. */ + if (!vddarm && freq->frequency > s3c64xx_cpufreq_get_speed(0)) + freq->frequency = CPUFREQ_ENTRY_INVALID; + + freq++; + } + + policy->cur = clk_get_rate(armclk) / 1000; + + /* Datasheet says PLL stabalisation time (if we were to use + * the PLLs, which we don't currently) is ~300us worst case, + * but add some fudge. + */ + policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency; + + ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table); + if (ret != 0) { + pr_err("cpufreq: Failed to configure frequency table: %d\n", + ret); + regulator_put(vddarm); + clk_put(armclk); + } + + return ret; +} + +static struct cpufreq_driver s3c64xx_cpufreq_driver = { + .owner = THIS_MODULE, + .flags = 0, + .verify = s3c64xx_cpufreq_verify_speed, + .target = s3c64xx_cpufreq_set_target, + .get = s3c64xx_cpufreq_get_speed, + .init = s3c64xx_cpufreq_driver_init, + .name = "s3c", +}; + +static int __init s3c64xx_cpufreq_init (void ) +{ + return cpufreq_register_driver(&s3c64xx_cpufreq_driver); +} +module_init (s3c64xx_cpufreq_init); --1.7.5.3
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [PATCH 1/5] CPUFREQ/S3C64xx: Move S3C64xx CPUfreq driver into drivers/cpufreq
Quoted 2 lines · Kyungmin Park
Instead of samsung tree, it should be handled at cpufreq tree. CCed the cpufreq maintainer.
Well, it's a something for both really as both trees are updated. I sent the orginal copy of this patch to both places but both sets of maintainers just ignored it (I've never seen any response from the cpufreq maintainers on this driver ever since I originally submitted it).
At the minute I'm mostly just trying to get some of the backlog of S3C64xx patches I'm accumilating out of my queue :(
Re: [PATCH 1/5] CPUFREQ/S3C64xx: Move S3C64xx CPUfreq driver into drivers/cpufreq
Quoted 10 lines · Mark Brown
Quoted 2 lines · Kyungmin Park
Instead of samsung tree, it should be handled at cpufreq tree. CCed the cpufreq maintainer.
Well, it's a something for both really as both trees are updated. I sent the orginal copy of this patch to both places but both sets of maintainers just ignored it (I've never seen any response from the cpufreq maintainers on this driver ever since I originally submitted it).
Sorry about that. It's actually in my 'to merge' mailbox, but I've been laggy at dealing with it recently. I'll try and clear the backlog in the next day or two.
thanks,
Dave
Re: [PATCH 1/5] CPUFREQ/S3C64xx: Move S3C64xx CPUfreq driver into drivers/cpufreq
Quoted 12 lines · Dave Jones
Quoted 10 lines · Mark Brown
Quoted 2 lines · Kyungmin Park
Instead of samsung tree, it should be handled at cpufreq tree. CCed the cpufreq maintainer.
Well, it's a something for both really as both trees are updated. I sent the orginal copy of this patch to both places but both sets of maintainers just ignored it (I've never seen any response from the cpufreq maintainers on this driver ever since I originally submitted it).
Quoted 3 lines
Sorry about that. It's actually in my 'to merge' mailbox, but I've been laggy at dealing with it recently. I'll try and clear the backlog in the next day or two.
Ok, I finally got around to sorting this out. It needed some small changes to fix up rejects in drivers/cpufreq/Makefile, but they looked trivial enough that I'm sure they're ok. But look them over anyway ?
I also applied the S5PV210/EXYNOS4210 patch which also needed the same fixing. Both pushed out to cpufreq.next
Let me know if there's anything I've missed
thanks,
Dave
Re: [PATCH 1/5] CPUFREQ/S3C64xx: Move S3C64xx CPUfreq driver into drivers/cpufreq
In reply to Mark BrownQuoted 11 lines · Mark Brown
Quoted 2 lines · Kyungmin Park
Instead of samsung tree, it should be handled at cpufreq tree. CCed the cpufreq maintainer.
Well, it's a something for both really as both trees are updated. I sent the orginal copy of this patch to both places but both sets of maintainers just ignored it (I've never seen any response from the cpufreq maintainers on this driver ever since I originally submitted it).
Hi Mark,
Sorry for late response.
Basically, you're moving is great to me and will review in 1 day.
As I remember, 800Mhz support on S3C6410 is ok and replied about that. Then isn't there any progress in my side?...I'm outside of my office.
Quoted 2 lines
At the minute I'm mostly just trying to get some of the backlog of S3C64xx patches I'm accumilating out of my queue :(
Dave, I'd like to talk about moving Samsung cpufreq drivers. I sent about Kconfig.arm. If you're ok, will submit remained one to move all of Samsung cpufreq drivers. And if possible would be better to me, if someone(you or me) could make some branch to merge into both.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
Re: [PATCH 1/5] CPUFREQ/S3C64xx: Move S3C64xx CPUfreq driver into drivers/cpufreq
Quoted 2 lines · Kukjin Kim
As I remember, 800Mhz support on S3C6410 is ok and replied about that. Then isn't there any progress in my side?...I'm outside of my office.
Yes, you replied and said it was OK but it's not appeared in -next yet.
Re: [PATCH 1/5] CPUFREQ/S3C64xx: Move S3C64xx CPUfreq driver into drivers/cpufreq
Quoted 6 lines · Mark Brown
Quoted 2 lines · Kukjin Kim
As I remember, 800Mhz support on S3C6410 is ok and replied about that. Then isn't there any progress in my side?...I'm outside of my office.
Yes, you replied and said it was OK but it's not appeared in -next yet.
Oops, sorry :(
Maybe I missed.
Ok, will apply in my after checking others.
Then if any updates, let you know.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.