2017-04-06 07:31:21

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH v1 1/3] nvmem: add snvs_lpgpr driver

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 <[email protected]>
Cc: Srinivas Kandagatla <[email protected]>
Cc: Maxime Ripard <[email protected]>
Cc: [email protected]
---
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 <[email protected]>
+ * Copyright (c) 2017 Pengutronix, Oleksij Rempel <[email protected]>
+ *
+ * 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 <[email protected]>");
+MODULE_DESCRIPTION("Low Power General Purpose Registe in i.MX6 Secure Non-Volatile Storage");
+MODULE_LICENSE("GPL");
--
2.11.0


2017-04-06 07:31:28

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH v1 2/3] ARM: dts: imx6qdl.dtsi: add "fsl,imx6q-snvs-lpgpr" node

This node is for Low Power General Purpose Registe wich can
be used as Non-Volatile Storage.

Signed-off-by: Oleksij Rempel <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: Rob Herring <[email protected]>
Cc: Shawn Guo <[email protected]>
---
arch/arm/boot/dts/imx6qdl.dtsi | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 6d7bf6496117..8e90014705c3 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -768,6 +768,12 @@
mask = <0x60>;
status = "disabled";
};
+
+ snvs_lpgpr: snvs-lpgpr {
+ compatible = "fsl,imx6q-snvs-lpgpr";
+ regmap = <&snvs>;
+ offset = <0x68>;
+ };
};

epit1: epit@020d0000 { /* EPIT1 */
--
2.11.0

2017-04-06 07:31:40

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH v1 3/3] nvmem: dt: document SNVS LPGPR binding

Documenation bindings for the Low Power General Purpose Registe
available on i.MX6 SoCs in the Secure Non-Volatile Storage.

Signed-off-by: Oleksij Rempel <[email protected]>
Cc: Srinivas Kandagatla <[email protected]>
Cc: Maxime Ripard <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Mark Rutland <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt | 15 +++++++++++++++
1 file changed, 15 insertions(+)
create mode 100644 Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt

diff --git a/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
new file mode 100644
index 000000000000..9a8be1a2d12e
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
@@ -0,0 +1,15 @@
+Device tree bindings for Low Power General Purpose Registe found in i.MX6Q/D
+Secure Non-Volatile Storage.
+
+Required properties:
+- compatible: should be one of
+ "fsl,imx6q-snvs-lpgpr" (i.MX6Q/D/DL/S).
+- offset: Should contain the offset relative to syscon parrent node.
+- regmap: Should contain a phandle pointing to syscon.
+
+Example:
+ snvs_lpgpr: snvs-lpgpr {
+ compatible = "fsl,imx6q-snvs-lpgpr";
+ regmap = <&snvs>;
+ offset = <0x68>;
+ };
--
2.11.0

2017-04-10 18:22:39

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH v1 3/3] nvmem: dt: document SNVS LPGPR binding

On Thu, Apr 06, 2017 at 09:31:07AM +0200, Oleksij Rempel wrote:
> Documenation bindings for the Low Power General Purpose Registe

s/Registe/Register/

> available on i.MX6 SoCs in the Secure Non-Volatile Storage.
>
> Signed-off-by: Oleksij Rempel <[email protected]>
> Cc: Srinivas Kandagatla <[email protected]>
> Cc: Maxime Ripard <[email protected]>
> Cc: Rob Herring <[email protected]>
> Cc: Mark Rutland <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> ---
> Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
>
> diff --git a/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
> new file mode 100644
> index 000000000000..9a8be1a2d12e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
> @@ -0,0 +1,15 @@
> +Device tree bindings for Low Power General Purpose Registe found in i.MX6Q/D
> +Secure Non-Volatile Storage.
> +
> +Required properties:
> +- compatible: should be one of
> + "fsl,imx6q-snvs-lpgpr" (i.MX6Q/D/DL/S).
> +- offset: Should contain the offset relative to syscon parrent node.

typo

