From patchwork Fri Sep 2 09:14:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 9310625 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5C672607D2 for ; Fri, 2 Sep 2016 09:16:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 489BA296BA for ; Fri, 2 Sep 2016 09:16:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3A7972971E; Fri, 2 Sep 2016 09:16:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C406B296BA for ; Fri, 2 Sep 2016 09:16:51 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bfkZD-0000t6-MK; Fri, 02 Sep 2016 09:15:19 +0000 Received: from mail-wm0-x229.google.com ([2a00:1450:400c:c09::229]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bfkYp-0000BZ-6a for linux-arm-kernel@lists.infradead.org; Fri, 02 Sep 2016 09:14:57 +0000 Received: by mail-wm0-x229.google.com with SMTP id v143so20952002wmv.0 for ; Fri, 02 Sep 2016 02:14:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fgdkzQpvJzzTDcp73S6IDlyCb83uwVrvPaThmtnFeLc=; b=hg/kHL/ISchLbhKbRQ8PcyB1P8FSA0mBQjgb/TvR5GobeaoHpXxkB4bbpUGcsQgJKi 4qzIYDItP2b/iwagzWjMju4WMkJGIUbYlcQNqt3bcIWLynZzcZEYGfoBxLkdHal2DMuU 5LR91mKnhbFS2L7+ekH4Y5vlnIAKaaQbFEnGw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fgdkzQpvJzzTDcp73S6IDlyCb83uwVrvPaThmtnFeLc=; b=EQj4wb7ypO31jG6pAxkff5y1ighlTneEVyD3Wpumx2kcAt1Pbvbn1l1bFVEK6xwf+0 0JqPbk4+fA1FPIAMvvAPW3i/XFnpzSD10u2LRreG61opoScsbhUifC6YHac95VJgAFEW 4X/Gviwyd++4ggKdAtcarbyrexMi81vgdXvkKKD2DrlAEH5tcZiHID4QwoIB1kbDlYO6 KuyCSW2Gt+5f0MkURgduApRFeFvrqYaca9yfX41mhagXsJqVs/y6NkpAfYSzCKVi20M7 gH/rwM0F9tZ9NhsAoslTXesZBViTx1K1DEhmdgJfsaIh/+ofKaaFtkCB/VOD5VcYIggx T13A== X-Gm-Message-State: AE9vXwNzpfKrPBdR4Ji45MlufUjes8ouR4KOhF2PgZzxkxftfyET3VyNhCGicYWUL1DCB3CD X-Received: by 10.194.249.74 with SMTP id ys10mr17723173wjc.145.1472807672916; Fri, 02 Sep 2016 02:14:32 -0700 (PDT) Received: from localhost.localdomain (host-2-103-180-164.as13285.net. [2.103.180.164]) by smtp.gmail.com with ESMTPSA id r67sm2615471wmb.14.2016.09.02.02.14.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 02 Sep 2016 02:14:32 -0700 (PDT) From: Srinivas Kandagatla To: gregkh@linuxfoundation.org Subject: [PATCH 2/2] nvmem: rockchip-efuse: add rk3399-efuse support Date: Fri, 2 Sep 2016 10:14:27 +0100 Message-Id: <1472807667-26782-2-git-send-email-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1472807667-26782-1-git-send-email-srinivas.kandagatla@linaro.org> References: <1472807667-26782-1-git-send-email-srinivas.kandagatla@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160902_021455_446982_BAC4EC3D X-CRM114-Status: GOOD ( 18.66 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Srinivas Kandagatla , maxime.ripard@free-electrons.com, finley.xiao@rock-chips.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Finley Xiao 1) the efuse timing of rk3399 is different from earlier SoCs. 2) rk3399-efuse is organized as 32bits by 32 one-time programmable electrical fuses, the efuse of earlier SoCs is organized as 32bits by 8 one-time programmable electrical fuses with random access interface. This patch adds a new read function for rk3399-efuse. Signed-off-by: Finley Xiao Reviewed-by: Heiko Stuebner Reviewed-by: Douglas Anderson Signed-off-by: Srinivas Kandagatla --- drivers/nvmem/rockchip-efuse.c | 133 +++++++++++++++++++++++++++++++++++------ 1 file changed, 114 insertions(+), 19 deletions(-) diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c index 4d3f391..423907b 100644 --- a/drivers/nvmem/rockchip-efuse.c +++ b/drivers/nvmem/rockchip-efuse.c @@ -22,17 +22,29 @@ #include #include #include +#include #include -#define EFUSE_A_SHIFT 6 -#define EFUSE_A_MASK 0x3ff -#define EFUSE_PGENB BIT(3) -#define EFUSE_LOAD BIT(2) -#define EFUSE_STROBE BIT(1) -#define EFUSE_CSB BIT(0) - -#define REG_EFUSE_CTRL 0x0000 -#define REG_EFUSE_DOUT 0x0004 +#define RK3288_A_SHIFT 6 +#define RK3288_A_MASK 0x3ff +#define RK3288_PGENB BIT(3) +#define RK3288_LOAD BIT(2) +#define RK3288_STROBE BIT(1) +#define RK3288_CSB BIT(0) + +#define RK3399_A_SHIFT 16 +#define RK3399_A_MASK 0x3ff +#define RK3399_NBYTES 4 +#define RK3399_STROBSFTSEL BIT(9) +#define RK3399_RSB BIT(7) +#define RK3399_PD BIT(5) +#define RK3399_PGENB BIT(3) +#define RK3399_LOAD BIT(2) +#define RK3399_STROBE BIT(1) +#define RK3399_CSB BIT(0) + +#define REG_EFUSE_CTRL 0x0000 +#define REG_EFUSE_DOUT 0x0004 struct rockchip_efuse_chip { struct device *dev; @@ -40,8 +52,8 @@ struct rockchip_efuse_chip { struct clk *clk; }; -static int rockchip_efuse_read(void *context, unsigned int offset, - void *val, size_t bytes) +static int rockchip_rk3288_efuse_read(void *context, unsigned int offset, + void *val, size_t bytes) { struct rockchip_efuse_chip *efuse = context; u8 *buf = val; @@ -53,27 +65,82 @@ static int rockchip_efuse_read(void *context, unsigned int offset, return ret; } - writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + REG_EFUSE_CTRL); + writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL); udelay(1); while (bytes--) { writel(readl(efuse->base + REG_EFUSE_CTRL) & - (~(EFUSE_A_MASK << EFUSE_A_SHIFT)), + (~(RK3288_A_MASK << RK3288_A_SHIFT)), efuse->base + REG_EFUSE_CTRL); writel(readl(efuse->base + REG_EFUSE_CTRL) | - ((offset++ & EFUSE_A_MASK) << EFUSE_A_SHIFT), + ((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT), efuse->base + REG_EFUSE_CTRL); udelay(1); writel(readl(efuse->base + REG_EFUSE_CTRL) | - EFUSE_STROBE, efuse->base + REG_EFUSE_CTRL); + RK3288_STROBE, efuse->base + REG_EFUSE_CTRL); udelay(1); *buf++ = readb(efuse->base + REG_EFUSE_DOUT); writel(readl(efuse->base + REG_EFUSE_CTRL) & - (~EFUSE_STROBE), efuse->base + REG_EFUSE_CTRL); + (~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL); + udelay(1); + } + + /* Switch to standby mode */ + writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL); + + clk_disable_unprepare(efuse->clk); + + return 0; +} + +static int rockchip_rk3399_efuse_read(void *context, unsigned int offset, + void *val, size_t bytes) +{ + struct rockchip_efuse_chip *efuse = context; + unsigned int addr_start, addr_end, addr_offset, addr_len; + u32 out_value; + u8 *buf; + int ret, i = 0; + + ret = clk_prepare_enable(efuse->clk); + if (ret < 0) { + dev_err(efuse->dev, "failed to prepare/enable efuse clk\n"); + return ret; + } + + addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES; + addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES; + addr_offset = offset % RK3399_NBYTES; + addr_len = addr_end - addr_start; + + buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL); + if (!buf) { + clk_disable_unprepare(efuse->clk); + return -ENOMEM; + } + + writel(RK3399_LOAD | RK3399_PGENB | RK3399_STROBSFTSEL | RK3399_RSB, + efuse->base + REG_EFUSE_CTRL); + udelay(1); + while (addr_len--) { + writel(readl(efuse->base + REG_EFUSE_CTRL) | RK3399_STROBE | + ((addr_start++ & RK3399_A_MASK) << RK3399_A_SHIFT), + efuse->base + REG_EFUSE_CTRL); udelay(1); + out_value = readl(efuse->base + REG_EFUSE_DOUT); + writel(readl(efuse->base + REG_EFUSE_CTRL) & (~RK3399_STROBE), + efuse->base + REG_EFUSE_CTRL); + udelay(1); + + memcpy(&buf[i], &out_value, RK3399_NBYTES); + i += RK3399_NBYTES; } /* Switch to standby mode */ - writel(EFUSE_PGENB | EFUSE_CSB, efuse->base + REG_EFUSE_CTRL); + writel(RK3399_PD | RK3399_CSB, efuse->base + REG_EFUSE_CTRL); + + memcpy(val, buf + addr_offset, bytes); + + kfree(buf); clk_disable_unprepare(efuse->clk); @@ -89,7 +156,27 @@ static struct nvmem_config econfig = { }; static const struct of_device_id rockchip_efuse_match[] = { - { .compatible = "rockchip,rockchip-efuse", }, + /* deprecated but kept around for dts binding compatibility */ + { + .compatible = "rockchip,rockchip-efuse", + .data = (void *)&rockchip_rk3288_efuse_read, + }, + { + .compatible = "rockchip,rk3066a-efuse", + .data = (void *)&rockchip_rk3288_efuse_read, + }, + { + .compatible = "rockchip,rk3188-efuse", + .data = (void *)&rockchip_rk3288_efuse_read, + }, + { + .compatible = "rockchip,rk3288-efuse", + .data = (void *)&rockchip_rk3288_efuse_read, + }, + { + .compatible = "rockchip,rk3399-efuse", + .data = (void *)&rockchip_rk3399_efuse_read, + }, { /* sentinel */}, }; MODULE_DEVICE_TABLE(of, rockchip_efuse_match); @@ -99,6 +186,14 @@ static int rockchip_efuse_probe(struct platform_device *pdev) struct resource *res; struct nvmem_device *nvmem; struct rockchip_efuse_chip *efuse; + const struct of_device_id *match; + struct device *dev = &pdev->dev; + + match = of_match_device(dev->driver->of_match_table, dev); + if (!match || !match->data) { + dev_err(dev, "failed to get match data\n"); + return -EINVAL; + } efuse = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_efuse_chip), GFP_KERNEL); @@ -116,7 +211,7 @@ static int rockchip_efuse_probe(struct platform_device *pdev) efuse->dev = &pdev->dev; econfig.size = resource_size(res); - econfig.reg_read = rockchip_efuse_read; + econfig.reg_read = match->data; econfig.priv = efuse; econfig.dev = efuse->dev; nvmem = nvmem_register(&econfig);