From patchwork Fri Nov 14 15:37:39 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roger Quadros X-Patchwork-Id: 40834 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ee0-f72.google.com (mail-ee0-f72.google.com [74.125.83.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 136B8240ED for ; Fri, 14 Nov 2014 15:38:20 +0000 (UTC) Received: by mail-ee0-f72.google.com with SMTP id d17sf10864185eek.3 for ; Fri, 14 Nov 2014 07:38:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:message-id:date:from:user-agent :mime-version:to:cc:subject:references:in-reply-to:sender:precedence :list-id:x-original-sender:x-original-authentication-results :mailing-list:list-post:list-help:list-archive:list-unsubscribe :content-type:content-transfer-encoding; bh=XPoUU0RrniE8C/UBLCrSbtaR4eaJD3eUTDuIs9oSgKo=; b=XtS5YUWMrhmXz2JYkU+hLkQPSfBWUqrrM6lfhUdVq0xqB7xpcD3HhC2QHJi+4tn4IM 4V480+ZyzbRgmAK1vL7MvWvsYKtkn/Jrd9CMnbVgf/E5aFw3HoIad0CROnjNTbT2t9Sa LK6CPbCEpgd7uXXEHTBC2Z51lrRpKbs0MA1qUVJS6cSgJziH+lzhpoXlL7q3U8y1b76E 1VITJabO1igN6IPS9bjgoZDiGud7j0hMfnykEK4CefvaaN75tb9bfuoTCEcbB4FMkzeW PWhmxCeZUnHTot896dKFM//UaFp++ZQSllkOvDLxTNgdZM9kGp6iivQ2wkS45f+ILJlF OfJg== X-Gm-Message-State: ALoCoQlgj9yLW6hR9oncDWe9jFxcZvdYzwA4dFKAjOufF2TQG5XpWkyyQ8TtBiTLl/9gRlv5Fj9C X-Received: by 10.112.50.243 with SMTP id f19mr7173439lbo.1.1415979499303; Fri, 14 Nov 2014 07:38:19 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.5.39 with SMTP id p7ls157125lap.5.gmail; Fri, 14 Nov 2014 07:38:19 -0800 (PST) X-Received: by 10.152.21.199 with SMTP id x7mr8872067lae.66.1415979499120; Fri, 14 Nov 2014 07:38:19 -0800 (PST) Received: from mail-la0-f51.google.com (mail-la0-f51.google.com. [209.85.215.51]) by mx.google.com with ESMTPS id ob1si41929552lbb.113.2014.11.14.07.38.18 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 14 Nov 2014 07:38:18 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.51 as permitted sender) client-ip=209.85.215.51; Received: by mail-la0-f51.google.com with SMTP id q1so15344704lam.10 for ; Fri, 14 Nov 2014 07:38:18 -0800 (PST) X-Received: by 10.153.7.170 with SMTP id dd10mr8839400lad.44.1415979498877; Fri, 14 Nov 2014 07:38:18 -0800 (PST) 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.112.184.201 with SMTP id ew9csp781485lbc; Fri, 14 Nov 2014 07:38:17 -0800 (PST) X-Received: by 10.66.255.7 with SMTP id am7mr10614674pad.134.1415979496745; Fri, 14 Nov 2014 07:38:16 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id qb7si28596444pdb.242.2014.11.14.07.38.16 for ; Fri, 14 Nov 2014 07:38:16 -0800 (PST) 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 S965783AbaKNPiL (ORCPT + 3 others); Fri, 14 Nov 2014 10:38:11 -0500 Received: from arroyo.ext.ti.com ([192.94.94.40]:46133 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965682AbaKNPiK (ORCPT ); Fri, 14 Nov 2014 10:38:10 -0500 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id sAEFbjUT017100; Fri, 14 Nov 2014 09:37:45 -0600 Received: from DLEE70.ent.ti.com (dlemailx.itg.ti.com [157.170.170.113]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id sAEFbijc026530; Fri, 14 Nov 2014 09:37:44 -0600 Received: from dlep32.itg.ti.com (157.170.170.100) by DLEE70.ent.ti.com (157.170.170.113) with Microsoft SMTP Server id 14.3.174.1; Fri, 14 Nov 2014 09:37:43 -0600 Received: from [192.168.2.6] (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep32.itg.ti.com (8.14.3/8.13.8) with ESMTP id sAEFbd7n031861; Fri, 14 Nov 2014 09:37:40 -0600 Message-ID: <546621C3.3010804@ti.com> Date: Fri, 14 Nov 2014 17:37:39 +0200 From: Roger Quadros User-Agent: Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Thunderbird/24.3.0 MIME-Version: 1.0 To: , CC: , , , , , , , , , , , , Roger Quadros Subject: [PATCH v5 4/8] net: can: c_can: Add syscon/regmap RAMINIT mechanism References: <1415371762-29885-1-git-send-email-rogerq@ti.com> <1415371762-29885-5-git-send-email-rogerq@ti.com> In-Reply-To: <1415371762-29885-5-git-send-email-rogerq@ti.com> 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.215.51 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 | 3 + drivers/net/can/c_can/c_can.h | 11 +- drivers/net/can/c_can/c_can_platform.c | 113 ++++++++++++++------- 3 files changed, 87 insertions(+), 40 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/c_can.txt b/Documentation/devicetree/bindings/net/can/c_can.txt index 8f1ae81..a3ca3ee 100644 --- a/Documentation/devicetree/bindings/net/can/c_can.txt +++ b/Documentation/devicetree/bindings/net/can/c_can.txt @@ -12,6 +12,9 @@ Required properties: Optional properties: - ti,hwmods : Must be "d_can" or "c_can", n being the instance number +- syscon-raminit : Handle to system control region that contains the + RAMINIT register, register offset to the RAMINIT + register and the CAN instance number (0 offset). Note: "ti,hwmods" field is used to fetch the base address and irq resources from TI, omap hwmod data base during device registration. diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 3c305a1..0e17c7b 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -179,6 +179,14 @@ struct c_can_driver_data { bool raminit_pulse; /* If set, sets and clears START bit (pulse) */ }; +/* 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; + u8 done_bit; +}; + /* c_can private data structure */ struct c_can_priv { struct can_priv can; /* must be the first member */ @@ -196,8 +204,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 1546c2b..89739a1 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,47 +71,61 @@ 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; + u8 start_bit, done_bit; + + start_bit = raminit->start_bit; + done_bit = raminit->done_bit; spin_lock(&raminit_lock); - ctrl = readl(priv->raminit_ctrlreg); + mask = 1 << start_bit | 1 << 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 << start_bit); + ctrl |= 1 << done_bit; + regmap_write(raminit->syscon, raminit->reg, ctrl); + + ctrl &= ~(1 << 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 << start_bit; + regmap_write(raminit->syscon, raminit->reg, ctrl); + + ctrl |= 1 << done_bit; + c_can_hw_raminit_wait_syscon(priv, mask, ctrl); } spin_unlock(&raminit_lock); } @@ -206,10 +219,11 @@ static int c_can_plat_probe(struct platform_device *pdev) struct net_device *dev; struct c_can_priv *priv; const struct of_device_id *match; - struct resource *mem, *res; + struct resource *mem; int irq; struct clk *clk; const struct c_can_driver_data *drvdata; + struct device_node *np = pdev->dev.of_node; match = of_match_device(c_can_of_table, &pdev->dev); if (match) { @@ -277,27 +291,50 @@ 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 - * if not specified in DT. + /* Check if we need custom RAMINIT via syscon. Mostly for TI + * platforms. Only supported with DT boot. */ - if (!res) { + if (np && of_property_read_bool(np, "syscon-raminit")) { + u32 id; + struct c_can_raminit *raminit = &priv->raminit_sys; + + ret = -EINVAL; + raminit->syscon = syscon_regmap_lookup_by_phandle(np, + "syscon-raminit"); + if (IS_ERR(raminit->syscon)) { + /* can fail with -EPROBE_DEFER */ + ret = PTR_ERR(raminit->syscon); + free_c_can_dev(dev); + return ret; + } + + if (of_property_read_u32_index(np, "syscon-raminit", 1, + &raminit->reg)) { + dev_err(&pdev->dev, + "couldn't get the RAMINIT reg. offset!\n"); + goto exit_free_device; + } + + if (of_property_read_u32_index(np, "syscon-raminit", 2, + &id)) { + dev_err(&pdev->dev, + "couldn't get the CAN instance ID\n"); + goto exit_free_device; + } + + if (id >= drvdata->num_can) { + dev_err(&pdev->dev, + "Invalid CAN instance ID\n"); + goto exit_free_device; + } + + raminit->start_bit = drvdata->raminit_start_bits[id]; + raminit->done_bit = drvdata->raminit_done_bits[id]; + + priv->raminit = c_can_hw_raminit_syscon; + } else { priv->raminit = c_can_hw_raminit; - 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; break; default: ret = -EINVAL;