Discussion:
[PATCH v1 1/2] nvmem: snvs_lpgpr: sync with latest version for kernel
Oleksij Rempel
2017-07-05 09:33:00 UTC
Permalink
DT format is ACKed now without "offset" parameter.
Make sure barebox driver will work with it properly.

Signed-off-by: Oleksij Rempel <***@pengutronix.de>
---
drivers/nvmem/snvs_lpgpr.c | 97 ++++++++++++++++++++++++++++++----------------
1 file changed, 64 insertions(+), 33 deletions(-)

diff --git a/drivers/nvmem/snvs_lpgpr.c b/drivers/nvmem/snvs_lpgpr.c
index 74118a6b75..ac68673bdc 100644
--- a/drivers/nvmem/snvs_lpgpr.c
+++ b/drivers/nvmem/snvs_lpgpr.c
@@ -11,45 +11,71 @@
#include <init.h>
#include <io.h>
#include <of.h>
+#include <of_device.h>
#include <malloc.h>
#include <regmap.h>
#include <mfd/syscon.h>
#include <linux/nvmem-provider.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
+
+struct snvs_lpgpr_cfg {
+ int offset;
+ int offset_hplr;
+ int offset_lplr;
+};
+
struct snvs_lpgpr_priv {
- struct device_d *dev;
- struct regmap *regmap;
- int offset;
- struct nvmem_config cfg;
+ struct device_d *dev;
+ struct regmap *regmap;
+ struct nvmem_config cfg;
+ const struct snvs_lpgpr_cfg *dcfg;
+};
+
+static const struct snvs_lpgpr_cfg snvs_lpgpr_cfg_imx6q = {
+ .offset = IMX6Q_SNVS_LPGPR,
+ .offset_hplr = IMX6Q_SNVS_HPLR,
+ .offset_lplr = IMX6Q_SNVS_LPLR,
};

-static int snvs_lpgpr_write(struct device_d *dev, const int reg,
- const void *_val, int bytes)
+static int snvs_lpgpr_write(struct device_d *dev, const int offset,
+ const void *val, int bytes)
{
struct snvs_lpgpr_priv *priv = dev->parent->priv;
- const u32 *val = _val;
- int i = 0, words = bytes / 4;
+ const struct snvs_lpgpr_cfg *dcfg = priv->dcfg;
+ unsigned int lock_reg;
+ int ret;

- while (words--)
- regmap_write(priv->regmap, priv->offset + reg + (i++ * 4),
- *val++);
+ ret = regmap_read(priv->regmap, dcfg->offset_hplr, &lock_reg);
+ if (ret < 0)
+ return ret;

- return 0;
+ if (lock_reg & IMX6Q_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)
+ return -EPERM;
+
+ return regmap_bulk_write(priv->regmap, dcfg->offset + offset, val,
+ bytes);
}

-static int snvs_lpgpr_read(struct device_d *dev, const int reg, void *_val,
- int bytes)
+static int snvs_lpgpr_read(struct device_d *dev, const int offset, void *val,
+ int bytes)
{
struct snvs_lpgpr_priv *priv = dev->parent->priv;
- u32 *val = _val;
- int i = 0, words = bytes / 4;
-
- while (words--)
- regmap_read(priv->regmap, priv->offset + reg + (i++ * 4),
- val++);
+ const struct snvs_lpgpr_cfg *dcfg = priv->dcfg;

-
- return 0;
+ return regmap_bulk_read(priv->regmap, dcfg->offset + offset,
+ val, bytes);
}