+- regmap: Should contain a phandle pointing to syscon.
> +
> +Example:
> + snvs_lpgpr: snvs-lpgpr {
> + compatible = "fsl,imx6q-snvs-lpgpr";
> + regmap = <&snvs>;
> + offset = <0x68>;

Why does this need to be in DT? Is something going to refer to this
node? If not, the &snvs node should be enough information for the OS.

Rob

2017-04-11 04:36:18

by Oleksij Rempel

[permalink] [raw]
Subject: Re: [PATCH v1 3/3] nvmem: dt: document SNVS LPGPR binding

Hi,

On 04/10/2017 08:22 PM, Rob Herring wrote:
> On Thu, Apr 06, 2017 at 09:31:07AM +0200, Oleksij Rempel wrote:
>> Documenation bindings for the Low Power General Purpose Registe
>
> s/Registe/Register/
>
>> available on i.MX6 SoCs in the Secure Non-Volatile Storage.
>>
>> Signed-off-by: Oleksij Rempel <[email protected]>
>> Cc: Srinivas Kandagatla <[email protected]>
>> Cc: Maxime Ripard <[email protected]>
>> Cc: Rob Herring <[email protected]>
>> Cc: Mark Rutland <[email protected]>
>> Cc: [email protected]
>> Cc: [email protected]
>> ---
>> Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt | 15 +++++++++++++++
>> 1 file changed, 15 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
>>
>> diff --git a/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
>> new file mode 100644
>> index 000000000000..9a8be1a2d12e
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
>> @@ -0,0 +1,15 @@
>> +Device tree bindings for Low Power General Purpose Registe found in i.MX6Q/D
>> +Secure Non-Volatile Storage.
>> +
>> +Required properties:
>> +- compatible: should be one of
>> + "fsl,imx6q-snvs-lpgpr" (i.MX6Q/D/DL/S).
>> +- offset: Should contain the offset relative to syscon parrent node.
>
> typo

ok.

> +- regmap: Should contain a phandle pointing to syscon.
>> +
>> +Example:
>> + snvs_lpgpr: snvs-lpgpr {
>> + compatible = "fsl,imx6q-snvs-lpgpr";
>> + regmap = <&snvs>;
>> + offset = <0x68>;
>
> Why does this need to be in DT? Is something going to refer to this
> node? If not, the &snvs node should be enough information for the OS.

Jes, it is refereed by other driver.

Thank you.

2017-04-11 13:35:32

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH v1 3/3] nvmem: dt: document SNVS LPGPR binding

On Mon, Apr 10, 2017 at 11:36 PM, Oleksij Rempel <[email protected]> wrote:
> Hi,
>
>
> On 04/10/2017 08:22 PM, Rob Herring wrote:
>>
>> On Thu, Apr 06, 2017 at 09:31:07AM +0200, Oleksij Rempel wrote:
>>>
>>> Documenation bindings for the Low Power General Purpose Registe
>>
>>
>> s/Registe/Register/
>>
>>> available on i.MX6 SoCs in the Secure Non-Volatile Storage.
>>>
>>> Signed-off-by: Oleksij Rempel <[email protected]>
>>> Cc: Srinivas Kandagatla <[email protected]>
>>> Cc: Maxime Ripard <[email protected]>
>>> Cc: Rob Herring <[email protected]>
>>> Cc: Mark Rutland <[email protected]>
>>> Cc: [email protected]
>>> Cc: [email protected]
>>> ---
>>> Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt | 15
>>> +++++++++++++++
>>> 1 file changed, 15 insertions(+)
>>> create mode 100644
>>> Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
>>> b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
>>> new file mode 100644
>>> index 000000000000..9a8be1a2d12e
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt
>>> @@ -0,0 +1,15 @@
>>> +Device tree bindings for Low Power General Purpose Registe found in
>>> i.MX6Q/D
>>> +Secure Non-Volatile Storage.
>>> +
>>> +Required properties:
>>> +- compatible: should be one of
>>> + "fsl,imx6q-snvs-lpgpr" (i.MX6Q/D/DL/S).
>>> +- offset: Should contain the offset relative to syscon parrent node.
>>
>>
>> typo
>
>
> ok.
>
>> +- regmap: Should contain a phandle pointing to syscon.
>>>
>>> +
>>> +Example:
>>> + snvs_lpgpr: snvs-lpgpr {
>>> + compatible = "fsl,imx6q-snvs-lpgpr";
>>> + regmap = <&snvs>;
>>> + offset = <0x68>;
>>
>>
>> Why does this need to be in DT? Is something going to refer to this
>> node? If not, the &snvs node should be enough information for the OS.
>
>
> Jes, it is refereed by other driver.

What I mean is snvs-lpgpr referenced elsewhere in DT, not by some
driver? You are not using the nvmem binding here so it doesn't seem
like it is. If that's the case, then you don't need this node. The
only information here is the offset which can be part of a driver for
the parent node. To put it another way, we don't want to fill DT with
a node per register.

Rob

2017-04-12 06:24:02

by Oleksij Rempel

[permalink] [raw]
Subject: Re: [PATCH v1 3/3] nvmem: dt: document SNVS LPGPR binding

On Tue, Apr 11, 2017 at 08:35:00AM -0500, Rob Herring wrote:
> On Mon, Apr 10, 2017 at 11:36 PM, Oleksij Rempel <[email protected]> wrote:
> > Hi,
> > On 04/10/2017 08:22 PM, Rob Herring wrote:
> >>
> >> On Thu, Apr 06, 2017 at 09:31:07AM +0200, Oleksij Rempel wrote:
> >>>
> >>> Documenation bindings for the Low Power General Purpose Registe
> >>
> > Jes, it is refereed by other driver.
>
> What I mean is snvs-lpgpr referenced elsewhere in DT, not by some
> driver? You are not using the nvmem binding here so it doesn't seem
> like it is. If that's the case, then you don't need this node. The
> only information here is the offset which can be part of a driver for
> the parent node. To put it another way, we don't want to fill DT with
> a node per register.

This node is referenced insight of product DT. Since the system has
or may have more then one nvmem node we need to assigne aliase to it.

--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |