All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Walmsley <paul@pwsan.com>
To: linux-arm-kernel@lists.arm.linux.org.uk
Cc: Paul Walmsley <paul@pwsan.com>, Tony Lindgren <tony@atomide.com>,
	linux-omap@vger.kernel.org
Subject: [PATCH 7/7] OMAP2/3 GPTIMER: allow system tick GPTIMER to be changed in board-*.c files
Date: Tue, 14 Apr 2009 12:23:34 -0600	[thread overview]
Message-ID: <20090414182333.22344.33317.stgit@localhost.localdomain> (raw)
In-Reply-To: <20090414182039.22344.49790.stgit@localhost.localdomain>

Add a function omap2_gp_clockevent_set_gptimer() for board-*.c files
to use in .init_irq functions to configure the system tick GPTIMER.
Practical choices at this point are GPTIMER1 or GPTIMER12.  Both of
these timers are in the WKUP powerdomain, and so are unaffected by
chip power management.  GPTIMER1 can use sys_clk as a source, for
applications where a high-resolution timer is more important than
power management.  GPTIMER12 has the special property that it has the
secure 32kHz oscillator as its source clock, which may be less prone
to glitches than the off-chip 32kHz oscillator.  But on HS devices, it
may not be available for Linux use.

It appears that most boards are fine with GPTIMER1, but BeagleBoard
should use GPTIMER12 when using a 32KiHz timer source, due to hardware bugs
in revisions B4 and below.  Modify board-omap3beagle.c to use GPTIMER12.

This patch originally used a Kbuild config option to select the GPTIMER,
but was changed to allow this to be specified in board-*.c files, per
Tony's request.

Tested on Beagle rev B4 ES2.1, with and without CONFIG_OMAP_32K_TIMER, and
3430SDP.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-omap3beagle.c    |    4 ++
 arch/arm/mach-omap2/clock24xx.c            |    1 +
 arch/arm/mach-omap2/clock24xx.h            |   10 +++++-
 arch/arm/mach-omap2/clock34xx.h            |    1 -
 arch/arm/mach-omap2/timer-gp.c             |   48 ++++++++++++++++++++++++++--
 arch/arm/plat-omap/dmtimer.c               |   20 ++++++++----
 arch/arm/plat-omap/include/mach/dmtimer.h  |    2 +
 arch/arm/plat-omap/include/mach/timer-gp.h |   17 ++++++++++
 8 files changed, 91 insertions(+), 12 deletions(-)
 create mode 100644 arch/arm/plat-omap/include/mach/timer-gp.h

diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 744740a..3a7a29d 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -42,6 +42,7 @@
 #include <mach/nand.h>
 #include <mach/mux.h>
 #include <mach/usb.h>
+#include <mach/timer-gp.h>
 
 #include "mmc-twl4030.h"
 
