From patchwork Mon Jun 20 09:23:39 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Lindgren X-Patchwork-Id: 896562 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p5K9Pj1M011383 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 20 Jun 2011 09:26:07 GMT Received: from canuck.infradead.org ([134.117.69.58]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QYajN-0002ti-Ht; Mon, 20 Jun 2011 09:25:19 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QYajL-0003yu-QK; Mon, 20 Jun 2011 09:25:15 +0000 Received: from mho-04-ewr.mailhop.org ([204.13.248.74] helo=mho-02-ewr.mailhop.org) by canuck.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QYahp-0003hN-Bp for linux-arm-kernel@lists.infradead.org; Mon, 20 Jun 2011 09:23:46 +0000 Received: from c-98-234-237-12.hsd1.ca.comcast.net ([98.234.237.12] helo=[192.168.111.2]) by mho-02-ewr.mailhop.org with esmtpa (Exim 4.72) (envelope-from ) id 1QYaho-000Mpc-2G; Mon, 20 Jun 2011 09:23:40 +0000 X-Mail-Handler: MailHop Outbound by DynDNS X-Originating-IP: 98.234.237.12 X-Report-Abuse-To: abuse@dyndns.com (see http://www.dyndns.com/services/mailhop/outbound_abuse.html for abuse reporting information) X-MHO-User: U2FsdGVkX19+DLcUgj2Cp3rAPAz6fNwj Subject: [PATCH 05/10] omap2+: Use dmtimer macros for clockevent To: linux-arm-kernel@lists.infradead.org From: Tony Lindgren Date: Mon, 20 Jun 2011 02:23:39 -0700 Message-ID: <20110620092339.357.10396.stgit@kaulin> In-Reply-To: <20110620091754.357.56441.stgit@kaulin> References: <20110620091754.357.56441.stgit@kaulin> User-Agent: StGit/0.15 MIME-Version: 1.0 X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110620_052341_707401_743640AA X-CRM114-Status: GOOD ( 17.42 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, low trust [204.13.248.74 listed in list.dnswl.org] Cc: Kevin Hilman , linux-omap@vger.kernel.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 20 Jun 2011 09:26:07 +0000 (UTC) This patch makes timer-gp.c to use only a subset of dmtimer functions without the need to initialize dmtimer code early. Also note that now with the inline functions, timer_set_next_event becomes more efficient in the lines of assembly code. Signed-off-by: Tony Lindgren Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/timer-gp.c | 147 ++++++++++++++++++++++------- arch/arm/plat-omap/include/plat/dmtimer.h | 1 2 files changed, 113 insertions(+), 35 deletions(-) diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index a0d8e83..62c0d5c 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -45,10 +45,33 @@ #include "timer-gp.h" +/* Parent clocks, eventually these will come from the clock framework */ + +#define OMAP2_MPU_SOURCE "sys_ck" +#define OMAP3_MPU_SOURCE OMAP2_MPU_SOURCE +#define OMAP4_MPU_SOURCE "sys_clkin_ck" +#define OMAP2_32K_SOURCE "func_32k_ck" +#define OMAP3_32K_SOURCE "omap_32k_fck" +#define OMAP4_32K_SOURCE "sys_32k_ck" + +#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 +#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 +/* Clockevent code */ + +static struct omap_dm_timer clkev; static struct omap_dm_timer *gptimer; static struct clock_event_device clockevent_gpt; static u8 __initdata gptimer_id = 1; @@ -57,10 +80,9 @@ struct omap_dm_timer *gptimer_wakeup; static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id) { - struct omap_dm_timer *gpt = (struct omap_dm_timer *)dev_id; struct clock_event_device *evt = &clockevent_gpt; - omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_OVERFLOW); + __omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW); evt->event_handler(evt); return IRQ_HANDLED; @@ -75,7 +97,8 @@ static struct irqaction omap2_gp_timer_irq = { static int omap2_gp_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { - omap_dm_timer_set_load_start(gptimer, 0, 0xffffffff - cycles); + __omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST, + 0xffffffff - cycles, 1); return 0; } @@ -85,13 +108,18 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, { u32 period; - omap_dm_timer_stop(gptimer); + __omap_dm_timer_stop(clkev.io_base, 1, clkev.rate); switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ; + period = clkev.rate / HZ; period -= 1; - omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period); + /* Looks like we need to first set the load value separately */ + __omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG, + 0xffffffff - period, 1); + __omap_dm_timer_load_start(clkev.io_base, + OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST, + 0xffffffff - period, 1); break; case CLOCK_EVT_MODE_ONESHOT: break; @@ -130,43 +158,89 @@ int __init omap2_gp_clockevent_set_gptimer(u8 id) return 0; } -static void __init omap2_gp_clockevent_init(void) +static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, + int gptimer_id, + const char *fck_source) { - u32 tick_rate; - int src; - char clockevent_hwmod_name[8]; /* 8 = sizeof("timerXX0") */ + char name[10]; /* 10 = sizeof("gptXX_Xck0") */ + struct omap_hwmod *oh; + size_t size; + int res = 0; + + sprintf(name, "timer%d", gptimer_id); + omap_hwmod_setup_one(name); + oh = omap_hwmod_lookup(name); + if (!oh) + return -ENODEV; + + timer->irq = oh->mpu_irqs[0].irq; + timer->phys_base = oh->slaves[0]->addr->pa_start; + size = oh->slaves[0]->addr->pa_end - timer->phys_base; + + /* Static mapping, never released */ + timer->io_base = ioremap(timer->phys_base, size); + if (!timer->io_base) + return -ENXIO; + + /* After the dmtimer is using hwmod these clocks won't be needed */ + sprintf(name, "gpt%d_fck", gptimer_id); + timer->fclk = clk_get(NULL, name); + if (IS_ERR(timer->fclk)) + return -ENODEV; + + sprintf(name, "gpt%d_ick", gptimer_id); + timer->iclk = clk_get(NULL, name); + if (IS_ERR(timer->iclk)) { + clk_put(timer->fclk); + return -ENODEV; + } - inited = 1; + omap_hwmod_enable(oh); + + if (gptimer_id != 12) { + struct clk *src; + + src = clk_get(NULL, fck_source); + if (IS_ERR(src)) { + res = -EINVAL; + } else { + res = __omap_dm_timer_set_source(timer->fclk, src); + if (IS_ERR_VALUE(res)) + pr_warning("%s: timer%i cannot set source\n", + __func__, gptimer_id); + clk_put(src); + } + } + __omap_dm_timer_reset(timer->io_base, 1, 1); + timer->posted = 1; + + timer->rate = clk_get_rate(timer->fclk); - sprintf(clockevent_hwmod_name, "timer%d", gptimer_id); - omap_hwmod_setup_one(clockevent_hwmod_name); + timer->reserved = 1; gptimer = omap_dm_timer_request_specific(gptimer_id); BUG_ON(gptimer == NULL); gptimer_wakeup = gptimer; -#if defined(CONFIG_OMAP_32K_TIMER) - src = OMAP_TIMER_SRC_32_KHZ; -#else - src = OMAP_TIMER_SRC_SYS_CLK; - WARN(gptimer_id == 12, "WARNING: GPTIMER12 can only use the " - "secure 32KiHz clock source\n"); -#endif + return res; +} - if (gptimer_id != 12) - WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)), - "timer-gp: omap_dm_timer_set_source() failed\n"); +static void __init omap2_gp_clockevent_init(int gptimer_id, + const char *fck_source) +{ + int res; - tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer)); + inited = 1; - pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n", - gptimer_id, tick_rate); + res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source); + BUG_ON(res); 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); + setup_irq(clkev.irq, &omap2_gp_timer_irq); - clockevent_gpt.mult = div_sc(tick_rate, NSEC_PER_SEC, + __omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW); + + clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC, clockevent_gpt.shift); clockevent_gpt.max_delta_ns = clockevent_delta2ns(0xffffffff, &clockevent_gpt); @@ -176,6 +250,9 @@ static void __init omap2_gp_clockevent_init(void) clockevent_gpt.cpumask = cpumask_of(0); clockevents_register_device(&clockevent_gpt); + + pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n", + gptimer_id, clkev.rate); } /* Clocksource code */ @@ -247,11 +324,11 @@ static void __init omap2_gp_clocksource_init(void) } #endif -#define OMAP_SYS_TIMER_INIT(name) \ +#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src) \ static void __init omap##name##_timer_init(void) \ { \ omap_dm_timer_init(); \ - omap2_gp_clockevent_init(); \ + omap2_gp_clockevent_init((clkev_nr), clkev_src); \ omap2_gp_clocksource_init(); \ } @@ -261,14 +338,14 @@ struct sys_timer omap##name##_timer = { \ }; #ifdef CONFIG_ARCH_OMAP2 -OMAP_SYS_TIMER_INIT(2) +OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE) OMAP_SYS_TIMER(2) #endif #ifdef CONFIG_ARCH_OMAP3 -OMAP_SYS_TIMER_INIT(3) +OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE) OMAP_SYS_TIMER(3) -OMAP_SYS_TIMER_INIT(3_secure) +OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE) OMAP_SYS_TIMER(3_secure) #endif @@ -280,7 +357,7 @@ static void __init omap4_timer_init(void) BUG_ON(!twd_base); #endif omap_dm_timer_init(); - omap2_gp_clockevent_init(); + omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE); omap2_gp_clocksource_init(); } OMAP_SYS_TIMER(4) diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 54664a7..dd8b3ff 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -216,6 +216,7 @@ struct omap_dm_timer { struct clk *iclk, *fclk; #endif void __iomem *io_base; + unsigned long rate; unsigned reserved:1; unsigned enabled:1; unsigned posted:1;