* [PATCH 1/3] kernel: add calibration_delay_done()
2014-05-20 15:36 [PATCH 0/3] Use Tegra's microsecond counter for udelay() Peter De Schrijver
@ 2014-05-20 15:36 ` Peter De Schrijver
2014-05-20 17:41 ` Sergei Shtylyov
2014-05-20 15:36 ` [PATCH 2/3] ARM: choose highest resolution delay timer Peter De Schrijver
2014-05-20 15:36 ` [PATCH 3/3] clocksource: tegra: Use uS counter as " Peter De Schrijver
2 siblings, 1 reply; 7+ messages in thread
From: Peter De Schrijver @ 2014-05-20 15:36 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Russell King, Daniel Lezcano, Thomas Gleixner, Stephen Warren,
Thierry Reding, Paul Gortmaker, linux-arm-kernel, linux-kernel,
linux-tegra
Add calibration_delay_done() call and dummy implementation. This allows
architectures to stop accepting registrations for new timer based delay
functions.
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
init/calibrate.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/init/calibrate.c b/init/calibrate.c
index 520702d..31cae76 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -262,6 +262,16 @@ unsigned long __attribute__((weak)) calibrate_delay_is_known(void)
return 0;
}
+/*
+ * Indicate the cpu delay calibration is done. This can be used by
+ * architectures to stop accepting delay timer registrations after this point.
+ */
+
+void __attribute__((weak)) calibration_delay_done(void)
+{
+ return;
+}
+
void calibrate_delay(void)
{
unsigned long lpj;
@@ -301,4 +311,6 @@ void calibrate_delay(void)
loops_per_jiffy = lpj;
printed = true;
+
+ calibration_delay_done();
}
--
1.7.7.rc0.72.g4b5ea.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] kernel: add calibration_delay_done()
2014-05-20 15:36 ` [PATCH 1/3] kernel: add calibration_delay_done() Peter De Schrijver
@ 2014-05-20 17:41 ` Sergei Shtylyov
0 siblings, 0 replies; 7+ messages in thread
From: Sergei Shtylyov @ 2014-05-20 17:41 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Russell King, Stephen Warren, Daniel Lezcano, linux-kernel,
Paul Gortmaker, Thierry Reding, linux-tegra, Thomas Gleixner,
linux-arm-kernel
On 05/20/2014 07:36 PM, Peter De Schrijver wrote:
> Add calibration_delay_done() call and dummy implementation. This allows
> architectures to stop accepting registrations for new timer based delay
> functions.
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
> init/calibrate.c | 12 ++++++++++++
> 1 files changed, 12 insertions(+), 0 deletions(-)
> diff --git a/init/calibrate.c b/init/calibrate.c
> index 520702d..31cae76 100644
> --- a/init/calibrate.c
> +++ b/init/calibrate.c
> @@ -262,6 +262,16 @@ unsigned long __attribute__((weak)) calibrate_delay_is_known(void)
> return 0;
> }
>
> +/*
> + * Indicate the cpu delay calibration is done. This can be used by
> + * architectures to stop accepting delay timer registrations after this point.
> + */
> +
> +void __attribute__((weak)) calibration_delay_done(void)
> +{
> + return;
Not really needed.
> +}
> +
> void calibrate_delay(void)
> {
> unsigned long lpj;
WBR, Sergei
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/3] ARM: choose highest resolution delay timer
2014-05-20 15:36 [PATCH 0/3] Use Tegra's microsecond counter for udelay() Peter De Schrijver
2014-05-20 15:36 ` [PATCH 1/3] kernel: add calibration_delay_done() Peter De Schrijver
@ 2014-05-20 15:36 ` Peter De Schrijver
2014-05-20 15:36 ` [PATCH 3/3] clocksource: tegra: Use uS counter as " Peter De Schrijver
2 siblings, 0 replies; 7+ messages in thread
From: Peter De Schrijver @ 2014-05-20 15:36 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Russell King, Daniel Lezcano, Thomas Gleixner, Stephen Warren,
Thierry Reding, Paul Gortmaker, linux-arm-kernel, linux-kernel,
linux-tegra
In case there are several possible delay timers, choose the one with the
highest resolution. This code relies on the fact secondary CPUs have not yet
been brought online when register_current_timer_delay() is called. This is
ensured by implementing calibration_delay_done(),
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
arch/arm/lib/delay.c | 26 ++++++++++++++++++++++----
1 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c
index 5306de3..312d43e 100644
--- a/arch/arm/lib/delay.c
+++ b/arch/arm/lib/delay.c
@@ -19,6 +19,7 @@
* Author: Will Deacon <will.deacon@arm.com>
*/
+#include <linux/clocksource.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -36,6 +37,7 @@ struct arm_delay_ops arm_delay_ops = {
static const struct delay_timer *delay_timer;
static bool delay_calibrated;
+static u64 delay_res;
int read_current_timer(unsigned long *timer_val)
{
@@ -47,6 +49,11 @@ int read_current_timer(unsigned long *timer_val)
}
EXPORT_SYMBOL_GPL(read_current_timer);
+static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
+{
+ return (cyc * mult) >> shift;
+}
+
static void __timer_delay(unsigned long cycles)
{
cycles_t start = get_cycles();
@@ -69,18 +76,24 @@ static void __timer_udelay(unsigned long usecs)
void __init register_current_timer_delay(const struct delay_timer *timer)
{
- if (!delay_calibrated) {
- pr_info("Switching to timer-based delay loop\n");
+ u32 new_mult, new_shift;
+ u64 res;
+
+ clocks_calc_mult_shift(&new_mult, &new_shift, timer->freq,
+ NSEC_PER_SEC, 3600);
+ res = cyc_to_ns(1ULL, new_mult, new_shift);
+
+ if (!delay_calibrated && (!delay_res || (res < delay_res))) {
+ pr_info("Switching to timer-based delay loop, resolution %lluns\n", res);
delay_timer = timer;
lpj_fine = timer->freq / HZ;
+ delay_res = res;
/* cpufreq may scale loops_per_jiffy, so keep a private copy */
arm_delay_ops.ticks_per_jiffy = lpj_fine;
arm_delay_ops.delay = __timer_delay;
arm_delay_ops.const_udelay = __timer_const_udelay;
arm_delay_ops.udelay = __timer_udelay;
-
- delay_calibrated = true;
} else {
pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
}
@@ -91,3 +104,8 @@ unsigned long calibrate_delay_is_known(void)
delay_calibrated = true;
return lpj_fine;
}
+
+void calibration_delay_done(void)
+{
+ delay_calibrated = true;
+}
--
1.7.7.rc0.72.g4b5ea.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] clocksource: tegra: Use uS counter as delay timer
2014-05-20 15:36 [PATCH 0/3] Use Tegra's microsecond counter for udelay() Peter De Schrijver
2014-05-20 15:36 ` [PATCH 1/3] kernel: add calibration_delay_done() Peter De Schrijver
2014-05-20 15:36 ` [PATCH 2/3] ARM: choose highest resolution delay timer Peter De Schrijver
@ 2014-05-20 15:36 ` Peter De Schrijver
2014-05-20 18:37 ` Stephen Warren
2014-05-22 13:56 ` Thierry Reding
2 siblings, 2 replies; 7+ messages in thread
From: Peter De Schrijver @ 2014-05-20 15:36 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Russell King, Daniel Lezcano, Thomas Gleixner, Stephen Warren,
Thierry Reding, Paul Gortmaker, linux-arm-kernel, linux-kernel,
linux-tegra
All Tegra SoCs have a freerunning microsecond counter which can be used as a
delay timer.
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
drivers/clocksource/tegra20_timer.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index d1869f0..ed49a0b 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -28,6 +28,7 @@
#include <linux/of_irq.h>
#include <linux/sched_clock.h>
+#include <asm/delay.h>
#include <asm/mach/time.h>
#include <asm/smp_twd.h>
@@ -53,6 +54,8 @@ static void __iomem *rtc_base;
static struct timespec persistent_ts;
static u64 persistent_ms, last_persistent_ms;
+static struct delay_timer tegra_delay_timer;
+
#define timer_writel(value, reg) \
__raw_writel(value, timer_reg_base + (reg))
#define timer_readl(reg) \
@@ -139,6 +142,11 @@ static void tegra_read_persistent_clock(struct timespec *ts)
*ts = *tsp;
}
+static unsigned long tegra_delay_timer_read_counter_long(void)
+{
+ return readl(timer_reg_base + TIMERUS_CNTR_1US);
+}
+
static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = (struct clock_event_device *)dev_id;
@@ -206,6 +214,11 @@ static void __init tegra20_init_timer(struct device_node *np)
BUG();
}
+ tegra_delay_timer.read_current_timer =
+ tegra_delay_timer_read_counter_long;
+ tegra_delay_timer.freq = 1000000;
+ register_current_timer_delay(&tegra_delay_timer);
+
ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
if (ret) {
pr_err("Failed to register timer IRQ: %d\n", ret);
--
1.7.7.rc0.72.g4b5ea.dirty
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] clocksource: tegra: Use uS counter as delay timer
2014-05-20 15:36 ` [PATCH 3/3] clocksource: tegra: Use uS counter as " Peter De Schrijver
@ 2014-05-20 18:37 ` Stephen Warren
2014-05-22 13:56 ` Thierry Reding
1 sibling, 0 replies; 7+ messages in thread
From: Stephen Warren @ 2014-05-20 18:37 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Russell King, Daniel Lezcano, Thomas Gleixner, Thierry Reding,
Paul Gortmaker, linux-arm-kernel, linux-kernel, linux-tegra
On 05/20/2014 09:36 AM, Peter De Schrijver wrote:
> All Tegra SoCs have a freerunning microsecond counter which can be used as a
> delay timer.
Patch 3 looks fine to me. I'll be happy to apply it once the other
patches are applied (or ack it or create a topic branch containing all 3
if needed, so it can be applied without waiting for dependencies to
filter up to Linus).
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] clocksource: tegra: Use uS counter as delay timer
2014-05-20 15:36 ` [PATCH 3/3] clocksource: tegra: Use uS counter as " Peter De Schrijver
2014-05-20 18:37 ` Stephen Warren
@ 2014-05-22 13:56 ` Thierry Reding
1 sibling, 0 replies; 7+ messages in thread
From: Thierry Reding @ 2014-05-22 13:56 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Russell King, Daniel Lezcano, Thomas Gleixner, Stephen Warren,
Paul Gortmaker, linux-arm-kernel, linux-kernel, linux-tegra
[-- Attachment #1: Type: text/plain, Size: 61 bytes --]
In the subject: s/uS/us/; S == Siemens, s == second
Thierry
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread