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