summaryrefslogtreecommitdiffstats
path: root/drivers/nvmem
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/nvmem')
-rw-r--r--drivers/nvmem/Kconfig4
-rw-r--r--drivers/nvmem/bcm-ocotp.c15
-rw-r--r--drivers/nvmem/core.c70
-rw-r--r--drivers/nvmem/imx-iim.c18
-rw-r--r--drivers/nvmem/imx-ocotp.c18
-rw-r--r--drivers/nvmem/lpc18xx_otp.c16
-rw-r--r--drivers/nvmem/meson-efuse.c16
-rw-r--r--drivers/nvmem/meson-mx-efuse.c16
-rw-r--r--drivers/nvmem/mtk-efuse.c16
-rw-r--r--drivers/nvmem/qfprom.c16
-rw-r--r--drivers/nvmem/rockchip-efuse.c32
-rw-r--r--drivers/nvmem/snvs_lpgpr.c53
-rw-r--r--drivers/nvmem/sunxi_sid.c71
-rw-r--r--drivers/nvmem/uniphier-efuse.c16
-rw-r--r--drivers/nvmem/vf610-ocotp.c24
15 files changed, 181 insertions, 220 deletions
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 55cf64ee7f7b..1090924efdb1 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -167,10 +167,10 @@ config MESON_MX_EFUSE
config NVMEM_SNVS_LPGPR
tristate "Support for Low Power General Purpose Register"
- depends on SOC_IMX6 || COMPILE_TEST
+ depends on SOC_IMX6 || SOC_IMX7D || COMPILE_TEST
help
This is a driver for Low Power General Purpose Register (LPGPR) available on
- i.MX6 SoCs in Secure Non-Volatile Storage (SNVS) of this chip.
+ i.MX6 and i.MX7 SoCs in Secure Non-Volatile Storage (SNVS) of this chip.
This driver can also be built as a module. If so, the module
will be called nvmem-snvs-lpgpr.
diff --git a/drivers/nvmem/bcm-ocotp.c b/drivers/nvmem/bcm-ocotp.c
index 5e9e324427f9..4159b3f41d79 100644
--- a/drivers/nvmem/bcm-ocotp.c
+++ b/drivers/nvmem/bcm-ocotp.c
@@ -262,8 +262,7 @@ static int bcm_otpc_probe(struct platform_device *pdev)
else if (of_device_is_compatible(dev->of_node, "brcm,ocotp-v2"))
priv->map = &otp_map_v2;
else {
- dev_err(&pdev->dev,
- "%s otpc config map not defined\n", __func__);
+ dev_err(dev, "%s otpc config map not defined\n", __func__);
return -EINVAL;
}
@@ -302,27 +301,17 @@ static int bcm_otpc_probe(struct platform_device *pdev)
priv->config = &bcm_otpc_nvmem_config;
- nvmem = nvmem_register(&bcm_otpc_nvmem_config);
+ nvmem = devm_nvmem_register(dev, &bcm_otpc_nvmem_config);
if (IS_ERR(nvmem)) {
dev_err(dev, "error registering nvmem config\n");
return PTR_ERR(nvmem);
}
- platform_set_drvdata(pdev, nvmem);
-
return 0;
}
-static int bcm_otpc_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
-
- return nvmem_unregister(nvmem);
-}
-
static struct platform_driver bcm_otpc_driver = {
.probe = bcm_otpc_probe,
- .remove = bcm_otpc_remove,
.driver = {
.name = "brcm-otpc",
.of_match_table = bcm_otpc_dt_ids,
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 35a3dbeea324..b05aa8e81303 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -473,9 +473,14 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
nvmem->reg_read = config->reg_read;
nvmem->reg_write = config->reg_write;
nvmem->dev.of_node = config->dev->of_node;
- dev_set_name(&nvmem->dev, "%s%d",
- config->name ? : "nvmem",
- config->name ? config->id : nvmem->id);
+
+ if (config->id == -1 && config->name) {
+ dev_set_name(&nvmem->dev, "%s", config->name);
+ } else {
+ dev_set_name(&nvmem->dev, "%s%d",
+ config->name ? : "nvmem",
+ config->name ? config->id : nvmem->id);
+ }
nvmem->read_only = device_property_present(config->dev, "read-only") |
config->read_only;
@@ -544,6 +549,65 @@ int nvmem_unregister(struct nvmem_device *nvmem)
}
EXPORT_SYMBOL_GPL(nvmem_unregister);
+static void devm_nvmem_release(struct device *dev, void *res)
+{
+ WARN_ON(nvmem_unregister(*(struct nvmem_device **)res));
+}
+
+/**
+ * devm_nvmem_register() - Register a managed nvmem device for given
+ * nvmem_config.
+ * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
+ *
+ * @config: nvmem device configuration with which nvmem device is created.
+ *
+ * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
+ * on success.
+ */
+struct nvmem_device *devm_nvmem_register(struct device *dev,
+ const struct nvmem_config *config)
+{
+ struct nvmem_device **ptr, *nvmem;
+
+ ptr = devres_alloc(devm_nvmem_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ nvmem = nvmem_register(config);
+
+ if (!IS_ERR(nvmem)) {
+ *ptr = nvmem;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return nvmem;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_register);
+
+static int devm_nvmem_match(struct device *dev, void *res, void *data)
+{
+ struct nvmem_device **r = res;
+
+ return *r == data;
+}
+
+/**
+ * devm_nvmem_unregister() - Unregister previously registered managed nvmem
+ * device.
+ *
+ * @nvmem: Pointer to previously registered nvmem device.
+ *
+ * Return: Will be an negative on error or a zero on success.
+ */
+int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
+{
+ return devres_release(dev, devm_nvmem_release, devm_nvmem_match, nvmem);
+}
+EXPORT_SYMBOL(devm_nvmem_unregister);
+
+
static struct nvmem_device *__nvmem_device_get(struct device_node *np,
struct nvmem_cell **cellp,
const char *cell_id)
diff --git a/drivers/nvmem/imx-iim.c b/drivers/nvmem/imx-iim.c
index 52cfe91d9762..6651e4cdc002 100644
--- a/drivers/nvmem/imx-iim.c
+++ b/drivers/nvmem/imx-iim.c
@@ -125,7 +125,7 @@ static int imx_iim_probe(struct platform_device *pdev)
drvdata = of_id->data;
- iim->clk = devm_clk_get(&pdev->dev, NULL);
+ iim->clk = devm_clk_get(dev, NULL);
if (IS_ERR(iim->clk))
return PTR_ERR(iim->clk);
@@ -138,25 +138,13 @@ static int imx_iim_probe(struct platform_device *pdev)
cfg.size = drvdata->nregs;
cfg.priv = iim;
- nvmem = nvmem_register(&cfg);
- if (IS_ERR(nvmem))
- return PTR_ERR(nvmem);
+ nvmem = devm_nvmem_register(dev, &cfg);
- platform_set_drvdata(pdev, nvmem);
-
- return 0;
-}
-
-static int imx_iim_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
-
- return nvmem_unregister(nvmem);
+ return PTR_ERR_OR_ZERO(nvmem);
}
static struct platform_driver imx_iim_driver = {
.probe = imx_iim_probe,
- .remove = imx_iim_remove,
.driver = {
.name = "imx-iim",
.of_match_table = imx_iim_dt_ids,
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c
index d7ba351a70c9..60816c856dd6 100644
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -439,7 +439,6 @@ MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids);
static int imx_ocotp_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id;
struct device *dev = &pdev->dev;
struct resource *res;
struct ocotp_priv *priv;
@@ -460,32 +459,19 @@ static int imx_ocotp_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
- of_id = of_match_device(imx_ocotp_dt_ids, dev);
priv->params = of_device_get_match_data(&pdev->dev);
imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
imx_ocotp_nvmem_config.dev = dev;
imx_ocotp_nvmem_config.priv = priv;
priv->config = &imx_ocotp_nvmem_config;
- nvmem = nvmem_register(&imx_ocotp_nvmem_config);
+ nvmem = devm_nvmem_register(dev, &imx_ocotp_nvmem_config);
- if (IS_ERR(nvmem))
- return PTR_ERR(nvmem);
- platform_set_drvdata(pdev, nvmem);
-
- return 0;
-}
-
-static int imx_ocotp_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
-
- return nvmem_unregister(nvmem);
+ return PTR_ERR_OR_ZERO(nvmem);
}
static struct platform_driver imx_ocotp_driver = {
.probe = imx_ocotp_probe,
- .remove = imx_ocotp_remove,
.driver = {
.name = "imx_ocotp",
.of_match_table = imx_ocotp_dt_ids,
diff --git a/drivers/nvmem/lpc18xx_otp.c b/drivers/nvmem/lpc18xx_otp.c
index 95268db155e9..549b5298ac4c 100644
--- a/drivers/nvmem/lpc18xx_otp.c
+++ b/drivers/nvmem/lpc18xx_otp.c
@@ -86,20 +86,9 @@ static int lpc18xx_otp_probe(struct platform_device *pdev)
lpc18xx_otp_nvmem_config.dev = &pdev->dev;
lpc18xx_otp_nvmem_config.priv = otp;
- nvmem = nvmem_register(&lpc18xx_otp_nvmem_config);
- if (IS_ERR(nvmem))
- return PTR_ERR(nvmem);
+ nvmem = devm_nvmem_register(&pdev->dev, &lpc18xx_otp_nvmem_config);
- platform_set_drvdata(pdev, nvmem);
-
- return 0;
-}
-
-static int lpc18xx_otp_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
-
- return nvmem_unregister(nvmem);
+ return PTR_ERR_OR_ZERO(nvmem);
}
static const struct of_device_id lpc18xx_otp_dt_ids[] = {
@@ -110,7 +99,6 @@ MODULE_DEVICE_TABLE(of, lpc18xx_otp_dt_ids);
static struct platform_driver lpc18xx_otp_driver = {
.probe = lpc18xx_otp_probe,
- .remove = lpc18xx_otp_remove,
.driver = {
.name = "lpc18xx_otp",
.of_match_table = lpc18xx_otp_dt_ids,
diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c
index a43c68f90937..71823d1403c5 100644
--- a/drivers/nvmem/meson-efuse.c
+++ b/drivers/nvmem/meson-efuse.c
@@ -60,25 +60,13 @@ static int meson_efuse_probe(struct platform_device *pdev)
econfig.reg_read = meson_efuse_read;
econfig.size = size;
- nvmem = nvmem_register(&econfig);
- if (IS_ERR(nvmem))
- return PTR_ERR(nvmem);
+ nvmem = devm_nvmem_register(&pdev->dev, &econfig);
- platform_set_drvdata(pdev, nvmem);
-
- return 0;
-}
-
-static int meson_efuse_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
-
- return nvmem_unregister(nvmem);
+ return PTR_ERR_OR_ZERO(nvmem);
}
static struct platform_driver meson_efuse_driver = {
.probe = meson_efuse_probe,
- .remove = meson_efuse_remove,
.driver = {
.name = "meson-efuse",
.of_match_table = meson_efuse_match,
diff --git a/drivers/nvmem/meson-mx-efuse.c b/drivers/nvmem/meson-mx-efuse.c
index 41d3a3c1104e..a085563e39e3 100644
--- a/drivers/nvmem/meson-mx-efuse.c
+++ b/drivers/nvmem/meson-mx-efuse.c
@@ -233,25 +233,13 @@ static int meson_mx_efuse_probe(struct platform_device *pdev)
return PTR_ERR(efuse->core_clk);
}
- efuse->nvmem = nvmem_register(&efuse->config);
- if (IS_ERR(efuse->nvmem))
- return PTR_ERR(efuse->nvmem);
+ efuse->nvmem = devm_nvmem_register(&pdev->dev, &efuse->config);
- platform_set_drvdata(pdev, efuse);
-
- return 0;
-}
-
-static int meson_mx_efuse_remove(struct platform_device *pdev)
-{
- struct meson_mx_efuse *efuse = platform_get_drvdata(pdev);
-
- return nvmem_unregister(efuse->nvmem);
+ return PTR_ERR_OR_ZERO(efuse->nvmem);
}
static struct platform_driver meson_mx_efuse_driver = {
.probe = meson_mx_efuse_probe,
- .remove = meson_mx_efuse_remove,
.driver = {
.name = "meson-mx-efuse",
.of_match_table = meson_mx_efuse_match,
diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
index 9ee3479cfc7b..e66adf17a747 100644
--- a/drivers/nvmem/mtk-efuse.c
+++ b/drivers/nvmem/mtk-efuse.c
@@ -72,20 +72,9 @@ static int mtk_efuse_probe(struct platform_device *pdev)
econfig.size = resource_size(res);
econfig.priv = priv;
econfig.dev = dev;
- nvmem = nvmem_register(&econfig);
- if (IS_ERR(nvmem))
- return PTR_ERR(nvmem);
+ nvmem = devm_nvmem_register(dev, &econfig);
- platform_set_drvdata(pdev, nvmem);
-
- return 0;
-}
-
-static int mtk_efuse_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
-
- return nvmem_unregister(nvmem);
+ return PTR_ERR_OR_ZERO(nvmem);
}
static const struct of_device_id mtk_efuse_of_match[] = {
@@ -97,7 +86,6 @@ MODULE_DEVICE_TABLE(of, mtk_efuse_of_match);
static struct platform_driver mtk_efuse_driver = {
.probe = mtk_efuse_probe,
- .remove = mtk_efuse_remove,
.driver = {
.name = "mediatek,efuse",
.of_match_table = mtk_efuse_of_match,
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
index cb3b48b47d64..4f650baad983 100644
--- a/drivers/nvmem/qfprom.c
+++ b/drivers/nvmem/qfprom.c
@@ -47,13 +47,6 @@ static int qfprom_reg_write(void *context,
return 0;
}
-static int qfprom_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
-
- return nvmem_unregister(nvmem);
-}
-
static struct nvmem_config econfig = {
.name = "qfprom",
.stride = 1,
@@ -82,13 +75,9 @@ static int qfprom_probe(struct platform_device *pdev)
econfig.dev = dev;
econfig.priv = priv;
- nvmem = nvmem_register(&econfig);
- if (IS_ERR(nvmem))
- return PTR_ERR(nvmem);
-
- platform_set_drvdata(pdev, nvmem);
+ nvmem = devm_nvmem_register(dev, &econfig);
- return 0;
+ return PTR_ERR_OR_ZERO(nvmem);
}
static const struct of_device_id qfprom_of_match[] = {
@@ -99,7 +88,6 @@ MODULE_DEVICE_TABLE(of, qfprom_of_match);
static struct platform_driver qfprom_driver = {
.probe = qfprom_probe,
- .remove = qfprom_remove,
.driver = {
.name = "qcom,qfprom",
.of_match_table = qfprom_of_match,
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index f13a8335f364..b3b0b648be62 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -259,55 +259,43 @@ 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;
+ const void *data;
struct device *dev = &pdev->dev;
- match = of_match_device(dev->driver->of_match_table, dev);
- if (!match || !match->data) {
+ data = of_device_get_match_data(dev);
+ if (!data) {
dev_err(dev, "failed to get match data\n");
return -EINVAL;
}
- efuse = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_efuse_chip),
+ efuse = devm_kzalloc(dev, sizeof(struct rockchip_efuse_chip),
GFP_KERNEL);
if (!efuse)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- efuse->base = devm_ioremap_resource(&pdev->dev, res);
+ efuse->base = devm_ioremap_resource(dev, res);
if (IS_ERR(efuse->base))
return PTR_ERR(efuse->base);
- efuse->clk = devm_clk_get(&pdev->dev, "pclk_efuse");
+ efuse->clk = devm_clk_get(dev, "pclk_efuse");
if (IS_ERR(efuse->clk))
return PTR_ERR(efuse->clk);
- efuse->dev = &pdev->dev;
+ efuse->dev = dev;
if (of_property_read_u32(dev->of_node, "rockchip,efuse-size",
&econfig.size))
econfig.size = resource_size(res);
- econfig.reg_read = match->data;
+ econfig.reg_read = data;
econfig.priv = efuse;
econfig.dev = efuse->dev;
- nvmem = nvmem_register(&econfig);
- if (IS_ERR(nvmem))
- return PTR_ERR(nvmem);
+ nvmem = devm_nvmem_register(dev, &econfig);
- platform_set_drvdata(pdev, nvmem);
-
- return 0;
-}
-
-static int rockchip_efuse_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
-
- return nvmem_unregister(nvmem);
+ return PTR_ERR_OR_ZERO(nvmem);
}
static struct platform_driver rockchip_efuse_driver = {
.probe = rockchip_efuse_probe,
- .remove = rockchip_efuse_remove,
.driver = {
.name = "rockchip-efuse",
.of_match_table = rockchip_efuse_match,
diff --git a/drivers/nvmem/snvs_lpgpr.c b/drivers/nvmem/snvs_lpgpr.c
index e5c2a4a17f03..c050a23a9f2b 100644
--- a/drivers/nvmem/snvs_lpgpr.c
+++ b/drivers/nvmem/snvs_lpgpr.c
@@ -14,15 +14,21 @@
#include <linux/regmap.h>
#define IMX6Q_SNVS_HPLR 0x00
-#define IMX6Q_GPR_SL BIT(5)
#define IMX6Q_SNVS_LPLR 0x34
-#define IMX6Q_GPR_HL BIT(5)
#define IMX6Q_SNVS_LPGPR 0x68
+#define IMX7D_SNVS_HPLR 0x00
+#define IMX7D_SNVS_LPLR 0x34
+#define IMX7D_SNVS_LPGPR 0x90
+
+#define IMX_GPR_SL BIT(5)
+#define IMX_GPR_HL BIT(5)
+
struct snvs_lpgpr_cfg {
int offset;
int offset_hplr;
int offset_lplr;
+ int size;
};
struct snvs_lpgpr_priv {
@@ -36,6 +42,14 @@ static const struct snvs_lpgpr_cfg snvs_lpgpr_cfg_imx6q = {
.offset = IMX6Q_SNVS_LPGPR,
.offset_hplr = IMX6Q_SNVS_HPLR,
.offset_lplr = IMX6Q_SNVS_LPLR,
+ .size = 4,
+};
+
+static const struct snvs_lpgpr_cfg snvs_lpgpr_cfg_imx7d = {
+ .offset = IMX7D_SNVS_LPGPR,
+ .offset_hplr = IMX7D_SNVS_HPLR,
+ .offset_lplr = IMX7D_SNVS_LPLR,
+ .size = 16,
};
static int snvs_lpgpr_write(void *context, unsigned int offset, void *val,
@@ -50,14 +64,14 @@ static int snvs_lpgpr_write(void *context, unsigned int offset, void *val,
if (ret < 0)
return ret;
- if (lock_reg & IMX6Q_GPR_SL)
+ if (lock_reg & IMX_GPR_SL)
return -EPERM;
ret = regmap_read(priv->regmap, dcfg->offset_lplr, &lock_reg);
if (ret < 0)
return ret;
- if (lock_reg & IMX6Q_GPR_HL)
+ if (lock_reg & IMX_GPR_HL)
return -EPERM;
return regmap_bulk_write(priv->regmap, dcfg->offset + offset, val,
@@ -110,40 +124,29 @@ static int snvs_lpgpr_probe(struct platform_device *pdev)
cfg->priv = priv;
cfg->name = dev_name(dev);
cfg->dev = dev;
- cfg->stride = 4,
- cfg->word_size = 4,
- cfg->size = 4,
- cfg->owner = THIS_MODULE,
- cfg->reg_read = snvs_lpgpr_read,
- cfg->reg_write = snvs_lpgpr_write,
-
- nvmem = nvmem_register(cfg);
- if (IS_ERR(nvmem))
- return PTR_ERR(nvmem);
+ cfg->stride = 4;
+ cfg->word_size = 4;
+ cfg->size = dcfg->size,
+ cfg->owner = THIS_MODULE;
+ cfg->reg_read = snvs_lpgpr_read;
+ cfg->reg_write = snvs_lpgpr_write;
- platform_set_drvdata(pdev, nvmem);
-
- return 0;
-}
-
-static int snvs_lpgpr_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+ nvmem = devm_nvmem_register(dev, cfg);
- return nvmem_unregister(nvmem);
+ return PTR_ERR_OR_ZERO(nvmem);
}
static const struct of_device_id snvs_lpgpr_dt_ids[] = {
{ .compatible = "fsl,imx6q-snvs-lpgpr", .data = &snvs_lpgpr_cfg_imx6q },
{ .compatible = "fsl,imx6ul-snvs-lpgpr",
.data = &snvs_lpgpr_cfg_imx6q },
+ { .compatible = "fsl,imx7d-snvs-lpgpr", .data = &snvs_lpgpr_cfg_imx7d },
{ },
};
MODULE_DEVICE_TABLE(of, snvs_lpgpr_dt_ids);
static struct platform_driver snvs_lpgpr_driver = {
.probe = snvs_lpgpr_probe,
- .remove = snvs_lpgpr_remove,
.driver = {
.name = "snvs_lpgpr",
.of_match_table = snvs_lpgpr_dt_ids,
@@ -152,5 +155,5 @@ static struct platform_driver snvs_lpgpr_driver = {
module_platform_driver(snvs_lpgpr_driver);
MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
-MODULE_DESCRIPTION("Low Power General Purpose Register in i.MX6 Secure Non-Volatile Storage");
+MODULE_DESCRIPTION("Low Power General Purpose Register in i.MX6 and i.MX7 Secure Non-Volatile Storage");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c
index 99bd54d85fcb..26bb637afe92 100644
--- a/drivers/nvmem/sunxi_sid.c
+++ b/drivers/nvmem/sunxi_sid.c
@@ -85,13 +85,14 @@ static int sunxi_sid_read(void *context, unsigned int offset,
}
static int sun8i_sid_register_readout(const struct sunxi_sid *sid,
- const unsigned int word)
+ const unsigned int offset,
+ u32 *out)
{
u32 reg_val;
int ret;
/* Set word, lock access, and set read command */
- reg_val = (word & SUN8I_SID_OFFSET_MASK)
+ reg_val = (offset & SUN8I_SID_OFFSET_MASK)
<< SUN8I_SID_OFFSET_SHIFT;
reg_val |= SUN8I_SID_OP_LOCK | SUN8I_SID_READ;
writel(reg_val, sid->base + SUN8I_SID_PRCTL);
@@ -101,7 +102,49 @@ static int sun8i_sid_register_readout(const struct sunxi_sid *sid,
if (ret)
return ret;
+ if (out)
+ *out = readl(sid->base + SUN8I_SID_RDKEY);
+
writel(0, sid->base + SUN8I_SID_PRCTL);
+
+ return 0;
+}
+
+/*
+ * On Allwinner H3, the value on the 0x200 offset of the SID controller seems
+ * to be not reliable at all.
+ * Read by the registers instead.
+ */
+static int sun8i_sid_read_byte_by_reg(const struct sunxi_sid *sid,
+ const unsigned int offset,
+ u8 *out)
+{
+ u32 word;
+ int ret;
+
+ ret = sun8i_sid_register_readout(sid, offset & ~0x03, &word);
+
+ if (ret)
+ return ret;
+
+ *out = (word >> ((offset & 0x3) * 8)) & 0xff;
+
+ return 0;
+}
+
+static int sun8i_sid_read_by_reg(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct sunxi_sid *sid = context;
+ u8 *buf = val;
+ int ret;
+
+ while (bytes--) {
+ ret = sun8i_sid_read_byte_by_reg(sid, offset++, buf++);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
@@ -131,26 +174,12 @@ static int sunxi_sid_probe(struct platform_device *pdev)
size = cfg->size;
- if (cfg->need_register_readout) {
- /*
- * H3's SID controller have a bug that the value at 0x200
- * offset is not the correct value when the hardware is reseted.
- * However, after doing a register-based read operation, the
- * value become right.
- * Do a full read operation here, but ignore its value
- * (as it's more fast to read by direct MMIO value than
- * with registers)
- */
- for (i = 0; i < (size >> 2); i++) {
- ret = sun8i_sid_register_readout(sid, i);
- if (ret)
- return ret;
- }
- }
-
econfig.size = size;
econfig.dev = dev;
- econfig.reg_read = sunxi_sid_read;
+ if (cfg->need_register_readout)
+ econfig.reg_read = sun8i_sid_read_by_reg;
+ else
+ econfig.reg_read = sunxi_sid_read;
econfig.priv = sid;
nvmem = nvmem_register(&econfig);
if (IS_ERR(nvmem))
@@ -163,7 +192,7 @@ static int sunxi_sid_probe(struct platform_device *pdev)
}
for (i = 0; i < size; i++)
- randomness[i] = sunxi_sid_read_byte(sid, i);
+ econfig.reg_read(sid, i, &randomness[i], 1);
add_device_randomness(randomness, size);
kfree(randomness);
diff --git a/drivers/nvmem/uniphier-efuse.c b/drivers/nvmem/uniphier-efuse.c
index be11880a1358..271f0b2ff86a 100644
--- a/drivers/nvmem/uniphier-efuse.c
+++ b/drivers/nvmem/uniphier-efuse.c
@@ -60,20 +60,9 @@ static int uniphier_efuse_probe(struct platform_device *pdev)
econfig.size = resource_size(res);
econfig.priv = priv;
econfig.dev = dev;
- nvmem = nvmem_register(&econfig);
- if (IS_ERR(nvmem))
- return PTR_ERR(nvmem);
+ nvmem = devm_nvmem_register(dev, &econfig);
- platform_set_drvdata(pdev, nvmem);
-
- return 0;
-}
-
-static int uniphier_efuse_remove(struct platform_device *pdev)
-{
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
-
- return nvmem_unregister(nvmem);
+ return PTR_ERR_OR_ZERO(nvmem);
}
static const struct of_device_id uniphier_efuse_of_match[] = {
@@ -84,7 +73,6 @@ MODULE_DEVICE_TABLE(of, uniphier_efuse_of_match);
static struct platform_driver uniphier_efuse_driver = {
.probe = uniphier_efuse_probe,
- .remove = uniphier_efuse_remove,
.driver = {
.name = "uniphier-efuse",
.of_match_table = uniphier_efuse_of_match,
diff --git a/drivers/nvmem/vf610-ocotp.c b/drivers/nvmem/vf610-ocotp.c
index 5ae9e002f195..4662309489db 100644
--- a/drivers/nvmem/vf610-ocotp.c
+++ b/drivers/nvmem/vf610-ocotp.c
@@ -217,21 +217,13 @@ static const struct of_device_id ocotp_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ocotp_of_match);
-static int vf610_ocotp_remove(struct platform_device *pdev)
-{
- struct vf610_ocotp *ocotp_dev = platform_get_drvdata(pdev);
-
- return nvmem_unregister(ocotp_dev->nvmem);
-}
-
static int vf610_ocotp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct vf610_ocotp *ocotp_dev;
- ocotp_dev = devm_kzalloc(&pdev->dev,
- sizeof(struct vf610_ocotp), GFP_KERNEL);
+ ocotp_dev = devm_kzalloc(dev, sizeof(struct vf610_ocotp), GFP_KERNEL);
if (!ocotp_dev)
return -ENOMEM;
@@ -246,26 +238,20 @@ static int vf610_ocotp_probe(struct platform_device *pdev)
PTR_ERR(ocotp_dev->clk));
return PTR_ERR(ocotp_dev->clk);
}
+ ocotp_dev->dev = dev;
+ ocotp_dev->timing = vf610_ocotp_calculate_timing(ocotp_dev);
ocotp_config.size = resource_size(res);
ocotp_config.priv = ocotp_dev;
ocotp_config.dev = dev;
- ocotp_dev->nvmem = nvmem_register(&ocotp_config);
- if (IS_ERR(ocotp_dev->nvmem))
- return PTR_ERR(ocotp_dev->nvmem);
+ ocotp_dev->nvmem = devm_nvmem_register(dev, &ocotp_config);
- ocotp_dev->dev = dev;
- platform_set_drvdata(pdev, ocotp_dev);
-
- ocotp_dev->timing = vf610_ocotp_calculate_timing(ocotp_dev);
-
- return 0;
+ return PTR_ERR_OR_ZERO(ocotp_dev->nvmem);
}
static struct platform_driver vf610_ocotp_driver = {
.probe = vf610_ocotp_probe,
- .remove = vf610_ocotp_remove,
.driver = {
.name = "vf610-ocotp",
.of_match_table = ocotp_of_match,