4f1bfac806c9088eb72da589a96bf44a81d8569d
[openwrt/openwrt.git] /
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
5
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.
9
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
13 during reading.
14
15 At the moment, there is only support for the device tree path. You can
16 add the index to the phandle, e.g.
17
18 &net {
19 nvmem-cells = <&base_mac_address 2>;
20 nvmem-cell-names = "mac-address";
21 };
22
23 &nvmem_provider {
24 base_mac_address: base-mac-address@0 {
25 #nvmem-cell-cells = <1>;
26 reg = <0 6>;
27 };
28 };
29
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>
34 ---
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(-)
39
40 --- a/drivers/nvmem/core.c
41 +++ b/drivers/nvmem/core.c
42 @@ -60,6 +60,7 @@ struct nvmem_cell_entry {
43 struct nvmem_cell {
44 struct nvmem_cell_entry *entry;
45 const char *id;
46 + int index;
47 };
48
49 static DEFINE_MUTEX(nvmem_mutex);
50 @@ -1127,7 +1128,8 @@ struct nvmem_device *devm_nvmem_device_g
51 }
52 EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
53
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)
57 {
58 struct nvmem_cell *cell;
59 const char *name = NULL;
60 @@ -1146,6 +1148,7 @@ static struct nvmem_cell *nvmem_create_c
61
62 cell->id = name;
63 cell->entry = entry;
64 + cell->index = index;
65
66 return cell;
67 }
68 @@ -1184,7 +1187,7 @@ nvmem_cell_get_from_lookup(struct device
69 __nvmem_device_put(nvmem);
70 cell = ERR_PTR(-ENOENT);
71 } else {
72 - cell = nvmem_create_cell(cell_entry, con_id);
73 + cell = nvmem_create_cell(cell_entry, con_id, 0);
74 if (IS_ERR(cell))
75 __nvmem_device_put(nvmem);
76 }
77 @@ -1232,15 +1235,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;
82 int index = 0;
83 + int cell_index = 0;
84 + int ret;
85
86 /* if cell name exists, find index to the name */
87 if (id)
88 index = of_property_match_string(np, "nvmem-cell-names", id);
89
90 - cell_np = of_parse_phandle(np, "nvmem-cells", index);
91 - if (!cell_np)
92 - return ERR_PTR(-ENOENT);
93 + ret = of_parse_phandle_with_optional_args(np, "nvmem-cells",
94 + "#nvmem-cell-cells",
95 + index, &cell_spec);
96 + if (ret)
97 + return ERR_PTR(ret);
98 +
99 + if (cell_spec.args_count > 1)
100 + return ERR_PTR(-EINVAL);
101 +
102 + cell_np = cell_spec.np;
103 + if (cell_spec.args_count)
104 + cell_index = cell_spec.args[0];
105
106 nvmem_np = of_get_next_parent(cell_np);
107 if (!nvmem_np)
108 @@ -1257,7 +1272,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
109 return ERR_PTR(-ENOENT);
110 }
111
112 - cell = nvmem_create_cell(cell_entry, id);
113 + cell = nvmem_create_cell(cell_entry, id, cell_index);
114 if (IS_ERR(cell))
115 __nvmem_device_put(nvmem);
116
117 @@ -1410,8 +1425,8 @@ static void nvmem_shift_read_buffer_in_p
118 }
119
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)
125 {
126 int rc;
127
128 @@ -1425,7 +1440,7 @@ static int __nvmem_cell_read(struct nvme
129 nvmem_shift_read_buffer_in_place(cell, buf);
130
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);
135 if (rc)
136 return rc;
137 @@ -1460,7 +1475,7 @@ void *nvmem_cell_read(struct nvmem_cell
138 if (!buf)
139 return ERR_PTR(-ENOMEM);
140
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);
143 if (rc) {
144 kfree(buf);
145 return ERR_PTR(rc);
146 @@ -1773,7 +1788,7 @@ ssize_t nvmem_device_cell_read(struct nv
147 if (rc)
148 return rc;
149
150 - rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL);
151 + rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL, 0);
152 if (rc)
153 return rc;
154
155 --- a/drivers/nvmem/imx-ocotp.c
156 +++ b/drivers/nvmem/imx-ocotp.c
157 @@ -222,8 +222,8 @@ read_end:
158 return ret;
159 }
160
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)
165 {
166 struct ocotp_priv *priv = context;
167
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);
178
179 enum nvmem_type {
180 NVMEM_TYPE_UNKNOWN = 0,