Commit 795ddd18 authored by Srinivas Kandagatla's avatar Srinivas Kandagatla Committed by Greg Kroah-Hartman

nvmem: core: remove regmap dependency

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: default avatarRajendra Nayak <rjendra@qti.qualcomm.com>
Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 326071b3
menuconfig NVMEM menuconfig NVMEM
tristate "NVMEM Support" tristate "NVMEM Support"
select REGMAP
help help
Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES... Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES...
......
...@@ -23,12 +23,10 @@ ...@@ -23,12 +23,10 @@
#include <linux/nvmem-consumer.h> #include <linux/nvmem-consumer.h>
#include <linux/nvmem-provider.h> #include <linux/nvmem-provider.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
struct nvmem_device { struct nvmem_device {
const char *name; const char *name;
struct regmap *regmap;
struct module *owner; struct module *owner;
struct device dev; struct device dev;
int stride; int stride;
...@@ -41,6 +39,9 @@ struct nvmem_device { ...@@ -41,6 +39,9 @@ struct nvmem_device {
int flags; int flags;
struct bin_attribute eeprom; struct bin_attribute eeprom;
struct device *base_dev; struct device *base_dev;
nvmem_reg_read_t reg_read;
nvmem_reg_write_t reg_write;
void *priv;
}; };
#define FLAG_COMPAT BIT(0) #define FLAG_COMPAT BIT(0)
...@@ -66,6 +67,23 @@ static struct lock_class_key eeprom_lock_key; ...@@ -66,6 +67,23 @@ static struct lock_class_key eeprom_lock_key;
#endif #endif
#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev) #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, static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, struct bin_attribute *attr,
...@@ -93,7 +111,7 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj, ...@@ -93,7 +111,7 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
count = round_down(count, nvmem->word_size); 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)) if (IS_ERR_VALUE(rc))
return rc; return rc;
...@@ -127,7 +145,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj, ...@@ -127,7 +145,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
count = round_down(count, nvmem->word_size); 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)) if (IS_ERR_VALUE(rc))
return rc; return rc;
...@@ -421,18 +439,11 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) ...@@ -421,18 +439,11 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
{ {
struct nvmem_device *nvmem; struct nvmem_device *nvmem;
struct device_node *np; struct device_node *np;
struct regmap *rm;
int rval; int rval;
if (!config->dev) if (!config->dev)
return ERR_PTR(-EINVAL); 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); nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
if (!nvmem) if (!nvmem)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -444,14 +455,16 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) ...@@ -444,14 +455,16 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
} }
nvmem->id = rval; nvmem->id = rval;
nvmem->regmap = rm;
nvmem->owner = config->owner; nvmem->owner = config->owner;
nvmem->stride = regmap_get_reg_stride(rm); nvmem->stride = config->stride;
nvmem->word_size = regmap_get_val_bytes(rm); nvmem->word_size = config->word_size;
nvmem->size = regmap_get_max_register(rm) + nvmem->stride; nvmem->size = config->size;
nvmem->dev.type = &nvmem_provider_type; nvmem->dev.type = &nvmem_provider_type;
nvmem->dev.bus = &nvmem_bus_type; nvmem->dev.bus = &nvmem_bus_type;
nvmem->dev.parent = config->dev; 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; np = config->dev->of_node;
nvmem->dev.of_node = np; nvmem->dev.of_node = np;
dev_set_name(&nvmem->dev, "%s%d", dev_set_name(&nvmem->dev, "%s%d",
...@@ -948,7 +961,7 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem, ...@@ -948,7 +961,7 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
{ {
int rc; 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)) if (IS_ERR_VALUE(rc))
return rc; return rc;
...@@ -977,7 +990,7 @@ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len) ...@@ -977,7 +990,7 @@ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
u8 *buf; u8 *buf;
int rc; int rc;
if (!nvmem || !nvmem->regmap) if (!nvmem)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
buf = kzalloc(cell->bytes, GFP_KERNEL); buf = kzalloc(cell->bytes, GFP_KERNEL);
...@@ -1014,7 +1027,7 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell, ...@@ -1014,7 +1027,7 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
*b <<= bit_offset; *b <<= bit_offset;
/* setup the first byte with lsb bits from nvmem */ /* 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; *b++ |= GENMASK(bit_offset - 1, 0) & v;
/* setup rest of the byte if any */ /* setup rest of the byte if any */
...@@ -1031,7 +1044,7 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell, ...@@ -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 it's not end on byte boundary */
if ((nbits + bit_offset) % BITS_PER_BYTE) { if ((nbits + bit_offset) % BITS_PER_BYTE) {
/* setup the last byte with msb bits from nvmem */ /* 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); cell->offset + cell->bytes - 1, &v, 1);
*p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v; *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) ...@@ -1054,7 +1067,7 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
struct nvmem_device *nvmem = cell->nvmem; struct nvmem_device *nvmem = cell->nvmem;
int rc; int rc;
if (!nvmem || !nvmem->regmap || nvmem->read_only || if (!nvmem || nvmem->read_only ||
(cell->bit_offset == 0 && len != cell->bytes)) (cell->bit_offset == 0 && len != cell->bytes))
return -EINVAL; return -EINVAL;
...@@ -1064,7 +1077,7 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len) ...@@ -1064,7 +1077,7 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
return PTR_ERR(buf); 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 */ /* free the tmp buffer */
if (cell->bit_offset || cell->nbits) if (cell->bit_offset || cell->nbits)
...@@ -1094,7 +1107,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem, ...@@ -1094,7 +1107,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
int rc; int rc;
ssize_t len; ssize_t len;
if (!nvmem || !nvmem->regmap) if (!nvmem)
return -EINVAL; return -EINVAL;
rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell); rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
...@@ -1124,7 +1137,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem, ...@@ -1124,7 +1137,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
struct nvmem_cell cell; struct nvmem_cell cell;
int rc; int rc;
if (!nvmem || !nvmem->regmap) if (!nvmem)
return -EINVAL; return -EINVAL;
rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell); rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
...@@ -1152,10 +1165,10 @@ int nvmem_device_read(struct nvmem_device *nvmem, ...@@ -1152,10 +1165,10 @@ int nvmem_device_read(struct nvmem_device *nvmem,
{ {
int rc; int rc;
if (!nvmem || !nvmem->regmap) if (!nvmem)
return -EINVAL; return -EINVAL;
rc = regmap_raw_read(nvmem->regmap, offset, buf, bytes); rc = nvmem_reg_read(nvmem, offset, buf, bytes);
if (IS_ERR_VALUE(rc)) if (IS_ERR_VALUE(rc))
return rc; return rc;
...@@ -1180,10 +1193,10 @@ int nvmem_device_write(struct nvmem_device *nvmem, ...@@ -1180,10 +1193,10 @@ int nvmem_device_write(struct nvmem_device *nvmem,
{ {
int rc; int rc;
if (!nvmem || !nvmem->regmap) if (!nvmem)
return -EINVAL; return -EINVAL;
rc = regmap_raw_write(nvmem->regmap, offset, buf, bytes); rc = nvmem_reg_write(nvmem, offset, buf, bytes);
if (IS_ERR_VALUE(rc)) if (IS_ERR_VALUE(rc))
return rc; return rc;
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
struct nvmem_device; struct nvmem_device;
struct nvmem_cell_info; 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 nvmem_config {
struct device *dev; struct device *dev;
...@@ -24,6 +28,12 @@ struct nvmem_config { ...@@ -24,6 +28,12 @@ struct nvmem_config {
int ncells; int ncells;
bool read_only; bool read_only;
bool root_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 */ /* To be only used by old driver/misc/eeprom drivers */
bool compat; bool compat;
struct device *base_dev; struct device *base_dev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment