From patchwork Fri Mar 1 17:45:30 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bastian Hecht X-Patchwork-Id: 2202351 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 9B118DF24C for ; Fri, 1 Mar 2013 16:49:02 +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 1UBT5c-000365-9Z; Fri, 01 Mar 2013 16:45:44 +0000 Received: from mail-qa0-f46.google.com ([209.85.216.46]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UBT5Y-00034p-5E for linux-arm-kernel@lists.infradead.org; Fri, 01 Mar 2013 16:45:41 +0000 Received: by mail-qa0-f46.google.com with SMTP id o13so5149391qaj.5 for ; Fri, 01 Mar 2013 08:45:38 -0800 (PST) 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=Bf3j9wSFu+KzQUdlKfZ/uLDuu+hpCXhnHqNxKnOylDI=; b=u7okLrD0dun9h+5UfHvIPeQ8A5vFRZz4HW/aQ9V3VRP0pT1JxCwHjOjv0XD6Z79C8+ c9acvEcmVIuwjrupOnMewsBmrWUUD09iqMVl57AEMChIBefhtlJ2xfeKIzZ1TQ3vKjo6 jA/S/qWHGN+UTmTubXRyMeRiRLVE6aWL+WcE2gjiLSlxc36uNRrmASZb7TbmKvmMq7cs 79NS0pUqjrBEpGq79BEBW8jSK2mZSagrJ04r2/Vxwd8n/1HhJDc7q5klLl43B4LeBaAW xo8WceDLzM7KMsd20p5+wQ/BxbR/XLm6AbycrlUO8JB5vzdK3TT3RzMTQkOqb18YJQpm 2Z8A== X-Received: by 10.49.16.135 with SMTP id g7mr19008569qed.8.1362156337979; Fri, 01 Mar 2013 08:45:37 -0800 (PST) Received: from bender.routerdd3bcc.com (rrcs-50-74-208-202.nyc.biz.rr.com. [50.74.208.202]) by mx.google.com with ESMTPS id hr3sm20805038qab.4.2013.03.01.08.45.36 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 01 Mar 2013 08:45:37 -0800 (PST) From: Bastian Hecht To: linux-sh@vger.kernel.org Subject: [PATCH 1/3] clocksource: sh_cmt: Add Device Tree probing Date: Fri, 1 Mar 2013 11:45:30 -0600 Message-Id: <1362159932-18533-2-git-send-email-hechtb+renesas@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1362159932-18533-1-git-send-email-hechtb+renesas@gmail.com> References: <1362159932-18533-1-git-send-email-hechtb+renesas@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130301_114540_318706_E3067405 X-CRM114-Status: GOOD ( 19.63 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.216.46 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (hechtb[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -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: Magnus Damm , linux-arm-kernel@lists.infradead.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 We add the capabilty to probe SH CMT timer devices using Device Tree setup. We can deduce former platform data by the device IDs and channel IDs of our timer instances, so we choose this more intuitive info as our DT properties. Signed-off-by: Bastian Hecht --- .../bindings/timer/renesas,sh-cmt-timer.txt | 21 +++++ drivers/clocksource/sh_cmt.c | 94 +++++++++++++++++--- 2 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 Documentation/devicetree/bindings/timer/renesas,sh-cmt-timer.txt diff --git a/Documentation/devicetree/bindings/timer/renesas,sh-cmt-timer.txt b/Documentation/devicetree/bindings/timer/renesas,sh-cmt-timer.txt new file mode 100644 index 0000000..e5ad808 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/renesas,sh-cmt-timer.txt @@ -0,0 +1,21 @@ +* Renesas SH Mobile Compare Match Timer + +Required properties: +- compatible : Should be "renesas,cmt" +- reg : Address and length of the register set for the device +- interrupts : Timer IRQ +- renesas,timer-device-id : The ID of the timer device +- renesas,timer-channel-id : The channel ID of the timer device + +Example for CMT10 of the R8A7740 SoC: + + cmt@0xe6138010 { + compatible = "renesas,cmt"; + interrupt-parent = <&intca>; + reg = <0xe6138010 0xc>; + interrupts = <0x0b00>; + renesas,timer-device-id = <1>; + renesas,timer-channel-id = <0>; + renesas,clocksource-rating = <150>; + renesas,clockevent-rating = <150>; + }; diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index b72b724..9a7a7d4 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -38,6 +38,8 @@ struct sh_cmt_priv { void __iomem *mapbase; struct clk *clk; + long channel_offset; + int timer_bit; unsigned long width; /* 16 or 32 bit version of hardware block */ unsigned long overflow_bit; unsigned long clear_bits; @@ -109,9 +111,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs, static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; - - return p->read_control(p->mapbase - cfg->channel_offset, 0); + return p->read_control(p->mapbase - p->channel_offset, 0); } static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p) @@ -127,9 +127,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p) static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p, unsigned long value) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; - - p->write_control(p->mapbase - cfg->channel_offset, 0, value); + p->write_control(p->mapbase - p->channel_offset, 0, value); } static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p, @@ -176,7 +174,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock); static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; unsigned long flags, value; /* start stop register shared by multiple timer channels */ @@ -184,9 +181,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) value = sh_cmt_read_cmstr(p); if (start) - value |= 1 << cfg->timer_bit; + value |= 1 << p->timer_bit; else - value &= ~(1 << cfg->timer_bit); + value &= ~(1 << p->timer_bit); sh_cmt_write_cmstr(p, value); raw_spin_unlock_irqrestore(&sh_cmt_lock, flags); @@ -673,9 +670,71 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name, return 0; } -static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) +#ifdef CONFIG_OF +static const struct of_device_id of_sh_cmt_match[] = { + { .compatible = "renesas,cmt" }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_sh_cmt_match); + +static const int sh_timer_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40 }; + +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev) +{ + struct sh_timer_config *cfg; + struct device_node *np = dev->of_node; + const __be32 *prop; + int timer_id, channel_id; + + cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL); + if (!cfg) { + dev_err(dev, "failed to allocate DT config data\n"); + return NULL; + } + + prop = of_get_property(np, "renesas,timer-device-id", NULL); + if (!prop) { + dev_err(dev, "device id missing\n"); + return NULL; + } + timer_id = be32_to_cpup(prop); + + prop = of_get_property(np, "renesas,timer-channel-id", NULL); + if (!prop) { + dev_err(dev, "channel id missing\n"); + return NULL; + } + channel_id = be32_to_cpup(prop); + + if (timer_id >= ARRAY_SIZE(sh_timer_offset_multiplier)) { + dev_err(dev, "unsupported timer id\n"); + return NULL; + } + + cfg->channel_offset = sh_timer_offset_multiplier[timer_id] * + (channel_id + 1); + cfg->timer_bit = channel_id; + + prop = of_get_property(np, "renesas,clocksource-rating", NULL); + if (prop) + cfg->clocksource_rating = be32_to_cpup(prop); + + prop = of_get_property(np, "renesas,clockevent-rating", NULL); + if (prop) + cfg->clockevent_rating = be32_to_cpup(prop); + + return cfg; +} +#else +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev) +{ + return NULL; +} +#endif /* CONFIG_OF */ + +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev, + struct sh_timer_config *cfg) { - struct sh_timer_config *cfg = pdev->dev.platform_data; struct resource *res; int irq, ret; ret = -ENXIO; @@ -762,6 +821,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) goto err2; } + p->channel_offset = cfg->channel_offset; + p->timer_bit = cfg->timer_bit; + platform_set_drvdata(pdev, p); return 0; @@ -777,7 +839,7 @@ err0: static int sh_cmt_probe(struct platform_device *pdev) { struct sh_cmt_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; + struct sh_timer_config *cfg; int ret; if (!is_early_platform_device(pdev)) { @@ -785,6 +847,11 @@ static int sh_cmt_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); } + if (pdev->dev.of_node) + cfg = sh_cmt_parse_dt(&pdev->dev); + else + cfg = pdev->dev.platform_data; + if (p) { dev_info(&pdev->dev, "kept as earlytimer\n"); goto out; @@ -796,7 +863,7 @@ static int sh_cmt_probe(struct platform_device *pdev) return -ENOMEM; } - ret = sh_cmt_setup(p, pdev); + ret = sh_cmt_setup(p, pdev, cfg); if (ret) { kfree(p); pm_runtime_idle(&pdev->dev); @@ -824,6 +891,7 @@ static struct platform_driver sh_cmt_device_driver = { .remove = sh_cmt_remove, .driver = { .name = "sh_cmt", + .of_match_table = of_match_ptr(of_sh_cmt_match), } };