nvmem uses regmap_raw_read/write apis to read/write data from providers,
With recent patch 922a9f936e40 ("regmap: mmio: Convert to regmap_bus
and fix accessor usage") nvmem providers based on regmap-mmio stopped
working, as nvmem core was using raw accessors.
This issue can be fixed temporarly by moving to other regmap apis,
but we might hit same issue in future, and regmap looks like an
overdo for nvmem. Moving to interfaces based on read/write callbacks
from providers would be more robust.
This patchset converts the nvmem core and nvmem provider drivers to
use the new callbacks. Tested this patchset on qfprom and at24 drivers.
Other driver are only compile tested, any testing on them would be great.
Thanks,
srini
Srinivas Kandagatla (12):
nvmem: core: remove regmap dependency
eeprom: at24: remove nvmem regmap dependency
eeprom: at25: remove nvmem regmap dependency
nvmem: qfprom: remove nvmem regmap dependency
nvmem: vif610-ocotp: remove nvmem regmap dependency
nvmem: sunxi-sid: remove nvmem regmap dependency
nvmem: rockchip-efuse: remove nvmem regmap dependency
nvmem: mtk-efuse: remove nvmem regmap dependency
nvmem: imx-ocotp: remove nvmem regmap dependency
nvmem: lpc18xx-eeprom: remove nvmem regmap dependency
nvmem: mxs-ocotp: remove nvmem regmap dependency
nvmem: 93xx46: remove nvmem regmap dependency
drivers/misc/eeprom/Kconfig | 2 -
drivers/misc/eeprom/at24.c | 103 ++++++++----------------------------
drivers/misc/eeprom/at25.c | 89 +++++++------------------------
drivers/misc/eeprom/eeprom_93xx46.c | 90 +++++++------------------------
drivers/nvmem/Kconfig | 4 --
drivers/nvmem/core.c | 67 +++++++++++++----------
drivers/nvmem/imx-ocotp.c | 55 ++++---------------
drivers/nvmem/lpc18xx_eeprom.c | 94 +++++++++-----------------------
drivers/nvmem/mtk-efuse.c | 47 ++++++++++------
drivers/nvmem/mxs-ocotp.c | 79 ++++++++-------------------
drivers/nvmem/qfprom.c | 56 +++++++++++++-------
drivers/nvmem/rockchip-efuse.c | 49 ++++-------------
drivers/nvmem/sunxi_sid.c | 54 ++++---------------
drivers/nvmem/vf610-ocotp.c | 44 ++++-----------
include/linux/nvmem-provider.h | 10 ++++
15 files changed, 264 insertions(+), 579 deletions(-)
--
2.5.0
nvmem uses regmap_raw_read/write apis to read/write data from providers,
regmap raw apis stopped working with recent kernels which removed raw
accessors on mmio bus. This resulted in broken nvmem for providers
which are based on regmap mmio bus. This issue can be fixed temporarly
by moving to other regmap apis, but we might hit same issue in future.
Moving to interfaces based on read/write callbacks from providers would
be more robust.
This patch removes regmap dependency from nvmem and introduces
read/write callbacks from the providers.
Without this patch nvmem providers like qfprom based on regmap mmio
bus would not work.
Reported-by: Rajendra Nayak <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/Kconfig | 1 -
drivers/nvmem/core.c | 67 +++++++++++++++++++++++++-----------------
include/linux/nvmem-provider.h | 10 +++++++
3 files changed, 50 insertions(+), 28 deletions(-)
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index ca52952..36f4f4b 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -1,6 +1,5 @@
menuconfig NVMEM
tristate "NVMEM Support"
- select REGMAP
help
Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES...
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 0de3d87..bb4ea12 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -23,12 +23,10 @@
#include <linux/nvmem-consumer.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
-#include <linux/regmap.h>
#include <linux/slab.h>
struct nvmem_device {
const char *name;
- struct regmap *regmap;
struct module *owner;
struct device dev;
int stride;
@@ -41,6 +39,9 @@ struct nvmem_device {
int flags;
struct bin_attribute eeprom;
struct device *base_dev;
+ nvmem_reg_read_t reg_read;
+ nvmem_reg_write_t reg_write;
+ void *priv;
};
#define FLAG_COMPAT BIT(0)
@@ -66,6 +67,23 @@ static struct lock_class_key eeprom_lock_key;
#endif
#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
+static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
+ void *val, size_t bytes)
+{
+ if (nvmem->reg_read)
+ return nvmem->reg_read(nvmem->priv, offset, val, bytes);
+
+ return -EINVAL;
+}
+
+static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
+ void *val, size_t bytes)
+{
+ if (nvmem->reg_write)
+ return nvmem->reg_write(nvmem->priv, offset, val, bytes);
+
+ return -EINVAL;
+}
static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
@@ -93,7 +111,7 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
count = round_down(count, nvmem->word_size);
- rc = regmap_raw_read(nvmem->regmap, pos, buf, count);
+ rc = nvmem_reg_read(nvmem, pos, buf, count);
if (IS_ERR_VALUE(rc))
return rc;
@@ -127,7 +145,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
count = round_down(count, nvmem->word_size);
- rc = regmap_raw_write(nvmem->regmap, pos, buf, count);
+ rc = nvmem_reg_write(nvmem, pos, buf, count);
if (IS_ERR_VALUE(rc))
return rc;
@@ -421,18 +439,11 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
{
struct nvmem_device *nvmem;
struct device_node *np;
- struct regmap *rm;
int rval;
if (!config->dev)
return ERR_PTR(-EINVAL);
- rm = dev_get_regmap(config->dev, NULL);
- if (!rm) {
- dev_err(config->dev, "Regmap not found\n");
- return ERR_PTR(-EINVAL);
- }
-
nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
if (!nvmem)
return ERR_PTR(-ENOMEM);
@@ -444,14 +455,16 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
}
nvmem->id = rval;
- nvmem->regmap = rm;
nvmem->owner = config->owner;
- nvmem->stride = regmap_get_reg_stride(rm);
- nvmem->word_size = regmap_get_val_bytes(rm);
- nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
+ nvmem->stride = config->stride;
+ nvmem->word_size = config->word_size;
+ nvmem->size = config->size;
nvmem->dev.type = &nvmem_provider_type;
nvmem->dev.bus = &nvmem_bus_type;
nvmem->dev.parent = config->dev;
+ nvmem->priv = config->priv;
+ nvmem->reg_read = config->reg_read;
+ nvmem->reg_write = config->reg_write;
np = config->dev->of_node;
nvmem->dev.of_node = np;
dev_set_name(&nvmem->dev, "%s%d",
@@ -948,7 +961,7 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
{
int rc;
- rc = regmap_raw_read(nvmem->regmap, cell->offset, buf, cell->bytes);
+ rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
if (IS_ERR_VALUE(rc))
return rc;
@@ -977,7 +990,7 @@ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
u8 *buf;
int rc;
- if (!nvmem || !nvmem->regmap)
+ if (!nvmem)
return ERR_PTR(-EINVAL);
buf = kzalloc(cell->bytes, GFP_KERNEL);
@@ -1014,7 +1027,7 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
*b <<= bit_offset;
/* setup the first byte with lsb bits from nvmem */
- rc = regmap_raw_read(nvmem->regmap, cell->offset, &v, 1);
+ rc = nvmem_reg_read(nvmem, cell->offset, &v, 1);
*b++ |= GENMASK(bit_offset - 1, 0) & v;
/* setup rest of the byte if any */
@@ -1031,7 +1044,7 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
/* if it's not end on byte boundary */
if ((nbits + bit_offset) % BITS_PER_BYTE) {
/* setup the last byte with msb bits from nvmem */
- rc = regmap_raw_read(nvmem->regmap,
+ rc = nvmem_reg_read(nvmem,
cell->offset + cell->bytes - 1, &v, 1);
*p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
@@ -1054,7 +1067,7 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
struct nvmem_device *nvmem = cell->nvmem;
int rc;
- if (!nvmem || !nvmem->regmap || nvmem->read_only ||
+ if (!nvmem || nvmem->read_only ||
(cell->bit_offset == 0 && len != cell->bytes))
return -EINVAL;
@@ -1064,7 +1077,7 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
return PTR_ERR(buf);
}
- rc = regmap_raw_write(nvmem->regmap, cell->offset, buf, cell->bytes);
+ rc = nvmem_reg_write(nvmem, cell->offset, buf, cell->bytes);
/* free the tmp buffer */
if (cell->bit_offset || cell->nbits)
@@ -1094,7 +1107,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
int rc;
ssize_t len;
- if (!nvmem || !nvmem->regmap)
+ if (!nvmem)
return -EINVAL;
rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
@@ -1124,7 +1137,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
struct nvmem_cell cell;
int rc;
- if (!nvmem || !nvmem->regmap)
+ if (!nvmem)
return -EINVAL;
rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
@@ -1152,10 +1165,10 @@ int nvmem_device_read(struct nvmem_device *nvmem,
{
int rc;
- if (!nvmem || !nvmem->regmap)
+ if (!nvmem)
return -EINVAL;
- rc = regmap_raw_read(nvmem->regmap, offset, buf, bytes);
+ rc = nvmem_reg_read(nvmem, offset, buf, bytes);
if (IS_ERR_VALUE(rc))
return rc;
@@ -1180,10 +1193,10 @@ int nvmem_device_write(struct nvmem_device *nvmem,
{
int rc;
- if (!nvmem || !nvmem->regmap)
+ if (!nvmem)
return -EINVAL;
- rc = regmap_raw_write(nvmem->regmap, offset, buf, bytes);
+ rc = nvmem_reg_write(nvmem, offset, buf, bytes);
if (IS_ERR_VALUE(rc))
return rc;
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index a4fcc90..cd93416 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -14,6 +14,10 @@
struct nvmem_device;
struct nvmem_cell_info;
+typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset,
+ void *val, size_t bytes);
+typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
+ void *val, size_t bytes);
struct nvmem_config {
struct device *dev;
@@ -24,6 +28,12 @@ struct nvmem_config {
int ncells;
bool read_only;
bool root_only;
+ nvmem_reg_read_t reg_read;
+ nvmem_reg_write_t reg_write;
+ int size;
+ int word_size;
+ int stride;
+ void *priv;
/* To be only used by old driver/misc/eeprom drivers */
bool compat;
struct device *base_dev;
--
2.5.0
This patch moves to nvmem support in the driver to use callback instead of
regmap.
Reported-by: Rajendra Nayak <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/Kconfig | 1 -
drivers/nvmem/qfprom.c | 56 +++++++++++++++++++++++++++++++++-----------------
2 files changed, 37 insertions(+), 20 deletions(-)
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 36f4f4b..a87273b 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -60,7 +60,6 @@ config QCOM_QFPROM
tristate "QCOM QFPROM Support"
depends on ARCH_QCOM || COMPILE_TEST
depends on HAS_IOMEM
- select REGMAP_MMIO
help
Say y here to enable QFPROM support. The QFPROM provides access
functions for QFPROM data to rest of the drivers via nvmem interface.
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
index 3829e5f..b5305f0 100644
--- a/drivers/nvmem/qfprom.c
+++ b/drivers/nvmem/qfprom.c
@@ -13,21 +13,35 @@
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/io.h>
#include <linux/nvmem-provider.h>
#include <linux/platform_device.h>
-#include <linux/regmap.h>
-static struct regmap_config qfprom_regmap_config = {
- .reg_bits = 32,
- .val_bits = 8,
- .reg_stride = 1,
- .val_format_endian = REGMAP_ENDIAN_LITTLE,
-};
+static int qfprom_reg_read(void *context,
+ unsigned int reg, void *_val, size_t bytes)
+{
+ void __iomem *base = context;
+ u32 *val = _val;
+ int i = 0, words = bytes / 4;
-static struct nvmem_config econfig = {
- .name = "qfprom",
- .owner = THIS_MODULE,
-};
+ while (words--)
+ *val++ = readl(base + reg + (i++ * 4));
+
+ return 0;
+}
+
+static int qfprom_reg_write(void *context,
+ unsigned int reg, void *_val, size_t bytes)
+{
+ void __iomem *base = context;
+ u32 *val = _val;
+ int i = 0, words = bytes / 4;
+
+ while (words--)
+ writel(*val++, base + reg + (i++ * 4));
+
+ return 0;
+}
static int qfprom_remove(struct platform_device *pdev)
{
@@ -36,12 +50,20 @@ static int qfprom_remove(struct platform_device *pdev)
return nvmem_unregister(nvmem);
}
+static struct nvmem_config econfig = {
+ .name = "qfprom",
+ .owner = THIS_MODULE,
+ .stride = 4,
+ .word_size = 1,
+ .reg_read = qfprom_reg_read,
+ .reg_write = qfprom_reg_write,
+};
+
static int qfprom_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct nvmem_device *nvmem;
- struct regmap *regmap;
void __iomem *base;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -49,14 +71,10 @@ static int qfprom_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
- qfprom_regmap_config.max_register = resource_size(res) - 1;
-
- regmap = devm_regmap_init_mmio(dev, base, &qfprom_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(dev, "regmap init failed\n");
- return PTR_ERR(regmap);
- }
+ econfig.size = resource_size(res);
econfig.dev = dev;
+ econfig.priv = base;
+
nvmem = nvmem_register(&econfig);
if (IS_ERR(nvmem))
return PTR_ERR(nvmem);
--
2.5.0
This patch moves to nvmem support in the driver to use callback
instead of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/misc/eeprom/eeprom_93xx46.c | 90 ++++++++-----------------------------
1 file changed, 18 insertions(+), 72 deletions(-)
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index 426fe2f..5004d72 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -20,7 +20,6 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/nvmem-provider.h>
-#include <linux/regmap.h>
#include <linux/eeprom_93xx46.h>
#define OP_START 0x4
@@ -43,7 +42,6 @@ struct eeprom_93xx46_dev {
struct spi_device *spi;
struct eeprom_93xx46_platform_data *pdata;
struct mutex lock;
- struct regmap_config regmap_config;
struct nvmem_config nvmem_config;
struct nvmem_device *nvmem;
int addrlen;
@@ -60,11 +58,12 @@ static inline bool has_quirk_instruction_length(struct eeprom_93xx46_dev *edev)
return edev->pdata->quirks & EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH;
}
-static ssize_t
-eeprom_93xx46_read(struct eeprom_93xx46_dev *edev, char *buf,
- unsigned off, size_t count)
+static int eeprom_93xx46_read(void *priv, unsigned int off,
+ void *val, size_t count)
{
- ssize_t ret = 0;
+ struct eeprom_93xx46_dev *edev = priv;
+ char *buf = val;
+ int err = 0;
if (unlikely(off >= edev->size))
return 0;
@@ -84,7 +83,6 @@ eeprom_93xx46_read(struct eeprom_93xx46_dev *edev, char *buf,
u16 cmd_addr = OP_READ << edev->addrlen;
size_t nbytes = count;
int bits;
- int err;
if (edev->addrlen == 7) {
cmd_addr |= off & 0x7f;
@@ -120,21 +118,20 @@ eeprom_93xx46_read(struct eeprom_93xx46_dev *edev, char *buf,
if (err) {
dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n",
nbytes, (int)off, err);
- ret = err;
break;
}
buf += nbytes;
off += nbytes;
count -= nbytes;
- ret += nbytes;
}
if (edev->pdata->finish)
edev->pdata->finish(edev);
mutex_unlock(&edev->lock);
- return ret;
+
+ return err;
}
static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
@@ -230,10 +227,11 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
return ret;
}
-static ssize_t
-eeprom_93xx46_write(struct eeprom_93xx46_dev *edev, const char *buf,
- loff_t off, size_t count)
+static int eeprom_93xx46_write(void *priv, unsigned int off,
+ void *val, size_t count)
{
+ struct eeprom_93xx46_dev *edev = priv;
+ char *buf = val;
int i, ret, step = 1;
if (unlikely(off >= edev->size))
@@ -275,52 +273,9 @@ eeprom_93xx46_write(struct eeprom_93xx46_dev *edev, const char *buf,
/* erase/write disable */
eeprom_93xx46_ew(edev, 0);
- return ret ? : count;
-}
-
-/*
- * Provide a regmap interface, which is registered with the NVMEM
- * framework
-*/
-static int eeprom_93xx46_regmap_read(void *context, const void *reg,
- size_t reg_size, void *val,
- size_t val_size)
-{
- struct eeprom_93xx46_dev *eeprom_93xx46 = context;
- off_t offset = *(u32 *)reg;
- int err;
-
- err = eeprom_93xx46_read(eeprom_93xx46, val, offset, val_size);
- if (err)
- return err;
- return 0;
-}
-
-static int eeprom_93xx46_regmap_write(void *context, const void *data,
- size_t count)
-{
- struct eeprom_93xx46_dev *eeprom_93xx46 = context;
- const char *buf;
- u32 offset;
- size_t len;
- int err;
-
- memcpy(&offset, data, sizeof(offset));
- buf = (const char *)data + sizeof(offset);
- len = count - sizeof(offset);
-
- err = eeprom_93xx46_write(eeprom_93xx46, buf, offset, len);
- if (err)
- return err;
- return 0;
+ return ret;
}
-static const struct regmap_bus eeprom_93xx46_regmap_bus = {
- .read = eeprom_93xx46_regmap_read,
- .write = eeprom_93xx46_regmap_write,
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
-};
-
static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
{
struct eeprom_93xx46_platform_data *pd = edev->pdata;
@@ -480,7 +435,6 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
{
struct eeprom_93xx46_platform_data *pd;
struct eeprom_93xx46_dev *edev;
- struct regmap *regmap;
int err;
if (spi->dev.of_node) {
@@ -515,20 +469,6 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
edev->pdata = pd;
edev->size = 128;
-
- edev->regmap_config.reg_bits = 32;
- edev->regmap_config.val_bits = 8;
- edev->regmap_config.reg_stride = 1;
- edev->regmap_config.max_register = edev->size - 1;
-
- regmap = devm_regmap_init(&spi->dev, &eeprom_93xx46_regmap_bus, edev,
- &edev->regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "regmap init failed\n");
- err = PTR_ERR(regmap);
- goto fail;
- }
-
edev->nvmem_config.name = dev_name(&spi->dev);
edev->nvmem_config.dev = &spi->dev;
edev->nvmem_config.read_only = pd->flags & EE_READONLY;
@@ -536,6 +476,12 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
edev->nvmem_config.owner = THIS_MODULE;
edev->nvmem_config.compat = true;
edev->nvmem_config.base_dev = &spi->dev;
+ edev->nvmem_config.reg_read = eeprom_93xx46_read;
+ edev->nvmem_config.reg_write = eeprom_93xx46_write;
+ edev->nvmem_config.priv = edev;
+ edev->nvmem_config.stride = 4;
+ edev->nvmem_config.word_size = 1;
+ edev->nvmem_config.size = edev->size;
edev->nvmem = nvmem_register(&edev->nvmem_config);
if (IS_ERR(edev->nvmem)) {
--
2.5.0
This patch moves to nvmem support in the driver to use callback
instead of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/mxs-ocotp.c | 79 +++++++++++++----------------------------------
1 file changed, 21 insertions(+), 58 deletions(-)
diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c
index 8ba19bb..3bf962c 100644
--- a/drivers/nvmem/mxs-ocotp.c
+++ b/drivers/nvmem/mxs-ocotp.c
@@ -66,11 +66,10 @@ static int mxs_ocotp_wait(struct mxs_ocotp *otp)
return 0;
}
-static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
- void *val, size_t val_size)
+static int mxs_ocotp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
{
struct mxs_ocotp *otp = context;
- unsigned int offset = *(u32 *)reg;
u32 *buf = val;
int ret;
@@ -94,17 +93,16 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
if (ret)
goto close_banks;
- while (val_size) {
+ while (bytes) {
if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
/* fill up non-data register */
- *buf = 0;
+ *buf++ = 0;
} else {
- *buf = readl(otp->base + offset);
+ *buf++ = readl(otp->base + offset);
}
- buf++;
- val_size--;
- offset += reg_size;
+ bytes -= 4;
+ offset += 4;
}
close_banks:
@@ -117,57 +115,28 @@ disable_clk:
return ret;
}
-static int mxs_ocotp_write(void *context, const void *data, size_t count)
-{
- /* We don't want to support writing */
- return 0;
-}
-
-static bool mxs_ocotp_writeable_reg(struct device *dev, unsigned int reg)
-{
- return false;
-}
-
static struct nvmem_config ocotp_config = {
.name = "mxs-ocotp",
+ .stride = 16,
+ .word_size = 4,
.owner = THIS_MODULE,
};
-static const struct regmap_range imx23_ranges[] = {
- regmap_reg_range(OCOTP_DATA_OFFSET, 0x210),
-};
-
-static const struct regmap_access_table imx23_access = {
- .yes_ranges = imx23_ranges,
- .n_yes_ranges = ARRAY_SIZE(imx23_ranges),
-};
-
-static const struct regmap_range imx28_ranges[] = {
- regmap_reg_range(OCOTP_DATA_OFFSET, 0x290),
-};
-
-static const struct regmap_access_table imx28_access = {
- .yes_ranges = imx28_ranges,
- .n_yes_ranges = ARRAY_SIZE(imx28_ranges),
+struct imx_data {
+ int max_reg;
};
-static struct regmap_bus mxs_ocotp_bus = {
- .read = mxs_ocotp_read,
- .write = mxs_ocotp_write, /* make regmap_init() happy */
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
- .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+static const struct imx_data imx23_data = {
+ .max_reg = 0x210,
};
-static struct regmap_config mxs_ocotp_config = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 16,
- .writeable_reg = mxs_ocotp_writeable_reg,
+static const struct imx_data imx28_data = {
+ .max_reg = 0x290,
};
static const struct of_device_id mxs_ocotp_match[] = {
- { .compatible = "fsl,imx23-ocotp", .data = &imx23_access },
- { .compatible = "fsl,imx28-ocotp", .data = &imx28_access },
+ { .compatible = "fsl,imx23-ocotp", .data = &imx23_data },
+ { .compatible = "fsl,imx28-ocotp", .data = &imx23_data },
{ /* sentinel */},
};
MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
@@ -175,6 +144,7 @@ MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
static int mxs_ocotp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct imx_data *data;
struct mxs_ocotp *otp;
struct resource *res;
const struct of_device_id *match;
@@ -205,17 +175,10 @@ static int mxs_ocotp_probe(struct platform_device *pdev)
return ret;
}
- access = match->data;
- mxs_ocotp_config.rd_table = access;
- mxs_ocotp_config.max_register = access->yes_ranges[0].range_max;
-
- regmap = devm_regmap_init(dev, &mxs_ocotp_bus, otp, &mxs_ocotp_config);
- if (IS_ERR(regmap)) {
- dev_err(dev, "regmap init failed\n");
- ret = PTR_ERR(regmap);
- goto err_clk;
- }
+ data = match->data;
+ ocotp_config.size = data->max_reg;
+ ocotp_config.priv = otp;
ocotp_config.dev = dev;
otp->nvmem = nvmem_register(&ocotp_config);
if (IS_ERR(otp->nvmem)) {
--
2.5.0
This patch moves to nvmem support in the driver to use callback
instead of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/imx-ocotp.c | 55 ++++++++++-------------------------------------
1 file changed, 11 insertions(+), 44 deletions(-)
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c
index d7796eb..75e66ef 100644
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -22,7 +22,6 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
-#include <linux/regmap.h>
#include <linux/slab.h>
struct ocotp_priv {
@@ -31,59 +30,34 @@ struct ocotp_priv {
unsigned int nregs;
};
-static int imx_ocotp_read(void *context, const void *reg, size_t reg_size,
- void *val, size_t val_size)
+static int imx_ocotp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
{
struct ocotp_priv *priv = context;
- unsigned int offset = *(u32 *)reg;
unsigned int count;
+ u32 *buf = val;
int i;
u32 index;
index = offset >> 2;
- count = val_size >> 2;
+ count = bytes >> 2;
if (count > (priv->nregs - index))
count = priv->nregs - index;
- for (i = index; i < (index + count); i++) {
- *(u32 *)val = readl(priv->base + 0x400 + i * 0x10);
- val += 4;
- }
+ for (i = index; i < (index + count); i++)
+ *buf++ = readl(priv->base + 0x400 + i * 0x10);
return 0;
}
-static int imx_ocotp_write(void *context, const void *data, size_t count)
-{
- /* Not implemented */
- return 0;
-}
-
-static struct regmap_bus imx_ocotp_bus = {
- .read = imx_ocotp_read,
- .write = imx_ocotp_write,
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
- .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
-};
-
-static bool imx_ocotp_writeable_reg(struct device *dev, unsigned int reg)
-{
- return false;
-}
-
-static struct regmap_config imx_ocotp_regmap_config = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
- .writeable_reg = imx_ocotp_writeable_reg,
- .name = "imx-ocotp",
-};
-
static struct nvmem_config imx_ocotp_nvmem_config = {
.name = "imx-ocotp",
.read_only = true,
+ .word_size = 4,
+ .stride = 4,
.owner = THIS_MODULE,
+ .reg_read = imx_ocotp_read,
};
static const struct of_device_id imx_ocotp_dt_ids[] = {
@@ -99,7 +73,6 @@ 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 regmap *regmap;
struct ocotp_priv *priv;
struct nvmem_device *nvmem;
@@ -114,15 +87,9 @@ static int imx_ocotp_probe(struct platform_device *pdev)
of_id = of_match_device(imx_ocotp_dt_ids, dev);
priv->nregs = (unsigned int)of_id->data;
- imx_ocotp_regmap_config.max_register = 4 * priv->nregs - 4;
-
- regmap = devm_regmap_init(dev, &imx_ocotp_bus, priv,
- &imx_ocotp_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(dev, "regmap init failed\n");
- return PTR_ERR(regmap);
- }
+ imx_ocotp_nvmem_config.size = 4 * priv->nregs;
imx_ocotp_nvmem_config.dev = dev;
+ imx_ocotp_nvmem_config.priv = priv;
nvmem = nvmem_register(&imx_ocotp_nvmem_config);
if (IS_ERR(nvmem))
return PTR_ERR(nvmem);
--
2.5.0
This patch moves to nvmem support in the driver to use callback
instead of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/lpc18xx_eeprom.c | 94 ++++++++++++------------------------------
1 file changed, 26 insertions(+), 68 deletions(-)
diff --git a/drivers/nvmem/lpc18xx_eeprom.c b/drivers/nvmem/lpc18xx_eeprom.c
index 878fce7..c81ae4c 100644
--- a/drivers/nvmem/lpc18xx_eeprom.c
+++ b/drivers/nvmem/lpc18xx_eeprom.c
@@ -16,7 +16,6 @@
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/platform_device.h>
-#include <linux/regmap.h>
#include <linux/reset.h>
/* Registers */
@@ -51,12 +50,7 @@ struct lpc18xx_eeprom_dev {
struct nvmem_device *nvmem;
unsigned reg_bytes;
unsigned val_bytes;
-};
-
-static struct regmap_config lpc18xx_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
+ int size;
};
static inline void lpc18xx_eeprom_writel(struct lpc18xx_eeprom_dev *eeprom,
@@ -95,30 +89,35 @@ static int lpc18xx_eeprom_busywait_until_prog(struct lpc18xx_eeprom_dev *eeprom)
return -ETIMEDOUT;
}
-static int lpc18xx_eeprom_gather_write(void *context, const void *reg,
- size_t reg_size, const void *val,
- size_t val_size)
+static int lpc18xx_eeprom_gather_write(void *context, unsigned int reg,
+ void *val, size_t bytes)
{
struct lpc18xx_eeprom_dev *eeprom = context;
- unsigned int offset = *(u32 *)reg;
+ unsigned int offset = reg;
int ret;
- if (offset % lpc18xx_regmap_config.reg_stride)
+ /*
+ * The last page contains the EEPROM initialization data and is not
+ * writable.
+ */
+ if ((reg > eeprom->size - LPC18XX_EEPROM_PAGE_SIZE) ||
+ (reg + bytes > eeprom->size - LPC18XX_EEPROM_PAGE_SIZE))
return -EINVAL;
+
lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
LPC18XX_EEPROM_PWRDWN_NO);
/* Wait 100 us while the EEPROM wakes up */
usleep_range(100, 200);
- while (val_size) {
+ while (bytes) {
writel(*(u32 *)val, eeprom->mem_base + offset);
ret = lpc18xx_eeprom_busywait_until_prog(eeprom);
if (ret < 0)
return ret;
- val_size -= eeprom->val_bytes;
+ bytes -= eeprom->val_bytes;
val += eeprom->val_bytes;
offset += eeprom->val_bytes;
}
@@ -129,23 +128,10 @@ static int lpc18xx_eeprom_gather_write(void *context, const void *reg,
return 0;
}
-static int lpc18xx_eeprom_write(void *context, const void *data, size_t count)
+static int lpc18xx_eeprom_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
{
struct lpc18xx_eeprom_dev *eeprom = context;
- unsigned int offset = eeprom->reg_bytes;
-
- if (count <= offset)
- return -EINVAL;
-
- return lpc18xx_eeprom_gather_write(context, data, eeprom->reg_bytes,
- data + offset, count - offset);
-}
-
-static int lpc18xx_eeprom_read(void *context, const void *reg, size_t reg_size,
- void *val, size_t val_size)
-{
- struct lpc18xx_eeprom_dev *eeprom = context;
- unsigned int offset = *(u32 *)reg;
lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
LPC18XX_EEPROM_PWRDWN_NO);
@@ -153,9 +139,9 @@ static int lpc18xx_eeprom_read(void *context, const void *reg, size_t reg_size,
/* Wait 100 us while the EEPROM wakes up */
usleep_range(100, 200);
- while (val_size) {
+ while (bytes) {
*(u32 *)val = readl(eeprom->mem_base + offset);
- val_size -= eeprom->val_bytes;
+ bytes -= eeprom->val_bytes;
val += eeprom->val_bytes;
offset += eeprom->val_bytes;
}
@@ -166,31 +152,13 @@ static int lpc18xx_eeprom_read(void *context, const void *reg, size_t reg_size,
return 0;
}
-static struct regmap_bus lpc18xx_eeprom_bus = {
- .write = lpc18xx_eeprom_write,
- .gather_write = lpc18xx_eeprom_gather_write,
- .read = lpc18xx_eeprom_read,
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
- .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
-};
-
-static bool lpc18xx_eeprom_writeable_reg(struct device *dev, unsigned int reg)
-{
- /*
- * The last page contains the EEPROM initialization data and is not
- * writable.
- */
- return reg <= lpc18xx_regmap_config.max_register -
- LPC18XX_EEPROM_PAGE_SIZE;
-}
-
-static bool lpc18xx_eeprom_readable_reg(struct device *dev, unsigned int reg)
-{
- return reg <= lpc18xx_regmap_config.max_register;
-}
static struct nvmem_config lpc18xx_nvmem_config = {
.name = "lpc18xx-eeprom",
+ .stride = 4,
+ .word_size = 4,
+ .reg_read = lpc18xx_eeprom_read,
+ .reg_write = lpc18xx_eeprom_gather_write,
.owner = THIS_MODULE,
};
@@ -200,7 +168,6 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct reset_control *rst;
unsigned long clk_rate;
- struct regmap *regmap;
struct resource *res;
int ret;
@@ -243,8 +210,8 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev)
goto err_clk;
}
- eeprom->val_bytes = lpc18xx_regmap_config.val_bits / BITS_PER_BYTE;
- eeprom->reg_bytes = lpc18xx_regmap_config.reg_bits / BITS_PER_BYTE;
+ eeprom->val_bytes = 4;
+ eeprom->reg_bytes = 4;
/*
* Clock rate is generated by dividing the system bus clock by the
@@ -264,19 +231,10 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev)
lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN,
LPC18XX_EEPROM_PWRDWN_YES);
- lpc18xx_regmap_config.max_register = resource_size(res) - 1;
- lpc18xx_regmap_config.writeable_reg = lpc18xx_eeprom_writeable_reg;
- lpc18xx_regmap_config.readable_reg = lpc18xx_eeprom_readable_reg;
-
- regmap = devm_regmap_init(dev, &lpc18xx_eeprom_bus, eeprom,
- &lpc18xx_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(dev, "regmap init failed: %ld\n", PTR_ERR(regmap));
- ret = PTR_ERR(regmap);
- goto err_clk;
- }
-
+ eeprom->size = resource_size(res);
+ lpc18xx_nvmem_config.size = resource_size(res);
lpc18xx_nvmem_config.dev = dev;
+ lpc18xx_nvmem_config.priv = eeprom;
eeprom->nvmem = nvmem_register(&lpc18xx_nvmem_config);
if (IS_ERR(eeprom->nvmem)) {
--
2.5.0
This patch moves to nvmem support in the driver to use callback
instead of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/Kconfig | 1 -
drivers/nvmem/mtk-efuse.c | 47 ++++++++++++++++++++++++++++++++---------------
2 files changed, 32 insertions(+), 16 deletions(-)
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 377bc21..c158712 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -48,7 +48,6 @@ config NVMEM_MXS_OCOTP
config MTK_EFUSE
tristate "Mediatek SoCs EFUSE support"
depends on ARCH_MEDIATEK || COMPILE_TEST
- select REGMAP_MMIO
help
This is a driver to access hardware related data like sensor
calibration, HDMI impedance etc.
diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
index 9c49369..32fd572 100644
--- a/drivers/nvmem/mtk-efuse.c
+++ b/drivers/nvmem/mtk-efuse.c
@@ -14,15 +14,35 @@
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/io.h>
#include <linux/nvmem-provider.h>
#include <linux/platform_device.h>
-#include <linux/regmap.h>
-static struct regmap_config mtk_regmap_config = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
-};
+static int mtk_reg_read(void *context,
+ unsigned int reg, void *_val, size_t bytes)
+{
+ void __iomem *base = context;
+ u32 *val = _val;
+ int i = 0, words = bytes / 4;
+
+ while (words--)
+ *val++ = readl(base + reg + (i++ * 4));
+
+ return 0;
+}
+
+static int mtk_reg_write(void *context,
+ unsigned int reg, void *_val, size_t bytes)
+{
+ void __iomem *base = context;
+ u32 *val = _val;
+ int i = 0, words = bytes / 4;
+
+ while (words--)
+ writel(*val++, base + reg + (i++ * 4));
+
+ return 0;
+}
static int mtk_efuse_probe(struct platform_device *pdev)
{
@@ -30,7 +50,6 @@ static int mtk_efuse_probe(struct platform_device *pdev)
struct resource *res;
struct nvmem_device *nvmem;
struct nvmem_config *econfig;
- struct regmap *regmap;
void __iomem *base;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -42,14 +61,12 @@ static int mtk_efuse_probe(struct platform_device *pdev)
if (!econfig)
return -ENOMEM;
- mtk_regmap_config.max_register = resource_size(res) - 1;
-
- regmap = devm_regmap_init_mmio(dev, base, &mtk_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(dev, "regmap init failed\n");
- return PTR_ERR(regmap);
- }
-
+ econfig->stride = 4;
+ econfig->word_size = 4;
+ econfig->reg_read = mtk_reg_read;
+ econfig->reg_write = mtk_reg_write;
+ econfig->size = resource_size(res);
+ econfig->priv = base;
econfig->dev = dev;
econfig->owner = THIS_MODULE;
nvmem = nvmem_register(econfig);
--
2.5.0
This patch moves to nvmem support in the driver to use callback
instead of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/Kconfig | 1 -
drivers/nvmem/sunxi_sid.c | 54 ++++++++---------------------------------------
2 files changed, 9 insertions(+), 46 deletions(-)
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index a87273b..377bc21 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -81,7 +81,6 @@ config ROCKCHIP_EFUSE
config NVMEM_SUNXI_SID
tristate "Allwinner SoCs SID support"
depends on ARCH_SUNXI
- select REGMAP_MMIO
help
This is a driver for the 'security ID' available on various Allwinner
devices.
diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c
index bc88b40..1567ccc 100644
--- a/drivers/nvmem/sunxi_sid.c
+++ b/drivers/nvmem/sunxi_sid.c
@@ -21,13 +21,14 @@
#include <linux/nvmem-provider.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/random.h>
static struct nvmem_config econfig = {
.name = "sunxi-sid",
.read_only = true,
+ .stride = 4,
+ .word_size = 1,
.owner = THIS_MODULE,
};
@@ -51,54 +52,23 @@ static u8 sunxi_sid_read_byte(const struct sunxi_sid *sid,
return sid_key; /* Only return the last byte */
}
-static int sunxi_sid_read(void *context,
- const void *reg, size_t reg_size,
- void *val, size_t val_size)
+static int sunxi_sid_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
{
struct sunxi_sid *sid = context;
- unsigned int offset = *(u32 *)reg;
u8 *buf = val;
- while (val_size) {
- *buf++ = sunxi_sid_read_byte(sid, offset);
- val_size--;
- offset++;
- }
-
- return 0;
-}
+ while (bytes--)
+ *buf++ = sunxi_sid_read_byte(sid, offset++);
-static int sunxi_sid_write(void *context, const void *data, size_t count)
-{
- /* Unimplemented, dummy to keep regmap core happy */
return 0;
}
-static struct regmap_bus sunxi_sid_bus = {
- .read = sunxi_sid_read,
- .write = sunxi_sid_write,
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
- .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
-};
-
-static bool sunxi_sid_writeable_reg(struct device *dev, unsigned int reg)
-{
- return false;
-}
-
-static struct regmap_config sunxi_sid_regmap_config = {
- .reg_bits = 32,
- .val_bits = 8,
- .reg_stride = 1,
- .writeable_reg = sunxi_sid_writeable_reg,
-};
-
static int sunxi_sid_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct nvmem_device *nvmem;
- struct regmap *regmap;
struct sunxi_sid *sid;
int ret, i, size;
char *randomness;
@@ -113,16 +83,10 @@ static int sunxi_sid_probe(struct platform_device *pdev)
return PTR_ERR(sid->base);
size = resource_size(res) - 1;
- sunxi_sid_regmap_config.max_register = size;
-
- regmap = devm_regmap_init(dev, &sunxi_sid_bus, sid,
- &sunxi_sid_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(dev, "regmap init failed\n");
- return PTR_ERR(regmap);
- }
-
+ econfig.size = resource_size(res);
econfig.dev = dev;
+ econfig.reg_read = sunxi_sid_read;
+ econfig.priv = sid;
nvmem = nvmem_register(&econfig);
if (IS_ERR(nvmem))
return PTR_ERR(nvmem);
--
2.5.0
This patch moves to nvmem support in the driver to use callback
instead of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/rockchip-efuse.c | 49 ++++++++----------------------------------
1 file changed, 9 insertions(+), 40 deletions(-)
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index a009795..4d3f391 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -23,7 +23,6 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/regmap.h>
#define EFUSE_A_SHIFT 6
#define EFUSE_A_MASK 0x3ff
@@ -41,17 +40,9 @@ struct rockchip_efuse_chip {
struct clk *clk;
};
-static int rockchip_efuse_write(void *context, const void *data, size_t count)
+static int rockchip_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
{
- /* Nothing TBD, Read-Only */
- return 0;
-}
-
-static int rockchip_efuse_read(void *context,
- const void *reg, size_t reg_size,
- void *val, size_t val_size)
-{
- unsigned int offset = *(u32 *)reg;
struct rockchip_efuse_chip *efuse = context;
u8 *buf = val;
int ret;
@@ -64,12 +55,12 @@ static int rockchip_efuse_read(void *context,
writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + REG_EFUSE_CTRL);
udelay(1);
- while (val_size) {
+ while (bytes--) {
writel(readl(efuse->base + REG_EFUSE_CTRL) &
(~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
efuse->base + REG_EFUSE_CTRL);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
- ((offset & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+ ((offset++ & EFUSE_A_MASK) << EFUSE_A_SHIFT),
efuse->base + REG_EFUSE_CTRL);
udelay(1);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
@@ -79,9 +70,6 @@ static int rockchip_efuse_read(void *context,
writel(readl(efuse->base + REG_EFUSE_CTRL) &
(~EFUSE_STROBE), efuse->base + REG_EFUSE_CTRL);
udelay(1);
-
- val_size -= 1;
- offset += 1;
}
/* Switch to standby mode */
@@ -92,22 +80,11 @@ static int rockchip_efuse_read(void *context,
return 0;
}
-static struct regmap_bus rockchip_efuse_bus = {
- .read = rockchip_efuse_read,
- .write = rockchip_efuse_write,
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
- .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
-};
-
-static struct regmap_config rockchip_efuse_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 1,
- .val_bits = 8,
-};
-
static struct nvmem_config econfig = {
.name = "rockchip-efuse",
.owner = THIS_MODULE,
+ .stride = 1,
+ .word_size = 1,
.read_only = true,
};
@@ -121,7 +98,6 @@ static int rockchip_efuse_probe(struct platform_device *pdev)
{
struct resource *res;
struct nvmem_device *nvmem;
- struct regmap *regmap;
struct rockchip_efuse_chip *efuse;
efuse = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_efuse_chip),
@@ -139,16 +115,9 @@ static int rockchip_efuse_probe(struct platform_device *pdev)
return PTR_ERR(efuse->clk);
efuse->dev = &pdev->dev;
-
- rockchip_efuse_regmap_config.max_register = resource_size(res) - 1;
-
- regmap = devm_regmap_init(efuse->dev, &rockchip_efuse_bus,
- efuse, &rockchip_efuse_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(efuse->dev, "regmap init failed\n");
- return PTR_ERR(regmap);
- }
-
+ econfig.size = resource_size(res);
+ econfig.reg_read = rockchip_efuse_read;
+ econfig.priv = efuse;
econfig.dev = efuse->dev;
nvmem = nvmem_register(&econfig);
if (IS_ERR(nvmem))
--
2.5.0
This patch moves to nvmem support in the driver to use callback instead
of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/misc/eeprom/Kconfig | 1 -
drivers/misc/eeprom/at24.c | 103 ++++++++++----------------------------------
2 files changed, 22 insertions(+), 82 deletions(-)
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index cfc493c..2d70464 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -3,7 +3,6 @@ menu "EEPROM support"
config EEPROM_AT24
tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
depends on I2C && SYSFS
- select REGMAP
select NVMEM
help
Enable this driver to get read/write support to most I2C EEPROMs
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 089d694..de550a6 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -23,7 +23,6 @@
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/nvmem-provider.h>
-#include <linux/regmap.h>
#include <linux/platform_data/at24.h>
/*
@@ -69,7 +68,6 @@ struct at24_data {
unsigned write_max;
unsigned num_addresses;
- struct regmap_config regmap_config;
struct nvmem_config nvmem_config;
struct nvmem_device *nvmem;
@@ -252,10 +250,10 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
return -ETIMEDOUT;
}
-static ssize_t at24_read(struct at24_data *at24,
- char *buf, loff_t off, size_t count)
+static int at24_read(void *priv, unsigned int off, void *val, size_t count)
{
- ssize_t retval = 0;
+ struct at24_data *at24 = priv;
+ char *buf = val;
if (unlikely(!count))
return count;
@@ -267,23 +265,21 @@ static ssize_t at24_read(struct at24_data *at24,
mutex_lock(&at24->lock);
while (count) {
- ssize_t status;
+ int status;
status = at24_eeprom_read(at24, buf, off, count);
- if (status <= 0) {
- if (retval == 0)
- retval = status;
- break;
+ if (status < 0) {
+ mutex_unlock(&at24->lock);
+ return status;
}
buf += status;
off += status;
count -= status;
- retval += status;
}
mutex_unlock(&at24->lock);
- return retval;
+ return 0;
}
/*
@@ -372,13 +368,13 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
return -ETIMEDOUT;
}
-static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
- size_t count)
+static int at24_write(void *priv, unsigned int off, void *val, size_t count)
{
- ssize_t retval = 0;
+ struct at24_data *at24 = priv;
+ char *buf = val;
if (unlikely(!count))
- return count;
+ return -EINVAL;
/*
* Write data to chip, protecting against concurrent updates
@@ -387,70 +383,23 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
mutex_lock(&at24->lock);
while (count) {
- ssize_t status;
+ int status;
status = at24_eeprom_write(at24, buf, off, count);
- if (status <= 0) {
- if (retval == 0)
- retval = status;
- break;
+ if (status < 0) {
+ mutex_unlock(&at24->lock);
+ return status;
}
buf += status;
off += status;
count -= status;
- retval += status;
}
mutex_unlock(&at24->lock);
- return retval;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Provide a regmap interface, which is registered with the NVMEM
- * framework
-*/
-static int at24_regmap_read(void *context, const void *reg, size_t reg_size,
- void *val, size_t val_size)
-{
- struct at24_data *at24 = context;
- off_t offset = *(u32 *)reg;
- int err;
-
- err = at24_read(at24, val, offset, val_size);
- if (err)
- return err;
- return 0;
-}
-
-static int at24_regmap_write(void *context, const void *data, size_t count)
-{
- struct at24_data *at24 = context;
- const char *buf;
- u32 offset;
- size_t len;
- int err;
-
- memcpy(&offset, data, sizeof(offset));
- buf = (const char *)data + sizeof(offset);
- len = count - sizeof(offset);
-
- err = at24_write(at24, buf, offset, len);
- if (err)
- return err;
return 0;
}
-static const struct regmap_bus at24_regmap_bus = {
- .read = at24_regmap_read,
- .write = at24_regmap_write,
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
-};
-
-/*-------------------------------------------------------------------------*/
-
#ifdef CONFIG_OF
static void at24_get_ofdata(struct i2c_client *client,
struct at24_platform_data *chip)
@@ -482,7 +431,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct at24_data *at24;
int err;
unsigned i, num_addresses;
- struct regmap *regmap;
if (client->dev.platform_data) {
chip = *(struct at24_platform_data *)client->dev.platform_data;
@@ -612,19 +560,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
}
- at24->regmap_config.reg_bits = 32;
- at24->regmap_config.val_bits = 8;
- at24->regmap_config.reg_stride = 1;
- at24->regmap_config.max_register = chip.byte_len - 1;
-
- regmap = devm_regmap_init(&client->dev, &at24_regmap_bus, at24,
- &at24->regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&client->dev, "regmap init failed\n");
- err = PTR_ERR(regmap);
- goto err_clients;
- }
-
at24->nvmem_config.name = dev_name(&client->dev);
at24->nvmem_config.dev = &client->dev;
at24->nvmem_config.read_only = !writable;
@@ -632,6 +567,12 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
at24->nvmem_config.owner = THIS_MODULE;
at24->nvmem_config.compat = true;
at24->nvmem_config.base_dev = &client->dev;
+ at24->nvmem_config.reg_read = at24_read;
+ at24->nvmem_config.reg_write = at24_write;
+ at24->nvmem_config.priv = at24;
+ at24->nvmem_config.stride = 4;
+ at24->nvmem_config.word_size = 1;
+ at24->nvmem_config.size = chip.byte_len;
at24->nvmem = nvmem_register(&at24->nvmem_config);
--
2.5.0
This patch moves to nvmem support in the driver to use callback
instead of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/vf610-ocotp.c | 44 ++++++++++----------------------------------
1 file changed, 10 insertions(+), 34 deletions(-)
diff --git a/drivers/nvmem/vf610-ocotp.c b/drivers/nvmem/vf610-ocotp.c
index 8641319..72e4faa 100644
--- a/drivers/nvmem/vf610-ocotp.c
+++ b/drivers/nvmem/vf610-ocotp.c
@@ -25,7 +25,6 @@
#include <linux/nvmem-provider.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/regmap.h>
#include <linux/slab.h>
/* OCOTP Register Offsets */
@@ -152,23 +151,16 @@ static int vf610_get_fuse_address(int base_addr_offset)
return -EINVAL;
}
-static int vf610_ocotp_write(void *context, const void *data, size_t count)
-{
- return 0;
-}
-
-static int vf610_ocotp_read(void *context,
- const void *off, size_t reg_size,
- void *val, size_t val_size)
+static int vf610_ocotp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
{
struct vf610_ocotp *ocotp = context;
void __iomem *base = ocotp->base;
- unsigned int offset = *(u32 *)off;
u32 reg, *buf = val;
int fuse_addr;
int ret;
- while (val_size > 0) {
+ while (bytes > 0) {
fuse_addr = vf610_get_fuse_address(offset);
if (fuse_addr > 0) {
writel(ocotp->timing, base + OCOTP_TIMING);
@@ -205,29 +197,19 @@ static int vf610_ocotp_read(void *context,
}
buf++;
- val_size--;
- offset += reg_size;
+ bytes -= 4;
+ offset += 4;
}
return 0;
}
-static struct regmap_bus vf610_ocotp_bus = {
- .read = vf610_ocotp_read,
- .write = vf610_ocotp_write,
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
- .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
-};
-
-static struct regmap_config ocotp_regmap_config = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
-};
-
static struct nvmem_config ocotp_config = {
.name = "ocotp",
.owner = THIS_MODULE,
+ .stride = 4,
+ .word_size = 4,
+ .reg_read = vf610_ocotp_read,
};
static const struct of_device_id ocotp_of_match[] = {
@@ -247,7 +229,6 @@ static int vf610_ocotp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
- struct regmap *regmap;
struct vf610_ocotp *ocotp_dev;
ocotp_dev = devm_kzalloc(&pdev->dev,
@@ -267,13 +248,8 @@ static int vf610_ocotp_probe(struct platform_device *pdev)
return PTR_ERR(ocotp_dev->clk);
}
- ocotp_regmap_config.max_register = resource_size(res);
- regmap = devm_regmap_init(dev,
- &vf610_ocotp_bus, ocotp_dev, &ocotp_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(dev, "regmap init failed\n");
- return PTR_ERR(regmap);
- }
+ ocotp_config.size = resource_size(res);
+ ocotp_config.priv = ocotp_dev;
ocotp_config.dev = dev;
ocotp_dev->nvmem = nvmem_register(&ocotp_config);
--
2.5.0
This patch moves to nvmem support in the driver to use callback instead
of regmap.
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/misc/eeprom/Kconfig | 1 -
drivers/misc/eeprom/at25.c | 89 ++++++++++-----------------------------------
2 files changed, 19 insertions(+), 71 deletions(-)
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 2d70464..c4e41c2 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -31,7 +31,6 @@ config EEPROM_AT24
config EEPROM_AT25
tristate "SPI EEPROMs from most vendors"
depends on SPI && SYSFS
- select REGMAP
select NVMEM
help
Enable this driver to get read/write support to most SPI EEPROMs,
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index fa36a6e..a2858b3 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -17,7 +17,6 @@
#include <linux/sched.h>
#include <linux/nvmem-provider.h>
-#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/spi/eeprom.h>
#include <linux/property.h>
@@ -34,7 +33,6 @@ struct at25_data {
struct mutex lock;
struct spi_eeprom chip;
unsigned addrlen;
- struct regmap_config regmap_config;
struct nvmem_config nvmem_config;
struct nvmem_device *nvmem;
};
@@ -65,14 +63,11 @@ struct at25_data {
#define io_limit PAGE_SIZE /* bytes */
-static ssize_t
-at25_ee_read(
- struct at25_data *at25,
- char *buf,
- unsigned offset,
- size_t count
-)
+static int at25_ee_read(void *priv, unsigned int offset,
+ void *val, size_t count)
{
+ struct at25_data *at25 = priv;
+ char *buf = val;
u8 command[EE_MAXADDRLEN + 1];
u8 *cp;
ssize_t status;
@@ -81,11 +76,11 @@ at25_ee_read(
u8 instr;
if (unlikely(offset >= at25->chip.byte_len))
- return 0;
+ return -EINVAL;
if ((offset + count) > at25->chip.byte_len)
count = at25->chip.byte_len - offset;
if (unlikely(!count))
- return count;
+ return -EINVAL;
cp = command;
@@ -131,28 +126,14 @@ at25_ee_read(
count, offset, (int) status);
mutex_unlock(&at25->lock);
- return status ? status : count;
+ return status;
}
-static int at25_regmap_read(void *context, const void *reg, size_t reg_size,
- void *val, size_t val_size)
+static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)
{
- struct at25_data *at25 = context;
- off_t offset = *(u32 *)reg;
- int err;
-
- err = at25_ee_read(at25, val, offset, val_size);
- if (err)
- return err;
- return 0;
-}
-
-static ssize_t
-at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
- size_t count)
-{
- ssize_t status = 0;
- unsigned written = 0;
+ struct at25_data *at25 = priv;
+ const char *buf = val;
+ int status = 0;
unsigned buf_size;
u8 *bounce;
@@ -161,7 +142,7 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
if ((off + count) > at25->chip.byte_len)
count = at25->chip.byte_len - off;
if (unlikely(!count))
- return count;
+ return -EINVAL;
/* Temp buffer starts with command and address */
buf_size = at25->chip.page_size;
@@ -256,40 +237,15 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
off += segment;
buf += segment;
count -= segment;
- written += segment;
} while (count > 0);
mutex_unlock(&at25->lock);
kfree(bounce);
- return written ? written : status;
+ return status;
}
-static int at25_regmap_write(void *context, const void *data, size_t count)
-{
- struct at25_data *at25 = context;
- const char *buf;
- u32 offset;
- size_t len;
- int err;
-
- memcpy(&offset, data, sizeof(offset));
- buf = (const char *)data + sizeof(offset);
- len = count - sizeof(offset);
-
- err = at25_ee_write(at25, buf, offset, len);
- if (err)
- return err;
- return 0;
-}
-
-static const struct regmap_bus at25_regmap_bus = {
- .read = at25_regmap_read,
- .write = at25_regmap_write,
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
-};
-
/*-------------------------------------------------------------------------*/
static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
@@ -349,7 +305,6 @@ static int at25_probe(struct spi_device *spi)
{
struct at25_data *at25 = NULL;
struct spi_eeprom chip;
- struct regmap *regmap;
int err;
int sr;
int addrlen;
@@ -394,18 +349,6 @@ static int at25_probe(struct spi_device *spi)
spi_set_drvdata(spi, at25);
at25->addrlen = addrlen;
- at25->regmap_config.reg_bits = 32;
- at25->regmap_config.val_bits = 8;
- at25->regmap_config.reg_stride = 1;
- at25->regmap_config.max_register = chip.byte_len - 1;
-
- regmap = devm_regmap_init(&spi->dev, &at25_regmap_bus, at25,
- &at25->regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "regmap init failed\n");
- return PTR_ERR(regmap);
- }
-
at25->nvmem_config.name = dev_name(&spi->dev);
at25->nvmem_config.dev = &spi->dev;
at25->nvmem_config.read_only = chip.flags & EE_READONLY;
@@ -413,6 +356,12 @@ static int at25_probe(struct spi_device *spi)
at25->nvmem_config.owner = THIS_MODULE;
at25->nvmem_config.compat = true;
at25->nvmem_config.base_dev = &spi->dev;
+ at25->nvmem_config.reg_read = at25_ee_read;
+ at25->nvmem_config.reg_write = at25_ee_write;
+ at25->nvmem_config.priv = at25;
+ at25->nvmem_config.stride = 4;
+ at25->nvmem_config.word_size = 1;
+ at25->nvmem_config.size = chip.byte_len;
at25->nvmem = nvmem_register(&at25->nvmem_config);
if (IS_ERR(at25->nvmem))
--
2.5.0
Hello Srinivas,
On 16-04-24 20:28:09, Srinivas Kandagatla wrote:
> This patch moves to nvmem support in the driver to use callback
> instead of regmap.
Minor nit, it says "vif610-octop" it should have been vf610-ocotp.
For what it's worth, I tested this on Colibri Vybrid VF61 for a while and
all seems to work fine.
So with the testing for vf610-ocotp driver other than the minor nit
Acked-by: Sanchayan Maity <[email protected]>
Regards,
Sanchayan.
>
> Signed-off-by: Srinivas Kandagatla <[email protected]>
> ---
> drivers/nvmem/vf610-ocotp.c | 44 ++++++++++----------------------------------
> 1 file changed, 10 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/nvmem/vf610-ocotp.c b/drivers/nvmem/vf610-ocotp.c
> index 8641319..72e4faa 100644
> --- a/drivers/nvmem/vf610-ocotp.c
> +++ b/drivers/nvmem/vf610-ocotp.c
> @@ -25,7 +25,6 @@
> #include <linux/nvmem-provider.h>
> #include <linux/of.h>
> #include <linux/platform_device.h>
> -#include <linux/regmap.h>
> #include <linux/slab.h>
>
> /* OCOTP Register Offsets */
> @@ -152,23 +151,16 @@ static int vf610_get_fuse_address(int base_addr_offset)
> return -EINVAL;
> }
>
> -static int vf610_ocotp_write(void *context, const void *data, size_t count)
> -{
> - return 0;
> -}
> -
> -static int vf610_ocotp_read(void *context,
> - const void *off, size_t reg_size,
> - void *val, size_t val_size)
> +static int vf610_ocotp_read(void *context, unsigned int offset,
> + void *val, size_t bytes)
> {
> struct vf610_ocotp *ocotp = context;
> void __iomem *base = ocotp->base;
> - unsigned int offset = *(u32 *)off;
> u32 reg, *buf = val;
> int fuse_addr;
> int ret;
>
> - while (val_size > 0) {
> + while (bytes > 0) {
> fuse_addr = vf610_get_fuse_address(offset);
> if (fuse_addr > 0) {
> writel(ocotp->timing, base + OCOTP_TIMING);
> @@ -205,29 +197,19 @@ static int vf610_ocotp_read(void *context,
> }
>
> buf++;
> - val_size--;
> - offset += reg_size;
> + bytes -= 4;
> + offset += 4;
> }
>
> return 0;
> }
>
> -static struct regmap_bus vf610_ocotp_bus = {
> - .read = vf610_ocotp_read,
> - .write = vf610_ocotp_write,
> - .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
> - .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
> -};
> -
> -static struct regmap_config ocotp_regmap_config = {
> - .reg_bits = 32,
> - .val_bits = 32,
> - .reg_stride = 4,
> -};
> -
> static struct nvmem_config ocotp_config = {
> .name = "ocotp",
> .owner = THIS_MODULE,
> + .stride = 4,
> + .word_size = 4,
> + .reg_read = vf610_ocotp_read,
> };
>
> static const struct of_device_id ocotp_of_match[] = {
> @@ -247,7 +229,6 @@ static int vf610_ocotp_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> struct resource *res;
> - struct regmap *regmap;
> struct vf610_ocotp *ocotp_dev;
>
> ocotp_dev = devm_kzalloc(&pdev->dev,
> @@ -267,13 +248,8 @@ static int vf610_ocotp_probe(struct platform_device *pdev)
> return PTR_ERR(ocotp_dev->clk);
> }
>
> - ocotp_regmap_config.max_register = resource_size(res);
> - regmap = devm_regmap_init(dev,
> - &vf610_ocotp_bus, ocotp_dev, &ocotp_regmap_config);
> - if (IS_ERR(regmap)) {
> - dev_err(dev, "regmap init failed\n");
> - return PTR_ERR(regmap);
> - }
> + ocotp_config.size = resource_size(res);
> + ocotp_config.priv = ocotp_dev;
> ocotp_config.dev = dev;
>
> ocotp_dev->nvmem = nvmem_register(&ocotp_config);
> --
> 2.5.0
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Hi Srinivas,
On Sun, 2016-04-24 at 20:28 +0100, Srinivas Kandagatla wrote:
> This patch moves to nvmem support in the driver to use callback
> instead of regmap.
>
> Signed-off-by: Srinivas Kandagatla <[email protected]>
> ---
Thanks for the patch. It works on our platform. This driver doesn't
support "efuse write". I will send another patch for fixing this.
Acked-by: Andrew-CT Chen <[email protected]>
Andrew
> drivers/nvmem/Kconfig | 1 -
> drivers/nvmem/mtk-efuse.c | 47 ++++++++++++++++++++++++++++++++---------------
> 2 files changed, 32 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
> index 377bc21..c158712 100644
> --- a/drivers/nvmem/Kconfig
> +++ b/drivers/nvmem/Kconfig
> @@ -48,7 +48,6 @@ config NVMEM_MXS_OCOTP
> config MTK_EFUSE
> tristate "Mediatek SoCs EFUSE support"
> depends on ARCH_MEDIATEK || COMPILE_TEST
> - select REGMAP_MMIO
> help
> This is a driver to access hardware related data like sensor
> calibration, HDMI impedance etc.
> diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
> index 9c49369..32fd572 100644
> --- a/drivers/nvmem/mtk-efuse.c
> +++ b/drivers/nvmem/mtk-efuse.c
> @@ -14,15 +14,35 @@
>
> #include <linux/device.h>
> #include <linux/module.h>
> +#include <linux/io.h>
> #include <linux/nvmem-provider.h>
> #include <linux/platform_device.h>
> -#include <linux/regmap.h>
>
> -static struct regmap_config mtk_regmap_config = {
> - .reg_bits = 32,
> - .val_bits = 32,
> - .reg_stride = 4,
> -};
> +static int mtk_reg_read(void *context,
> + unsigned int reg, void *_val, size_t bytes)
> +{
> + void __iomem *base = context;
> + u32 *val = _val;
> + int i = 0, words = bytes / 4;
> +
> + while (words--)
> + *val++ = readl(base + reg + (i++ * 4));
> +
> + return 0;
> +}
> +
> +static int mtk_reg_write(void *context,
> + unsigned int reg, void *_val, size_t bytes)
> +{
> + void __iomem *base = context;
> + u32 *val = _val;
> + int i = 0, words = bytes / 4;
> +
> + while (words--)
> + writel(*val++, base + reg + (i++ * 4));
> +
> + return 0;
> +}
>
> static int mtk_efuse_probe(struct platform_device *pdev)
> {
> @@ -30,7 +50,6 @@ static int mtk_efuse_probe(struct platform_device *pdev)
> struct resource *res;
> struct nvmem_device *nvmem;
> struct nvmem_config *econfig;
> - struct regmap *regmap;
> void __iomem *base;
>
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -42,14 +61,12 @@ static int mtk_efuse_probe(struct platform_device *pdev)
> if (!econfig)
> return -ENOMEM;
>
> - mtk_regmap_config.max_register = resource_size(res) - 1;
> -
> - regmap = devm_regmap_init_mmio(dev, base, &mtk_regmap_config);
> - if (IS_ERR(regmap)) {
> - dev_err(dev, "regmap init failed\n");
> - return PTR_ERR(regmap);
> - }
> -
> + econfig->stride = 4;
> + econfig->word_size = 4;
> + econfig->reg_read = mtk_reg_read;
> + econfig->reg_write = mtk_reg_write;
> + econfig->size = resource_size(res);
> + econfig->priv = base;
> econfig->dev = dev;
> econfig->owner = THIS_MODULE;
> nvmem = nvmem_register(econfig);
Hi Srinivas,
Am 24.04.2016 um 21:28 schrieb Srinivas Kandagatla:
> This patch moves to nvmem support in the driver to use callback
> instead of regmap.
>
> Signed-off-by: Srinivas Kandagatla <[email protected]>
> ---
> drivers/nvmem/mxs-ocotp.c | 79 +++++++++++++----------------------------------
> 1 file changed, 21 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c
> index 8ba19bb..3bf962c 100644
> --- a/drivers/nvmem/mxs-ocotp.c
> +++ b/drivers/nvmem/mxs-ocotp.c
the include of regmap.h should also be removed.
> @@ -66,11 +66,10 @@ static int mxs_ocotp_wait(struct mxs_ocotp *otp)
> return 0;
> }
>
> -static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
> - void *val, size_t val_size)
> +static int mxs_ocotp_read(void *context, unsigned int offset,
> + void *val, size_t bytes)
> {
> struct mxs_ocotp *otp = context;
> - unsigned int offset = *(u32 *)reg;
> u32 *buf = val;
> int ret;
>
> @@ -94,17 +93,16 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
> if (ret)
> goto close_banks;
>
> - while (val_size) {
> + while (bytes) {
> if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
> /* fill up non-data register */
> - *buf = 0;
> + *buf++ = 0;
> } else {
> - *buf = readl(otp->base + offset);
> + *buf++ = readl(otp->base + offset);
> }
>
> - buf++;
> - val_size--;
> - offset += reg_size;
> + bytes -= 4;
> + offset += 4;
This change would also fix the buffer overflow but Stanislav's patch
should be applied before to get the fix in stable.
> }
>
> close_banks:
> @@ -117,57 +115,28 @@ disable_clk:
> return ret;
> }
>
> -static int mxs_ocotp_write(void *context, const void *data, size_t count)
> -{
> - /* We don't want to support writing */
> - return 0;
> -}
> -
> -static bool mxs_ocotp_writeable_reg(struct device *dev, unsigned int reg)
> -{
> - return false;
> -}
> -
> static struct nvmem_config ocotp_config = {
> .name = "mxs-ocotp",
> + .stride = 16,
> + .word_size = 4,
> .owner = THIS_MODULE,
.reg_read = mxs_ocotp_read,
> };
>
> -static const struct regmap_range imx23_ranges[] = {
> - regmap_reg_range(OCOTP_DATA_OFFSET, 0x210),
> -};
> -
> -static const struct regmap_access_table imx23_access = {
> - .yes_ranges = imx23_ranges,
> - .n_yes_ranges = ARRAY_SIZE(imx23_ranges),
> -};
> -
> -static const struct regmap_range imx28_ranges[] = {
> - regmap_reg_range(OCOTP_DATA_OFFSET, 0x290),
> -};
> -
> -static const struct regmap_access_table imx28_access = {
> - .yes_ranges = imx28_ranges,
> - .n_yes_ranges = ARRAY_SIZE(imx28_ranges),
> +struct imx_data {
struct mxs_data
These chips are named imx2x but the platform is mxs. Please don't ask why.
> + int max_reg;
Since nvmem_config uses "size" instead of "max_reg" we better use "size"
here, too. This avoids confusion and potential issues see below.
> };
>
> -static struct regmap_bus mxs_ocotp_bus = {
> - .read = mxs_ocotp_read,
> - .write = mxs_ocotp_write, /* make regmap_init() happy */
> - .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
> - .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
> +static const struct imx_data imx23_data = {
static const struct mxs_data imx23_data
> + .max_reg = 0x210,
.size = 0x220,
> };
>
> -static struct regmap_config mxs_ocotp_config = {
> - .reg_bits = 32,
> - .val_bits = 32,
> - .reg_stride = 16,
> - .writeable_reg = mxs_ocotp_writeable_reg,
> +static const struct imx_data imx28_data = {
static const struct mxs_data imx28_data
> + .max_reg = 0x290,
.size = 0x2a0,
> };
>
> static const struct of_device_id mxs_ocotp_match[] = {
> - { .compatible = "fsl,imx23-ocotp", .data = &imx23_access },
> - { .compatible = "fsl,imx28-ocotp", .data = &imx28_access },
> + { .compatible = "fsl,imx23-ocotp", .data = &imx23_data },
> + { .compatible = "fsl,imx28-ocotp", .data = &imx23_data },
.compatible = "fsl,imx28-ocotp", .data = &imx28_data
> { /* sentinel */},
> };
> MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
> @@ -175,6 +144,7 @@ MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
> static int mxs_ocotp_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> + struct imx_data *data;
const struct mxs_data *data
> struct mxs_ocotp *otp;
> struct resource *res;
> const struct of_device_id *match;
> @@ -205,17 +175,10 @@ static int mxs_ocotp_probe(struct platform_device *pdev)
> return ret;
> }
>
> - access = match->data;
> - mxs_ocotp_config.rd_table = access;
> - mxs_ocotp_config.max_register = access->yes_ranges[0].range_max;
> -
> - regmap = devm_regmap_init(dev, &mxs_ocotp_bus, otp, &mxs_ocotp_config);
> - if (IS_ERR(regmap)) {
> - dev_err(dev, "regmap init failed\n");
> - ret = PTR_ERR(regmap);
> - goto err_clk;
> - }
> + data = match->data;
>
> + ocotp_config.size = data->max_reg;
data->size
Regards
Stefan
> + ocotp_config.priv = otp;
> ocotp_config.dev = dev;
> otp->nvmem = nvmem_register(&ocotp_config);
> if (IS_ERR(otp->nvmem)) {