static const struct nvmem_bus snvs_lpgpr_nvmem_bus = {
@@ -60,10 +86,11 @@ static const struct nvmem_bus snvs_lpgpr_nvmem_bus = {
static int snvs_lpgpr_probe(struct device_d *dev)
{
struct device_node *node = dev->device_node;
+ struct device_node *syscon_node;
struct snvs_lpgpr_priv *priv;
struct nvmem_config *cfg;
+ const struct snvs_lpgpr_cfg *dcfg;
struct nvmem_device *nvmem;
- int err;

if (!node)
return -ENOENT;
@@ -72,15 +99,19 @@ static int snvs_lpgpr_probe(struct device_d *dev)
if (!priv)
return -ENOMEM;

- priv->regmap = syscon_node_to_regmap(of_get_parent(node));
- if (IS_ERR(priv->regmap)) {
- free(priv);
+ dcfg = of_device_get_match_data(dev);
+ if (!dcfg)
+ return -EINVAL;
+
+ syscon_node = of_get_parent(node);
+ if (!syscon_node)
+ return -ENODEV;
+
+ priv->regmap = syscon_node_to_regmap(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;
+ priv->dcfg = dcfg;

cfg = &priv->cfg;
cfg->name = dev_name(dev);
@@ -102,13 +133,13 @@ static int snvs_lpgpr_probe(struct device_d *dev)
}

static __maybe_unused struct of_device_id snvs_lpgpr_dt_ids[] = {
- { .compatible = "fsl,imx6sl-snvs-lpgpr", },
- { .compatible = "fsl,imx6q-snvs-lpgpr", },
+ { .compatible = "fsl,imx6q-snvs-lpgpr", .data = &snvs_lpgpr_cfg_imx6q },
+ { .compatible = "fsl,imx6ul-snvs-lpgpr", .data = &snvs_lpgpr_cfg_imx6q },
{ },
};

static struct driver_d snvs_lpgpr_driver = {
- .name = "nvmem-snvs-lpgpr",
+ .name = "snvs_lpgpr",
.probe = snvs_lpgpr_probe,
.of_compatible = DRV_OF_COMPAT(snvs_lpgpr_dt_ids),
};
--
2.11.0
Oleksij Rempel
2017-07-05 09:33:01 UTC
Permalink
Signed-off-by: Oleksij Rempel <***@pengutronix.de>
---
dts/src/arm/imx6qdl.dtsi | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/dts/src/arm/imx6qdl.dtsi b/dts/src/arm/imx6qdl.dtsi
index e426faa9c2..94e9925582 100644
--- a/dts/src/arm/imx6qdl.dtsi
+++ b/dts/src/arm/imx6qdl.dtsi
@@ -769,6 +769,10 @@
mask = <0x60>;
status = "disabled";
};
+
+ snvs_lpgpr: snvs-lpgpr {
+ compatible = "fsl,imx6q-snvs-lpgpr";
+ };
};

epit1: ***@020d0000 { /* EPIT1 */
--
2.11.0
Lucas Stach
2017-07-05 10:02:43 UTC
Permalink
Hi Oleksij,
Post by Oleksij Rempel
---
dts/src/arm/imx6qdl.dtsi | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/dts/src/arm/imx6qdl.dtsi b/dts/src/arm/imx6qdl.dtsi
Files in dts/src/arm/... are verbatim copies of the upstream DTS files
and can not be changed by Barebox patches. As long as the this node
addition hasn't been applied upstream the node needs to be carried in
the Barebox override files in arch/arm/dts/...

Regards,
Lucas
Post by Oleksij Rempel
index e426faa9c2..94e9925582 100644
--- a/dts/src/arm/imx6qdl.dtsi
+++ b/dts/src/arm/imx6qdl.dtsi
@@ -769,6 +769,10 @@
mask = <0x60>;
status = "disabled";
};
+
+ snvs_lpgpr: snvs-lpgpr {
+ compatible = "fsl,imx6q-snvs-lpgpr";
+ };
};
Lucas Stach
2017-07-05 10:13:51 UTC
Permalink
Post by Oleksij Rempel
DT format is ACKed now without "offset" parameter.
Make sure barebox driver will work with it properly.
---
drivers/nvmem/snvs_lpgpr.c | 97 ++++++++++++++++++++++++++++++----------------
1 file changed, 64 insertions(+), 33 deletions(-)
diff --git a/drivers/nvmem/snvs_lpgpr.c b/drivers/nvmem/snvs_lpgpr.c
index 74118a6b75..ac68673bdc 100644
--- a/drivers/nvmem/snvs_lpgpr.c
+++ b/drivers/nvmem/snvs_lpgpr.c
@@ -11,45 +11,71 @@
#include <init.h>
#include <io.h>
#include <of.h>
+#include <of_device.h>
#include <malloc.h>
#include <regmap.h>
#include <mfd/syscon.h>
#include <linux/nvmem-provider.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
+
+struct snvs_lpgpr_cfg {
+ int offset;
+ int offset_hplr;
+ int offset_lplr;
+};
+
struct snvs_lpgpr_priv {
- struct device_d *dev;
- struct regmap *regmap;
- int offset;
- struct nvmem_config cfg;
+ struct device_d *dev;
+ struct regmap *regmap;
+ struct nvmem_config cfg;
+ const struct snvs_lpgpr_cfg *dcfg;
+};
+
+static const struct snvs_lpgpr_cfg snvs_lpgpr_cfg_imx6q = {
+ .offset = IMX6Q_SNVS_LPGPR,
+ .offset_hplr = IMX6Q_SNVS_HPLR,
+ .offset_lplr = IMX6Q_SNVS_LPLR,
};
-static int snvs_lpgpr_write(struct device_d *dev, const int reg,
- const void *_val, int bytes)
+static int snvs_lpgpr_write(struct device_d *dev, const int offset,
+ const void *val, int bytes)
{
struct snvs_lpgpr_priv *priv = dev->parent->priv;
- const u32 *val = _val;
- int i = 0, words = bytes / 4;
+ const struct snvs_lpgpr_cfg *dcfg = priv->dcfg;
+ unsigned int lock_reg;
+ int ret;
- while (words--)
- regmap_write(priv->regmap, priv->offset + reg + (i++ * 4),
- *val++);
+ ret = regmap_read(priv->regmap, dcfg->offset_hplr, &lock_reg);
+ if (ret < 0)
+ return ret;
- return 0;
+ if (lock_reg & IMX6Q_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)
+ return -EPERM;
+
+ return regmap_bulk_write(priv->regmap, dcfg->offset + offset, val,
+ bytes);
}
-static int snvs_lpgpr_read(struct device_d *dev, const int reg, void *_val,
- int bytes)
+static int snvs_lpgpr_read(struct device_d *dev, const int offset, void *val,
+ int bytes)
{
struct snvs_lpgpr_priv *priv = dev->parent->priv;
- u32 *val = _val;
- int i = 0, words = bytes / 4;
-
- while (words--)
- regmap_read(priv->regmap, priv->offset + reg + (i++ * 4),
- val++);
+ const struct snvs_lpgpr_cfg *dcfg = priv->dcfg;
-
- return 0;
+ return regmap_bulk_read(priv->regmap, dcfg->offset + offset,
+ val, bytes);
}
static const struct nvmem_bus snvs_lpgpr_nvmem_bus = {
@@ -60,10 +86,11 @@ static const struct nvmem_bus snvs_lpgpr_nvmem_bus = {
static int snvs_lpgpr_probe(struct device_d *dev)
{
struct device_node *node = dev->device_node;
+ struct device_node *syscon_node;
struct snvs_lpgpr_priv *priv;
struct nvmem_config *cfg;
+ const struct snvs_lpgpr_cfg *dcfg;
No need for this, assing directly to priv->dcfg instead.
Post by Oleksij Rempel
struct nvmem_device *nvmem;
- int err;
if (!node)
return -ENOENT;
@@ -72,15 +99,19 @@ static int snvs_lpgpr_probe(struct device_d *dev)
if (!priv)
return -ENOMEM;
- priv->regmap = syscon_node_to_regmap(of_get_parent(node));
- if (IS_ERR(priv->regmap)) {
- free(priv);
+ dcfg = of_device_get_match_data(dev);
+ if (!dcfg)
+ return -EINVAL;
+
+ syscon_node = of_get_parent(node);
+ if (!syscon_node)
+ return -ENODEV;
+
+ priv->regmap = syscon_node_to_regmap(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;
+ priv->dcfg = dcfg;
cfg = &priv->cfg;
cfg->name = dev_name(dev);
@@ -102,13 +133,13 @@ static int snvs_lpgpr_probe(struct device_d *dev)
}
static __maybe_unused struct of_device_id snvs_lpgpr_dt_ids[] = {
- { .compatible = "fsl,imx6sl-snvs-lpgpr", },
- { .compatible = "fsl,imx6q-snvs-lpgpr", },
+ { .compatible = "fsl,imx6q-snvs-lpgpr", .data = &snvs_lpgpr_cfg_imx6q },
+ { .compatible = "fsl,imx6ul-snvs-lpgpr", .data = &snvs_lpgpr_cfg_imx6q },
{ },
};
static struct driver_d snvs_lpgpr_driver = {
- .name = "nvmem-snvs-lpgpr",
+ .name = "snvs_lpgpr",
.probe = snvs_lpgpr_probe,
.of_compatible = DRV_OF_COMPAT(snvs_lpgpr_dt_ids),
};
Loading...