aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2016-04-24 15:28:05 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-05-01 17:01:00 -0400
commit795ddd18d38f9762fbfefceab9aa16caef0cf431 (patch)
tree5faf142ac6c296188b0ad15068ae7a1a6eeef4ce
parent326071b3c985683f8a18417bed3ea2ab930a7ba1 (diff)
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: Rajendra Nayak <rjendra@qti.qualcomm.com> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/nvmem/Kconfig1
-rw-r--r--drivers/nvmem/core.c67
-rw-r--r--include/linux/nvmem-provider.h10
3 files changed, 50 insertions, 28 deletions
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 9c0c59d3b22b..15c58a5ff7ec 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -1,6 +1,5 @@
1menuconfig NVMEM 1menuconfig NVMEM
2 tristate "NVMEM Support" 2 tristate "NVMEM Support"
3 select REGMAP
4 help 3 help
5 Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES... 4 Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES...
6 5
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 0de3d878c439..bb4ea123547f 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -23,12 +23,10 @@
23#include <linux/nvmem-consumer.h> 23#include <linux/nvmem-consumer.h>
24#include <linux/nvmem-provider.h> 24#include <linux/nvmem-provider.h>
25#include <linux/of.h> 25#include <linux/of.h>
26#include <linux/regmap.h>
27#include <linux/slab.h> 26#include <linux/slab.h>
28 27
29struct nvmem_device { 28struct nvmem_device {
30 const char *name; 29 const char *name;
31 struct regmap *regmap;
32 struct module *owner; 30 struct module *owner;
33 struct device dev; 31 struct device dev;
34 int stride; 32 int stride;
@@ -41,6 +39,9 @@ struct nvmem_device {
41 int flags; 39 int flags;
42 struct bin_attribute eeprom; 40 struct bin_attribute eeprom;
43 struct device *base_dev; 41 struct device *base_dev;
42 nvmem_reg_read_t reg_read;
43 nvmem_reg_write_t reg_write;
44 void *priv;
44}; 45};
45 46
46#define FLAG_COMPAT BIT(0) 47#define FLAG_COMPAT BIT(0)
@@ -66,6 +67,23 @@ static struct lock_class_key eeprom_lock_key;
66#endif 67#endif
67 68
68#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev) 69#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
70static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
71 void *val, size_t bytes)
72{
73 if (nvmem->reg_read)
74 return nvmem->reg_read(nvmem->priv, offset, val, bytes);
75
76 return -EINVAL;
77}
78
79static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
80 void *val, size_t bytes)
81{
82 if (nvmem->reg_write)
83 return nvmem->reg_write(nvmem->priv, offset, val, bytes);
84
85 return -EINVAL;
86}
69 87
70static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj, 88static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
71 struct bin_attribute *attr, 89 struct bin_attribute *attr,
@@ -93,7 +111,7 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
93 111
94 count = round_down(count, nvmem->word_size); 112 count = round_down(count, nvmem->word_size);
95 113
96 rc = regmap_raw_read(nvmem->regmap, pos, buf, count); 114 rc = nvmem_reg_read(nvmem, pos, buf, count);
97 115
98 if (IS_ERR_VALUE(rc)) 116 if (IS_ERR_VALUE(rc))
99 return rc; 117 return rc;
@@ -127,7 +145,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
127 145
128 count = round_down(count, nvmem->word_size); 146 count = round_down(count, nvmem->word_size);
129 147
130 rc = regmap_raw_write(nvmem->regmap, pos, buf, count); 148 rc = nvmem_reg_write(nvmem, pos, buf, count);
131 149
132 if (IS_ERR_VALUE(rc)) 150 if (IS_ERR_VALUE(rc))
133 return rc; 151 return rc;
@@ -421,18 +439,11 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
421{ 439{
422 struct nvmem_device *nvmem; 440 struct nvmem_device *nvmem;
423 struct device_node *np; 441 struct device_node *np;
424 struct regmap *rm;
425 int rval; 442 int rval;
426 443
427 if (!config->dev) 444 if (!config->dev)
428 return ERR_PTR(-EINVAL); 445 return ERR_PTR(-EINVAL);
429 446
430 rm = dev_get_regmap(config->dev, NULL);
431 if (!rm) {
432 dev_err(config->dev, "Regmap not found\n");
433 return ERR_PTR(-EINVAL);
434 }
435
436 nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL); 447 nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
437 if (!nvmem) 448 if (!nvmem)
438 return ERR_PTR(-ENOMEM); 449 return ERR_PTR(-ENOMEM);
@@ -444,14 +455,16 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
444 } 455 }
445 456
446 nvmem->id = rval; 457 nvmem->id = rval;
447 nvmem->regmap = rm;
448 nvmem->owner = config->owner; 458 nvmem->owner = config->owner;
449 nvmem->stride = regmap_get_reg_stride(rm); 459 nvmem->stride = config->stride;
450 nvmem->word_size = regmap_get_val_bytes(rm); 460 nvmem->word_size = config->word_size;
451 nvmem->size = regmap_get_max_register(rm) + nvmem->stride; 461 nvmem->size = config->size;
452 nvmem->dev.type = &nvmem_provider_type; 462 nvmem->dev.type = &nvmem_provider_type;
453 nvmem->dev.bus = &nvmem_bus_type; 463 nvmem->dev.bus = &nvmem_bus_type;
454 nvmem->dev.parent = config->dev; 464 nvmem->dev.parent = config->dev;
465 nvmem->priv = config->priv;
466 nvmem->reg_read = config->reg_read;
467 nvmem->reg_write = config->reg_write;
455 np = config->dev->of_node; 468 np = config->dev->of_node;
456 nvmem->dev.of_node = np; 469 nvmem->dev.of_node = np;
457 dev_set_name(&nvmem->dev, "%s%d", 470 dev_set_name(&nvmem->dev, "%s%d",
@@ -948,7 +961,7 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
948{ 961{
949 int rc; 962 int rc;
950 963
951 rc = regmap_raw_read(nvmem->regmap, cell->offset, buf, cell->bytes); 964 rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
952 965
953 if (IS_ERR_VALUE(rc)) 966 if (IS_ERR_VALUE(rc))
954 return rc; 967 return rc;
@@ -977,7 +990,7 @@ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
977 u8 *buf; 990 u8 *buf;
978 int rc; 991 int rc;
979 992
980 if (!nvmem || !nvmem->regmap) 993 if (!nvmem)
981 return ERR_PTR(-EINVAL); 994 return ERR_PTR(-EINVAL);
982 995
983 buf = kzalloc(cell->bytes, GFP_KERNEL); 996 buf = kzalloc(cell->bytes, GFP_KERNEL);
@@ -1014,7 +1027,7 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
1014 *b <<= bit_offset; 1027 *b <<= bit_offset;
1015 1028
1016 /* setup the first byte with lsb bits from nvmem */ 1029 /* setup the first byte with lsb bits from nvmem */
1017 rc = regmap_raw_read(nvmem->regmap, cell->offset, &v, 1); 1030 rc = nvmem_reg_read(nvmem, cell->offset, &v, 1);
1018 *b++ |= GENMASK(bit_offset - 1, 0) & v; 1031 *b++ |= GENMASK(bit_offset - 1, 0) & v;
1019 1032
1020 /* setup rest of the byte if any */ 1033 /* setup rest of the byte if any */
@@ -1031,7 +1044,7 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
1031 /* if it's not end on byte boundary */ 1044 /* if it's not end on byte boundary */
1032 if ((nbits + bit_offset) % BITS_PER_BYTE) { 1045 if ((nbits + bit_offset) % BITS_PER_BYTE) {
1033 /* setup the last byte with msb bits from nvmem */ 1046 /* setup the last byte with msb bits from nvmem */
1034 rc = regmap_raw_read(nvmem->regmap, 1047 rc = nvmem_reg_read(nvmem,
1035 cell->offset + cell->bytes - 1, &v, 1); 1048 cell->offset + cell->bytes - 1, &v, 1);
1036 *p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v; 1049 *p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
1037 1050
@@ -1054,7 +1067,7 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
1054 struct nvmem_device *nvmem = cell->nvmem; 1067 struct nvmem_device *nvmem = cell->nvmem;
1055 int rc; 1068 int rc;
1056 1069
1057 if (!nvmem || !nvmem->regmap || nvmem->read_only || 1070 if (!nvmem || nvmem->read_only ||
1058 (cell->bit_offset == 0 && len != cell->bytes)) 1071 (cell->bit_offset == 0 && len != cell->bytes))
1059 return -EINVAL; 1072 return -EINVAL;
1060 1073
@@ -1064,7 +1077,7 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
1064 return PTR_ERR(buf); 1077 return PTR_ERR(buf);
1065 } 1078 }
1066 1079
1067 rc = regmap_raw_write(nvmem->regmap, cell->offset, buf, cell->bytes); 1080 rc = nvmem_reg_write(nvmem, cell->offset, buf, cell->bytes);
1068 1081
1069 /* free the tmp buffer */ 1082 /* free the tmp buffer */
1070 if (cell->bit_offset || cell->nbits) 1083 if (cell->bit_offset || cell->nbits)
@@ -1094,7 +1107,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
1094 int rc; 1107 int rc;
1095 ssize_t len; 1108 ssize_t len;
1096 1109
1097 if (!nvmem || !nvmem->regmap) 1110 if (!nvmem)
1098 return -EINVAL; 1111 return -EINVAL;
1099 1112
1100 rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell); 1113 rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
@@ -1124,7 +1137,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
1124 struct nvmem_cell cell; 1137 struct nvmem_cell cell;
1125 int rc; 1138 int rc;
1126 1139
1127 if (!nvmem || !nvmem->regmap) 1140 if (!nvmem)
1128 return -EINVAL; 1141 return -EINVAL;
1129 1142
1130 rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell); 1143 rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
@@ -1152,10 +1165,10 @@ int nvmem_device_read(struct nvmem_device *nvmem,
1152{ 1165{
1153 int rc; 1166 int rc;
1154 1167
1155 if (!nvmem || !nvmem->regmap) 1168 if (!nvmem)
1156 return -EINVAL; 1169 return -EINVAL;
1157 1170
1158 rc = regmap_raw_read(nvmem->regmap, offset, buf, bytes); 1171 rc = nvmem_reg_read(nvmem, offset, buf, bytes);
1159 1172
1160 if (IS_ERR_VALUE(rc)) 1173 if (IS_ERR_VALUE(rc))
1161 return rc; 1174 return rc;
@@ -1180,10 +1193,10 @@ int nvmem_device_write(struct nvmem_device *nvmem,
1180{ 1193{
1181 int rc; 1194 int rc;
1182 1195
1183 if (!nvmem || !nvmem->regmap) 1196 if (!nvmem)
1184 return -EINVAL; 1197 return -EINVAL;
1185 1198
1186 rc = regmap_raw_write(nvmem->regmap, offset, buf, bytes); 1199 rc = nvmem_reg_write(nvmem, offset, buf, bytes);
1187 1200
1188 if (IS_ERR_VALUE(rc)) 1201 if (IS_ERR_VALUE(rc))
1189 return rc; 1202 return rc;
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index a4fcc90b0f20..cd93416d762e 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -14,6 +14,10 @@
14 14
15struct nvmem_device; 15struct nvmem_device;
16struct nvmem_cell_info; 16struct nvmem_cell_info;
17typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset,
18 void *val, size_t bytes);
19typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
20 void *val, size_t bytes);
17 21
18struct nvmem_config { 22struct nvmem_config {
19 struct device *dev; 23 struct device *dev;
@@ -24,6 +28,12 @@ struct nvmem_config {
24 int ncells; 28 int ncells;
25 bool read_only; 29 bool read_only;
26 bool root_only; 30 bool root_only;
31 nvmem_reg_read_t reg_read;
32 nvmem_reg_write_t reg_write;
33 int size;
34 int word_size;
35 int stride;
36 void *priv;
27 /* To be only used by old driver/misc/eeprom drivers */ 37 /* To be only used by old driver/misc/eeprom drivers */
28 bool compat; 38 bool compat;
29 struct device *base_dev; 39 struct device *base_dev;