* [PATCH v4 0/4] ARM: zynq: cpufreq support
@ 2014-02-19 23:14 Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 1/4] clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs enabled Soren Brinkmann
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Soren Brinkmann @ 2014-02-19 23:14 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
another iteration of this series. The patches are the same as in v3, but
the series shrank a bit. I rebased this series on tip/timers/core, hence
the two patches for the clockevent core fell out, since Thomas already
applied those.
Additionally I removed the patch 'clocksource/cadence_ttc: Use only one
counter'. Thomas brought up some questions regarding that patch which
need to be investigated. Since it is not required for the rest of this
series, I just dropped it for now.
Thanks,
S?ren
Soren Brinkmann (4):
clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs
enabled
clocksource/cadence_ttc: Overhaul clocksource frequency adjustment
arm: zynq: Don't use arm_global_timer with cpufreq
arm: zynq: Add support for cpufreq
arch/arm/boot/dts/zynq-7000.dtsi | 6 ++
arch/arm/mach-zynq/Kconfig | 4 +-
arch/arm/mach-zynq/common.c | 3 +
drivers/clocksource/cadence_ttc_timer.c | 121 +++++++++++++++++++++++---------
4 files changed, 98 insertions(+), 36 deletions(-)
--
1.9.0.1.g4196000
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v4 1/4] clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs enabled
2014-02-19 23:14 [PATCH v4 0/4] ARM: zynq: cpufreq support Soren Brinkmann
@ 2014-02-19 23:14 ` Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 2/4] clocksource/cadence_ttc: Overhaul clocksource frequency adjustment Soren Brinkmann
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Soren Brinkmann @ 2014-02-19 23:14 UTC (permalink / raw)
To: linux-arm-kernel
The timer core takes care of serialization and IRQs. Hence the driver is
no longer required to disable interrupts when calling
clockevents_update_freq().
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
v4:
- no change
drivers/clocksource/cadence_ttc_timer.c | 17 ++---------------
1 file changed, 2 insertions(+), 15 deletions(-)
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
index 63f176de0d02..f05b9fdc7425 100644
--- a/drivers/clocksource/cadence_ttc_timer.c
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -321,25 +321,12 @@ static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
switch (event) {
case POST_RATE_CHANGE:
- {
- unsigned long flags;
-
- /*
- * clockevents_update_freq should be called with IRQ disabled on
- * the CPU the timer provides events for. The timer we use is
- * common to both CPUs, not sure if we need to run on both
- * cores.
- */
- local_irq_save(flags);
- clockevents_update_freq(&ttcce->ce,
- ndata->new_rate / PRESCALE);
- local_irq_restore(flags);
-
/* update cached frequency */
ttc->freq = ndata->new_rate;
+ clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE);
+
/* fall through */
- }
case PRE_RATE_CHANGE:
case ABORT_RATE_CHANGE:
default:
--
1.9.0.1.g4196000
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 2/4] clocksource/cadence_ttc: Overhaul clocksource frequency adjustment
2014-02-19 23:14 [PATCH v4 0/4] ARM: zynq: cpufreq support Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 1/4] clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs enabled Soren Brinkmann
@ 2014-02-19 23:14 ` Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 3/4] arm: zynq: Don't use arm_global_timer with cpufreq Soren Brinkmann
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Soren Brinkmann @ 2014-02-19 23:14 UTC (permalink / raw)
To: linux-arm-kernel
The currently used method adjusting the clocksource to a changing input
frequency does not work on kernels from 3.11 on.
The new approach is to keep the timer frequency as constant as possible.
I.e.
- due to the TTC's prescaler limitations, allow frequency changes
only if the frequency scales by a power of 2
- adjust the counter's divider on the fly when a frequency change
occurs
This limits cpufreq to scale by certain factors only.
But we may keep the time base somewhat constant, so that sleep() & co
keep working as expected, while supporting cpufreq.
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
v4:
- no changes
v3:
- Clock notifier data does not behave as documented. Adjust code
accordingly (https://lkml.org/lkml/2014/1/22/412)
v2:
- remove PM notifier and associated code
---
drivers/clocksource/cadence_ttc_timer.c | 104 ++++++++++++++++++++++++++------
1 file changed, 84 insertions(+), 20 deletions(-)
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
index f05b9fdc7425..49fbe2847c84 100644
--- a/drivers/clocksource/cadence_ttc_timer.c
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -16,6 +16,7 @@
*/
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/interrupt.h>
#include <linux/clockchips.h>
#include <linux/of_address.h>
@@ -52,6 +53,8 @@
#define TTC_CNT_CNTRL_DISABLE_MASK 0x1
#define TTC_CLK_CNTRL_CSRC_MASK (1 << 5) /* clock source */
+#define TTC_CLK_CNTRL_PSV_MASK 0x1e
+#define TTC_CLK_CNTRL_PSV_SHIFT 1
/*
* Setup the timers to use pre-scaling, using a fixed value for now that will
@@ -63,6 +66,8 @@
#define CLK_CNTRL_PRESCALE_EN 1
#define CNT_CNTRL_RESET (1 << 4)
+#define MAX_F_ERR 50
+
/**
* struct ttc_timer - This definition defines local timer structure
*
@@ -82,6 +87,8 @@ struct ttc_timer {
container_of(x, struct ttc_timer, clk_rate_change_nb)
struct ttc_timer_clocksource {
+ u32 scale_clk_ctrl_reg_old;
+ u32 scale_clk_ctrl_reg_new;
struct ttc_timer ttc;
struct clocksource cs;
};
@@ -229,32 +236,89 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb,
struct ttc_timer_clocksource, ttc);
switch (event) {
- case POST_RATE_CHANGE:
+ case PRE_RATE_CHANGE:
+ {
+ u32 psv;
+ unsigned long factor, rate_low, rate_high;
+
+ if (ndata->new_rate > ndata->old_rate) {
+ factor = DIV_ROUND_CLOSEST(ndata->new_rate,
+ ndata->old_rate);
+ rate_low = ndata->old_rate;
+ rate_high = ndata->new_rate;
+ } else {
+ factor = DIV_ROUND_CLOSEST(ndata->old_rate,
+ ndata->new_rate);
+ rate_low = ndata->new_rate;
+ rate_high = ndata->old_rate;
+ }
+
+ if (!is_power_of_2(factor))
+ return NOTIFY_BAD;
+
+ if (abs(rate_high - (factor * rate_low)) > MAX_F_ERR)
+ return NOTIFY_BAD;
+
+ factor = __ilog2_u32(factor);
+
/*
- * Do whatever is necessary to maintain a proper time base
- *
- * I cannot find a way to adjust the currently used clocksource
- * to the new frequency. __clocksource_updatefreq_hz() sounds
- * good, but does not work. Not sure what's that missing.
- *
- * This approach works, but triggers two clocksource switches.
- * The first after unregister to clocksource jiffies. And
- * another one after the register to the newly registered timer.
- *
- * Alternatively we could 'waste' another HW timer to ping pong
- * between clock sources. That would also use one register and
- * one unregister call, but only trigger one clocksource switch
- * for the cost of another HW timer used by the OS.
+ * store timer clock ctrl register so we can restore it in case
+ * of an abort.
*/
- clocksource_unregister(&ttccs->cs);
- clocksource_register_hz(&ttccs->cs,
- ndata->new_rate / PRESCALE);
- /* fall through */
- case PRE_RATE_CHANGE:
+ ttccs->scale_clk_ctrl_reg_old =
+ __raw_readl(ttccs->ttc.base_addr +
+ TTC_CLK_CNTRL_OFFSET);
+
+ psv = (ttccs->scale_clk_ctrl_reg_old &
+ TTC_CLK_CNTRL_PSV_MASK) >>
+ TTC_CLK_CNTRL_PSV_SHIFT;
+ if (ndata->new_rate < ndata->old_rate)
+ psv -= factor;
+ else
+ psv += factor;
+
+ /* prescaler within legal range? */
+ if (psv & ~(TTC_CLK_CNTRL_PSV_MASK >> TTC_CLK_CNTRL_PSV_SHIFT))
+ return NOTIFY_BAD;
+
+ ttccs->scale_clk_ctrl_reg_new = ttccs->scale_clk_ctrl_reg_old &
+ ~TTC_CLK_CNTRL_PSV_MASK;
+ ttccs->scale_clk_ctrl_reg_new |= psv << TTC_CLK_CNTRL_PSV_SHIFT;
+
+
+ /* scale down: adjust divider in post-change notification */
+ if (ndata->new_rate < ndata->old_rate)
+ return NOTIFY_DONE;
+
+ /* scale up: adjust divider now - before frequency change */
+ __raw_writel(ttccs->scale_clk_ctrl_reg_new,
+ ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+ break;
+ }
+ case POST_RATE_CHANGE:
+ /* scale up: pre-change notification did the adjustment */
+ if (ndata->new_rate > ndata->old_rate)
+ return NOTIFY_OK;
+
+ /* scale down: adjust divider now - after frequency change */
+ __raw_writel(ttccs->scale_clk_ctrl_reg_new,
+ ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+ break;
+
case ABORT_RATE_CHANGE:
+ /* we have to undo the adjustment in case we scale up */
+ if (ndata->new_rate < ndata->old_rate)
+ return NOTIFY_OK;
+
+ /* restore original register value */
+ __raw_writel(ttccs->scale_clk_ctrl_reg_old,
+ ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+ /* fall through */
default:
return NOTIFY_DONE;
}
+
+ return NOTIFY_DONE;
}
static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
--
1.9.0.1.g4196000
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 3/4] arm: zynq: Don't use arm_global_timer with cpufreq
2014-02-19 23:14 [PATCH v4 0/4] ARM: zynq: cpufreq support Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 1/4] clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs enabled Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 2/4] clocksource/cadence_ttc: Overhaul clocksource frequency adjustment Soren Brinkmann
@ 2014-02-19 23:14 ` Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 4/4] arm: zynq: Add support for cpufreq Soren Brinkmann
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Soren Brinkmann @ 2014-02-19 23:14 UTC (permalink / raw)
To: linux-arm-kernel
The timer frequency of the arm_global_timer depends on the CPU
frequency. With cpufreq altering that frequency the arm_global_timer
does not maintain a stable time base. Therefore don't enable that timer
in case cpufreq is enabled.
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
v4:
- no change
arch/arm/mach-zynq/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index 6b04260aa142..f84fab14f0b7 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -13,6 +13,6 @@ config ARCH_ZYNQ
select HAVE_SMP
select SPARSE_IRQ
select CADENCE_TTC_TIMER
- select ARM_GLOBAL_TIMER
+ select ARM_GLOBAL_TIMER if !CPU_FREQ
help
Support for Xilinx Zynq ARM Cortex A9 Platform
--
1.9.0.1.g4196000
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 4/4] arm: zynq: Add support for cpufreq
2014-02-19 23:14 [PATCH v4 0/4] ARM: zynq: cpufreq support Soren Brinkmann
` (2 preceding siblings ...)
2014-02-19 23:14 ` [PATCH v4 3/4] arm: zynq: Don't use arm_global_timer with cpufreq Soren Brinkmann
@ 2014-02-19 23:14 ` Soren Brinkmann
2014-02-27 17:52 ` [PATCH v4 0/4] ARM: zynq: cpufreq support Sören Brinkmann
[not found] ` <20140227175217.GW13293@xsjandreislx>
5 siblings, 0 replies; 8+ messages in thread
From: Soren Brinkmann @ 2014-02-19 23:14 UTC (permalink / raw)
To: linux-arm-kernel
The generic cpufreq-cpu0 driver can scale the CPU frequency on Zynq
SOCs. Add the required platform device to the BSP and appropriate
OPPs to the dts.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: devicetree at vger.kernel.org
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
v4:
- no change
v3:
- change lowest frequency to 222223 (F_max / 3)
---
arch/arm/boot/dts/zynq-7000.dtsi | 6 ++++++
arch/arm/mach-zynq/Kconfig | 2 ++
arch/arm/mach-zynq/common.c | 3 +++
3 files changed, 11 insertions(+)
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index 8b67b19392ec..789d0bacc110 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -24,6 +24,12 @@
device_type = "cpu";
reg = <0>;
clocks = <&clkc 3>;
+ operating-points = <
+ /* kHz uV */
+ 666667 1000000
+ 333334 1000000
+ 222223 1000000
+ >;
};
cpu at 1 {
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index f84fab14f0b7..f03e75bd0b2b 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -2,6 +2,8 @@ config ARCH_ZYNQ
bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7
select ARM_AMBA
select ARM_GIC
+ select ARCH_HAS_CPUFREQ
+ select ARCH_HAS_OPP
select COMMON_CLK
select CPU_V7
select GENERIC_CLOCKEVENTS
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 1db2a5ca9ab8..644468151c04 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -51,6 +51,8 @@ static struct platform_device zynq_cpuidle_device = {
*/
static void __init zynq_init_machine(void)
{
+ struct platform_device_info devinfo = { .name = "cpufreq-cpu0", };
+
/*
* 64KB way size, 8-way associativity, parity disabled
*/
@@ -59,6 +61,7 @@ static void __init zynq_init_machine(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
platform_device_register(&zynq_cpuidle_device);
+ platform_device_register_full(&devinfo);
}
static void __init zynq_timer_init(void)
--
1.9.0.1.g4196000
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 0/4] ARM: zynq: cpufreq support
2014-02-19 23:14 [PATCH v4 0/4] ARM: zynq: cpufreq support Soren Brinkmann
` (3 preceding siblings ...)
2014-02-19 23:14 ` [PATCH v4 4/4] arm: zynq: Add support for cpufreq Soren Brinkmann
@ 2014-02-27 17:52 ` Sören Brinkmann
2014-02-28 6:58 ` Daniel Lezcano
[not found] ` <20140227175217.GW13293@xsjandreislx>
5 siblings, 1 reply; 8+ messages in thread
From: Sören Brinkmann @ 2014-02-27 17:52 UTC (permalink / raw)
To: linux-arm-kernel
Hi Daniel, Michal,
On Wed, 2014-02-19 at 03:14PM -0800, Soren Brinkmann wrote:
> Hi,
>
> another iteration of this series. The patches are the same as in v3, but
> the series shrank a bit. I rebased this series on tip/timers/core, hence
> the two patches for the clockevent core fell out, since Thomas already
> applied those.
> Additionally I removed the patch 'clocksource/cadence_ttc: Use only one
> counter'. Thomas brought up some questions regarding that patch which
> need to be investigated. Since it is not required for the rest of this
> series, I just dropped it for now.
>
> Thanks,
> S?ren
>
> Soren Brinkmann (4):
> clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs
> enabled
> clocksource/cadence_ttc: Overhaul clocksource frequency adjustment
> arm: zynq: Don't use arm_global_timer with cpufreq
> arm: zynq: Add support for cpufreq
Any comments? I think most of these should be pretty straight forward
and it would be nice to get some ACKs - or tell me what's wrong. :)
'clocksource/cadence_ttc: Overhaul clocksource frequency adjustment'
might deserve a more thorough review.
Thanks,
S?ren
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v4 0/4] ARM: zynq: cpufreq support
[not found] ` <20140227175217.GW13293@xsjandreislx>
@ 2014-02-28 6:26 ` Michal Simek
0 siblings, 0 replies; 8+ messages in thread
From: Michal Simek @ 2014-02-28 6:26 UTC (permalink / raw)
To: linux-arm-kernel
On 02/27/2014 06:52 PM, S?ren Brinkmann wrote:
> Hi Daniel, Michal,
>
> On Wed, 2014-02-19 at 03:14PM -0800, Soren Brinkmann wrote:
>> Hi,
>>
>> another iteration of this series. The patches are the same as in v3, but
>> the series shrank a bit. I rebased this series on tip/timers/core, hence
>> the two patches for the clockevent core fell out, since Thomas already
>> applied those.
>> Additionally I removed the patch 'clocksource/cadence_ttc: Use only one
>> counter'. Thomas brought up some questions regarding that patch which
>> need to be investigated. Since it is not required for the rest of this
>> series, I just dropped it for now.
>>
>> Thanks,
>> S?ren
>>
>> Soren Brinkmann (4):
>> clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs
>> enabled
>> clocksource/cadence_ttc: Overhaul clocksource frequency adjustment
>> arm: zynq: Don't use arm_global_timer with cpufreq
>> arm: zynq: Add support for cpufreq
>
> Any comments? I think most of these should be pretty straight forward
> and it would be nice to get some ACKs - or tell me what's wrong. :)
> 'clocksource/cadence_ttc: Overhaul clocksource frequency adjustment'
> might deserve a more thorough review.
No problem from my side.
Daniel?
Thanks,
Michal
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v4 0/4] ARM: zynq: cpufreq support
2014-02-27 17:52 ` [PATCH v4 0/4] ARM: zynq: cpufreq support Sören Brinkmann
@ 2014-02-28 6:58 ` Daniel Lezcano
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Lezcano @ 2014-02-28 6:58 UTC (permalink / raw)
To: linux-arm-kernel
On 02/27/2014 06:52 PM, S?ren Brinkmann wrote:
> Hi Daniel, Michal,
>
> On Wed, 2014-02-19 at 03:14PM -0800, Soren Brinkmann wrote:
>> Hi,
>>
>> another iteration of this series. The patches are the same as in v3, but
>> the series shrank a bit. I rebased this series on tip/timers/core, hence
>> the two patches for the clockevent core fell out, since Thomas already
>> applied those.
>> Additionally I removed the patch 'clocksource/cadence_ttc: Use only one
>> counter'. Thomas brought up some questions regarding that patch which
>> need to be investigated. Since it is not required for the rest of this
>> series, I just dropped it for now.
>>
>> Thanks,
>> S?ren
>>
>> Soren Brinkmann (4):
>> clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs
>> enabled
>> clocksource/cadence_ttc: Overhaul clocksource frequency adjustment
>> arm: zynq: Don't use arm_global_timer with cpufreq
>> arm: zynq: Add support for cpufreq
>
> Any comments? I think most of these should be pretty straight forward
> and it would be nice to get some ACKs - or tell me what's wrong. :)
> 'clocksource/cadence_ttc: Overhaul clocksource frequency adjustment'
> might deserve a more thorough review.
Hi Soren,
I will be at Linaro Connect. Give me a couple of days, I will review
them again.
Thanks
-- Daniel
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2014-02-28 6:58 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-19 23:14 [PATCH v4 0/4] ARM: zynq: cpufreq support Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 1/4] clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs enabled Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 2/4] clocksource/cadence_ttc: Overhaul clocksource frequency adjustment Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 3/4] arm: zynq: Don't use arm_global_timer with cpufreq Soren Brinkmann
2014-02-19 23:14 ` [PATCH v4 4/4] arm: zynq: Add support for cpufreq Soren Brinkmann
2014-02-27 17:52 ` [PATCH v4 0/4] ARM: zynq: cpufreq support Sören Brinkmann
2014-02-28 6:58 ` Daniel Lezcano
[not found] ` <20140227175217.GW13293@xsjandreislx>
2014-02-28 6:26 ` Michal Simek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox