From patchwork Wed Mar 20 22:54:03 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 2310351 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 3857040213 for ; Wed, 20 Mar 2013 22:58:56 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UIRvU-0002gS-7g; Wed, 20 Mar 2013 22:56:08 +0000 Received: from mail-oa0-f46.google.com ([209.85.219.46]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UIRtx-0002ID-Sx for linux-arm-kernel@lists.infradead.org; Wed, 20 Mar 2013 22:54:36 +0000 Received: by mail-oa0-f46.google.com with SMTP id k1so2463672oag.33 for ; Wed, 20 Mar 2013 15:54:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=VuY9xZLkQtVafj60Pei1WcFquy26XoK+bXk8tAP6vmw=; b=xcfHGzVo04A67bHpoqHReG89B1Ft6ppiDADMkR+NqJqHGeXG6s6vaLjXCxeW/nA2Nm D9r+mdY5ukWMeCIIhnGJhHhR0pKjP0eD32cV8Ng5d7HJ+58f2K4dRcdqU5iONM0c8F5+ SlcHylC/YlJzokLbBQTyDWkncrWRaYjAYUsz0zfL7dmWSo4wVVuNWwXMqVH1hjoRey/c gl07w1zLVPj/6X7YCTA4HJikuKgdK2sQNdnLIpdlWW5Hmh76fJBzNYAsMnDA59iPGpF1 /WRNsrWX3KGGfdlOsvDrADXAhCX+Vs9KcVFeQP4DQ5a/l+ZKTKmiw4LgNBQ4Uzpev3zC xmuw== X-Received: by 10.60.29.129 with SMTP id k1mr5535016oeh.8.1363820071744; Wed, 20 Mar 2013 15:54:31 -0700 (PDT) Received: from rob-laptop.calxeda.com ([173.226.190.126]) by mx.google.com with ESMTPS id be1sm4358963obb.11.2013.03.20.15.54.30 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 20 Mar 2013 15:54:31 -0700 (PDT) From: Rob Herring To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree-discuss@lists.ozlabs.org Subject: [PATCH 03/11] ARM: timer-sp: convert to use CLKSRC_OF init Date: Wed, 20 Mar 2013 17:54:03 -0500 Message-Id: <1363820051-24428-4-git-send-email-robherring2@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1363820051-24428-1-git-send-email-robherring2@gmail.com> References: <1363820051-24428-1-git-send-email-robherring2@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130320_185434_002462_3A419918 X-CRM114-Status: GOOD ( 18.34 ) X-Spam-Score: -2.5 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.219.46 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (robherring2[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (robherring2[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Russell King , Arnd Bergmann , pawel.moll@arm.com, linus.walleij@linaro.org, Rob Herring , john.stultz@linaro.org, haojian.zhuang@linaro.org, tglx@linutronix.de X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Rob Herring This adds CLKSRC_OF based init for sp804 timer. The clock initialization is refactored to support retrieving the clock(s) from the DT. Signed-off-by: Rob Herring Acked-by: Linus Walleij --- arch/arm/Kconfig | 1 + arch/arm/common/timer-sp.c | 98 +++++++++++++++++++++++++----- arch/arm/include/asm/hardware/timer-sp.h | 16 +++-- 3 files changed, 95 insertions(+), 20 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f0f90f0..774131a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1172,6 +1172,7 @@ config PLAT_VERSATILE config ARM_TIMER_SP804 bool select CLKSRC_MMIO + select CLKSRC_OF if OF select HAVE_SCHED_CLOCK source arch/arm/mm/Kconfig diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 9d2d3ba..3e86835 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -25,33 +25,28 @@ #include #include #include +#include +#include +#include #include #include -static long __init sp804_get_clock_rate(const char *name) +static long __init sp804_get_clock_rate(struct clk *clk) { - struct clk *clk; long rate; int err; - clk = clk_get_sys("sp804", name); - if (IS_ERR(clk)) { - pr_err("sp804: %s clock not found: %d\n", name, - (int)PTR_ERR(clk)); - return PTR_ERR(clk); - } - err = clk_prepare(clk); if (err) { - pr_err("sp804: %s clock failed to prepare: %d\n", name, err); + pr_err("sp804: clock failed to prepare: %d\n", err); clk_put(clk); return err; } err = clk_enable(clk); if (err) { - pr_err("sp804: %s clock failed to enable: %d\n", name, err); + pr_err("sp804: clock failed to enable: %d\n", err); clk_unprepare(clk); clk_put(clk); return err; @@ -59,7 +54,7 @@ static long __init sp804_get_clock_rate(const char *name) rate = clk_get_rate(clk); if (rate < 0) { - pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate); + pr_err("sp804: clock failed to get rate: %ld\n", rate); clk_disable(clk); clk_unprepare(clk); clk_put(clk); @@ -77,9 +72,21 @@ 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; + + if (!clk) { + clk = clk_get_sys("sp804", name); + if (IS_ERR(clk)) { + pr_err("sp804: clock not found: %d\n", + (int)PTR_ERR(clk)); + return; + } + } + + rate = sp804_get_clock_rate(clk); if (rate < 0) return; @@ -171,12 +178,20 @@ static struct irqaction sp804_timer_irq = { .dev_id = &sp804_clockevent, }; -void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, - const char *name) +void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name) { struct clock_event_device *evt = &sp804_clockevent; - long rate = sp804_get_clock_rate(name); + long rate; + + 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)); + return; + } + rate = sp804_get_clock_rate(clk); if (rate < 0) return; @@ -186,6 +201,57 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, evt->irq = irq; evt->cpumask = cpu_possible_mask; + writel(0, clkevt_base + TIMER_CTRL); + setup_irq(irq, &sp804_timer_irq); clockevents_config_and_register(evt, rate, 0xf, 0xffffffff); } + +static void __init sp804_of_init(struct device_node *np) +{ + static bool initialized = false; + void __iomem *base; + int irq; + u32 irq_num = 0; + bool tmr2_evt = false; + struct clk *clk0, *clk1; + const char *name = of_get_property(np, "compatible", NULL); + + if (initialized || !of_device_is_available(np)) + return; + + base = of_iomap(np, 0); + if (WARN_ON(!base)) + return; + + clk0 = of_clk_get(np, 0); + if (IS_ERR(clk0)) + clk0 = NULL; + + /* Get the 2nd clock if the timer has 2 timer clocks */ + if (of_count_phandle_with_args(np, "clocks", "#clock-cells") == 3) { + clk1 = of_clk_get(np, 1); + if (IS_ERR(clk1)) { + pr_err("sp804: %s clock not found: %d\n", np->name, + (int)PTR_ERR(clk1)); + return; + } + } else + clk1 = clk0; + + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) + return; + + of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); + if (irq_num == 2) + tmr2_evt = true; + + __sp804_clockevents_init(base + (tmr2_evt ? TIMER_2_BASE : 0), + irq, tmr2_evt ? clk1 : clk0, name); + __sp804_clocksource_and_sched_clock_init(base + (tmr2_evt ? 0 : TIMER_2_BASE), + name, tmr2_evt ? clk0 : clk1, 1); + + initialized = true; +} +CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_of_init); diff --git a/arch/arm/include/asm/hardware/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h index 2dd9d3f..bb28af7 100644 --- a/arch/arm/include/asm/hardware/timer-sp.h +++ b/arch/arm/include/asm/hardware/timer-sp.h @@ -1,15 +1,23 @@ +struct clk; + void __sp804_clocksource_and_sched_clock_init(void __iomem *, - const char *, int); + const char *, struct clk *, int); +void __sp804_clockevents_init(void __iomem *, unsigned int, + struct clk *, const char *); static inline void sp804_clocksource_init(void __iomem *base, const char *name) { - __sp804_clocksource_and_sched_clock_init(base, name, 0); + __sp804_clocksource_and_sched_clock_init(base, name, NULL, 0); } static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base, const char *name) { - __sp804_clocksource_and_sched_clock_init(base, name, 1); + __sp804_clocksource_and_sched_clock_init(base, name, NULL, 1); } -void sp804_clockevents_init(void __iomem *, unsigned int, const char *); +static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name) +{ + __sp804_clockevents_init(base, irq, NULL, name); + +}