[PATCH 1/3] ARM: OMAP2+: 32k-counter: Use hwmod lookup to check presence of 32k timer
Hiremath, Vaibhav
hvaibhav at ti.com
Fri Mar 30 02:34:17 EDT 2012
On Wed, Mar 28, 2012 at 20:19:07, Shilimkar, Santosh wrote:
> On Wed, Mar 28, 2012 at 8:07 PM, Hiremath, Vaibhav <hvaibhav at ti.com> wrote:
> > On Wed, Mar 28, 2012 at 19:50:02, Shilimkar, Santosh wrote:
> >> On Wed, Mar 28, 2012 at 7:46 PM, Hiremath, Vaibhav <hvaibhav at ti.com> wrote:
> >> > On Wed, Mar 21, 2012 at 19:30:01, Shilimkar, Santosh wrote:
> >> >> On Wed, Mar 21, 2012 at 5:12 PM, Hiremath, Vaibhav <hvaibhav at ti.com> wrote:
> >> >> > On Mon, Mar 19, 2012 at 17:45:32, Shilimkar, Santosh wrote:
> >> >> >> On Monday 19 March 2012 05:14 PM, Ming Lei wrote:
> >> >> >> > On Mon, Mar 19, 2012 at 7:11 PM, Hiremath, Vaibhav <hvaibhav at ti.com> wrote:
> >>
> >> [...]
> >>
> >> >
> >> >> Btw, if you need PM, how are you going to use GPTIMER
> >> >> as a clocksource. Note sys-clock is generally stopped in
> >> >> low power states. So that leaves you option with using
> >> >> gptimer with 32K clock and in that case, GPTIMER
> >> >> is not a better clock-source compare to 32K sync timer
> >> >> and so shouldn't be the rating.
> >> >>
> >> >
> >> > AM33xx has GPTIMER1 in wakeup domain, so that we are already using as a
> >> > Clocksource, without any issues.
> >> >
> >> GPTIMER1 is in wakeup domain on OMAP too but that doesn't
> >> solve the issue I am talking. Once the sysclock is stopped, GPTIMER
> >> can't tick anymore even if it is in wakeup domain.
> >>
> >> The only way it will work is using always running 32KHz clock as
> >> the clock input to GPT1. And then the end result is the accuracy
> >> of GPTIMER = sync 32K timer. So they are of same rating.
> >>
> >
> > Ohh ok, sorry I should have clarified it in my last response itself.
> >
> np.
>
> > AM33xx architecture is bit different than OMAP family, and gmtimer1 is
> > sourced from RTC32K clock, which is in wakeup domain.
> > This means we have RTC32K clock always running across suspend/resume.
> >
> > 0 - SEL1: Select CLK_M_OSC clock
> > 1 - SEL2: Select CLK_32KHZ clock
> > 2 - SEL3: Select TCLKIN clock
> > 3 - SEL4: Select CLK_RC32K clock
> > 4 - SEL5: Selects the CLK_32768 from 32KHz Crystal Osc
> >
> >
> > We use value "4" here, for RTC32K (always on clock).
> > I hope this clarifies what I am trying to say here.
> >
> I thought so and now if you look at last part of my comment.
>
> Rating of 32K based synctimer and 32K based GPTIMER
> should be same because of the precision. That's the main
> point why I was saying that GPTIMER is not a better
> clock-source( with 32k clock src) than sync timer when
> both are enabled together.
>
Santosh,
In case of OMAP, we are using timer 2 for clocksource
OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE)
OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE)
And timer2 as clocksource is never used, since we have CONFIG_OMAP_32K_TIMER
defined in our defconfig.
Also, after looking at the code, I came across another problem, setup_sched_clock(). But this can be easily fixed, if we source both the timers with same clock (here 32k_fck).
Let me propose this,
How about, if I keep timer2 source always set to 32k_fclk for omap2,3,4?
And also, as mentioned by Santosh, I will register both the clocks as
clocksource with the same rating.
By default, kernel is going to use 32k_counter as a clocksource, and through
Command prompt user can override it without any issues.
Just to make sure that, whatever I am trying to propse here works and don't get into unknown issue; I changed my code for this, and it is working for me without any issues.
Also, this way I can completely get rid of option CONFIG_OMAP_32K_TIMER_HZ.
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 6b12372..ded78b7 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -45,6 +45,7 @@
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
#include <plat/omap-pm.h>
+#include <plat/clock.h>
#include "powerdomain.h"
@@ -57,18 +58,18 @@
#define OMAP3_32K_SOURCE "omap_32k_fck"
#define OMAP4_32K_SOURCE "sys_32k_ck"
-#ifdef CONFIG_OMAP_32K_TIMER
+//#ifdef CONFIG_OMAP_32K_TIMER
#define OMAP2_CLKEV_SOURCE OMAP2_32K_SOURCE
#define OMAP3_CLKEV_SOURCE OMAP3_32K_SOURCE
#define OMAP4_CLKEV_SOURCE OMAP4_32K_SOURCE
#define OMAP3_SECURE_TIMER 12
-#else
+/*#else
#define OMAP2_CLKEV_SOURCE OMAP2_MPU_SOURCE
#define OMAP3_CLKEV_SOURCE OMAP3_MPU_SOURCE
#define OMAP4_CLKEV_SOURCE OMAP4_MPU_SOURCE
#define OMAP3_SECURE_TIMER 1
#endif
-
+*/
/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
#define MAX_GPTIMER_ID 12
@@ -244,6 +245,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
/* Clocksource code */
static struct omap_dm_timer clksrc;
+static bool is_dmtimer_clocksource;
/*
* clocksource
@@ -253,20 +255,38 @@ static cycle_t clocksource_read_cycles(struct clocksource *cs)
return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
}
+static int clocksource_enable(struct clocksource *cs)
+{
+ __omap_dm_timer_load_start(&clksrc,
+ OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
+ omap_32k_read_sched_clock(), 1);
+
+ is_dmtimer_clocksource = true;
+ return 0;
+}
+
+static void clocksource_disable(struct clocksource *cs)
+{
+ __omap_dm_timer_stop(&clksrc, 1, clksrc.rate);
+ is_dmtimer_clocksource = false;
+}
+
static struct clocksource clocksource_gpt = {
.name = "gp timer",
- .rating = 300,
+ .rating = 250,
.read = clocksource_read_cycles,
+ .enable = clocksource_enable,
+ .disable = clocksource_disable,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
-static u32 notrace dmtimer_read_sched_clock(void)
+static u32 notrace read_sched_clock(void)
{
- if (clksrc.reserved)
+ if (is_dmtimer_clocksource && clksrc.reserved)
return __omap_dm_timer_read_counter(&clksrc, 1);
-
- return 0;
+ else
+ return omap_32k_read_sched_clock();
}
/* Setup free-running counter for clocksource */
@@ -282,8 +302,8 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
* execution will fallback to gp-timer.
*/
res = omap_init_clocksource_32k();
- if (!res)
- return;
+ if (res)
+ pr_err("failed to init 32k_counter as a clocksource %d\n", res);
/* Fall back to gp-timer code */
res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source);
@@ -292,9 +312,9 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
gptimer_id, clksrc.rate);
- __omap_dm_timer_load_start(&clksrc,
- OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
- setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate);
+// __omap_dm_timer_load_start(&clksrc,
+// OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
+ setup_sched_clock(read_sched_clock, 32, clksrc.rate);
if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
pr_err("Could not register clocksource %s\n",
@@ -315,12 +335,12 @@ struct sys_timer omap##name##_timer = { \
};
#ifdef CONFIG_ARCH_OMAP2
-OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE)
+OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP3_CLKEV_SOURCE)
OMAP_SYS_TIMER(2)
#endif
#ifdef CONFIG_ARCH_OMAP3
-OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE)
+OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_CLKEV_SOURCE)
OMAP_SYS_TIMER(3)
OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
2, OMAP3_MPU_SOURCE)
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index 5a25de0..4d65c2f 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -37,7 +37,7 @@ static void __iomem *timer_32k_base;
#define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410
-static u32 notrace omap_32k_read_sched_clock(void)
+u32 notrace omap_32k_read_sched_clock(void)
{
return timer_32k_base ? __raw_readl(timer_32k_base) : 0;
}
@@ -118,7 +118,7 @@ int __init omap_init_clocksource_32k(void)
printk(KERN_ERR "%s: can't register clocksource!\n",
"32k_counter");
- setup_sched_clock(omap_32k_read_sched_clock, 32, 32768);
+// setup_sched_clock(omap_32k_read_sched_clock, 32, 32768);
return 0;
}
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index b4d7ec3..4afb19b 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -31,6 +31,7 @@
#include <plat/omap_hwmod.h>
extern int __init omap_init_clocksource_32k(void);
+extern u32 notrace omap_32k_read_sched_clock(void);
extern void omap_reserve(void);
extern int omap_dss_reset(struct omap_hwmod *);
Thanks,
Vaibhav
More information about the linux-arm-kernel
mailing list