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

* Paul Walmsley <paul@pwsan.com> [090414 11:27]:
> 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.

Although this adds new code, it would be nice to merge this during the
-rc cycle as it fixes an issue on quite a few boards out there.

Without this fix a large number of Beagle boards will eventually hang with
no timer interrupts happening.

Tony

 
> 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
> +
> 
> 

      reply	other threads:[~2009-04-14 21:45 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 ` [PATCH 7/7] OMAP2/3 GPTIMER: allow system tick GPTIMER to be changed in board-*.c files Paul Walmsley
2009-04-14 21:45   ` Tony Lindgren [this message]

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=20090414214547.GE2167@atomide.com \
    --to=tony@atomide.com \
    --cc=linux-arm-kernel@lists.arm.linux.org.uk \
    --cc=linux-omap@vger.kernel.org \
    --cc=paul@pwsan.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox