From patchwork Tue Sep 9 14:31:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roger Quadros X-Patchwork-Id: 37117 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oi0-f72.google.com (mail-oi0-f72.google.com [209.85.218.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8DE7020566 for ; Tue, 9 Sep 2014 14:31:53 +0000 (UTC) Received: by mail-oi0-f72.google.com with SMTP id v63sf2943605oia.11 for ; Tue, 09 Sep 2014 07:31:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe:content-type; bh=OfjASm3qEVFx9xCGco2NgmvIOBwP9tKlj0vi4Rv2vA8=; b=SsVACB7TAT1qTlVLRhHLUnoXTAECpj1PeOZk/8M58tKrB1n9+Gb/TDUUOwkGnpNaBq V4q5mNBbdx/0ODPNxfKc3z6zsM4qhl4gblTutVOXu5zMo773s4fGPsgb3BLIKRSsaXQO 01bxqi16UymNNFyB99sr7C5EDq+wXDz/IpyNoyISLZLYMubexcsyQxTn3lPtZ16RAQse NnSAaPwP1v8vmnG9Nr04wcQ1CZS0Fi/EGvMjkhWVeDvOzpUjTjWMxUqIcMANTZ7FsoIU cfhFmBUmIwd8I7g12M/8YwWnYMIi41u4VIR+adNZg7UbwayKT6L6tHcInROBW3ztJKWA /0jg== X-Gm-Message-State: ALoCoQmKylqjd9wk5/YbsCQm8yT9joDq6efOOyeXQoLVNF9C4RF8JnBPyME21aPKNuw2hjcv9nfn X-Received: by 10.42.133.2 with SMTP id f2mr1887451ict.14.1410273113121; Tue, 09 Sep 2014 07:31:53 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.101.207 with SMTP id u73ls1159460qge.34.gmail; Tue, 09 Sep 2014 07:31:53 -0700 (PDT) X-Received: by 10.52.1.39 with SMTP id 7mr25952941vdj.17.1410273112929; Tue, 09 Sep 2014 07:31:52 -0700 (PDT) Received: from mail-vc0-f176.google.com (mail-vc0-f176.google.com [209.85.220.176]) by mx.google.com with ESMTPS id bb7si5806240vdc.58.2014.09.09.07.31.52 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 09 Sep 2014 07:31:52 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.176 as permitted sender) client-ip=209.85.220.176; Received: by mail-vc0-f176.google.com with SMTP id la4so1005242vcb.35 for ; Tue, 09 Sep 2014 07:31:52 -0700 (PDT) X-Received: by 10.52.120.51 with SMTP id kz19mr380081vdb.95.1410273112811; Tue, 09 Sep 2014 07:31:52 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp293059vcb; Tue, 9 Sep 2014 07:31:52 -0700 (PDT) X-Received: by 10.69.31.10 with SMTP id ki10mr30761255pbd.11.1410273111678; Tue, 09 Sep 2014 07:31:51 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id dd1si23497638pbc.122.2014.09.09.07.31.51 for ; Tue, 09 Sep 2014 07:31:51 -0700 (PDT) Received-SPF: none (google.com: netdev-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932200AbaIIObt (ORCPT + 3 others); Tue, 9 Sep 2014 10:31:49 -0400 Received: from comal.ext.ti.com ([198.47.26.152]:58302 "EHLO comal.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751484AbaIIObr (ORCPT ); Tue, 9 Sep 2014 10:31:47 -0400 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id s89EVPiG012733; Tue, 9 Sep 2014 09:31:25 -0500 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id s89EVPt4004720; Tue, 9 Sep 2014 09:31:25 -0500 Received: from dflp32.itg.ti.com (10.64.6.15) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.3.174.1; Tue, 9 Sep 2014 09:31:24 -0500 Received: from localhost.localdomain (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id s89EVD15002296; Tue, 9 Sep 2014 09:31:21 -0500 From: Roger Quadros To: , CC: , , , , , , , , , , , Roger Quadros Subject: [PATCH v2 2/3] net: can: c_can: Add syscon/regmap RAMINIT mechanism Date: Tue, 9 Sep 2014 17:31:09 +0300 Message-ID: <1410273070-22485-3-git-send-email-rogerq@ti.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1410273070-22485-1-git-send-email-rogerq@ti.com> References: <1410273070-22485-1-git-send-email-rogerq@ti.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: netdev@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: rogerq@ti.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.176 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Some TI SoCs like DRA7 have a RAMINIT register specification different from the other AMxx SoCs and as expected by the existing driver. To add more insanity, this register is shared with other IPs like DSS, PCIe and PWM. Provides a more generic mechanism to specify the RAMINIT register location and START/DONE bit position and use the syscon/regmap framework to access the register. Signed-off-by: Roger Quadros --- .../devicetree/bindings/net/can/c_can.txt | 7 ++ drivers/net/can/c_can/c_can.h | 11 ++- drivers/net/can/c_can/c_can_platform.c | 109 +++++++++++++++------ 3 files changed, 95 insertions(+), 32 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/c_can.txt b/Documentation/devicetree/bindings/net/can/c_can.txt index 8f1ae81..e12d1a1 100644 --- a/Documentation/devicetree/bindings/net/can/c_can.txt +++ b/Documentation/devicetree/bindings/net/can/c_can.txt @@ -13,6 +13,13 @@ Optional properties: - ti,hwmods : Must be "d_can" or "c_can", n being the instance number +- ti,raminit-syscon : Handle to system control region that contains the + RAMINIT register. If specified, the second memory resource + in the reg property must index into the RAMINIT + register within the syscon region +- ti,raminit-start-bit : Bit posistion of START bit in the RAMINIT register +- ti,raminit-done-bit : Bit position of DONE bit in the RAMINIT register + Note: "ti,hwmods" field is used to fetch the base address and irq resources from TI, omap hwmod data base during device registration. Future plan is to migrate hwmod data base contents into device tree diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 99ad1aa..bf68822 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -169,6 +169,14 @@ enum c_can_dev_id { BOSCH_D_CAN, }; +/* Out of band RAMINIT register access via syscon regmap */ +struct c_can_raminit { + struct regmap *syscon; /* for raminit ctrl. reg. access */ + unsigned int reg; /* register index within syscon */ + u8 start_bit; /* START bit position in raminit reg. */ + u8 done_bit; /* DONE bit position in raminit reg. */ +}; + /* c_can private data structure */ struct c_can_priv { struct can_priv can; /* must be the first member */ @@ -186,8 +194,7 @@ struct c_can_priv { const u16 *regs; void *priv; /* for board-specific data */ enum c_can_dev_id type; - u32 __iomem *raminit_ctrlreg; - int instance; + struct c_can_raminit raminit_sys; /* RAMINIT via syscon regmap */ void (*raminit) (const struct c_can_priv *priv, bool enable); u32 comm_rcv_high; u32 rxmasked; diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index b144e71..fb0c35b 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -32,14 +32,13 @@ #include #include #include +#include +#include #include #include "c_can.h" -#define CAN_RAMINIT_START_MASK(i) (0x001 << (i)) -#define CAN_RAMINIT_DONE_MASK(i) (0x100 << (i)) -#define CAN_RAMINIT_ALL_MASK(i) (0x101 << (i)) #define DCAN_RAM_INIT_BIT (1 << 3) static DEFINE_SPINLOCK(raminit_lock); /* @@ -72,48 +71,59 @@ static void c_can_plat_write_reg_aligned_to_32bit(const struct c_can_priv *priv, writew(val, priv->base + 2 * priv->regs[index]); } -static void c_can_hw_raminit_wait_ti(const struct c_can_priv *priv, u32 mask, - u32 val) +static void c_can_hw_raminit_wait_syscon(const struct c_can_priv *priv, + u32 mask, u32 val) { int timeout = 0; + const struct c_can_raminit *raminit = &priv->raminit_sys; + u32 ctrl; + /* We look only at the bits of our instance. */ val &= mask; - while ((readl(priv->raminit_ctrlreg) & mask) != val) { + do { udelay(1); timeout++; + regmap_read(raminit->syscon, raminit->reg, &ctrl); if (timeout == 1000) { dev_err(&priv->dev->dev, "%s: time out\n", __func__); break; } - } + } while ((ctrl & mask) != val); } -static void c_can_hw_raminit_ti(const struct c_can_priv *priv, bool enable) +static void c_can_hw_raminit_syscon(const struct c_can_priv *priv, bool enable) { - u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance); + u32 mask; u32 ctrl; + const struct c_can_raminit *raminit = &priv->raminit_sys; spin_lock(&raminit_lock); - ctrl = readl(priv->raminit_ctrlreg); + mask = 1 << raminit->start_bit | 1 << raminit->done_bit; + regmap_read(raminit->syscon, raminit->reg, &ctrl); + /* We clear the done and start bit first. The start bit is * looking at the 0 -> transition, but is not self clearing; * And we clear the init done bit as well. + * NOTE: DONE must be written with 1 to clear it. */ - ctrl &= ~CAN_RAMINIT_START_MASK(priv->instance); - ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); - writel(ctrl, priv->raminit_ctrlreg); - ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance); - c_can_hw_raminit_wait_ti(priv, mask, ctrl); + ctrl &= ~(1 << raminit->start_bit); + ctrl |= 1 << raminit->done_bit; + regmap_write(raminit->syscon, raminit->reg, ctrl); + + ctrl &= ~(1 << raminit->done_bit); + c_can_hw_raminit_wait_syscon(priv, mask, ctrl); if (enable) { /* Set start bit and wait for the done bit. */ - ctrl |= CAN_RAMINIT_START_MASK(priv->instance); - writel(ctrl, priv->raminit_ctrlreg); - ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); - c_can_hw_raminit_wait_ti(priv, mask, ctrl); + ctrl |= 1 << raminit->start_bit; + regmap_write(raminit->syscon, raminit->reg, ctrl); + + ctrl |= 1 << raminit->done_bit; + c_can_hw_raminit_wait_syscon(priv, mask, ctrl); } + spin_unlock(&raminit_lock); } @@ -202,6 +212,8 @@ static int c_can_plat_probe(struct platform_device *pdev) struct resource *mem, *res; int irq; struct clk *clk; + struct device_node *np = pdev->dev.of_node; + u32 val; if (pdev->dev.of_node) { match = of_match_device(c_can_of_table, &pdev->dev); @@ -271,11 +283,6 @@ static int c_can_plat_probe(struct platform_device *pdev) priv->read_reg32 = d_can_plat_read_reg32; priv->write_reg32 = d_can_plat_write_reg32; - if (pdev->dev.of_node) - priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can"); - else - priv->instance = pdev->id; - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); /* Not all D_CAN modules have a separate register for the D_CAN * RAM initialization. Use default RAM init bit in D_CAN module @@ -286,12 +293,54 @@ static int c_can_plat_probe(struct platform_device *pdev) break; } - priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!priv->raminit_ctrlreg || priv->instance < 0) - dev_info(&pdev->dev, "control memory is not used for raminit\n"); - else - priv->raminit = c_can_hw_raminit_ti; + /* If separate RAMINIT register is specified access + * it using syscon regmap. Mostly for TI platforms. + */ + ret = -EINVAL; + if (!np) { + dev_err(&pdev->dev, + "separate RAMINIT reg. not supported on non DT\n"); + goto exit_free_device; + } + + priv->raminit_sys.syscon = syscon_regmap_lookup_by_phandle(np, + "ti,raminit-syscon"); + if (IS_ERR(priv->raminit_sys.syscon)) { + dev_err(&pdev->dev, + "couldn't get syscon regmap for RAMINIT reg.\n"); + goto exit_free_device; + } + + priv->raminit_sys.reg = res->start; + if (of_property_read_u32(np, "ti,raminit-start-bit", + &val)) { + dev_err(&pdev->dev, + "missing ti,raminit-start-bit property\n"); + goto exit_free_device; + } + + if (val > 31) { + dev_err(&pdev->dev, + "invalid ti,raminit-start-bit property\n"); + goto exit_free_device; + } + + priv->raminit_sys.start_bit = val; + if (of_property_read_u32(np, "ti,raminit-done-bit", + &val)) { + dev_err(&pdev->dev, + "missing ti,raminit-done-bit property\n"); + goto exit_free_device; + } + + if (val > 31) { + dev_err(&pdev->dev, + "invalid ti,raminit-done-bit property\n"); + goto exit_free_device; + } + + priv->raminit_sys.done_bit = val; + priv->raminit = c_can_hw_raminit_syscon; break; default: ret = -EINVAL;