From patchwork Tue Feb 12 18:12:52 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pawel Moll X-Patchwork-Id: 2130371 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id B6699DFB7B for ; Tue, 12 Feb 2013 18:15:39 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1U5KLo-0004S3-PC; Tue, 12 Feb 2013 18:13:04 +0000 Received: from service87.mimecast.com ([91.220.42.44]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1U5KLj-0004MZ-Pj for linux-arm-kernel@lists.infradead.org; Tue, 12 Feb 2013 18:13:01 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Tue, 12 Feb 2013 18:12:53 +0000 Received: from [10.2.201.42] ([10.1.255.212]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 12 Feb 2013 18:12:52 +0000 Message-ID: <1360692772.4045.87.camel@hornet> Subject: Re: sp804 DT initialization From: Pawel Moll To: Rob Herring Date: Tue, 12 Feb 2013 18:12:52 +0000 In-Reply-To: <5115312E.1040307@gmail.com> References: <5115312E.1040307@gmail.com> X-Mailer: Evolution 3.6.2-0ubuntu0.1 Mime-Version: 1.0 X-OriginalArrivalTime: 12 Feb 2013 18:12:52.0855 (UTC) FILETIME=[92FD2070:01CE094C] X-MC-Unique: 113021218125306201 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130212_131300_150185_11E219C3 X-CRM114-Status: GOOD ( 29.06 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [91.220.42.44 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Kevin Hilman , Linus Walleij , Russell King - ARM Linux , "linux-arm-kernel@lists.infradead.org" X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 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 On Fri, 2013-02-08 at 17:09 +0000, Rob Herring wrote: > I'm trying to move the sp804 timer init to DT based init using > CLKSRC_OF. Cool, it would make my life much easier :-) > The challenge is how do we match each timer to be used as > clksrc, clkevt, or sched_clock. Ideally we would have h/w based > properties of the timers such that we could select which one to use just > based on properties. I'm trying to avoid the use of aliases or linux > specific properties. OMAP timers are an example of describing the h/w > properties of timers to drive their selection. What I finally came up with is the current v2m.c "solution" and patch below (I'll post it together with a SP810 sort-of-driver for 3.10)... Effectively I just grab either of the two available motherboard SP804s and provide the current code with a clock derived from the tree. > sched_clock selection - What's the reason to use the 24MHz counter vs. > the sp804 on the ARM boards? Is it purely based on the higher frequency > and having more accuracy? Would this be universally true? I think it was selected because of 1) the higher frequency and 2) the fact that it is there, no mater what, no configuration required. > We could make > setup_sched_clock replace it's current counter with a new one if the new > one is higher frequency. Hmm... It is being replaced with the architected timer, isn't it? > sp804 selection - The versatile and realview boards use timer 0 for > clkevt and timer 3 for clksrc. AFAICT searching thru kernel and mail > list history, timer 0 was always used and timer 3 use is arbitrary when > clksrc support was added by Kevin. Timer 1 could be used as the clksrc, > or timer 2 and 3 could be used. Some platforms like highbank don't have > an interrupt for the 2nd timer, so that would have to be accounted for > in the selection process. Bottom line is it should not matter which ones > get used by the kernel, right? Yes, this is my feeling exactly. Provided that one describes what clocks determine the rates (which could be more complex that I'd guess, due to possible relations between PCLK, TIMCLK and TIMCLKENx) and how the interrupt is wired up, everything should Just Work (TM). Cheers! Pawel 8<----- From 524087cc76d3ea415752b231f37d9bf91cf35154 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Tue, 29 Jan 2013 12:25:28 +0000 Subject: [PATCH] ARM: sp804: Use explicitly specified clock if possible This patch allows platform code to explicitly specify a clock to be used as SP804's input, in particular to obtain such information from the platform's Device Tree. Signed-off-by: Pawel Moll --- arch/arm/common/timer-sp.c | 14 ++++++++------ arch/arm/include/asm/hardware/timer-sp.h | 15 +++++++++------ arch/arm/mach-highbank/highbank.c | 5 +++-- arch/arm/mach-integrator/integrator_cp.c | 8 ++++---- arch/arm/mach-realview/core.c | 4 ++-- arch/arm/mach-versatile/core.c | 4 ++-- arch/arm/mach-vexpress/v2m.c | 13 ++++++++----- 7 files changed, 36 insertions(+), 27 deletions(-) diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 9d2d3ba..2c64c4b 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -29,13 +29,14 @@ #include #include -static long __init sp804_get_clock_rate(const char *name) +static long __init sp804_get_clock_rate(struct clk *clk, + const char *name) { - struct clk *clk; long rate; int err; - clk = clk_get_sys("sp804", name); + if (!clk) + clk = clk_get_sys("sp804", name); if (IS_ERR(clk)) { pr_err("sp804: %s clock not found: %d\n", name, (int)PTR_ERR(clk)); @@ -77,9 +78,10 @@ static u32 sp804_read(void) void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, const char *name, + struct clk *clk, int use_sched_clock) { - long rate = sp804_get_clock_rate(name); + long rate = sp804_get_clock_rate(clk, name); if (rate < 0) return; @@ -172,10 +174,10 @@ static struct irqaction sp804_timer_irq = { }; void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, - const char *name) + const char *name, struct clk *clk) { struct clock_event_device *evt = &sp804_clockevent; - long rate = sp804_get_clock_rate(name); + long rate = sp804_get_clock_rate(clk, name); if (rate < 0) return; diff --git a/arch/arm/include/asm/hardware/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h index 2dd9d3f..4cba3e6 100644 --- a/arch/arm/include/asm/hardware/timer-sp.h +++ b/arch/arm/include/asm/hardware/timer-sp.h @@ -1,15 +1,18 @@ void __sp804_clocksource_and_sched_clock_init(void __iomem *, - const char *, int); + const char *, struct clk *, int); -static inline void sp804_clocksource_init(void __iomem *base, const char *name) +static inline void sp804_clocksource_init(void __iomem *base, const char *name, + struct clk *clk) { - __sp804_clocksource_and_sched_clock_init(base, name, 0); + __sp804_clocksource_and_sched_clock_init(base, name, clk, 0); } static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base, - const char *name) + const char *name, + struct clk *clk) { - __sp804_clocksource_and_sched_clock_init(base, name, 1); + __sp804_clocksource_and_sched_clock_init(base, name, clk, 1); } -void sp804_clockevents_init(void __iomem *, unsigned int, const char *); +void sp804_clockevents_init(void __iomem *, unsigned int, const char *, + struct clk *); diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 981dc1e..36048e4 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -120,8 +120,9 @@ static void __init highbank_timer_init(void) lookup.clk = of_clk_get(np, 0); clkdev_add(&lookup); - sp804_clocksource_and_sched_clock_init(timer_base + 0x20, "timer1"); - sp804_clockevents_init(timer_base, irq, "timer0"); + sp804_clocksource_and_sched_clock_init(timer_base + 0x20, "timer1", + NULL); + sp804_clockevents_init(timer_base, irq, "timer0", NULL); twd_local_timer_of_register(); diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 7322838..57cf158 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -268,7 +268,7 @@ static void __init intcp_timer_init_of(void) if (WARN_ON(!base)) return; writel(0, base + TIMER_CTRL); - sp804_clocksource_init(base, node->name); + sp804_clocksource_init(base, node->name, NULL); err = of_property_read_string(of_aliases, "arm,timer-secondary", &path); @@ -280,7 +280,7 @@ static void __init intcp_timer_init_of(void) return; irq = irq_of_parse_and_map(node, 0); writel(0, base + TIMER_CTRL); - sp804_clockevents_init(base, irq, node->name); + sp804_clockevents_init(base, irq, node->name, NULL); } static struct sys_timer cp_of_timer = { @@ -518,8 +518,8 @@ static void __init intcp_timer_init(void) writel(0, TIMER1_VA_BASE + TIMER_CTRL); writel(0, TIMER2_VA_BASE + TIMER_CTRL); - sp804_clocksource_init(TIMER2_VA_BASE, "timer2"); - sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1"); + sp804_clocksource_init(TIMER2_VA_BASE, "timer2", NULL); + sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1", NULL); } static struct sys_timer cp_timer = { diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 6824674..e50369d 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -364,8 +364,8 @@ void __init realview_timer_init(unsigned int timer_irq) writel(0, timer2_va_base + TIMER_CTRL); writel(0, timer3_va_base + TIMER_CTRL); - sp804_clocksource_init(timer3_va_base, "timer3"); - sp804_clockevents_init(timer0_va_base, timer_irq, "timer0"); + sp804_clocksource_init(timer3_va_base, "timer3", NULL); + sp804_clockevents_init(timer0_va_base, timer_irq, "timer0", NULL); } /* diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 5d59294..1ddc3a4 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -794,8 +794,8 @@ static void __init versatile_timer_init(void) writel(0, TIMER2_VA_BASE + TIMER_CTRL); writel(0, TIMER3_VA_BASE + TIMER_CTRL); - sp804_clocksource_init(TIMER3_VA_BASE, "timer3"); - sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1, "timer0"); + sp804_clocksource_init(TIMER3_VA_BASE, "timer3", NULL); + sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1, "timer0", NULL); } struct sys_timer versatile_timer = { diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 011661a..ac3d71b 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -56,7 +56,8 @@ static struct map_desc v2m_io_desc[] __initdata = { }, }; -static void __init v2m_sp804_init(void __iomem *base, unsigned int irq) +static void __init v2m_sp804_init(void __iomem *base, unsigned int irq, + struct clk *clk1, struct clk *clk2) { if (WARN_ON(!base || irq == NO_IRQ)) return; @@ -64,8 +65,8 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq) writel(0, base + TIMER_1_BASE + TIMER_CTRL); writel(0, base + TIMER_2_BASE + TIMER_CTRL); - sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1"); - sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0"); + sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1", clk2); + sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0", clk1); } @@ -288,7 +289,7 @@ static struct amba_device *v2m_amba_devs[] __initdata = { static void __init v2m_timer_init(void) { vexpress_clk_init(ioremap(V2M_SYSCTL, SZ_4K)); - v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0); + v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0, NULL, NULL); } static struct sys_timer v2m_timer = { @@ -457,7 +458,9 @@ static void __init v2m_dt_timer_init(void) pr_info("Using SP804 '%s' as a clock & events source\n", node->full_name); v2m_sp804_init(of_iomap(node, 0), - irq_of_parse_and_map(node, 0)); + irq_of_parse_and_map(node, 0), + of_clk_get_by_name(node, "timclken1"), + of_clk_get_by_name(node, "timclken2")); } if (arch_timer_of_register() != 0)