1 From 5d8e6e6c10a3d37486d263b16ddc15991a7e4a88 Mon Sep 17 00:00:00 2001
2 From: Michael Walle <michael@walle.cc>
3 Date: Mon, 6 Feb 2023 13:43:46 +0000
4 Subject: [PATCH] nvmem: core: add an index parameter to the cell
6 Sometimes a cell can represend multiple values. For example, a base
7 ethernet address stored in the NVMEM can be expanded into multiple
8 discreet ones by adding an offset.
10 For this use case, introduce an index parameter which is then used to
11 distiguish between values. This parameter will then be passed to the
12 post process hook which can then use it to create different values
15 At the moment, there is only support for the device tree path. You can
16 add the index to the phandle, e.g.
19 nvmem-cells = <&base_mac_address 2>;
20 nvmem-cell-names = "mac-address";
24 base_mac_address: base-mac-address@0 {
25 #nvmem-cell-cells = <1>;
30 Signed-off-by: Michael Walle <michael@walle.cc>
31 Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
32 Link: https://lore.kernel.org/r/20230206134356.839737-13-srinivas.kandagatla@linaro.org
33 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
35 drivers/nvmem/core.c | 37 ++++++++++++++++++++++++----------
36 drivers/nvmem/imx-ocotp.c | 4 ++--
37 include/linux/nvmem-provider.h | 4 ++--
38 3 files changed, 30 insertions(+), 15 deletions(-)
40 --- a/drivers/nvmem/core.c
41 +++ b/drivers/nvmem/core.c
42 @@ -60,6 +60,7 @@ struct nvmem_cell_entry {
44 struct nvmem_cell_entry *entry;
49 static DEFINE_MUTEX(nvmem_mutex);
50 @@ -1125,7 +1126,8 @@ struct nvmem_device *devm_nvmem_device_g
52 EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
54 -static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id)
55 +static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry,
56 + const char *id, int index)
58 struct nvmem_cell *cell;
59 const char *name = NULL;
60 @@ -1144,6 +1146,7 @@ static struct nvmem_cell *nvmem_create_c
64 + cell->index = index;
68 @@ -1182,7 +1185,7 @@ nvmem_cell_get_from_lookup(struct device
69 __nvmem_device_put(nvmem);
70 cell = ERR_PTR(-ENOENT);
72 - cell = nvmem_create_cell(cell_entry, con_id);
73 + cell = nvmem_create_cell(cell_entry, con_id, 0);
75 __nvmem_device_put(nvmem);
77 @@ -1230,15 +1233,27 @@ struct nvmem_cell *of_nvmem_cell_get(str
78 struct nvmem_device *nvmem;
79 struct nvmem_cell_entry *cell_entry;
80 struct nvmem_cell *cell;
81 + struct of_phandle_args cell_spec;
86 /* if cell name exists, find index to the name */
88 index = of_property_match_string(np, "nvmem-cell-names", id);
90 - cell_np = of_parse_phandle(np, "nvmem-cells", index);
92 - return ERR_PTR(-ENOENT);
93 + ret = of_parse_phandle_with_optional_args(np, "nvmem-cells",
94 + "#nvmem-cell-cells",
97 + return ERR_PTR(ret);
99 + if (cell_spec.args_count > 1)
100 + return ERR_PTR(-EINVAL);
102 + cell_np = cell_spec.np;
103 + if (cell_spec.args_count)
104 + cell_index = cell_spec.args[0];
106 nvmem_np = of_get_next_parent(cell_np);
108 @@ -1255,7 +1270,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
109 return ERR_PTR(-ENOENT);
112 - cell = nvmem_create_cell(cell_entry, id);
113 + cell = nvmem_create_cell(cell_entry, id, cell_index);
115 __nvmem_device_put(nvmem);
117 @@ -1408,8 +1423,8 @@ static void nvmem_shift_read_buffer_in_p
120 static int __nvmem_cell_read(struct nvmem_device *nvmem,
121 - struct nvmem_cell_entry *cell,
122 - void *buf, size_t *len, const char *id)
123 + struct nvmem_cell_entry *cell,
124 + void *buf, size_t *len, const char *id, int index)
128 @@ -1423,7 +1438,7 @@ static int __nvmem_cell_read(struct nvme
129 nvmem_shift_read_buffer_in_place(cell, buf);
131 if (nvmem->cell_post_process) {
132 - rc = nvmem->cell_post_process(nvmem->priv, id,
133 + rc = nvmem->cell_post_process(nvmem->priv, id, index,
134 cell->offset, buf, cell->bytes);
137 @@ -1458,7 +1473,7 @@ void *nvmem_cell_read(struct nvmem_cell
139 return ERR_PTR(-ENOMEM);
141 - rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id);
142 + rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id, cell->index);
146 @@ -1771,7 +1786,7 @@ ssize_t nvmem_device_cell_read(struct nv
150 - rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL);
151 + rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL, 0);
155 --- a/drivers/nvmem/imx-ocotp.c
156 +++ b/drivers/nvmem/imx-ocotp.c
157 @@ -222,8 +222,8 @@ read_end:
161 -static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset,
162 - void *data, size_t bytes)
163 +static int imx_ocotp_cell_pp(void *context, const char *id, int index,
164 + unsigned int offset, void *data, size_t bytes)
166 struct ocotp_priv *priv = context;
168 --- a/include/linux/nvmem-provider.h
169 +++ b/include/linux/nvmem-provider.h
170 @@ -20,8 +20,8 @@ typedef int (*nvmem_reg_read_t)(void *pr
171 typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
172 void *val, size_t bytes);
173 /* used for vendor specific post processing of cell data */
174 -typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, unsigned int offset,
175 - void *buf, size_t bytes);
176 +typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index,
177 + unsigned int offset, void *buf, size_t bytes);
180 NVMEM_TYPE_UNKNOWN = 0,