Thread (11 messages) 11 messages, 3 authors, 2012-04-05

[PATCH-V2 3/3] ARM: OMAP: Make OMAP clocksource source selection runtime

From: Hiremath, Vaibhav <hidden>
Date: 2012-04-02 06:06:49
Also in: linux-omap

On Fri, Mar 30, 2012 at 21:04:40, Hunter, Jon wrote:
Hi Vaibhav,

On 3/30/2012 8:54, Vaibhav Hiremath wrote:
quoted
Current OMAP code supports couple of clocksource options based
on compilation flag (CONFIG_OMAP_32K_TIMER). The 32KHz sync-timer
and a gptimer which can run on 32KHz or system clock (e.g 38.4 MHz).
So there can be 3 options -

1. 32KHz sync-timer
2. Sys_clock based (e.g 13/19.2/26/38.4 MHz) gptimer
3. 32KHz based gptimer.

The optional gptimer based clocksource was added so that it can
give the high precision than sync-timer, so expected usage was 2
and not 3.
Unfortunately option 2, clocksource doesn't meet the requirement of
free-running clock as per clocksource need. It stops in low power states
when sys_clock is cut. That makes gptimer based clocksource option
useless for OMAP2/3/4 devices with sys_clock as a clock input.
Option 3 will still work but it is no better than 32K sync-timer
based clocksource.

So ideally we can kill the gptimer based clocksource option but there
are some OMAP based derivative SoCs like AM33XX which doesn't have
32K sync-timer hardware IP and need to fallback on 32KHz based gptimer
clocksource.
Considering above, make sync-timer and gptimer clocksource runtime
selectable so that both OMAP and AMXXXX continue to use the same code.

Use hwmod database lookup mechanism, through which at run-time
we can identify availability of 32k-sync timer on the device,
else fall back to gptimer.

Signed-off-by: Vaibhav Hiremath <redacted>
Signed-off-by: Felipe Balbi <redacted>
CC: Santosh Shilimkar <redacted>
Cc: Benoit Cousson <redacted>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Tarun Kanti DebBarma <redacted>
Cc: Ming Lei <tom.leiming@gmail.com>
---
 arch/arm/mach-omap1/timer32k.c           |    6 ++-
 arch/arm/mach-omap2/timer.c              |   45 +++++++++-------
 arch/arm/plat-omap/counter_32k.c         |   86 ++++++++++++-----------------
 arch/arm/plat-omap/include/plat/common.h |    2 +-
 4 files changed, 68 insertions(+), 71 deletions(-)
[...]
quoted
@@ -280,13 +265,33 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
 						const char *fck_source)
 {
 	int res;
+	struct omap_hwmod *oh;
+	const char *oh_name = "counter_32k";
+
+	/*
+	 * First check for availability for 32k-sync timer.
+	 *
+	 * In case of failure in finding 32k_counter module or
+	 * registering it as clocksource, execution will fallback to
+	 * gp-timer.
+	 */
+	oh = omap_hwmod_lookup(oh_name);
+	if (oh && oh->slaves_cnt != 0) {
+		u32 pbase;
+		unsigned long size;
+
+		pbase = oh->slaves[0]->addr->pa_start + 0x10;
+		size = oh->slaves[0]->addr->pa_end -
+			oh->slaves[0]->addr->pa_start;
+		res = omap_init_clocksource_32k(pbase, size);
+		if (!res)
+			return;

If omap_init_clocksource_32k() fails should we also call BUG_ON here?
I don't think we should do that, for following reasons,

	- There will be platforms without 32k_counter modules, like am33xx.
        For them, this BUG_ON will miss-leading.
	- pr_err is already used to provide failure in this function.
	- We have safe fallback option here.

quoted
+	}

+	/* Fall back to gp-timer code */
 	res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source);
 	BUG_ON(res);

-	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);
@@ -294,8 +299,10 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
 	if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
 		pr_err("Could not register clocksource %s\n",
 			clocksource_gpt.name);
+	else
+		pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
+			gptimer_id, clksrc.rate);
 }
-#endif

 #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src,			\
 				clksrc_nr, clksrc_src)			\
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index 5068fe5..c1af18c 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -35,8 +35,6 @@
  */
 static void __iomem *timer_32k_base;

