From patchwork Wed Mar 13 05:05:34 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 2261501 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 8D4983FD8C for ; Wed, 13 Mar 2013 05:11:37 +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 1UFdvG-0005M4-0q; Wed, 13 Mar 2013 05:08:18 +0000 Received: from mail-pb0-f42.google.com ([209.85.160.42]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UFduE-00052B-0a for linux-arm-kernel@lists.infradead.org; Wed, 13 Mar 2013 05:07:15 +0000 Received: by mail-pb0-f42.google.com with SMTP id xb4so611854pbc.29 for ; Tue, 12 Mar 2013 22:07:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:x-gm-message-state; bh=HyMQvc2YbCqp+NKCt/eGiWrb8kKq5FgXoUYD+MnBxvk=; b=lmhtDQwdSt5Hfc0bXs2gp10vZ6SXzruTdmYvDd7XrDEEuJsUm8jMuuKnhOAht+Y4aN B7oFLf9laRS2LQADYDfQuwIzZBOV/gUqofg+sSXuuEDMBGz0N4yauotDQLIbsZUz9adG F3m3L96CgymuCtkFYwV3BWbfXBKfToRlz+5utacZRpm7jx3PWRLht4aXC1WfNwBXFFBb TFhToMCbyXr1PR3ZqMvABWhZmk3dt+/Ba5Odjj2DHt/hOTDTA/Z96RkTZwnYY7w2kGJz m/wAbaqiAkEuvLRkNmRQq7BEXBXbP3nBPLsVYkvPZxUaSlwuNpnInPHnz2WQ58MvcWhi 525g== X-Received: by 10.68.190.195 with SMTP id gs3mr36712173pbc.14.1363151230788; Tue, 12 Mar 2013 22:07:10 -0700 (PDT) Received: from localhost.localdomain ([67.198.145.34]) by mx.google.com with ESMTPS id ab1sm27947630pbd.37.2013.03.12.22.07.06 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 12 Mar 2013 22:07:10 -0700 (PDT) From: Haojian Zhuang To: linux@arm.linux.org.uk, linus.walleij@linaro.org, arnd@arndb.de, olof@lixom.net, rob.herring@calxeda.com, linux-arm-kernel@lists.infradead.org, pawel.moll@arm.com, swarren@nvidia.com, john.stultz@linaro.org, tglx@linutronix.de, mturquette@linaro.org Subject: [PATCH v3 03/11] clocksource: sp804: add device tree support Date: Wed, 13 Mar 2013 13:05:34 +0800 Message-Id: <1363151142-32162-4-git-send-email-haojian.zhuang@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1363151142-32162-1-git-send-email-haojian.zhuang@linaro.org> References: <1363151142-32162-1-git-send-email-haojian.zhuang@linaro.org> X-Gm-Message-State: ALoCoQmwgp5qrEm06cZiay1rwa06OonMVDxXX7jYv7fmdHjiIRsyl64oydPvpjSWiVN+lKThp1Sw X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130313_010714_240021_BFCB8A5A X-CRM114-Status: GOOD ( 16.91 ) 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 [209.85.160.42 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Haojian Zhuang , patches@linaro.org 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 Parse clock & irq from device tree for sp804. Signed-off-by: Haojian Zhuang --- .../devicetree/bindings/timer/arm,sp804.txt | 27 +++++ drivers/clocksource/timer-sp.c | 105 ++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/arm,sp804.txt diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt new file mode 100644 index 0000000..ec1ae45 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt @@ -0,0 +1,27 @@ +ARM sp804 Dual Timers +--------------------------------------- + +Required properties: +- compatible: Should be "arm,sp804" & "arm,primecell" +- interrupts: Should contain the list of Dual Timer interrupts + interrupts = <0 0 4>, <0 1 4>; +- reg: Should contain location and length for dual timer register. +- clocks: clock driving the dual timer hardware + clocks = <&timclk0 &timclk1>; + +Optional properties: +- arm,sp804-clocksource: Should contain the register offset of TIMER1 or + TIMER2 in Dual Timer Controller. + arm,sp804-clocksource = <0x20>; + +Example: + + timer0: timer@fc800000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0xfc800000 0x1000>; + /* timer00 & timer01 */ + interrupts = <0 0 4>, <0 1 4>; + clocks = <&timclk0 &timclk1>; + clock-names = "apb_pclk"; + status = "disabled"; + }; diff --git a/drivers/clocksource/timer-sp.c b/drivers/clocksource/timer-sp.c index a7f2510..63f757d 100644 --- a/drivers/clocksource/timer-sp.c +++ b/drivers/clocksource/timer-sp.c @@ -19,16 +19,23 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #include #include #include #include #include +#include +#include #include +#include #include +#define SP804_CLKSRC "sp804 source" +#define SP804_CLKEVT "sp804 event" + static long __init sp804_get_clock_rate(const char *name) { struct clk *clk; @@ -189,3 +196,101 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, setup_irq(irq, &sp804_timer_irq); clockevents_config_and_register(evt, rate, 0xf, 0xffffffff); } + +static struct device_node *from = NULL; + +static struct of_device_id sp804_timer_match[] __initdata = { + { .compatible = "arm,sp804", }, + {} +}; + +static struct clk __init *sp804_dt_init_clk(struct device_node *np, int i, + const char *name) +{ + struct clk_lookup *lookup = NULL; + struct clk *clk; + + clk = of_clk_get(np, i); + if (IS_ERR(clk)) + return clk; + lookup = clkdev_alloc(clk, name, "sp804"); + if (!lookup) { + clk_put(clk); + return ERR_PTR(-EINVAL); + } + clkdev_add(lookup); + return clk; +} + +static void __attribute__((__unused__)) __init sp804_dt_init(void) +{ + struct device_node *np = NULL; + struct clk *clksrc = NULL, *clkevt = NULL; + void __iomem *base; + int retsrc, retevt, i = 0, irq = 0; + u32 srcoffs = 0, evtoffs = 0; + + np = of_find_matching_node(from, sp804_timer_match); + WARN_ON(!np); + if (!np) { + pr_err("Failed to find sp804 timer\n"); + return; + } + from = np; + /* check whether timer node is available */ + if (!of_device_is_available(np)) + return; + + base = of_iomap(np, 0); + WARN_ON(!base); + if (!base) + return; + + retsrc = of_property_read_u32(np, "arm,sp804-clocksource", &srcoffs); + retevt = of_property_read_u32(np, "arm,sp804-clockevent", &evtoffs); + if (retsrc < 0 && retevt < 0) + goto err; + + if (!retsrc) { + if (srcoffs) { + /* TIMER2 is clock source */ + i = 1; + srcoffs = TIMER_2_BASE; + } else { + /* TIMER1 is clock source */ + i = 0; + srcoffs = TIMER_1_BASE; + } + clksrc = sp804_dt_init_clk(np, i, SP804_CLKSRC); + if (IS_ERR(clksrc)) + goto err; + sp804_clocksource_and_sched_clock_init(base + srcoffs, + SP804_CLKSRC); + } + if (!retevt) { + if (evtoffs) { + /* TIMER2 is clock event */ + i = 1; + evtoffs = TIMER_2_BASE; + } else { + /* TIMER1 is clock event */ + i = 0; + evtoffs = TIMER_1_BASE; + } + irq = irq_of_parse_and_map(np, i); + if (irq < 0) + goto err_evt; + clkevt = sp804_dt_init_clk(np, i, SP804_CLKEVT); + if (IS_ERR(clkevt)) + goto err_evt; + sp804_clockevents_init(base + evtoffs, irq, SP804_CLKEVT); + } + + return; +err_evt: + if (clksrc) + clk_put(clksrc); +err: + iounmap(base); +} +CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_dt_init)