454d3bf0ed1a4b31fa601c51903700b23f944b63
[librecmc/librecmc.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 @@ -1122,7 +1123,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 @@ -1141,6 +1143,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 @@ -1179,7 +1182,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 @@ -1227,15 +1230,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_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,