* [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
@ 2006-11-07 15:32 Dirk Behme
[not found] ` <4550CA9E.6090500@mvista.com>
0 siblings, 1 reply; 30+ messages in thread
From: Dirk Behme @ 2006-11-07 15:32 UTC (permalink / raw)
To: OMAP-Linux
[-- Attachment #1: Type: text/plain, Size: 1480 bytes --]
Add clocksource driver for OMAP1.
Signed-off-by: Dirk Behme <dirk.behme_at_gmail.com>
What do you think about this? OSK still boots and I can't
see any runtime issues. But maybe others?
For reference see
- The two new files highres.txt and hrtimers.txt in
http://tglx.de/projects/hrtimers/2.6.18/patch-2.6.18-hrt-dyntick2.patch
-
http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036695.html
(and the other "clocksource" patches there)
-
http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036713.html
Next steps would be:
* Move omap_clocksource_init() to something like
http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036700.html
* Add clockevent system, e.g.
http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036705.html
(and the other "clockevent" patches there)
* Enable generic time and generic clock events:
http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036696.html
http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036711.html
But seems that we have to wait some integration cylces
of mainline for this.
Cheers
Dirk
Btw: With clocksource added, we should be able to use
rt-preempt patch:
http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036496.html
rt.wiki.kernel.org
http://www.linuxdevices.com/news/NS9566944929.html
if it will be available for 2.6.19 (with some small OMAP
specific adaptions) .
[-- Attachment #2: omap1_clocksource_patch.txt --]
[-- Type: text/plain, Size: 4969 bytes --]
Index: linux-osk/arch/arm/mach-omap1/time.c
===================================================================
--- linux-osk.orig/arch/arm/mach-omap1/time.c
+++ linux-osk/arch/arm/mach-omap1/time.c
@@ -39,6 +39,7 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
+#include <linux/clocksource.h>
#include <asm/system.h>
#include <asm/hardware.h>
@@ -58,36 +59,6 @@ struct sys_timer omap_timer;
#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE
#define OMAP_MPU_TIMER_OFFSET 0x100
-/* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c,
- * converted to use kHz by Kevin Hilman */
-/* convert from cycles(64bits) => nanoseconds (64bits)
- * basic equation:
- * ns = cycles / (freq / ns_per_sec)
- * ns = cycles * (ns_per_sec / freq)
- * ns = cycles * (10^9 / (cpu_khz * 10^3))
- * ns = cycles * (10^6 / cpu_khz)
- *
- * Then we use scaling math (suggested by george at mvista.com) to get:
- * ns = cycles * (10^6 * SC / cpu_khz / SC
- * ns = cycles * cyc2ns_scale / SC
- *
- * And since SC is a constant power of two, we can convert the div
- * into a shift.
- * -johnstul at us.ibm.com "math is hard, lets go shopping!"
- */
-static unsigned long cyc2ns_scale;
-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
-
-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
-{
- cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
-}
-
-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
-{
- return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
-}
-
/*
* MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs
* will break. On P2, the timer count rate is 6.5 MHz after programming PTV
@@ -131,43 +102,9 @@ static inline void omap_mpu_timer_start(
timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST);
}
-unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks)
-{
- unsigned long long nsec;
-
- nsec = cycles_2_ns((unsigned long long)nr_ticks);
- return (unsigned long)nsec / 1000;
-}
-
-/*
- * Last processed system timer interrupt
- */
-static unsigned long omap_mpu_timer_last = 0;
-
-/*
- * Returns elapsed usecs since last system timer interrupt
- */
-static unsigned long omap_mpu_timer_gettimeoffset(void)
-{
- unsigned long now = 0 - omap_mpu_timer_read(0);
- unsigned long elapsed = now - omap_mpu_timer_last;
-
- return omap_mpu_timer_ticks_to_usecs(elapsed);
-}
-
-/*
- * Elapsed time between interrupts is calculated using timer0.
- * Latency during the interrupt is calculated using timer1.
- * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz).
- */
static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id)
{
- unsigned long now, latency;
-
write_seqlock(&xtime_lock);
- now = 0 - omap_mpu_timer_read(0);
- latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1);
- omap_mpu_timer_last = now - latency;
timer_tick();
write_sequnlock(&xtime_lock);
@@ -180,42 +117,33 @@ static struct irqaction omap_mpu_timer_i
.handler = omap_mpu_timer_interrupt,
};
-static unsigned long omap_mpu_timer1_overflows;
-static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
+static __init void omap_init_mpu_timer(void)
{
- omap_mpu_timer1_overflows++;
- return IRQ_HANDLED;
+ setup_irq(INT_TIMER1, &omap_mpu_timer_irq);
+ omap_mpu_timer_start(0, MPU_TIMER_TICK_PERIOD);
}
-static struct irqaction omap_mpu_timer1_irq = {
- .name = "mpu timer1 overflow",
- .flags = IRQF_DISABLED,
- .handler = omap_mpu_timer1_interrupt,
-};
-
-static __init void omap_init_mpu_timer(void)
+cycle_t omap_get_cycles(void)
{
- set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000);
- omap_timer.offset = omap_mpu_timer_gettimeoffset;
- setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
- setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
- omap_mpu_timer_start(0, 0xffffffff);
- omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
+ return omap_mpu_timer_read(0);
}
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
- unsigned long ticks = 0 - omap_mpu_timer_read(0);
- unsigned long long ticks64;
+static struct clocksource clocksource_omap = {
+ .name = "timer0",
+ .rating = 200,
+ .read = omap_get_cycles,
+ .mask = 0xFFFFFFFF,
+ .shift = 20,
+ .is_continuous = 1,
+};
- ticks64 = omap_mpu_timer1_overflows;
- ticks64 <<= 32;
- ticks64 |= ticks;
+static int __init omap_init_clocksource(void)
+{
+ clocksource_omap.mult = clocksource_khz2mult(MPU_TICKS_PER_SEC/1000,
+ clocksource_omap.shift);
+ clocksource_register(&clocksource_omap);
- return cycles_2_ns(ticks64);
+ return 0;
}
/*
@@ -226,9 +154,9 @@ unsigned long long sched_clock(void)
static void __init omap_timer_init(void)
{
omap_init_mpu_timer();
+ omap_init_clocksource();
}
struct sys_timer omap_timer = {
.init = omap_timer_init,
- .offset = NULL, /* Initialized later */
};
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
[not found] ` <4550CA9E.6090500@mvista.com>
@ 2006-11-08 16:44 ` Dirk Behme
2006-11-10 0:29 ` Tony Lindgren
2006-11-30 17:55 ` Dirk Behme
1 sibling, 1 reply; 30+ messages in thread
From: Dirk Behme @ 2006-11-08 16:44 UTC (permalink / raw)
To: Kevin Hilman, OMAP-Linux
Kevin Hilman wrote:
> Dirk Behme wrote:
>>Add clocksource driver for OMAP1.
>>
>>Signed-off-by: Dirk Behme <dirk.behme_at_gmail.com>
>>
>>What do you think about this? OSK still boots and I can't
>>see any runtime issues. But maybe others?
>
> Daniel Walker and myself have done both the clocksource and clockevent
> drivers for the 32k timer and MPU timers on OMAP1.
Ah, thanks for the hint! I overlooked [1].
> The clocksource driver has been submitted to RMK's patchsystem (but not
> yet integrated, RMK is waiting some settling in mainline too)
http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=3876/1
- For clocksource_mpu.mult and clocksource_register stuff we
should (later?) have a seperate function
omap_init_clocksource() to be able to call it by something like
http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036700.html
- While working on same topic I wonder if we still need both
HW timers in timer.c
setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
omap_mpu_timer_start(0, 0xffffffff);
omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
?
My test worked with using only one HW timer and removing all
other stuff:
setup_irq(INT_TIMER1, &omap_mpu_timer_irq);
omap_mpu_timer_start(0, MPU_TIMER_TICK_PERIOD);
But maybe I missed anything?
> and the
> rest has been submitted to Thomas Gliexner and will be included in his
> next -hrt-dyntick patcheset[2]
>
> The active -hrt-dyntick work is going on in -mm right now. The attached
> patchset (against 2.6.19-rc2-mm2) includes the latest OMAP patches which
> will be part of the next -hrt-dyntick patchset.
I think OMAP in mainline is slightly different from our git
tree here. Some parts are missing in mainline. If mainline
has merged everything and we pull it back to our OMAP git,
do we need a patch to adapt OMAP stuff not in mainline yet
to changes for -hrt-dyntick?
See RT preemt: If you try to apply RT preemt 2.6.18-rt7
(which is against OMAP in mainline) to OMAP 2.6.18 git, it
doesn't apply cleanly. Parts are missing and different
between OMAP git and OMAP mainline.
> We've tested these with Ingo's -rt patchset on 16xx/H2 and 1710/H3 and
> see good performance. We've also validated the new generic dynamic tick
> support which is part of the -hrt-dyntick patchset
Full text untouched here because seems that large attachment
prevented it from keeping in list archive.
> [2] http://tglx.de/projects/hrtimers/
Cheers,
Dirk
[1]
http://linux.omap.com/pipermail/linux-omap-open-source/2006-September/008008.html
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-08 16:44 ` Dirk Behme
@ 2006-11-10 0:29 ` Tony Lindgren
2006-11-10 0:48 ` Kevin Hilman
0 siblings, 1 reply; 30+ messages in thread
From: Tony Lindgren @ 2006-11-10 0:29 UTC (permalink / raw)
To: Dirk Behme; +Cc: OMAP-Linux
* Dirk Behme <dirk.behme@googlemail.com> [061108 18:45]:
> Kevin Hilman wrote:
> >Dirk Behme wrote:
> >>Add clocksource driver for OMAP1.
> >>
> >>Signed-off-by: Dirk Behme <dirk.behme_at_gmail.com>
> >>
> >>What do you think about this? OSK still boots and I can't
> >>see any runtime issues. But maybe others?
> >
> >Daniel Walker and myself have done both the clocksource and clockevent
> >drivers for the 32k timer and MPU timers on OMAP1.
>
> Ah, thanks for the hint! I overlooked [1].
>
> >The clocksource driver has been submitted to RMK's patchsystem (but not
> >yet integrated, RMK is waiting some settling in mainline too)
>
> http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=3876/1
Great!
> - For clocksource_mpu.mult and clocksource_register stuff we
> should (later?) have a seperate function
> omap_init_clocksource() to be able to call it by something like
>
> http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036700.html
>
> - While working on same topic I wonder if we still need both
> HW timers in timer.c
>
> setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
> setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
> omap_mpu_timer_start(0, 0xffffffff);
> omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
>
> ?
Well if that one timer is continuous, it should be enough. However, if
it was being continuously reprogrammed, it would not be accurate for
keeping time, and then you would need another timer for timesource.
> My test worked with using only one HW timer and removing all
> other stuff:
>
> setup_irq(INT_TIMER1, &omap_mpu_timer_irq);
> omap_mpu_timer_start(0, MPU_TIMER_TICK_PERIOD);
>
> But maybe I missed anything?
No, I think the use of two timers is just legacy code from the
original RidgeRun code.
Regards,
Tony
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-10 0:29 ` Tony Lindgren
@ 2006-11-10 0:48 ` Kevin Hilman
2006-11-10 0:53 ` Tony Lindgren
0 siblings, 1 reply; 30+ messages in thread
From: Kevin Hilman @ 2006-11-10 0:48 UTC (permalink / raw)
To: Tony Lindgren; +Cc: OMAP-Linux
Tony Lindgren wrote:
> * Dirk Behme <dirk.behme@googlemail.com> [061108 18:45]:
>> Kevin Hilman wrote:
>>> Dirk Behme wrote:
>>>> Add clocksource driver for OMAP1.
>>>>
>>>> Signed-off-by: Dirk Behme <dirk.behme_at_gmail.com>
>>>>
>>>> What do you think about this? OSK still boots and I can't
>>>> see any runtime issues. But maybe others?
>>> Daniel Walker and myself have done both the clocksource and clockevent
>>> drivers for the 32k timer and MPU timers on OMAP1.
>> Ah, thanks for the hint! I overlooked [1].
>>
>>> The clocksource driver has been submitted to RMK's patchsystem (but not
>>> yet integrated, RMK is waiting some settling in mainline too)
>> http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=3876/1
>
> Great!
>
>> - For clocksource_mpu.mult and clocksource_register stuff we
>> should (later?) have a seperate function
>> omap_init_clocksource() to be able to call it by something like
>>
>> http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036700.html
>>
>> - While working on same topic I wonder if we still need both
>> HW timers in timer.c
>>
>> setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
>> setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
>> omap_mpu_timer_start(0, 0xffffffff);
>> omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
>>
>> ?
>
> Well if that one timer is continuous, it should be enough. However, if
> it was being continuously reprogrammed, it would not be accurate for
> keeping time, and then you would need another timer for timesource.
The goal of the generic clockevents layer is to have a continually
re-programmable clocksource. This is then used for high-res timers, but
also for the generic dynamic tick support.
The ideal is to have 2 hardware timers: on continuous for the
clocksource and the other reprogrammable for the clockevents.
There probably are some clever ways to use one timer to do this, but for
this first pass, we haven't spent time on that.
Kevin
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-10 0:48 ` Kevin Hilman
@ 2006-11-10 0:53 ` Tony Lindgren
2006-11-30 19:57 ` Woodruff, Richard
0 siblings, 1 reply; 30+ messages in thread
From: Tony Lindgren @ 2006-11-10 0:53 UTC (permalink / raw)
To: Kevin Hilman; +Cc: OMAP-Linux
* Kevin Hilman <khilman@mvista.com> [061110 02:48]:
> Tony Lindgren wrote:
> > * Dirk Behme <dirk.behme@googlemail.com> [061108 18:45]:
> >> Kevin Hilman wrote:
> >>> Dirk Behme wrote:
> >>>> Add clocksource driver for OMAP1.
> >>>>
> >>>> Signed-off-by: Dirk Behme <dirk.behme_at_gmail.com>
> >>>>
> >>>> What do you think about this? OSK still boots and I can't
> >>>> see any runtime issues. But maybe others?
> >>> Daniel Walker and myself have done both the clocksource and clockevent
> >>> drivers for the 32k timer and MPU timers on OMAP1.
> >> Ah, thanks for the hint! I overlooked [1].
> >>
> >>> The clocksource driver has been submitted to RMK's patchsystem (but not
> >>> yet integrated, RMK is waiting some settling in mainline too)
> >> http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=3876/1
> >
> > Great!
> >
> >> - For clocksource_mpu.mult and clocksource_register stuff we
> >> should (later?) have a seperate function
> >> omap_init_clocksource() to be able to call it by something like
> >>
> >> http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2006-October/036700.html
> >>
> >> - While working on same topic I wonder if we still need both
> >> HW timers in timer.c
> >>
> >> setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
> >> setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
> >> omap_mpu_timer_start(0, 0xffffffff);
> >> omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
> >>
> >> ?
> >
> > Well if that one timer is continuous, it should be enough. However, if
> > it was being continuously reprogrammed, it would not be accurate for
> > keeping time, and then you would need another timer for timesource.
>
> The goal of the generic clockevents layer is to have a continually
> re-programmable clocksource. This is then used for high-res timers, but
> also for the generic dynamic tick support.
>
> The ideal is to have 2 hardware timers: on continuous for the
> clocksource and the other reprogrammable for the clockevents.
>
> There probably are some clever ways to use one timer to do this, but for
> this first pass, we haven't spent time on that.
In this case it will start drifting if you try to do it with just one
timer. On omaps, we should use the always running 32 KiHZ timer for
clocksource like the timer32k.c does. Unfortunately that's does not seem
to be available on 1510, and maybe that's why the original mpu timer
code from RidgeRun used two timers.
If anybody with 1510 has a chance, it may be worth scanning through some
registers in case there is some continuously running timer for this..
Tony
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 17:55 ` Dirk Behme
@ 2006-11-30 17:50 ` Daniel Walker
2006-12-01 16:12 ` Dirk Behme
2006-11-30 19:14 ` David Brownell
1 sibling, 1 reply; 30+ messages in thread
From: Daniel Walker @ 2006-11-30 17:50 UTC (permalink / raw)
To: Dirk Behme; +Cc: OMAP-Linux
On Thu, 2006-11-30 at 18:55 +0100, Dirk Behme wrote:
> I checked links below and can't find anything of your
> patches integrated there. Do I miss anything?
>
> I wonder because 2.6.19 is out now and mainline patch window
> opens for 2.6.20.
>
> Cheers
>
> Dirk
>
> http://tglx.de/projects/hrtimers/2.6.19-rc4-mm1/patch-2.6.19-rc4-mm1-hrt-dyntick4.patch
> http://people.redhat.com/mingo/realtime-preempt/patch-2.6.19-rt1
> http://kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.19-rc6/2.6.19-rc6-mm2/
They went to RMK as far as I know. Someplace in his patch system.
Daniel
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
[not found] ` <4550CA9E.6090500@mvista.com>
2006-11-08 16:44 ` Dirk Behme
@ 2006-11-30 17:55 ` Dirk Behme
2006-11-30 17:50 ` Daniel Walker
2006-11-30 19:14 ` David Brownell
1 sibling, 2 replies; 30+ messages in thread
From: Dirk Behme @ 2006-11-30 17:55 UTC (permalink / raw)
To: Kevin Hilman; +Cc: OMAP-Linux
Kevin Hilman wrote:
> Daniel Walker and myself have done both the clocksource and clockevent
> drivers for the 32k timer and MPU timers on OMAP1.
>
> The clocksource driver has been submitted to RMK's patchsystem (but not
> yet integrated, RMK is waiting some settling in mainline too) and the
> rest has been submitted to Thomas Gliexner and will be included in his
> next -hrt-dyntick patcheset[2]
>
> The active -hrt-dyntick work is going on in -mm right now. The attached
> patchset (against 2.6.19-rc2-mm2) includes the latest OMAP patches which
> will be part of the next -hrt-dyntick patchset.
I checked links below and can't find anything of your
patches integrated there. Do I miss anything?
I wonder because 2.6.19 is out now and mainline patch window
opens for 2.6.20.
Cheers
Dirk
http://tglx.de/projects/hrtimers/2.6.19-rc4-mm1/patch-2.6.19-rc4-mm1-hrt-dyntick4.patch
http://people.redhat.com/mingo/realtime-preempt/patch-2.6.19-rt1
http://kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.19-rc6/2.6.19-rc6-mm2/
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 17:55 ` Dirk Behme
2006-11-30 17:50 ` Daniel Walker
@ 2006-11-30 19:14 ` David Brownell
2006-11-30 20:33 ` Dirk Behme
1 sibling, 1 reply; 30+ messages in thread
From: David Brownell @ 2006-11-30 19:14 UTC (permalink / raw)
To: linux-omap-open-source
On Thursday 30 November 2006 9:55 am, Dirk Behme wrote:
> I checked links below and can't find anything of your
> patches integrated there. Do I miss anything?
>
> I wonder because 2.6.19 is out now and mainline patch window
> opens for 2.6.20.
BTW, please examine the appended patch to consider updating the
merge candidate. I verified that the MPU timer patch works,
it updates two things:
- consults the actual xtal clock, instead of compile-time constants;
- uses another mpu timer for a free-running clock
The use of only _one_ MPU timer in the original patch seems wrong
to me ... it's just resetting itself after each tick, so it can't
be used to detect missed ticks.
In my testing, this updated MPU timer worked ok. But the 32k timer
did NOT, although AFAICT there are no substantive changes to what
was posted. (Had to copy it by hand, somehow in the midst of the
many patch versions posted, I didn't have the "right" one saved.)
The original MPU time patch I had in my mailbox didn't work either.
(That's on OMAP 5912 fwiw.)
- Dave
Modified version of clocksource patches:
- MPU timer based:
* consult clock framework to determine xtal clock
* use timer1 as a real free-running clock
- Both: minor cleanups
- Kconfig updates:
Largely copied by hand from list archives; I didn't have one patch
that was current (though Dirk did post a similar one).
Index: osk2/arch/arm/plat-omap/Kconfig
===================================================================
--- osk2.orig/arch/arm/plat-omap/Kconfig 2006-11-15 21:11:10.000000000 -0800
+++ osk2/arch/arm/plat-omap/Kconfig 2006-11-28 11:41:24.000000000 -0800
@@ -125,6 +125,7 @@ choice
config OMAP_MPU_TIMER
bool "Use mpu timer"
+ select GENERIC_TIME if ARCH_OMAP1
help
Select this option if you want to use the OMAP mpu timer. This
timer provides more intra-tick resolution than the 32KHz timer,
@@ -133,6 +134,7 @@ config OMAP_MPU_TIMER
config OMAP_32K_TIMER
bool "Use 32KHz timer"
depends on ARCH_OMAP16XX || ARCH_OMAP24XX
+ select GENERIC_TIME
help
Select this option if you want to enable the OMAP 32KHz timer.
This timer saves power compared to the OMAP_MPU_TIMER, and has
Index: osk2/arch/arm/mach-omap1/time.c
===================================================================
--- osk2.orig/arch/arm/mach-omap1/time.c 2006-10-25 14:06:18.000000000 -0700
+++ osk2/arch/arm/mach-omap1/time.c 2006-11-28 11:39:18.000000000 -0800
@@ -39,6 +39,9 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/clocksource.h>
#include <asm/system.h>
#include <asm/hardware.h>
@@ -52,58 +55,12 @@ struct sys_timer omap_timer;
/*
* ---------------------------------------------------------------------------
- * MPU timer
+ * MPU timer 0 ... count down to zero, interrupt, reload
* ---------------------------------------------------------------------------
*/
#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE
#define OMAP_MPU_TIMER_OFFSET 0x100
-/* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c,
- * converted to use kHz by Kevin Hilman */
-/* convert from cycles(64bits) => nanoseconds (64bits)
- * basic equation:
- * ns = cycles / (freq / ns_per_sec)
- * ns = cycles * (ns_per_sec / freq)
- * ns = cycles * (10^9 / (cpu_khz * 10^3))
- * ns = cycles * (10^6 / cpu_khz)
- *
- * Then we use scaling math (suggested by george at mvista.com) to get:
- * ns = cycles * (10^6 * SC / cpu_khz / SC
- * ns = cycles * cyc2ns_scale / SC
- *
- * And since SC is a constant power of two, we can convert the div
- * into a shift.
- * -johnstul at us.ibm.com "math is hard, lets go shopping!"
- */
-static unsigned long cyc2ns_scale;
-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
-
-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
-{
- cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
-}
-
-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
-{
- return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
-}
-
-/*
- * MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs
- * will break. On P2, the timer count rate is 6.5 MHz after programming PTV
- * with 0. This divides the 13MHz input by 2, and is undocumented.
- */
-#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE)
-/* REVISIT: This ifdef construct should be replaced by a query to clock
- * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz.
- */
-#define MPU_TICKS_PER_SEC (13000000 / 2)
-#else
-#define MPU_TICKS_PER_SEC (12000000 / 2)
-#endif
-
-#define MPU_TIMER_TICK_PERIOD ((MPU_TICKS_PER_SEC / HZ) - 1)
-
typedef struct {
u32 cntl; /* CNTL_TIMER, R/W */
u32 load_tim; /* LOAD_TIM, W */
@@ -131,43 +88,9 @@ static inline void omap_mpu_timer_start(
timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST);
}
-unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks)
-{
- unsigned long long nsec;
-
- nsec = cycles_2_ns((unsigned long long)nr_ticks);
- return (unsigned long)nsec / 1000;
-}
-
-/*
- * Last processed system timer interrupt
- */
-static unsigned long omap_mpu_timer_last = 0;
-
-/*
- * Returns elapsed usecs since last system timer interrupt
- */
-static unsigned long omap_mpu_timer_gettimeoffset(void)
-{
- unsigned long now = 0 - omap_mpu_timer_read(0);
- unsigned long elapsed = now - omap_mpu_timer_last;
-
- return omap_mpu_timer_ticks_to_usecs(elapsed);
-}
-
-/*
- * Elapsed time between interrupts is calculated using timer0.
- * Latency during the interrupt is calculated using timer1.
- * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz).
- */
static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id)
{
- unsigned long now, latency;
-
write_seqlock(&xtime_lock);
- now = 0 - omap_mpu_timer_read(0);
- latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1);
- omap_mpu_timer_last = now - latency;
timer_tick();
write_sequnlock(&xtime_lock);
@@ -175,47 +98,47 @@ static irqreturn_t omap_mpu_timer_interr
}
static struct irqaction omap_mpu_timer_irq = {
- .name = "mpu timer",
+ .name = "mpu_timer0",
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = omap_mpu_timer_interrupt,
};
-static unsigned long omap_mpu_timer1_overflows;
-static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
+static __init void omap_init_mpu_timer(unsigned long rate)
{
- omap_mpu_timer1_overflows++;
- return IRQ_HANDLED;
+ setup_irq(INT_TIMER1, &omap_mpu_timer_irq);
+ omap_mpu_timer_start(0, (rate / HZ) - 1);
}
-static struct irqaction omap_mpu_timer1_irq = {
- .name = "mpu timer1 overflow",
- .flags = IRQF_DISABLED,
- .handler = omap_mpu_timer1_interrupt,
-};
-
-static __init void omap_init_mpu_timer(void)
+/*
+ * ---------------------------------------------------------------------------
+ * MPU timer 1 ... free running 32-bit clock source
+ * ---------------------------------------------------------------------------
+ */
+static cycle_t mpu_read(void)
{
- set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000);
- omap_timer.offset = omap_mpu_timer_gettimeoffset;
- setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
- setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
- omap_mpu_timer_start(0, 0xffffffff);
- omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
+ return ~omap_mpu_timer_read(1);
}
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
+static struct clocksource clocksource_mpu = {
+ .name = "mpu_timer1",
+ .rating = 300,
+ .read = mpu_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 24,
+ .is_continuous = 1,
+};
+
+static void __init omap_init_clocksource(unsigned long rate)
{
- unsigned long ticks = 0 - omap_mpu_timer_read(0);
- unsigned long long ticks64;
+ static char err[] __initdata = KERN_ERR
+ "%s: can't register clocksource!\n";
- ticks64 = omap_mpu_timer1_overflows;
- ticks64 <<= 32;
- ticks64 |= ticks;
+ clocksource_mpu.mult
+ = clocksource_khz2mult(rate/1000, clocksource_mpu.shift);
- return cycles_2_ns(ticks64);
+ omap_mpu_timer_start(1, clocksource_mpu.mask);
+ if (clocksource_register(&clocksource_mpu))
+ printk(err, clocksource_mpu.name);
}
/*
@@ -225,10 +148,21 @@ unsigned long long sched_clock(void)
*/
static void __init omap_timer_init(void)
{
- omap_init_mpu_timer();
+ struct clk *ck_ref = clk_get(NULL, "ck_ref");
+ unsigned long rate;
+
+ BUG_ON(IS_ERR(ck_ref));
+
+ rate = clk_get_rate(ck_ref);
+ clk_put(ck_ref);
+
+ /* PTV = 0 */
+ rate /= 2;
+
+ omap_init_mpu_timer(rate);
+ omap_init_clocksource(rate);
}
struct sys_timer omap_timer = {
.init = omap_timer_init,
- .offset = NULL, /* Initialized later */
};
Index: osk2/arch/arm/plat-omap/timer32k.c
===================================================================
--- osk2.orig/arch/arm/plat-omap/timer32k.c 2006-10-25 14:06:19.000000000 -0700
+++ osk2/arch/arm/plat-omap/timer32k.c 2006-11-28 12:02:50.000000000 -0800
@@ -42,6 +42,7 @@
#include <linux/spinlock.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/clocksource.h>
#include <asm/system.h>
#include <asm/hardware.h>
@@ -171,15 +172,6 @@ omap_32k_ticks_to_nsecs(unsigned long ti
static unsigned long omap_32k_last_tick = 0;
/*
- * Returns elapsed usecs since last 32k timer interrupt
- */
-static unsigned long omap_32k_timer_gettimeoffset(void)
-{
- unsigned long now = omap_32k_sync_timer_read();
- return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
-}
-
-/*
* Returns current time from boot in nsecs. It's OK for this to wrap
* around for now, as it's just a relative time stamp.
*/
@@ -217,6 +209,19 @@ static inline irqreturn_t _omap_32k_time
return IRQ_HANDLED;
}
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
+{
+ unsigned long flags;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+ _omap_32k_timer_interrupt(irq, dev_id);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+
static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id)
{
unsigned long now;
@@ -233,18 +238,6 @@ static irqreturn_t omap_32k_timer_handle
return _omap_32k_timer_interrupt(irq, dev_id);
}
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
-{
- unsigned long flags;
-
- write_seqlock_irqsave(&xtime_lock, flags);
- _omap_32k_timer_interrupt(irq, dev_id);
- write_sequnlock_irqrestore(&xtime_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NO_IDLE_HZ
/*
* Programs the next timer interrupt needed. Called when dynamic tick is
* enabled, and to reprogram the ticks to skip from pm_idle. Note that
@@ -302,7 +295,6 @@ static __init void omap_init_32k_timer(v
if (cpu_class_is_omap1())
setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
- omap_timer.offset = omap_32k_timer_gettimeoffset;
omap_32k_last_tick = omap_32k_sync_timer_read();
#ifdef CONFIG_ARCH_OMAP2
@@ -322,6 +314,39 @@ static __init void omap_init_32k_timer(v
omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
}
+
+/*
+ * ---------------------------------------------------------------------------
+ * 32KHz clocksource
+ * ---------------------------------------------------------------------------
+ */
+static cycle_t omap_32k_read(void)
+{
+ return omap_32k_sync_timer_read();
+}
+
+static struct clocksource clocksource_32k = {
+ .name = "32k_timer",
+ .rating = 250,
+ .read = omap_32k_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 10,
+ .is_continuous = 1,
+};
+
+static void __init omap_init_clocksource_32k(void)
+{
+ static char err[] __initdata = KERN_ERR
+ "%s: can't register clocksource!\n";
+
+ clocksource_32k.mult =
+ clocksource_khz2mult(32768, clocksource_32k.shift);
+
+ if (clocksource_register(&clocksource_32k))
+ printk(err, clocksource_32k.name);
+}
+
+
/*
* ---------------------------------------------------------------------------
* Timer initialization
@@ -333,9 +358,9 @@ static void __init omap_timer_init(void)
omap_dm_timer_init();
#endif
omap_init_32k_timer();
+ omap_init_clocksource_32k();
}
struct sys_timer omap_timer = {
.init = omap_timer_init,
- .offset = NULL, /* Initialized later */
};
^ permalink raw reply [flat|nested] 30+ messages in thread
* RE: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-10 0:53 ` Tony Lindgren
@ 2006-11-30 19:57 ` Woodruff, Richard
2006-11-30 21:30 ` David Brownell
2006-11-30 21:59 ` tony
0 siblings, 2 replies; 30+ messages in thread
From: Woodruff, Richard @ 2006-11-30 19:57 UTC (permalink / raw)
To: Tony Lindgren, Kevin Hilman; +Cc: OMAP-Linux
> In this case it will start drifting if you try to do it with just one
> timer. On omaps, we should use the always running 32 KiHZ timer for
> clocksource like the timer32k.c does. Unfortunately that's does not
seem
> to be available on 1510, and maybe that's why the original mpu timer
> code from RidgeRun used two timers.
That code uses two timers to account for isr latency and to provide
accurate timestamps. One timer is periodic and the other is free
running. The 2nd is used as a relative reference. Along with being used
as a reference the 2nd free runner uses its current value and its roll
over interrupt to sum/calculate the number of ns the system has been up.
This enables sched_clock to be enabled with accuracy (vs. just
multiplying times jiffies).
The single timer method does not do either of these. The code was
reasonably clear, I also sent in a path long ago to enable this. Is
there some aspect of this which I mis-understood?
> If anybody with 1510 has a chance, it may be worth scanning through
some
> registers in case there is some continuously running timer for this..
TRM shows 1510 has 3 general timers and 1 32KHz timer. The 32KHz timer
is at base=0xFFFB9000. TVR=base+0, TCR=base+4, CR=base+8. It comes in
on L2-Pic-IRQ22. It has a 24 bit counter.
Regards,
Richard W.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 19:14 ` David Brownell
@ 2006-11-30 20:33 ` Dirk Behme
2006-11-30 21:22 ` [RFC] [PATCH] ARM: Add clocksource driver for OMAP1 and OMAP2 David Brownell
0 siblings, 1 reply; 30+ messages in thread
From: Dirk Behme @ 2006-11-30 20:33 UTC (permalink / raw)
To: David Brownell; +Cc: linux-omap-open-source
David Brownell wrote:
> BTW, please examine the appended patch to consider updating the
> merge candidate.
Mmh, maybe I'm wrong here or anything is long term
misconfigured, but looks to me that I don't get a login
prompt with this patch and rt applied. With [1] I get
-- cut --
Kernel boot message ...
...
Loading modules ...
...
Welcome to OSK (ARM926T) - Kernel 2.6.19-rc6-rt3-omap1 (ttyS0).
OSK login: root
login[992]: root login on `ttyS0'
BusyBox v1.00 (2005.01.31-19:22+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
#
-- cut --
With your patch instead [1], everything including output of
/etc/issue ("Welcome...") is missing. Module output is still
there.
Strange.
Dirk
[1]
http://linux.omap.com/pipermail/linux-omap-open-source/2006-November/008370.html
^ permalink raw reply [flat|nested] 30+ messages in thread
* [RFC] [PATCH] ARM: Add clocksource driver for OMAP1 and OMAP2
2006-11-30 20:33 ` Dirk Behme
@ 2006-11-30 21:22 ` David Brownell
2006-12-01 18:21 ` Dirk Behme
0 siblings, 1 reply; 30+ messages in thread
From: David Brownell @ 2006-11-30 21:22 UTC (permalink / raw)
To: Dirk Behme; +Cc: linux-omap-open-source
On Thursday 30 November 2006 12:33 pm, Dirk Behme wrote:
> David Brownell wrote:
> > BTW, please examine the appended patch to consider updating the
> > merge candidate.
>
> Mmh, maybe I'm wrong here or anything is long term
> misconfigured, but looks to me that I don't get a login
> prompt with this patch and rt applied. With [1] I get
That's what I meant when I said the 32k timer doesn't
work for me -- that's _without_ the RT patch too. The
Linux-OMAP list archives don't have a way to get non-HTML
versions of _single_ messages so I had to copy the [1] bits
by hand. Presumably something significant differed? If so,
what? Too many versions of OMAP clocksource patches have
been flung around ...
In any case, the "please examine" bits were primarily
for the MPU timer.
On a related topic, here's an updated version with OMAP2
timers working. Again, the scheduler tick IRQ uses one
timer that resets itself, while the clocksource uses a
different timer running freely.
- Dave
Modified version of clocksource patches:
- OMAP1 MPU timer:
* consult clock framework to determine xtal clock
* use timer1 as a real free-running clock
- OMAP2 GP timer
* use timer2 as a real free-running clock
- Both: minor cleanups
- Kconfig updates:
Largely copied by hand from list archives; I didn't have one patch
that was (though Dirk did post a similar one).
Index: h4/arch/arm/plat-omap/Kconfig
===================================================================
--- h4.orig/arch/arm/plat-omap/Kconfig 2006-11-28 12:56:19.000000000 -0800
+++ h4/arch/arm/plat-omap/Kconfig 2006-11-30 13:03:49.000000000 -0800
@@ -125,6 +125,7 @@ choice
config OMAP_MPU_TIMER
bool "Use mpu timer"
+ select GENERIC_TIME
help
Select this option if you want to use the OMAP mpu timer. This
timer provides more intra-tick resolution than the 32KHz timer,
@@ -133,6 +134,7 @@ config OMAP_MPU_TIMER
config OMAP_32K_TIMER
bool "Use 32KHz timer"
depends on ARCH_OMAP16XX || ARCH_OMAP24XX
+ select GENERIC_TIME
help
Select this option if you want to enable the OMAP 32KHz timer.
This timer saves power compared to the OMAP_MPU_TIMER, and has
Index: h4/arch/arm/mach-omap1/time.c
===================================================================
--- h4.orig/arch/arm/mach-omap1/time.c 2006-10-25 13:37:17.000000000 -0700
+++ h4/arch/arm/mach-omap1/time.c 2006-11-28 15:06:13.000000000 -0800
@@ -39,6 +39,9 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/clocksource.h>
#include <asm/system.h>
#include <asm/hardware.h>
@@ -52,58 +55,12 @@ struct sys_timer omap_timer;
/*
* ---------------------------------------------------------------------------
- * MPU timer
+ * MPU timer 0 ... count down to zero, interrupt, reload
* ---------------------------------------------------------------------------
*/
#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE
#define OMAP_MPU_TIMER_OFFSET 0x100
-/* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c,
- * converted to use kHz by Kevin Hilman */
-/* convert from cycles(64bits) => nanoseconds (64bits)
- * basic equation:
- * ns = cycles / (freq / ns_per_sec)
- * ns = cycles * (ns_per_sec / freq)
- * ns = cycles * (10^9 / (cpu_khz * 10^3))
- * ns = cycles * (10^6 / cpu_khz)
- *
- * Then we use scaling math (suggested by george at mvista.com) to get:
- * ns = cycles * (10^6 * SC / cpu_khz / SC
- * ns = cycles * cyc2ns_scale / SC
- *
- * And since SC is a constant power of two, we can convert the div
- * into a shift.
- * -johnstul at us.ibm.com "math is hard, lets go shopping!"
- */
-static unsigned long cyc2ns_scale;
-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
-
-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
-{
- cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
-}
-
-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
-{
- return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
-}
-
-/*
- * MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs
- * will break. On P2, the timer count rate is 6.5 MHz after programming PTV
- * with 0. This divides the 13MHz input by 2, and is undocumented.
- */
-#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE)
-/* REVISIT: This ifdef construct should be replaced by a query to clock
- * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz.
- */
-#define MPU_TICKS_PER_SEC (13000000 / 2)
-#else
-#define MPU_TICKS_PER_SEC (12000000 / 2)
-#endif
-
-#define MPU_TIMER_TICK_PERIOD ((MPU_TICKS_PER_SEC / HZ) - 1)
-
typedef struct {
u32 cntl; /* CNTL_TIMER, R/W */
u32 load_tim; /* LOAD_TIM, W */
@@ -131,43 +88,9 @@ static inline void omap_mpu_timer_start(
timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST);
}
-unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks)
-{
- unsigned long long nsec;
-
- nsec = cycles_2_ns((unsigned long long)nr_ticks);
- return (unsigned long)nsec / 1000;
-}
-
-/*
- * Last processed system timer interrupt
- */
-static unsigned long omap_mpu_timer_last = 0;
-
-/*
- * Returns elapsed usecs since last system timer interrupt
- */
-static unsigned long omap_mpu_timer_gettimeoffset(void)
-{
- unsigned long now = 0 - omap_mpu_timer_read(0);
- unsigned long elapsed = now - omap_mpu_timer_last;
-
- return omap_mpu_timer_ticks_to_usecs(elapsed);
-}
-
-/*
- * Elapsed time between interrupts is calculated using timer0.
- * Latency during the interrupt is calculated using timer1.
- * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz).
- */
static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id)
{
- unsigned long now, latency;
-
write_seqlock(&xtime_lock);
- now = 0 - omap_mpu_timer_read(0);
- latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1);
- omap_mpu_timer_last = now - latency;
timer_tick();
write_sequnlock(&xtime_lock);
@@ -175,47 +98,47 @@ static irqreturn_t omap_mpu_timer_interr
}
static struct irqaction omap_mpu_timer_irq = {
- .name = "mpu timer",
+ .name = "mpu_timer0",
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = omap_mpu_timer_interrupt,
};
-static unsigned long omap_mpu_timer1_overflows;
-static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
+static __init void omap_init_mpu_timer(unsigned long rate)
{
- omap_mpu_timer1_overflows++;
- return IRQ_HANDLED;
+ setup_irq(INT_TIMER1, &omap_mpu_timer_irq);
+ omap_mpu_timer_start(0, (rate / HZ) - 1);
}
-static struct irqaction omap_mpu_timer1_irq = {
- .name = "mpu timer1 overflow",
- .flags = IRQF_DISABLED,
- .handler = omap_mpu_timer1_interrupt,
-};
-
-static __init void omap_init_mpu_timer(void)
+/*
+ * ---------------------------------------------------------------------------
+ * MPU timer 1 ... free running 32-bit clock source
+ * ---------------------------------------------------------------------------
+ */
+static cycle_t mpu_read(void)
{
- set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000);
- omap_timer.offset = omap_mpu_timer_gettimeoffset;
- setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
- setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
- omap_mpu_timer_start(0, 0xffffffff);
- omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
+ return ~omap_mpu_timer_read(1);
}
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
+static struct clocksource clocksource_mpu = {
+ .name = "mpu_timer1",
+ .rating = 300,
+ .read = mpu_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 24,
+ .is_continuous = 1,
+};
+
+static void __init omap_init_clocksource(unsigned long rate)
{
- unsigned long ticks = 0 - omap_mpu_timer_read(0);
- unsigned long long ticks64;
+ static char err[] __initdata = KERN_ERR
+ "%s: can't register clocksource!\n";
- ticks64 = omap_mpu_timer1_overflows;
- ticks64 <<= 32;
- ticks64 |= ticks;
+ clocksource_mpu.mult
+ = clocksource_khz2mult(rate/1000, clocksource_mpu.shift);
- return cycles_2_ns(ticks64);
+ omap_mpu_timer_start(1, clocksource_mpu.mask);
+ if (clocksource_register(&clocksource_mpu))
+ printk(err, clocksource_mpu.name);
}
/*
@@ -225,10 +148,21 @@ unsigned long long sched_clock(void)
*/
static void __init omap_timer_init(void)
{
- omap_init_mpu_timer();
+ struct clk *ck_ref = clk_get(NULL, "ck_ref");
+ unsigned long rate;
+
+ BUG_ON(IS_ERR(ck_ref));
+
+ rate = clk_get_rate(ck_ref);
+ clk_put(ck_ref);
+
+ /* PTV = 0 */
+ rate /= 2;
+
+ omap_init_mpu_timer(rate);
+ omap_init_clocksource(rate);
}
struct sys_timer omap_timer = {
.init = omap_timer_init,
- .offset = NULL, /* Initialized later */
};
Index: h4/arch/arm/plat-omap/timer32k.c
===================================================================
--- h4.orig/arch/arm/plat-omap/timer32k.c 2006-10-25 13:37:17.000000000 -0700
+++ h4/arch/arm/plat-omap/timer32k.c 2006-11-28 15:06:13.000000000 -0800
@@ -42,6 +42,7 @@
#include <linux/spinlock.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/clocksource.h>
#include <asm/system.h>
#include <asm/hardware.h>
@@ -171,15 +172,6 @@ omap_32k_ticks_to_nsecs(unsigned long ti
static unsigned long omap_32k_last_tick = 0;
/*
- * Returns elapsed usecs since last 32k timer interrupt
- */
-static unsigned long omap_32k_timer_gettimeoffset(void)
-{
- unsigned long now = omap_32k_sync_timer_read();
- return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
-}
-
-/*
* Returns current time from boot in nsecs. It's OK for this to wrap
* around for now, as it's just a relative time stamp.
*/
@@ -217,6 +209,19 @@ static inline irqreturn_t _omap_32k_time
return IRQ_HANDLED;
}
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
+{
+ unsigned long flags;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+ _omap_32k_timer_interrupt(irq, dev_id);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+
static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id)
{
unsigned long now;
@@ -233,18 +238,6 @@ static irqreturn_t omap_32k_timer_handle
return _omap_32k_timer_interrupt(irq, dev_id);
}
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
-{
- unsigned long flags;
-
- write_seqlock_irqsave(&xtime_lock, flags);
- _omap_32k_timer_interrupt(irq, dev_id);
- write_sequnlock_irqrestore(&xtime_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NO_IDLE_HZ
/*
* Programs the next timer interrupt needed. Called when dynamic tick is
* enabled, and to reprogram the ticks to skip from pm_idle. Note that
@@ -302,7 +295,6 @@ static __init void omap_init_32k_timer(v
if (cpu_class_is_omap1())
setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
- omap_timer.offset = omap_32k_timer_gettimeoffset;
omap_32k_last_tick = omap_32k_sync_timer_read();
#ifdef CONFIG_ARCH_OMAP2
@@ -322,6 +314,39 @@ static __init void omap_init_32k_timer(v
omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
}
+
+/*
+ * ---------------------------------------------------------------------------
+ * 32KHz clocksource
+ * ---------------------------------------------------------------------------
+ */
+static cycle_t omap_32k_read(void)
+{
+ return omap_32k_sync_timer_read();
+}
+
+static struct clocksource clocksource_32k = {
+ .name = "32k_timer",
+ .rating = 250,
+ .read = omap_32k_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 10,
+ .is_continuous = 1,
+};
+
+static void __init omap_init_clocksource_32k(void)
+{
+ static char err[] __initdata = KERN_ERR
+ "%s: can't register clocksource!\n";
+
+ clocksource_32k.mult =
+ clocksource_khz2mult(32768, clocksource_32k.shift);
+
+ if (clocksource_register(&clocksource_32k))
+ printk(err, clocksource_32k.name);
+}
+
+
/*
* ---------------------------------------------------------------------------
* Timer initialization
@@ -333,9 +358,9 @@ static void __init omap_timer_init(void)
omap_dm_timer_init();
#endif
omap_init_32k_timer();
+ omap_init_clocksource_32k();
}
struct sys_timer omap_timer = {
.init = omap_timer_init,
- .offset = NULL, /* Initialized later */
};
Index: h4/arch/arm/mach-omap2/timer-gp.c
===================================================================
--- h4.orig/arch/arm/mach-omap2/timer-gp.c 2006-11-28 12:56:19.000000000 -0800
+++ h4/arch/arm/mach-omap2/timer-gp.c 2006-11-28 16:06:24.000000000 -0800
@@ -25,12 +25,15 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/irq.h>
+#include <linux/clocksource.h>
#include <asm/mach/time.h>
#include <asm/arch/dmtimer.h>
-static struct omap_dm_timer *gptimer;
+static struct omap_dm_timer *gptimer, *clocksource;
+
+/* GP timer 1 generates timer tick irqs */
static inline void omap2_gp_timer_start(unsigned long load_val)
{
omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val);
@@ -51,25 +54,55 @@ static irqreturn_t omap2_gp_timer_interr
}
static struct irqaction omap2_gp_timer_irq = {
- .name = "gp timer",
+ .name = "gp_timer1",
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = omap2_gp_timer_interrupt,
};
+
+/* GP timer 2 is a free running clock */
+static cycle_t gp_read(void)
+{
+ return omap_dm_timer_read_counter(clocksource);
+}
+
+static struct clocksource clocksource_gp = {
+ .name = "gp_timer2",
+ .rating = 300,
+ .read = gp_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 24,
+ .is_continuous = 1,
+};
+
+
static void __init omap2_gp_timer_init(void)
{
- u32 tick_period;
+ unsigned long rate;
omap_dm_timer_init();
+
+ /* GP timer 1 */
gptimer = omap_dm_timer_request_specific(1);
BUG_ON(gptimer == NULL);
-
omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK);
- tick_period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
- tick_period -= 1;
+
+ rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
- omap2_gp_timer_start(tick_period);
+ omap2_gp_timer_start((rate / HZ) - 1);
+
+ /* GP timer 2 */
+ clocksource = omap_dm_timer_request_specific(2);
+ BUG_ON(clocksource == NULL);
+ omap_dm_timer_set_source(clocksource, OMAP_TIMER_SRC_SYS_CLK);
+
+ clocksource_gp.mult
+ = clocksource_khz2mult(rate/1000, clocksource_gp.shift);
+ omap_dm_timer_set_load(clocksource, 1, 0);
+ omap_dm_timer_start(clocksource);
+
+ (void) clocksource_register(&clocksource_gp);
}
struct sys_timer omap_timer = {
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 19:57 ` Woodruff, Richard
@ 2006-11-30 21:30 ` David Brownell
2006-11-30 21:49 ` Woodruff, Richard
2006-11-30 22:12 ` tony
2006-11-30 21:59 ` tony
1 sibling, 2 replies; 30+ messages in thread
From: David Brownell @ 2006-11-30 21:30 UTC (permalink / raw)
To: linux-omap-open-source
On Thursday 30 November 2006 11:57 am, Woodruff, Richard wrote:
> That code uses two timers to account for isr latency and to provide
> accurate timestamps. One timer is periodic and the other is free
> running. The 2nd is used as a relative reference. Along with being used
> as a reference the 2nd free runner uses its current value and its roll
> over interrupt to sum/calculate the number of ns the system has been up.
> This enables sched_clock to be enabled with accuracy (vs. just
> multiplying times jiffies).
>
> The single timer method does not do either of these. The code was
> reasonably clear, I also sent in a path long ago to enable this. Is
> there some aspect of this which I mis-understood?
If you did, I had the same mis-understanding. Ergo the patch(es) I've
sent.
I don't think the roll-over IRQ is significant in the new clock framework,
but I do think that the second MPU timer is important if there's a chance
of lost timer IRQs ... probably negligible at HZ=100, less so when the option
of HZ=1000 is configured.
Plus, ISTR that the upcoming generic dyntick support will need to reprogram
the periodic IRQ, just like the current OMAP-specific code using timer32k.
- Dave
^ permalink raw reply [flat|nested] 30+ messages in thread
* RE: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 21:30 ` David Brownell
@ 2006-11-30 21:49 ` Woodruff, Richard
2006-11-30 22:32 ` David Brownell
2006-11-30 22:12 ` tony
1 sibling, 1 reply; 30+ messages in thread
From: Woodruff, Richard @ 2006-11-30 21:49 UTC (permalink / raw)
To: David Brownell, linux-omap-open-source
> From: David Brownell [mailto:david-b@pacbell.net]
> I don't think the roll-over IRQ is significant in the new clock
framework,
> but I do think that the second MPU timer is important if there's a
chance
> of lost timer IRQs ... probably negligible at HZ=100, less so when the
> option
> of HZ=1000 is configured.
>
> Plus, ISTR that the upcoming generic dyntick support will need to
> reprogram
> the periodic IRQ, just like the current OMAP-specific code using
timer32k.
The only thing about using two timers which made me think twice was what
happens during retention/off mode sleeps. This forces you to add a
little code to account for clock switching (sys_clk to 32KHz) at the
periodic timer, and adding knowledge about the stopped free running one.
Having a single GPT1 timer active which is wake up capable makes it all
simpler. I did ask for a 2nd timer in the wake up domain and that
actually happened in 3430.
... Actually, I would guess many use cases would be find using a CORE
domain timer and setting the target for the system sleep to be
'request-idle' this removes any worry about the clock transition as the
functional clock of the CORE timer can run and its ISR can issue a PRCM
wake up. This is the state you want to generally go into anyway in an
idle routine if you any kind of peripheral activity.
Regards,
Richard W.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 19:57 ` Woodruff, Richard
2006-11-30 21:30 ` David Brownell
@ 2006-11-30 21:59 ` tony
2006-11-30 22:24 ` Woodruff, Richard
1 sibling, 1 reply; 30+ messages in thread
From: tony @ 2006-11-30 21:59 UTC (permalink / raw)
To: Woodruff, Richard; +Cc: OMAP-Linux
Hi,
* Woodruff, Richard <r-woodruff2@ti.com> [061130 11:58]:
>
> > If anybody with 1510 has a chance, it may be worth scanning through
> some
> > registers in case there is some continuously running timer for this..
>
> TRM shows 1510 has 3 general timers and 1 32KHz timer. The 32KHz timer
> is at base=0xFFFB9000. TVR=base+0, TCR=base+4, CR=base+8. It comes in
> on L2-Pic-IRQ22. It has a 24 bit counter.
Thanks for the info, I guess I was looking for the continuously running
32KHz timer in addition to that, as then we could use the same dyntick
code on 1510 also. Do you know if there is continuously running 32KHz
timer on 1510?
Regards,
Tony
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 21:30 ` David Brownell
2006-11-30 21:49 ` Woodruff, Richard
@ 2006-11-30 22:12 ` tony
1 sibling, 0 replies; 30+ messages in thread
From: tony @ 2006-11-30 22:12 UTC (permalink / raw)
To: David Brownell; +Cc: linux-omap-open-source
* David Brownell <david-b@pacbell.net> [061130 13:30]:
> On Thursday 30 November 2006 11:57 am, Woodruff, Richard wrote:
>
> > That code uses two timers to account for isr latency and to provide
> > accurate timestamps. One timer is periodic and the other is free
> > running. The 2nd is used as a relative reference. Along with being used
> > as a reference the 2nd free runner uses its current value and its roll
> > over interrupt to sum/calculate the number of ns the system has been up.
> > This enables sched_clock to be enabled with accuracy (vs. just
> > multiplying times jiffies).
> >
> > The single timer method does not do either of these. The code was
> > reasonably clear, I also sent in a path long ago to enable this. Is
> > there some aspect of this which I mis-understood?
>
> If you did, I had the same mis-understanding. Ergo the patch(es) I've
> sent.
>
> I don't think the roll-over IRQ is significant in the new clock framework,
> but I do think that the second MPU timer is important if there's a chance
> of lost timer IRQs ... probably negligible at HZ=100, less so when the option
> of HZ=1000 is configured.
>
> Plus, ISTR that the upcoming generic dyntick support will need to reprogram
> the periodic IRQ, just like the current OMAP-specific code using timer32k.
Yeah, with the upcoming timer code time is updated from a freely running
timer, so time should be always as accurate as the hardware timer.
Regards,
Tony
^ permalink raw reply [flat|nested] 30+ messages in thread
* RE: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 21:59 ` tony
@ 2006-11-30 22:24 ` Woodruff, Richard
2006-11-30 22:37 ` tony
0 siblings, 1 reply; 30+ messages in thread
From: Woodruff, Richard @ 2006-11-30 22:24 UTC (permalink / raw)
To: tony; +Cc: OMAP-Linux
> Thanks for the info, I guess I was looking for the continuously
running
> 32KHz timer in addition to that, as then we could use the same dyntick
> code on 1510 also. Do you know if there is continuously running 32KHz
> timer on 1510?
You are looking for 32K Sync timer? I don't think 1510 had one. 1510
did have an RTC which 32K goes to and can wake you. Other OMAPs dropped
it. I seem to recall it may have used to much current and the
recommendation was to use an external one. Granularity isn't so great.
Regards,
Richard W.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 21:49 ` Woodruff, Richard
@ 2006-11-30 22:32 ` David Brownell
2006-11-30 22:57 ` Woodruff, Richard
0 siblings, 1 reply; 30+ messages in thread
From: David Brownell @ 2006-11-30 22:32 UTC (permalink / raw)
To: Woodruff, Richard; +Cc: linux-omap-open-source
On Thursday 30 November 2006 1:49 pm, Woodruff, Richard wrote:
> The only thing about using two timers which made me think twice was what
> happens during retention/off mode sleeps. This forces you to add a
> little code to account for clock switching (sys_clk to 32KHz) at the
> periodic timer, and adding knowledge about the stopped free running one.
>
> Having a single GPT1 timer active which is wake up capable makes it all
> simpler. I did ask for a 2nd timer in the wake up domain and that
> actually happened in 3430.
>
> ... Actually, I would guess many use cases would be find using a CORE
> domain timer and setting the target for the system sleep to be
> 'request-idle' this removes any worry about the clock transition as the
> functional clock of the CORE timer can run and its ISR can issue a PRCM
> wake up. This is the state you want to generally go into anyway in an
> idle routine if you any kind of peripheral activity.
Not that I have time to look into OMAP2 low power modes ... but I'd thought
the preferred solution when low power was a concern would be to use the
32k timers not the general purpose ones, and that you more or less said
just that. Did I translate that correctly? :)
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 22:24 ` Woodruff, Richard
@ 2006-11-30 22:37 ` tony
0 siblings, 0 replies; 30+ messages in thread
From: tony @ 2006-11-30 22:37 UTC (permalink / raw)
To: Woodruff, Richard; +Cc: OMAP-Linux
* Woodruff, Richard <r-woodruff2@ti.com> [061130 14:24]:
> > Thanks for the info, I guess I was looking for the continuously
> running
> > 32KHz timer in addition to that, as then we could use the same dyntick
> > code on 1510 also. Do you know if there is continuously running 32KHz
> > timer on 1510?
>
> You are looking for 32K Sync timer? I don't think 1510 had one. 1510
> did have an RTC which 32K goes to and can wake you. Other OMAPs dropped
> it. I seem to recall it may have used to much current and the
> recommendation was to use an external one. Granularity isn't so great.
Yeah, sync timer was what I was looking. If it does not exist on 1510,
then the dyntick code should use the 32KHz timer as the freely running
timer, and one of the mpu timers for the interrupts.
Regards,
Tony
^ permalink raw reply [flat|nested] 30+ messages in thread
* RE: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 22:32 ` David Brownell
@ 2006-11-30 22:57 ` Woodruff, Richard
0 siblings, 0 replies; 30+ messages in thread
From: Woodruff, Richard @ 2006-11-30 22:57 UTC (permalink / raw)
To: David Brownell; +Cc: linux-omap-open-source
> -----Original Message-----
> From: David Brownell [mailto:david-b@pacbell.net]
> Not that I have time to look into OMAP2 low power modes ... but I'd
> thought
> the preferred solution when low power was a concern would be to use
the
> 32k timers not the general purpose ones, and that you more or less
said
> just that. Did I translate that correctly? :)
Mostly :), but you have more options depending on your target mode.
There is one GPT in the wake up domain and a bunch in the CORE domain.
The all can have source 32K/SYSCK/ALTCK. All of them are 'wakeup
capable' however, depending on the depth of your sleep the CORE ones may
not wake you. You can target sleep modes where you can sleep in between
peripheral activity and use the CORE peripheral wake you. In those
cases interface clocks are auto gated but some functional clocks can
run. (a timer can do this). So you can use a CORE timer and still hit
perhaps your most used power mode. For Retention you (non-functional)
must use a WKUP one.
One sort of nice aspect of using SYSCLK is its value can be more
accurate and its resolution is higher for time stamps.
A 32K timer is really 32768 no 32000 and over timer you accumulate error
faster. Some users alternate sleep times over an interval to account
for this error. It is less necessary to do this with a MHz timer, but
perhaps a bit depending on your input speed.
For a 1ms tick target 32*1/32768=.976ms and a 33*1/32768=1.007ms. You
can fix this by alternating between 32 and 33 over an interval.
Regards,
Richard W.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-11-30 17:50 ` Daniel Walker
@ 2006-12-01 16:12 ` Dirk Behme
2006-12-02 3:21 ` Daniel Walker
0 siblings, 1 reply; 30+ messages in thread
From: Dirk Behme @ 2006-12-01 16:12 UTC (permalink / raw)
To: Daniel Walker, Kevin Hilman; +Cc: OMAP-Linux
Daniel Walker wrote:
> On Thu, 2006-11-30 at 18:55 +0100, Dirk Behme wrote:
>
>>I checked links below and can't find anything of your
>>patches integrated there. Do I miss anything?
>>
>>I wonder because 2.6.19 is out now and mainline patch window
>>opens for 2.6.20.
>>
>>http://tglx.de/projects/hrtimers/2.6.19-rc4-mm1/patch-2.6.19-rc4-mm1-hrt-dyntick4.patch
>>http://people.redhat.com/mingo/realtime-preempt/patch-2.6.19-rt1
>>http://kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.19-rc6/2.6.19-rc6-mm2/
>
> They went to RMK as far as I know. Someplace in his patch system.
Yes and no ;)
The Versatile and OMAP clocksource patches are in RMKs patch
system. The OMAP one is updated here on the list.
But as I understand Kevin, the rest has been submitted to
Thomas Gleixner and was planned to be included in the
-hrt-dyntick patcheset and then in -mm. And there I couldn't
find them. Would be a shame if they get lost. Especially the
OMAP clockevent one.
Cheers
Dirk
Content of your patches-2.6.19-rc2.tar.bz2:
arm-hrt-kconfig.patch
arm-ixp4xx-clockevent.patch
arm-leds-timer.patch
arm-no-hz.patch
arm-versatile-clockevents.patch
arm-versatile-clocksource.patch -> RMK patch system
arm_omap_clockevents.patch
arm_omap_clocksource.patch -> RMK patch system/ OMAP list
hrt-add-regs-include.patch
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: Add clocksource driver for OMAP1 and OMAP2
2006-11-30 21:22 ` [RFC] [PATCH] ARM: Add clocksource driver for OMAP1 and OMAP2 David Brownell
@ 2006-12-01 18:21 ` Dirk Behme
2006-12-01 19:03 ` David Brownell
0 siblings, 1 reply; 30+ messages in thread
From: Dirk Behme @ 2006-12-01 18:21 UTC (permalink / raw)
To: David Brownell; +Cc: linux-omap-open-source
David Brownell wrote:
> On Thursday 30 November 2006 12:33 pm, Dirk Behme wrote:
>
>>Mmh, maybe I'm wrong here or anything is long term
>>misconfigured, but looks to me that I don't get a login
>>prompt with this patch and rt applied. With [1] I get
>
> That's what I meant when I said the 32k timer doesn't
> work for me -- that's _without_ the RT patch too. The
> Linux-OMAP list archives don't have a way to get non-HTML
> versions of _single_ messages so I had to copy the [1] bits
> by hand. Presumably something significant differed? If so,
> what?
> +++ h4/arch/arm/plat-omap/timer32k.c 2006-11-28 15:06:13.000000000 -0800
> + clocksource_khz2mult(32768, clocksource_32k.shift);
Using clocksource_hz2mult instead (you see, hz vs. khz) does
the trick here ;)
Will send an update.
Dirk
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: Add clocksource driver for OMAP1 and OMAP2
2006-12-01 18:21 ` Dirk Behme
@ 2006-12-01 19:03 ` David Brownell
2006-12-01 22:13 ` Tony Lindgren
0 siblings, 1 reply; 30+ messages in thread
From: David Brownell @ 2006-12-01 19:03 UTC (permalink / raw)
To: dirk.behme; +Cc: linux-omap-open-source
> > + clocksource_khz2mult(32768, clocksource_32k.shift);
>
> Using clocksource_hz2mult instead (you see, hz vs. khz) does
> the trick here ;)
Ah, the old "off by one (letter)" trick. I knew it had to be
something like that ... thanks! :)
Evidently you agree that using a second timer is appropriate.
However, I'm not sure that a better solution might not be to
register the 32k timer clocksource by default (except on 1510),
since it seems cheap (and "always available"). Clocksource
logic can select a higher precision one if it's available.
Even with as many non-32k timer options as OMAP has (dmtimer for
both OMAP1 and OMAP2, MPU timer for OMAP1, 32k), I could imagine
usage conflicts, as reported this AM on l-a-k for ixp4xx. And
the only really general way around those seems to be a Kconfig
option for which clocksource to use (other than 32k sync timer).
Comments?
- Dave
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: Add clocksource driver for OMAP1 and OMAP2
2006-12-01 19:03 ` David Brownell
@ 2006-12-01 22:13 ` Tony Lindgren
2006-12-03 2:58 ` David Brownell
0 siblings, 1 reply; 30+ messages in thread
From: Tony Lindgren @ 2006-12-01 22:13 UTC (permalink / raw)
To: David Brownell; +Cc: linux-omap-open-source
* David Brownell <david-b@pacbell.net> [061201 11:11]:
> > > + clocksource_khz2mult(32768, clocksource_32k.shift);
> >
> > Using clocksource_hz2mult instead (you see, hz vs. khz) does
> > the trick here ;)
>
> Ah, the old "off by one (letter)" trick. I knew it had to be
> something like that ... thanks! :)
>
> Evidently you agree that using a second timer is appropriate.
>
> However, I'm not sure that a better solution might not be to
> register the 32k timer clocksource by default (except on 1510),
> since it seems cheap (and "always available"). Clocksource
> logic can select a higher precision one if it's available.
Yeah, I think the 32k sync timer for clock source would be best.
On omap2, the 32k gptimer1 is needed for timer interrupts to
produce wake-up events.
> Even with as many non-32k timer options as OMAP has (dmtimer for
> both OMAP1 and OMAP2, MPU timer for OMAP1, 32k), I could imagine
> usage conflicts, as reported this AM on l-a-k for ixp4xx. And
> the only really general way around those seems to be a Kconfig
> option for which clocksource to use (other than 32k sync timer).
>
> Comments?
Using the 32k sync timer for the clocksource is best from PM
point of view as it always runs.
I'd rather go for that by default, and then have the optional
mpu timer clocksource available as a Kconfig option.
Regards,
Tony
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-12-01 16:12 ` Dirk Behme
@ 2006-12-02 3:21 ` Daniel Walker
2006-12-02 6:11 ` Dirk Behme
0 siblings, 1 reply; 30+ messages in thread
From: Daniel Walker @ 2006-12-02 3:21 UTC (permalink / raw)
To: Dirk Behme; +Cc: OMAP-Linux
On Fri, 2006-12-01 at 17:12 +0100, Dirk Behme wrote:
> Yes and no ;)
>
> The Versatile and OMAP clocksource patches are in RMKs patch
> system. The OMAP one is updated here on the list.
Updated from someone other than Kevin I assume , or myself. I saw one
clocksource driver in response to your original email that looked
nothing like the one Kevin and I worked on, is that what your referring
to?
> But as I understand Kevin, the rest has been submitted to
> Thomas Gleixner and was planned to be included in the
> -hrt-dyntick patcheset and then in -mm. And there I couldn't
> find them. Would be a shame if they get lost. Especially the
> OMAP clockevent one.
When Thomas did his -mm update all the clocksources got dropped .. Later
we resubmitted to him, but that was after hrt was included into -mm ..
It's not up to Thomas to merge OMAP, etc .. , clocksources. It's up to
us (Kevin, and myself) to submit to arch maintainers at this point. If
someone on this list has an update to our code we can resubmit to RMK,
or they can directly. Nothing should go via Thomas.
Daniel
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-12-02 3:21 ` Daniel Walker
@ 2006-12-02 6:11 ` Dirk Behme
2006-12-02 6:54 ` Daniel Walker
0 siblings, 1 reply; 30+ messages in thread
From: Dirk Behme @ 2006-12-02 6:11 UTC (permalink / raw)
To: Daniel Walker; +Cc: OMAP-Linux
Daniel Walker wrote:
> On Fri, 2006-12-01 at 17:12 +0100, Dirk Behme wrote:
>>The Versatile and OMAP clocksource patches are in RMKs patch
>>system. The OMAP one is updated here on the list.
>
> Updated from someone other than Kevin I assume , or myself. I saw one
> clocksource driver in response to your original email that looked
> nothing like the one Kevin and I worked on, is that what your referring
> to?
Regarding clocksource for OMAP, I refer to [1]. This is
based on the patch from Kevin and you. Updated by me (acked
by Kevin [2]) and then more improvements by David.
>>But as I understand Kevin, the rest has been submitted to
>>Thomas Gleixner and was planned to be included in the
>>-hrt-dyntick patcheset and then in -mm. And there I couldn't
>>find them. Would be a shame if they get lost. Especially the
>>OMAP clockevent one.
>
> When Thomas did his -mm update all the clocksources got dropped
I'm not talking about (OMAP) clocksource here. I'm talking
about the rest [3], especially OMAP clockevent patch.
> It's not up to Thomas to merge OMAP, etc .. , clocksources. It's up to
> us (Kevin, and myself) to submit to arch maintainers at this point. If
> someone on this list has an update to our code we can resubmit to RMK,
> or they can directly.
While we are talking on this list, I think we have to split
the patches in your patchset:
- OMAP clocksource is currently discussed on this list. I
think it will be merged here when it is clear how it should
look like.
- OMAP clockevent is potentially something for this list as
well. But currently, it isn't discussed here and I can't
find it discussed or included anywhere else. So it looks to
me that it is lost (until anybody cares again). This is the
core of my question: Is it currently nowhere maintained?
- The other patches, e.g. for ixp4xx and versatile, I think
nobody will care on this list and update them here. So until
they are not handled somewhere else (are they?), they will
be lost as well.
> Nothing should go via Thomas.
You originally sent most of the patches to Thomas, don't you? ;)
Dirk
[1]
http://linux.omap.com/pipermail/linux-omap-open-source/2006-December/008558.html
[2]
http://linux.omap.com/pipermail/linux-omap-open-source/2006-November/008380.html
[3] Patches we talk about (content of
patches-2.6.19-rc2.tar.bz2)
arm-hrt-kconfig.patch
arm-ixp4xx-clockevent.patch
arm-leds-timer.patch
arm-no-hz.patch
arm-versatile-clockevents.patch
arm-versatile-clocksource.patch -> RMK patch system
arm_omap_clockevents.patch
arm_omap_clocksource.patch -> RMK patch system/ OMAP list
hrt-add-regs-include.patch
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-12-02 6:11 ` Dirk Behme
@ 2006-12-02 6:54 ` Daniel Walker
2006-12-02 7:06 ` Dirk Behme
0 siblings, 1 reply; 30+ messages in thread
From: Daniel Walker @ 2006-12-02 6:54 UTC (permalink / raw)
To: Dirk Behme; +Cc: OMAP-Linux
On Sat, 2006-12-02 at 07:11 +0100, Dirk Behme wrote:
> > When Thomas did his -mm update all the clocksources got dropped
>
> I'm not talking about (OMAP) clocksource here. I'm talking
> about the rest [3], especially OMAP clockevent patch.
ok.
> - OMAP clockevent is potentially something for this list as
> well. But currently, it isn't discussed here and I can't
> find it discussed or included anywhere else. So it looks to
> me that it is lost (until anybody cares again). This is the
> core of my question: Is it currently nowhere maintained?
I guess Kevin and I maintain it. It's not such a large piece of code.
The reason that it's not getting pushed hard at the moment is because
HRT is testing in -mm .. So we're at a limbo point when we can't move
the code to RMK, and it's not really appropriate for the code to go into
-mm .. We just have to wait till HRT gets shaken out in -mm .
The reason we are able to send the clocksource to RMK is cause generic
time went into the 2.6.18 stable release.
> - The other patches, e.g. for ixp4xx and versatile, I think
> nobody will care on this list and update them here. So until
> they are not handled somewhere else (are they?), they will
> be lost as well.
>
> > Nothing should go via Thomas.
>
> You originally sent most of the patches to Thomas, don't you? ;)
Yes, before HRT went to -mm. The reason that it was useful to send them
to Thomas was for our own testing, and progressing HRT at an early
point. I wouldn't have minded if the OMAP clockevents when into -mm ,
but I've never seen anything like that happen (i.e. non-i386 board
specific code going into -mm).
Daniel
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-12-02 6:54 ` Daniel Walker
@ 2006-12-02 7:06 ` Dirk Behme
2006-12-02 7:18 ` Daniel Walker
2006-12-04 23:34 ` Kevin Hilman
0 siblings, 2 replies; 30+ messages in thread
From: Dirk Behme @ 2006-12-02 7:06 UTC (permalink / raw)
To: Daniel Walker; +Cc: OMAP-Linux
Daniel Walker wrote:
> On Sat, 2006-12-02 at 07:11 +0100, Dirk Behme wrote:
>
>>>When Thomas did his -mm update all the clocksources got dropped
>>
>>I'm not talking about (OMAP) clocksource here. I'm talking
>>about the rest [3], especially OMAP clockevent patch.
>
> ok.
>
>>- OMAP clockevent is potentially something for this list as
>>well. But currently, it isn't discussed here and I can't
>>find it discussed or included anywhere else. So it looks to
>>me that it is lost (until anybody cares again). This is the
>>core of my question: Is it currently nowhere maintained?
>
> I guess Kevin and I maintain it. It's not such a large piece of code.
> The reason that it's not getting pushed hard at the moment is because
> HRT is testing in -mm .. So we're at a limbo point when we can't move
> the code to RMK, and it's not really appropriate for the code to go into
> -mm .. We just have to wait till HRT gets shaken out in -mm .
>
> The reason we are able to send the clocksource to RMK is cause generic
> time went into the 2.6.18 stable release.
>
>>- The other patches, e.g. for ixp4xx and versatile, I think
>>nobody will care on this list and update them here. So until
>>they are not handled somewhere else (are they?), they will
>>be lost as well.
>>
>>>Nothing should go via Thomas.
>>
>>You originally sent most of the patches to Thomas, don't you? ;)
>
> Yes, before HRT went to -mm. The reason that it was useful to send them
> to Thomas was for our own testing, and progressing HRT at an early
> point. I wouldn't have minded if the OMAP clockevents when into -mm ,
> but I've never seen anything like that happen (i.e. non-i386 board
> specific code going into -mm).
Okay. Many thanks for clarifying these tricky dependencies!
Looks like then nothing is lost, only "waiting". Would be
nice if you can keep us updated regarding this.
Dirk
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-12-02 7:06 ` Dirk Behme
@ 2006-12-02 7:18 ` Daniel Walker
2006-12-04 23:34 ` Kevin Hilman
1 sibling, 0 replies; 30+ messages in thread
From: Daniel Walker @ 2006-12-02 7:18 UTC (permalink / raw)
To: Dirk Behme; +Cc: OMAP-Linux
On Sat, 2006-12-02 at 08:06 +0100, Dirk Behme wrote:
> > Yes, before HRT went to -mm. The reason that it was useful to send them
> > to Thomas was for our own testing, and progressing HRT at an early
> > point. I wouldn't have minded if the OMAP clockevents when into -mm ,
> > but I've never seen anything like that happen (i.e. non-i386 board
> > specific code going into -mm).
>
> Okay. Many thanks for clarifying these tricky dependencies!
>
> Looks like then nothing is lost, only "waiting". Would be
> nice if you can keep us updated regarding this.
No problem. I think Kevin will be the one send out and update tho.
Daniel
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: Add clocksource driver for OMAP1 and OMAP2
2006-12-01 22:13 ` Tony Lindgren
@ 2006-12-03 2:58 ` David Brownell
0 siblings, 0 replies; 30+ messages in thread
From: David Brownell @ 2006-12-03 2:58 UTC (permalink / raw)
To: Tony Lindgren; +Cc: linux-omap-open-source
On Friday 01 December 2006 2:13 pm, Tony Lindgren wrote:
> Using the 32k sync timer for the clocksource is best from PM
> point of view as it always runs.
>
> I'd rather go for that by default, and then have the optional
> mpu timer clocksource available as a Kconfig option.
Here's an updated version of the patch most recently sent by
Dirk. The change adds adds the 32K clocksource for all OMAP1
and OMAP2 systems, removing the OMAP2 gptimer2 clocksource
and cleaning up the OMAP1 mpu timer source (plus, hmm, fixing
a sched_timer bug).
I left the mpu_timer2 clocksource in, since OMAP 730 and 1510
will look like they'll be needing it. I suppose it could be
disabled there unless Kconfig re-enables it.
- Dave
=================== CUT HERE
Add clocksource driver for OMAP.
This is an update of
http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=3876/1
from Daniel Walker and Kevin Hilman.
Changes from Dirk Behme:
- Apply cleanly to recent git (pt_regs change)
- Move clocksource init to extra function. Can be called
later by clocksource subsystem
- Remove warning: 'omap_32k_timer_handler' defined but not used
when CONFIG_NO_IDLE_HZ isn't set.
- Minor cleanups
Changes from David Brownell:
- OMAP1, OMAP2: 32k clocksource is always available on 16xx and 24xx
- OMAP1 MPU timer:
* consult clock framework to determine xtal clock
* bugfix sched_clock() low order bits
* cleanup
- Kconfig updates
Note that "MPU timer" still doesn't have lost tick support.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Index: osk2/arch/arm/Kconfig
===================================================================
--- osk2.orig/arch/arm/Kconfig 2006-12-02 12:23:14.000000000 -0800
+++ osk2/arch/arm/Kconfig 2006-12-02 12:23:25.000000000 -0800
@@ -314,6 +314,7 @@ config ARCH_LH7A40X
config ARCH_OMAP
bool "TI OMAP"
+ select GENERIC_TIME
help
Support for TI's OMAP platform (OMAP1 and OMAP2).
Index: osk2/arch/arm/plat-omap/common.c
===================================================================
--- osk2.orig/arch/arm/plat-omap/common.c 2006-12-02 12:23:14.000000000 -0800
+++ osk2/arch/arm/plat-omap/common.c 2006-12-02 13:37:46.000000000 -0800
@@ -180,3 +180,53 @@ static int __init omap_add_serial_consol
return add_preferred_console("ttyS", line, opt);
}
console_initcall(omap_add_serial_console);
+
+
+/*
+ * 32KHz clocksource ... always available, on pretty most chips except
+ * OMAP 730 and 1510. Other timers could be used as clocksources, with
+ * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
+ * but systems won't necessarily want to spend resources that way.
+ */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+#define TIMER_32K_SYNCHRONIZED 0xfffbc410
+#elif defined(CONFIG_ARCH_OMAP24XX)
+#define TIMER_32K_SYNCHRONIZED 0x48004010
+#endif
+
+#ifdef TIMER_32K_SYNCHRONIZED
+
+#include <linux/clocksource.h>
+
+static cycle_t omap_32k_read(void)
+{
+ return omap_readl(TIMER_32K_SYNCHRONIZED);
+}
+
+static struct clocksource clocksource_32k = {
+ .name = "32k_counter",
+ .rating = 250,
+ .read = omap_32k_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 10,
+ .is_continuous = 1,
+};
+
+static int __init omap_init_clocksource_32k(void)
+{
+ static char err[] __initdata = KERN_ERR
+ "%s: can't register clocksource!\n";
+
+ if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+ clocksource_32k.mult = clocksource_hz2mult(32768,
+ clocksource_32k.shift);
+
+ if (clocksource_register(&clocksource_32k))
+ printk(err, clocksource_32k.name);
+ }
+ return 0;
+}
+arch_initcall(omap_init_clocksource_32k);
+
+#endif /* TIMER_32K_SYNCHRONIZED */
Index: osk2/arch/arm/plat-omap/timer32k.c
===================================================================
--- osk2.orig/arch/arm/plat-omap/timer32k.c 2006-12-02 12:23:14.000000000 -0800
+++ osk2/arch/arm/plat-omap/timer32k.c 2006-12-02 12:23:25.000000000 -0800
@@ -42,6 +42,7 @@
#include <linux/spinlock.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/clocksource.h>
#include <asm/system.h>
#include <asm/hardware.h>
@@ -171,15 +172,6 @@ omap_32k_ticks_to_nsecs(unsigned long ti
static unsigned long omap_32k_last_tick = 0;
/*
- * Returns elapsed usecs since last 32k timer interrupt
- */
-static unsigned long omap_32k_timer_gettimeoffset(void)
-{
- unsigned long now = omap_32k_sync_timer_read();
- return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
-}
-
-/*
* Returns current time from boot in nsecs. It's OK for this to wrap
* around for now, as it's just a relative time stamp.
*/
@@ -217,22 +209,6 @@ static inline irqreturn_t _omap_32k_time
return IRQ_HANDLED;
}
-static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id)
-{
- unsigned long now;
-
- now = omap_32k_sync_timer_read();
-
- /* Don't bother reprogramming timer if last tick was before next
- * jiffie. We will get another interrupt when previously programmed
- * timer expires. This cuts down interrupt load quite a bit.
- */
- if (now - omap_32k_last_tick < OMAP_32K_TICKS_PER_HZ)
- return IRQ_HANDLED;
-
- return _omap_32k_timer_interrupt(irq, dev_id);
-}
-
static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
{
unsigned long flags;
@@ -245,6 +221,7 @@ static irqreturn_t omap_32k_timer_interr
}
#ifdef CONFIG_NO_IDLE_HZ
+
/*
* Programs the next timer interrupt needed. Called when dynamic tick is
* enabled, and to reprogram the ticks to skip from pm_idle. Note that
@@ -280,6 +257,22 @@ static int omap_32k_timer_disable_dyn_ti
return 0;
}
+static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id)
+{
+ unsigned long now;
+
+ now = omap_32k_sync_timer_read();
+
+ /* Don't bother reprogramming timer if last tick was before next
+ * jiffie. We will get another interrupt when previously programmed
+ * timer expires. This cuts down interrupt load quite a bit.
+ */
+ if (now - omap_32k_last_tick < OMAP_32K_TICKS_PER_HZ)
+ return IRQ_HANDLED;
+
+ return _omap_32k_timer_interrupt(irq, dev_id);
+}
+
static struct dyn_tick_timer omap_dyn_tick_timer = {
.enable = omap_32k_timer_enable_dyn_tick,
.disable = omap_32k_timer_disable_dyn_tick,
@@ -302,7 +295,6 @@ static __init void omap_init_32k_timer(v
if (cpu_class_is_omap1())
setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
- omap_timer.offset = omap_32k_timer_gettimeoffset;
omap_32k_last_tick = omap_32k_sync_timer_read();
#ifdef CONFIG_ARCH_OMAP2
@@ -337,5 +329,4 @@ static void __init omap_timer_init(void)
struct sys_timer omap_timer = {
.init = omap_timer_init,
- .offset = NULL, /* Initialized later */
};
Index: osk2/arch/arm/mach-omap1/time.c
===================================================================
--- osk2.orig/arch/arm/mach-omap1/time.c 2006-12-02 12:23:14.000000000 -0800
+++ osk2/arch/arm/mach-omap1/time.c 2006-12-02 14:29:43.000000000 -0800
@@ -39,6 +39,9 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/clocksource.h>
#include <asm/system.h>
#include <asm/hardware.h>
@@ -48,13 +51,7 @@
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
-struct sys_timer omap_timer;
-/*
- * ---------------------------------------------------------------------------
- * MPU timer
- * ---------------------------------------------------------------------------
- */
#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE
#define OMAP_MPU_TIMER_OFFSET 0x100
@@ -88,21 +85,6 @@ static inline unsigned long long cycles_
return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
}
-/*
- * MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs
- * will break. On P2, the timer count rate is 6.5 MHz after programming PTV
- * with 0. This divides the 13MHz input by 2, and is undocumented.
- */
-#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE)
-/* REVISIT: This ifdef construct should be replaced by a query to clock
- * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz.
- */
-#define MPU_TICKS_PER_SEC (13000000 / 2)
-#else
-#define MPU_TICKS_PER_SEC (12000000 / 2)
-#endif
-
-#define MPU_TIMER_TICK_PERIOD ((MPU_TICKS_PER_SEC / HZ) - 1)
typedef struct {
u32 cntl; /* CNTL_TIMER, R/W */
@@ -131,87 +113,94 @@ static inline void omap_mpu_timer_start(
timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST);
}
-unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks)
+/*
+ * ---------------------------------------------------------------------------
+ * MPU timer 1 ... count down to zero, interrupt, reload
+ * ---------------------------------------------------------------------------
+ */
+static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
{
- unsigned long long nsec;
+ write_seqlock(&xtime_lock);
+ /* NOTE: no lost-tick detection/handling! */
+ timer_tick();
+ write_sequnlock(&xtime_lock);
- nsec = cycles_2_ns((unsigned long long)nr_ticks);
- return (unsigned long)nsec / 1000;
+ return IRQ_HANDLED;
}
-/*
- * Last processed system timer interrupt
- */
-static unsigned long omap_mpu_timer_last = 0;
+static struct irqaction omap_mpu_timer1_irq = {
+ .name = "mpu_timer1",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = omap_mpu_timer1_interrupt,
+};
-/*
- * Returns elapsed usecs since last system timer interrupt
- */
-static unsigned long omap_mpu_timer_gettimeoffset(void)
+static __init void omap_init_mpu_timer(unsigned long rate)
{
- unsigned long now = 0 - omap_mpu_timer_read(0);
- unsigned long elapsed = now - omap_mpu_timer_last;
+ set_cyc2ns_scale(rate / 1000);
- return omap_mpu_timer_ticks_to_usecs(elapsed);
+ setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
+ omap_mpu_timer_start(0, (rate / HZ) - 1);
}
/*
- * Elapsed time between interrupts is calculated using timer0.
- * Latency during the interrupt is calculated using timer1.
- * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz).
+ * ---------------------------------------------------------------------------
+ * MPU timer 2 ... free running 32-bit clock source and scheduler clock
+ * ---------------------------------------------------------------------------
*/
-static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id)
-{
- unsigned long now, latency;
- write_seqlock(&xtime_lock);
- now = 0 - omap_mpu_timer_read(0);
- latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1);
- omap_mpu_timer_last = now - latency;
- timer_tick();
- write_sequnlock(&xtime_lock);
+static unsigned long omap_mpu_timer2_overflows;
+static irqreturn_t omap_mpu_timer2_interrupt(int irq, void *dev_id)
+{
+ omap_mpu_timer2_overflows++;
return IRQ_HANDLED;
}
-static struct irqaction omap_mpu_timer_irq = {
- .name = "mpu timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
- .handler = omap_mpu_timer_interrupt,
+static struct irqaction omap_mpu_timer2_irq = {
+ .name = "mpu_timer2",
+ .flags = IRQF_DISABLED,
+ .handler = omap_mpu_timer2_interrupt,
};
-static unsigned long omap_mpu_timer1_overflows;
-static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
+static cycle_t mpu_read(void)
{
- omap_mpu_timer1_overflows++;
- return IRQ_HANDLED;
+ return ~omap_mpu_timer_read(1);
}
-static struct irqaction omap_mpu_timer1_irq = {
- .name = "mpu timer1 overflow",
- .flags = IRQF_DISABLED,
- .handler = omap_mpu_timer1_interrupt,
+static struct clocksource clocksource_mpu = {
+ .name = "mpu_timer2",
+ .rating = 300,
+ .read = mpu_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 24,
+ .is_continuous = 1,
};
-static __init void omap_init_mpu_timer(void)
+static void __init omap_init_clocksource(unsigned long rate)
{
- set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000);
- omap_timer.offset = omap_mpu_timer_gettimeoffset;
- setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
- setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
- omap_mpu_timer_start(0, 0xffffffff);
- omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
+ static char err[] __initdata = KERN_ERR
+ "%s: can't register clocksource!\n";
+
+ clocksource_mpu.mult
+ = clocksource_khz2mult(rate/1000, clocksource_mpu.shift);
+
+ setup_irq(INT_TIMER2, &omap_mpu_timer2_irq);
+ omap_mpu_timer_start(1, ~0);
+
+ if (clocksource_register(&clocksource_mpu))
+ printk(err, clocksource_mpu.name);
}
+
/*
* Scheduler clock - returns current time in nanosec units.
*/
unsigned long long sched_clock(void)
{
- unsigned long ticks = 0 - omap_mpu_timer_read(0);
+ unsigned long ticks = 0 - omap_mpu_timer_read(1);
unsigned long long ticks64;
- ticks64 = omap_mpu_timer1_overflows;
+ ticks64 = omap_mpu_timer2_overflows;
ticks64 <<= 32;
ticks64 |= ticks;
@@ -225,10 +214,21 @@ unsigned long long sched_clock(void)
*/
static void __init omap_timer_init(void)
{
- omap_init_mpu_timer();
+ struct clk *ck_ref = clk_get(NULL, "ck_ref");
+ unsigned long rate;
+
+ BUG_ON(IS_ERR(ck_ref));
+
+ rate = clk_get_rate(ck_ref);
+ clk_put(ck_ref);
+
+ /* PTV = 0 */
+ rate /= 2;
+
+ omap_init_mpu_timer(rate);
+ omap_init_clocksource(rate);
}
struct sys_timer omap_timer = {
.init = omap_timer_init,
- .offset = NULL, /* Initialized later */
};
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1
2006-12-02 7:06 ` Dirk Behme
2006-12-02 7:18 ` Daniel Walker
@ 2006-12-04 23:34 ` Kevin Hilman
1 sibling, 0 replies; 30+ messages in thread
From: Kevin Hilman @ 2006-12-04 23:34 UTC (permalink / raw)
To: Dirk Behme; +Cc: OMAP-Linux
> Okay. Many thanks for clarifying these tricky dependencies!
>
> Looks like then nothing is lost, only "waiting". Would be
> nice if you can keep us updated regarding this.
Just a quick update... sorry to jump into this thread so late, I've been
travelling.
There's been some discussion between myself and RMK about some
clocksource init details. As soon as that's resolved, he will be ready
to accept clocksource patches for other platforms.
I will review/merge the stuff from Dirk and Dave and resubmit a patch to
RMK based on those updates.
Kevin
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2006-12-04 23:34 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-07 15:32 [RFC] [PATCH] ARM: OMAP1: Add clocksource driver for OMAP1 Dirk Behme
[not found] ` <4550CA9E.6090500@mvista.com>
2006-11-08 16:44 ` Dirk Behme
2006-11-10 0:29 ` Tony Lindgren
2006-11-10 0:48 ` Kevin Hilman
2006-11-10 0:53 ` Tony Lindgren
2006-11-30 19:57 ` Woodruff, Richard
2006-11-30 21:30 ` David Brownell
2006-11-30 21:49 ` Woodruff, Richard
2006-11-30 22:32 ` David Brownell
2006-11-30 22:57 ` Woodruff, Richard
2006-11-30 22:12 ` tony
2006-11-30 21:59 ` tony
2006-11-30 22:24 ` Woodruff, Richard
2006-11-30 22:37 ` tony
2006-11-30 17:55 ` Dirk Behme
2006-11-30 17:50 ` Daniel Walker
2006-12-01 16:12 ` Dirk Behme
2006-12-02 3:21 ` Daniel Walker
2006-12-02 6:11 ` Dirk Behme
2006-12-02 6:54 ` Daniel Walker
2006-12-02 7:06 ` Dirk Behme
2006-12-02 7:18 ` Daniel Walker
2006-12-04 23:34 ` Kevin Hilman
2006-11-30 19:14 ` David Brownell
2006-11-30 20:33 ` Dirk Behme
2006-11-30 21:22 ` [RFC] [PATCH] ARM: Add clocksource driver for OMAP1 and OMAP2 David Brownell
2006-12-01 18:21 ` Dirk Behme
2006-12-01 19:03 ` David Brownell
2006-12-01 22:13 ` Tony Lindgren
2006-12-03 2:58 ` David Brownell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox