All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 1/3] nvmem: add snvs_lpgpr driver
@ 2017-04-06  7:31 Oleksij Rempel
  2017-04-06  7:31   ` [PATCH v1 2/3] ARM: dts: imx6qdl.dtsi: add "fsl,imx6q-snvs-lpgpr" node Oleksij Rempel
  2017-04-06  7:31 ` [PATCH v1 3/3] nvmem: dt: document SNVS LPGPR binding Oleksij Rempel
  0 siblings, 2 replies; 20+ messages in thread
From: Oleksij Rempel @ 2017-04-06  7:31 UTC (permalink / raw)
  To: o.rempel; +Cc: Srinivas Kandagatla, Maxime Ripard, linux-kernel

This is a driver for Low Power General Purpose Registe (LPGPR)
available on i.MX6 SoCs in Secure Non-Volatile Storage (SNVS)
of this chip.

It is a 32-bit read/write register located in the low power domain.
Since LPGPR is located in the battery-backed power domain, LPGPR can
be used by any application for retaining data during an SoC power-down
mode.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: linux-kernel@vger.kernel.org
---
 drivers/nvmem/Kconfig      |  13 +++++
 drivers/nvmem/Makefile     |   2 +
 drivers/nvmem/snvs_lpgpr.c | 132 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 drivers/nvmem/snvs_lpgpr.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 650f1b1797ad..925885e494a8 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -133,4 +133,17 @@ config MESON_EFUSE
 	  This driver can also be built as a module. If so, the module
 	  will be called nvmem_meson_efuse.
 
+config NVMEM_SNVS_LPGPR
+	tristate "Support for Low Power General Purpose Registe"
+	depends on HAS_IOMEM
+	depends on OF
+	select REGMAP_MMIO
+	select MFD_SYSCON
+	help
+	  This is a driver for Low Power General Purpose Registe (LPGPR) available on
+	  i.MX6 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.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 86e45995fdad..4ba7685e36ff 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -28,3 +28,5 @@ obj-$(CONFIG_NVMEM_VF610_OCOTP)	+= nvmem-vf610-ocotp.o
 nvmem-vf610-ocotp-y		:= vf610-ocotp.o
 obj-$(CONFIG_MESON_EFUSE)	+= nvmem_meson_efuse.o
 nvmem_meson_efuse-y		:= meson-efuse.o
+obj-$(CONFIG_NVMEM_SNVS_LPGPR)	+= nvmem_snvs_lpgpr.o
+nvmem_snvs_lpgpr-y		:= snvs_lpgpr.o
diff --git a/drivers/nvmem/snvs_lpgpr.c b/drivers/nvmem/snvs_lpgpr.c
new file mode 100644
index 000000000000..341f452a36ae
--- /dev/null
+++ b/drivers/nvmem/snvs_lpgpr.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
+ * Copyright (c) 2017 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+struct snvs_lpgpr_priv {
+	struct device_d		*dev;
+	struct regmap		*regmap;
+	int			offset;
+	struct nvmem_config	cfg;
+};
+
+static int snvs_lpgpr_write(void *context, unsigned int offset, void *_val,
+			    size_t bytes)
+{
+	struct snvs_lpgpr_priv *priv = context;
+	const u32 *val = _val;
+	int i = 0, words = bytes / 4;
+
+	while (words--)
+		regmap_write(priv->regmap, priv->offset + offset + (i++ * 4),
+			     *val++);
+
+	return 0;
+}
+
+static int snvs_lpgpr_read(void *context, unsigned int offset, void *_val,
+			   size_t bytes)
+{
+	struct snvs_lpgpr_priv *priv = context;
+	u32 *val = _val;
+	int i = 0, words = bytes / 4;
+
+	while (words--)
+		regmap_read(priv->regmap, priv->offset + offset + (i++ * 4),
+			    val++);
+
+	return 0;
+}
+
+static int snvs_lpgpr_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct device_node *syscon_node;
+	struct snvs_lpgpr_priv *priv;
+	struct nvmem_config *cfg;
+	struct nvmem_device *nvmem;
+	int err;
+
+	if (!node)
+		return -ENOENT;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+        syscon_node = of_get_parent(node);
+	if (!syscon_node)
+		return -ENODEV;
+
+	priv->regmap = syscon_node_to_regmap(syscon_node);
+	of_node_put(syscon_node);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	err = of_property_read_u32(node, "offset", &priv->offset);
+	if (err)
+		return err;
+
+	cfg = &priv->cfg;
+	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);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static int snvs_lpgpr_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static const struct of_device_id snvs_lpgpr_dt_ids[] = {
+	{ .compatible = "fsl,imx6q-snvs-lpgpr", },
+	{ },
+};
+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,
+	},
+};
+module_platform_driver(snvs_lpgpr_driver);
+
+MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
+MODULE_DESCRIPTION("Low Power General Purpose Registe in i.MX6 Secure Non-Volatile Storage");
+MODULE_LICENSE("GPL");
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2017-05-17  7:37 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-06  7:31 [PATCH v1 1/3] nvmem: add snvs_lpgpr driver Oleksij Rempel
2017-04-06  7:31 ` [PATCH v1 2/3] ARM: dts: imx6qdl.dtsi: add "fsl,imx6q-snvs-lpgpr" node Oleksij Rempel
2017-04-06  7:31   ` [PATCH v1 2/3] ARM: dts: imx6qdl.dtsi: add "fsl, imx6q-snvs-lpgpr" node Oleksij Rempel
2017-04-06  7:31   ` [PATCH v1 2/3] ARM: dts: imx6qdl.dtsi: add "fsl,imx6q-snvs-lpgpr" node Oleksij Rempel
2017-04-06  7:31 ` [PATCH v1 3/3] nvmem: dt: document SNVS LPGPR binding Oleksij Rempel
2017-04-10 18:22   ` Rob Herring
2017-04-10 18:22     ` Rob Herring
2017-04-11  4:36     ` Oleksij Rempel
2017-04-11  4:36       ` Oleksij Rempel
2017-04-11 13:35       ` Rob Herring
2017-04-11 13:35         ` Rob Herring
2017-04-12  6:23         ` Oleksij Rempel
2017-04-12  6:23           ` Oleksij Rempel
2017-05-17  7:37           ` Oleksij Rempel
2017-05-17  7:37             ` Oleksij Rempel
     [not found]     ` <20170411052725.17464-1-o.rempel@pengutronix.de>
2017-04-11  5:27       ` [PATCH v2 1/3] nvmem: add snvs_lpgpr driver Oleksij Rempel
2017-04-11  5:27       ` [PATCH v2 2/3] ARM: dts: imx6qdl.dtsi: add "fsl,imx6q-snvs-lpgpr" node Oleksij Rempel
2017-04-11  5:27         ` [PATCH v2 2/3] ARM: dts: imx6qdl.dtsi: add "fsl, imx6q-snvs-lpgpr" node Oleksij Rempel
2017-04-11  5:27         ` Oleksij Rempel
2017-04-11  5:27       ` [PATCH v2 3/3] nvmem: dt: document SNVS LPGPR binding Oleksij Rempel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.