From: Caesar Wang <wxt@rock-chips.com>
To: heiko@sntech.de
Cc: devicetree@vger.kernel.org, jay.xu@rock-chips.com,
linus.walleij@linaro.org, galak@codeaurora.org,
linux-kernel@vger.kernel.org, ijc+devicetree@hellion.org.uk,
linux-rockchip@lists.infradead.org, robh+dt@kernel.org,
matthias.bgg@gmail.com, pawel.moll@arm.com, mark.rutland@arm.com,
linux@arm.linux.org.uk, linux-arm-kernel@lists.infradead.org,
wxt@rock-chips.com
Subject: [PATCH v2 2/3] soc/rockchip: efuse: Add Rockchip SoC efuse support
Date: Tue, 16 Jun 2015 15:27:44 +0800 [thread overview]
Message-ID: <1434439665-27781-3-git-send-email-wxt@rock-chips.com> (raw)
In-Reply-To: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
Add driver for efuse found on Rockchip RK3066,RK3188,RK3288 and
RK3368 SoCs.
eFuse is organized as 32bits by 8 one-time programmable
electrical fuses with random access interface.
Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com>
Signed-off-by: Caesar Wang <wxt@rock-chips.com>
---
Changes in v2:
- Move the efuse driver into driver/soc/vendor.
- update the efuse driver.
drivers/soc/Makefile | 1 +
drivers/soc/rockchip/Makefile | 4 +
drivers/soc/rockchip/efuse.c | 212 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 217 insertions(+)
create mode 100644 drivers/soc/rockchip/Makefile
create mode 100644 drivers/soc/rockchip/efuse.c
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 70042b2..91f7f18 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_QCOM) += qcom/
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_SOC_TI) += ti/
obj-$(CONFIG_PLAT_VERSATILE) += versatile/
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
new file mode 100644
index 0000000..4f5f9bd
--- /dev/null
+++ b/drivers/soc/rockchip/Makefile
@@ -0,0 +1,4 @@
+#
+# Rockchip Soc drivers
+#
+obj-$(CONFIG_ARCH_ROCKCHIP) += efuse.o
diff --git a/drivers/soc/rockchip/efuse.c b/drivers/soc/rockchip/efuse.c
new file mode 100644
index 0000000..1125320
--- /dev/null
+++ b/drivers/soc/rockchip/efuse.c
@@ -0,0 +1,212 @@
+/*
+ * Rockchip eFuse Driver
+ *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Jianqun Xu <jay.xu@rock-chips.com>
+ * Author: Caesar Wang <wxt@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#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 EFUSE_BUF_SIZE 32
+#define EFUSE_CHIP_VERSION_OFFSET 6
+#define EFUSE_CHIP_VERSION_MASK 0xf
+#define EFUSE_BUF_LKG_CPU 23
+
+struct rockchip_efuse_info {
+ struct device *dev;
+ void __iomem *regs;
+ u32 buf[EFUSE_BUF_SIZE];
+};
+
+static void efuse_writel(struct rockchip_efuse_info *efuse,
+ unsigned int value,
+ unsigned int offset)
+{
+ writel_relaxed(value, efuse->regs + offset);
+}
+
+static unsigned int efuse_readl(struct rockchip_efuse_info *efuse,
+ unsigned int offset)
+{
+ return readl_relaxed(efuse->regs + offset);
+}
+
+int rockchip_efuse_get_cpuleakage(struct platform_device *pdev,
+ unsigned int *value)
+{
+ struct rockchip_efuse_info *efuse;
+
+ efuse = platform_get_drvdata(pdev);
+ if (!efuse)
+ return -EAGAIN;
+
+ *value = efuse->buf[EFUSE_BUF_LKG_CPU];
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_efuse_get_cpuleakage);
+
+int rockchip_efuse_get_chip_version(struct platform_device *pdev,
+ unsigned int *value)
+{
+ struct rockchip_efuse_info *efuse;
+
+ efuse = platform_get_drvdata(pdev);
+ if (!efuse)
+ return -EAGAIN;
+
+ *value = efuse->buf[EFUSE_CHIP_VERSION_OFFSET] &
+ EFUSE_CHIP_VERSION_MASK;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_efuse_get_chip_version);
+
+static ssize_t cpu_leakage_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int leakage;
+ int ret;
+ struct platform_device *pdev = to_platform_device(dev);
+
+ ret = rockchip_efuse_get_cpuleakage(pdev, &leakage);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", leakage);
+}
+
+static ssize_t cpu_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int version;
+ int ret;
+ struct platform_device *pdev = to_platform_device(dev);
+
+ ret = rockchip_efuse_get_chip_version(pdev, &version);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", version);
+}
+
+static void rockchip_efuse_init(struct rockchip_efuse_info *efuse)
+{
+ unsigned int start;
+
+ efuse_writel(efuse, EFUSE_LOAD | EFUSE_PGENB, REG_EFUSE_CTRL);
+ udelay(1);
+
+ for (start = 0; start <= EFUSE_BUF_SIZE; start++) {
+ efuse_writel(efuse, efuse_readl(efuse, REG_EFUSE_CTRL) &
+ (~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
+ REG_EFUSE_CTRL);
+ efuse_writel(efuse, efuse_readl(efuse, REG_EFUSE_CTRL) |
+ ((start & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+ REG_EFUSE_CTRL);
+ udelay(1);
+ efuse_writel(efuse, efuse_readl(efuse, REG_EFUSE_CTRL) |
+ EFUSE_STROBE, REG_EFUSE_CTRL);
+ udelay(1);
+
+ efuse->buf[start] = efuse_readl(efuse, REG_EFUSE_DOUT);
+
+ efuse_writel(efuse, efuse_readl(efuse, REG_EFUSE_CTRL) &
+ (~EFUSE_STROBE), REG_EFUSE_CTRL);
+ udelay(1);
+ }
+
+ /* Switch to standby mode */
+ efuse_writel(efuse, EFUSE_PGENB | EFUSE_CSB, REG_EFUSE_CTRL);
+}
+
+static DEVICE_ATTR(cpu_leakage_show, 0444, cpu_leakage_show, NULL);
+static DEVICE_ATTR(cpu_version_show, 0444, cpu_version_show, NULL);
+
+static struct attribute *efuse_attributes[] = {
+ &dev_attr_cpu_leakage_show.attr,
+ &dev_attr_cpu_version_show.attr,
+ NULL,
+};
+
+static const struct attribute_group efuse_attr_group = {
+ .attrs = efuse_attributes,
+};
+
+static int rockchip_efuse_probe(struct platform_device *pdev)
+{
+ struct rockchip_efuse_info *efuse;
+ struct resource *mem;
+ int ret;
+
+ efuse = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_efuse_info),
+ GFP_KERNEL);
+ if (!efuse)
+ return -ENOMEM;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ efuse->regs = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(efuse->regs))
+ return PTR_ERR(efuse->regs);
+
+ efuse->dev = &pdev->dev;
+
+ rockchip_efuse_init(efuse);
+
+ /*
+ * We set driver data only after fully initializing efuse
+ * to make sure rockchip_efuse_get_cpuleakage() and
+ * rockchip_efuse_get_cpu_version do not return garbage.
+ */
+ platform_set_drvdata(pdev, efuse);
+
+ ret = sysfs_create_group(&efuse->dev->kobj, &efuse_attr_group);
+ if (ret) {
+ dev_err(efuse->dev,
+ "failed to register sysfs. err: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id rockchip_efuse_match[] = {
+ { .compatible = "rockchip,rk3066-efuse", },
+ { /* sentinel */},
+};
+
+static struct platform_driver rockchip_efuse_driver = {
+ .probe = rockchip_efuse_probe,
+ .driver = {
+ .name = "rockchip-efuse",
+ .of_match_table = of_match_ptr(rockchip_efuse_match),
+ .suppress_bind_attrs = true,
+ },
+};
+
+module_platform_driver(rockchip_efuse_driver);
--
1.9.1
next prev parent reply other threads:[~2015-06-16 7:28 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-16 7:27 [PATCH v2 0/3] Add the efuse driver on rockchip platform Caesar Wang
2015-06-16 7:27 ` [PATCH v2 1/3] soc/rockchip: Add efuse bindings for Rockchip SoC efuse driver Caesar Wang
2015-06-16 7:27 ` Caesar Wang [this message]
2015-06-16 7:27 ` [PATCH v2 3/3] ARM: dts: Add RK3288 efuse node Caesar Wang
2015-06-16 8:52 ` [PATCH v2 0/3] Add the efuse driver on rockchip platform Stefan Wahren
2015-06-16 9:21 ` Srinivas Kandagatla
2015-06-16 10:06 ` Caesar Wang
2015-06-16 10:54 ` Srinivas Kandagatla
2015-06-18 7:05 ` Stefan Wahren
2015-06-18 8:29 ` Srinivas Kandagatla
2015-06-18 9:08 ` Caesar Wang
2015-07-31 9:27 ` Shunqian Zheng
2015-08-04 16:11 ` Srinivas Kandagatla
2015-08-06 1:10 ` Shunqian Zheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1434439665-27781-3-git-send-email-wxt@rock-chips.com \
--to=wxt@rock-chips.com \
--cc=devicetree@vger.kernel.org \
--cc=galak@codeaurora.org \
--cc=heiko@sntech.de \
--cc=ijc+devicetree@hellion.org.uk \
--cc=jay.xu@rock-chips.com \
--cc=linus.walleij@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=linux@arm.linux.org.uk \
--cc=mark.rutland@arm.com \
--cc=matthias.bgg@gmail.com \
--cc=pawel.moll@arm.com \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®