-#define OMAP16XX_TIMER_32K_SYNCHRONIZED		0xfffbc410
-
 static u32 notrace omap_32k_read_sched_clock(void)
 {
 	return timer_32k_base ? __raw_readl(timer_32k_base) : 0;
@@ -68,54 +66,42 @@ void read_persistent_clock(struct timespec *ts)
 	*ts = *tsp;
 }

-int __init omap_init_clocksource_32k(void)
+int __init omap_init_clocksource_32k(u32 pbase, unsigned long size)
 {
-	static char err[] __initdata = KERN_ERR
-			"%s: can't register clocksource!\n";
-
-	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
-		u32 pbase;
-		unsigned long size = SZ_4K;
-		void __iomem *base;
-		struct clk *sync_32k_ick;
-
-		if (cpu_is_omap16xx()) {
-			pbase = OMAP16XX_TIMER_32K_SYNCHRONIZED;
-			size = SZ_1K;
-		} else if (cpu_is_omap2420())
-			pbase = OMAP2420_32KSYNCT_BASE + 0x10;
-		else if (cpu_is_omap2430())
-			pbase = OMAP2430_32KSYNCT_BASE + 0x10;
-		else if (cpu_is_omap34xx())
-			pbase = OMAP3430_32KSYNCT_BASE + 0x10;
-		else if (cpu_is_omap44xx())
-			pbase = OMAP4430_32KSYNCT_BASE + 0x10;
-		else
-			return -ENODEV;
-
-		/* For this to work we must have a static mapping in io.c for this area */
-		base = ioremap(pbase, size);
-		if (!base)
-			return -ENODEV;
-
-		sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
-		if (!IS_ERR(sync_32k_ick))
-			clk_enable(sync_32k_ick);
quoted
-
quoted
-		timer_32k_base = base;
-
-		/*
-		 * 120000 rough estimate from the calculations in
-		 * __clocksource_updatefreq_scale.
-		 */
-		clocks_calc_mult_shift(&persistent_mult, &persistent_shift,
-				32768, NSEC_PER_SEC, 120000);
-
-		if (clocksource_mmio_init(base, "32k_counter", 32768, 250, 32,
-					  clocksource_mmio_readl_up))
-			printk(err, "32k_counter");
-
-		setup_sched_clock(omap_32k_read_sched_clock, 32, 32768);
-	}
+	void __iomem *base;
+	struct clk *sync_32k_ick;
+
+	if (!pbase || !size)
+		return -ENODEV;
+	/*
+	 * For this to work we must have a static mapping in io.c
+	 * for this area
+	 */
+	base = ioremap(pbase, size);
+	if (!base)
+		return -ENODEV;
+
+	sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
+	if (!IS_ERR(sync_32k_ick))
+		clk_enable(sync_32k_ick);

I know that this is carry over from the original code, but seems that if
clk_get fails we should return an error. So maybe ...
I thought of this before, but again the next thought came to my mind was, 
somebody might have done this for some specific reasons, may be OMAP1 
dependency or something? So I choose it to keep it as is...

So before doing this, I thing we should conform from the original author
about this implementation.

May be Paul can comment and conform on this.

Thanks,
Vaibhav
	sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
	if (IS_ERR(sync_32k_ick))
		return -ENODEV;

	clk_enable(sync_32k_ick);
quoted
+
+	timer_32k_base = base;
+
+	/*
+	 * 120000 rough estimate from the calculations in
+	 * __clocksource_updatefreq_scale.
+	 */
+	clocks_calc_mult_shift(&persistent_mult, &persistent_shift,
+			32768, NSEC_PER_SEC, 120000);
+
+	if (clocksource_mmio_init(base, "32k_counter", 32768, 250, 32,
+				clocksource_mmio_readl_up))
+		pr_err("32k_counter: can't register clocksource!\n");
+

Extra line added here that should be removed.
Ohhh ok. Will remove this in next version.

I will wait for Tony's comment on this patch series, I need to 
align with Tony on selection of clocksource between 32k Vs gptimer.

Thanks,
Vaibhav
Cheers
Jon
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help