* [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[parent not found: <4550CA9E.6090500@mvista.com>]
* 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-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: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 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: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 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 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: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 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 [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-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 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: 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: 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
* 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-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: 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: 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
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