@@ -186,6 +187,9 @@ static void __init omap3_beagle_init_irq(void)
 {
 	omap2_init_common_hw(NULL);
 	omap_init_irq();
+#ifdef CONFIG_OMAP_32K_TIMER
+	omap2_gp_clockevent_set_gptimer(12);
+#endif
 	omap_gpio_init();
 }
 
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index 4306392..fa2bd09 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -66,6 +66,7 @@ struct omap_clk {
 static struct omap_clk omap24xx_clks[] = {
 	/* external root sources */
 	CLK(NULL,	"func_32k_ck",	&func_32k_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"secure_32k_ck", &secure_32k_ck, CK_243X | CK_242X),
 	CLK(NULL,	"osc_ck",	&osc_ck,	CK_243X | CK_242X),
 	CLK(NULL,	"sys_ck",	&sys_ck,	CK_243X | CK_242X),
 	CLK(NULL,	"alt_ck",	&alt_ck,	CK_243X | CK_242X),
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index 33c3e5b..72003f7 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -625,6 +625,14 @@ static struct clk func_32k_ck = {
 	.clkdm_name	= "wkup_clkdm",
 };
 
+static struct clk secure_32k_fck = {
+	.name		= "secure_32k_fck",
+	.ops		= &clkops_null,
+	.rate		= 32768,
+	.flags		= RATE_FIXED,
+	.clkdm_name	= "wkup_clkdm",
+};
+
 /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
 static struct clk osc_ck = {		/* (*12, *13, 19.2, *26, 38.4)MHz */
 	.name		= "osc_ck",
@@ -1790,7 +1798,7 @@ static struct clk gpt12_ick = {
 static struct clk gpt12_fck = {
 	.name		= "gpt12_fck",
 	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
+	.parent		= &secure_32k_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index f009017..6763b8f 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -2901,7 +2901,6 @@ static struct clk sr_l4_ick = {
 
 /* SECURE_32K_FCK clocks */
 
-/* XXX This clock no longer exists in 3430 TRM rev F */
 static struct clk gpt12_fck = {
 	.name		= "gpt12_fck",
 	.ops		= &clkops_null,
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 9fc13a2..7835048 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -3,6 +3,8 @@
  *
  * OMAP2 GP timer support.
  *
+ * Copyright (C) 2009 Nokia Corporation
+ *
  * Update to use new clocksource/clockevent layers
  * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
  * Copyright (C) 2007 MontaVista Software, Inc.
@@ -36,8 +38,13 @@
 #include <asm/mach/time.h>
 #include <mach/dmtimer.h>
 
+/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
+#define MAX_GPTIMER_ID		12
+
 static struct omap_dm_timer *gptimer;
 static struct clock_event_device clockevent_gpt;
+static u8 __initdata gptimer_id = 1;
+static u8 __initdata inited;
 
 static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
 {
@@ -95,20 +102,53 @@ static struct clock_event_device clockevent_gpt = {
 	.set_mode	= omap2_gp_timer_set_mode,
 };
 
+/**
+ * omap2_gp_clockevent_set_gptimer - set which GPTIMER is used for clockevents
+ * @id: GPTIMER to use (1..MAX_GPTIMER_ID)
+ *
+ * Define the GPTIMER that the system should use for the tick timer.
+ * Meant to be called from board-*.c files in the event that GPTIMER1, the
+ * default, is unsuitable.  Returns -EINVAL on error or 0 on success.
+ */
+int __init omap2_gp_clockevent_set_gptimer(u8 id)
+{
+	if (id < 1 || id > MAX_GPTIMER_ID)
+		return -EINVAL;
+
+	BUG_ON(inited);
+
+	gptimer_id = id;
+
+	return 0;
+}
+
 static void __init omap2_gp_clockevent_init(void)
 {
 	u32 tick_rate;
+	int src;
+
+	inited = 1;
 
-	gptimer = omap_dm_timer_request_specific(1);
+	gptimer = omap_dm_timer_request_specific(gptimer_id);
 	BUG_ON(gptimer == NULL);
 
 #if defined(CONFIG_OMAP_32K_TIMER)
-	omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ);
+	src = OMAP_TIMER_SRC_32_KHZ;
 #else
-	omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK);
+	src = OMAP_TIMER_SRC_SYS_CLK;
+	WARN(gptimer_id == 12, "WARNING: GPTIMER12 can only use the "
+	     "secure 32KiHz clock source\n");
 #endif
+
+	if (gptimer_id != 12)
+		WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)),
+		     "timer-gp: omap_dm_timer_set_source() failed\n");
+
 	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
 
+	pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n",
+		gptimer_id, tick_rate);
+
 	omap2_gp_timer_irq.dev_id = (void *)gptimer;
 	setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
 	omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
@@ -125,6 +165,8 @@ static void __init omap2_gp_clockevent_init(void)
 	clockevents_register_device(&clockevent_gpt);
 }
 
+/* Clocksource code */
+
 #ifdef CONFIG_OMAP_32K_TIMER
 /* 
  * When 32k-timer is enabled, don't use GPTimer for clocksource
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index a05205c..55bb996 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -509,7 +509,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
 #ifdef CONFIG_ARCH_OMAP1
 
-void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
 	int n = (timer - dm_timers) << 1;
 	u32 l;
@@ -517,23 +517,31 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 	l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
 	l |= source << n;
 	omap_writel(l, MOD_CONF_CTRL_1);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
 #else
 
-void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
+	int ret = -EINVAL;
+
 	if (source < 0 || source >= 3)
-		return;
+		return -EINVAL;
 
 	clk_disable(timer->fclk);
-	clk_set_parent(timer->fclk, dm_source_clocks[source]);
+	ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
 	clk_enable(timer->fclk);
 
-	/* When the functional clock disappears, too quick writes seem to
-	 * cause an abort. */
+	/*
+	 * When the functional clock disappears, too quick writes seem
+	 * to cause an abort. XXX Is this still necessary?
+	 */
 	__delay(150000);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
diff --git a/arch/arm/plat-omap/include/mach/dmtimer.h b/arch/arm/plat-omap/include/mach/dmtimer.h
index 6dc7031..20f1054 100644
--- a/arch/arm/plat-omap/include/mach/dmtimer.h
+++ b/arch/arm/plat-omap/include/mach/dmtimer.h
@@ -64,7 +64,7 @@ void omap_dm_timer_trigger(struct omap_dm_timer *timer);
 void omap_dm_timer_start(struct omap_dm_timer *timer);
 void omap_dm_timer_stop(struct omap_dm_timer *timer);
 
-void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
 void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
 void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
 void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
diff --git a/arch/arm/plat-omap/include/mach/timer-gp.h b/arch/arm/plat-omap/include/mach/timer-gp.h
new file mode 100644
index 0000000..c88d346
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/timer-gp.h
@@ -0,0 +1,17 @@
+/*
+ * OMAP2/3 GPTIMER support.headers
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
+
+int __init omap2_gp_clockevent_set_gptimer(u8 id);
+
+#endif
+



  parent reply	other threads:[~2009-04-14 18:27 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-14 18:23 [PATCH 0/7] OMAP clock fixes for v2.6.30-rc1 Paul Walmsley
2009-04-14 18:23 ` [PATCH 1/7] OMAP2xxx clock: init osc_ck, sys_ck internal lists early Paul Walmsley
2009-04-14 18:31   ` [PATCH 1/7] OMAP24xx/25xx " Paul Walmsley
2009-04-14 18:37     ` Russell King - ARM Linux
2009-04-21 19:54     ` Russell King - ARM Linux
2009-04-23  2:01       ` Paul Walmsley
2009-04-23  7:53         ` Russell King - ARM Linux
2009-04-23  8:32           ` Paul Walmsley
2009-04-23 18:00             ` Tony Lindgren
2009-04-23 22:26               ` Russell King - ARM Linux
2009-04-23 23:55                 ` Tony Lindgren
2009-04-24  3:13                   ` Paul Walmsley
2009-04-24  5:23                     ` Tony Lindgren
2009-04-24  6:29                       ` Paul Walmsley
2009-04-24 17:51                         ` Tony Lindgren
2009-04-14 18:23 ` [PATCH 2/7] OMAP2xxx clock: fix broken cpu_mask code Paul Walmsley
2009-04-14 18:32   ` [PATCH 2/7] OMAP24xx/OMAP25xx " Paul Walmsley
2009-04-14 18:23 ` [PATCH 3/7] OMAP3: clock: Camera module doesn't have IDLEST bit Paul Walmsley
2009-04-14 18:23 ` [PATCH 4/7] OMAP1: clock: Typo fix for clock in omap1 Paul Walmsley
2009-04-14 18:23 ` [PATCH 5/7] OMAP3 GPTIMER: fix GPTIMER12 IRQ Paul Walmsley
2009-04-14 18:23 ` [PATCH 6/7] OMAP: dmtimer: enable all timers to be wakeup events Paul Walmsley
2009-04-14 18:23 ` Paul Walmsley [this message]
2009-04-14 21:45   ` [PATCH 7/7] OMAP2/3 GPTIMER: allow system tick GPTIMER to be changed in board-*.c files Tony Lindgren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090414182333.22344.33317.stgit@localhost.localdomain \
    --to=paul@pwsan.com \
    --cc=linux-arm-kernel@lists.arm.linux.org.uk \
    --cc=linux-omap@vger.kernel.org \
    --cc=tony@atomide.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.