blob: 969ec3f7ad577e8bfa0d98fb2b690a53766d0d77 [file] [log] [blame]
developer44e1bbf2022-01-28 17:20:00 +08001From 8dc0b1158dcffd78ea2b3a5604b82ee826de687b Mon Sep 17 00:00:00 2001
2From: Zhanyong Wang <zhanyong.wang@mediatek.com>
3Date: Mon, 8 Nov 2021 13:58:51 +0800
4Subject: [PATCH 1/5] nvmem: core: Add functions to make number reading easy
5
6Sometimes the clients of nvmem just want to get a number out of
7nvmem. They don't want to think about exactly how many bytes the nvmem
8cell took up. They just want the number. Let's make it easy.
9
10In general this concept is useful because nvmem space is precious and
11usually the fewest bits are allocated that will hold a given value on
12a given system. However, even though small numbers might be fine on
13one system that doesn't mean that logically the number couldn't be
14bigger. Imagine nvmem containing a max frequency for a component. On
15one system perhaps that fits in 16 bits. On another system it might
16fit in 32 bits. The code reading this number doesn't care--it just
17wants the number.
18
19We'll provide two functions: nvmem_cell_read_variable_le_u32() and
20nvmem_cell_read_variable_le_u64().
21
22Comparing these to the existing functions like nvmem_cell_read_u32():
23* These new functions have no problems if the value was stored in
24 nvmem in fewer bytes. It's OK to use these function as long as the
25 value stored will fit in 32-bits (or 64-bits).
26* These functions avoid problems that the earlier APIs had with bit
27 offsets. For instance, you can't use nvmem_cell_read_u32() to read a
28 value has nbits=32 and bit_offset=4 because the nvmem cell must be
29 at least 5 bytes big to hold this value. The new API accounts for
30 this and works fine.
31* These functions make it very explicit that they assume that the
32 number was stored in little endian format. The old functions made
33 this assumption whenever bit_offset was non-zero (see
34 nvmem_shift_read_buffer_in_place()) but didn't whenever the
35 bit_offset was zero.
36
37NOTE: it's assumed that we don't need an 8-bit or 16-bit version of
38this function. The 32-bit version of the function can be used to read
398-bit or 16-bit data.
40
41At the moment, I'm only adding the "unsigned" versions of these
42functions, but if it ends up being useful someone could add a "signed"
43version that did 2's complement sign extension.
44
45At the moment, I'm only adding the "little endian" versions of these
46functions. Adding the "big endian" version would require adding "big
47endian" support to nvmem_shift_read_buffer_in_place().
48
49Signed-off-by: Douglas Anderson <dianders@chromium.org>
50Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
51Link: https://lore.kernel.org/r/20210330111241.19401-7-srinivas.kandagatla@linaro.org
52Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
53Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
54Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
55Change-Id: I3e1d96ec1680812d5e24681c79852c9b36899559
56---
57 drivers/nvmem/core.c | 161 +++++++++++++++++++++++++++------
58 include/linux/nvmem-consumer.h | 15 +++
59 2 files changed, 150 insertions(+), 26 deletions(-)
60
61diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
62index c0f4324d8f7c..e26b25b5c288 100644
63--- a/drivers/nvmem/core.c
64+++ b/drivers/nvmem/core.c
65@@ -1102,16 +1102,8 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
66 }
67 EXPORT_SYMBOL_GPL(nvmem_cell_write);
68
69-/**
70- * nvmem_cell_read_u16() - Read a cell value as an u16
71- *
72- * @dev: Device that requests the nvmem cell.
73- * @cell_id: Name of nvmem cell to read.
74- * @val: pointer to output value.
75- *
76- * Return: 0 on success or negative errno.
77- */
78-int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
79+static int nvmem_cell_read_common(struct device *dev, const char *cell_id,
80+ void *val, size_t count)
81 {
82 struct nvmem_cell *cell;
83 void *buf;
84@@ -1126,21 +1118,50 @@ int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
85 nvmem_cell_put(cell);
86 return PTR_ERR(buf);
87 }
88- if (len != sizeof(*val)) {
89+ if (len != count) {
90 kfree(buf);
91 nvmem_cell_put(cell);
92 return -EINVAL;
93 }
94- memcpy(val, buf, sizeof(*val));
95+ memcpy(val, buf, count);
96 kfree(buf);
97 nvmem_cell_put(cell);
98
99 return 0;
100 }
101+
102+/**
103+ * nvmem_cell_read_u8() - Read a cell value as a u8
104+ *
105+ * @dev: Device that requests the nvmem cell.
106+ * @cell_id: Name of nvmem cell to read.
107+ * @val: pointer to output value.
108+ *
109+ * Return: 0 on success or negative errno.
110+ */
111+int nvmem_cell_read_u8(struct device *dev, const char *cell_id, u8 *val)
112+{
113+ return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
114+}
115+EXPORT_SYMBOL_GPL(nvmem_cell_read_u8);
116+
117+/**
118+ * nvmem_cell_read_u16() - Read a cell value as a u16
119+ *
120+ * @dev: Device that requests the nvmem cell.
121+ * @cell_id: Name of nvmem cell to read.
122+ * @val: pointer to output value.
123+ *
124+ * Return: 0 on success or negative errno.
125+ */
126+int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
127+{
128+ return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
129+}
130 EXPORT_SYMBOL_GPL(nvmem_cell_read_u16);
131
132 /**
133- * nvmem_cell_read_u32() - Read a cell value as an u32
134+ * nvmem_cell_read_u32() - Read a cell value as a u32
135 *
136 * @dev: Device that requests the nvmem cell.
137 * @cell_id: Name of nvmem cell to read.
138@@ -1149,32 +1170,120 @@ EXPORT_SYMBOL_GPL(nvmem_cell_read_u16);
139 * Return: 0 on success or negative errno.
140 */
141 int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val)
142+{
143+ return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
144+}
145+EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
146+
147+/**
148+ * nvmem_cell_read_u64() - Read a cell value as a u64
149+ *
150+ * @dev: Device that requests the nvmem cell.
151+ * @cell_id: Name of nvmem cell to read.
152+ * @val: pointer to output value.
153+ *
154+ * Return: 0 on success or negative errno.
155+ */
156+int nvmem_cell_read_u64(struct device *dev, const char *cell_id, u64 *val)
157+{
158+ return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
159+}
160+EXPORT_SYMBOL_GPL(nvmem_cell_read_u64);
161+
162+static const void *nvmem_cell_read_variable_common(struct device *dev,
163+ const char *cell_id,
164+ size_t max_len, size_t *len)
165 {
166 struct nvmem_cell *cell;
167+ int nbits;
168 void *buf;
169- size_t len;
170
171 cell = nvmem_cell_get(dev, cell_id);
172 if (IS_ERR(cell))
173- return PTR_ERR(cell);
174+ return cell;
175
176- buf = nvmem_cell_read(cell, &len);
177- if (IS_ERR(buf)) {
178- nvmem_cell_put(cell);
179- return PTR_ERR(buf);
180- }
181- if (len != sizeof(*val)) {
182+ nbits = cell->nbits;
183+ buf = nvmem_cell_read(cell, len);
184+ nvmem_cell_put(cell);
185+ if (IS_ERR(buf))
186+ return buf;
187+
188+ /*
189+ * If nbits is set then nvmem_cell_read() can significantly exaggerate
190+ * the length of the real data. Throw away the extra junk.
191+ */
192+ if (nbits)
193+ *len = DIV_ROUND_UP(nbits, 8);
194+
195+ if (*len > max_len) {
196 kfree(buf);
197- nvmem_cell_put(cell);
198- return -EINVAL;
199+ return ERR_PTR(-ERANGE);
200 }
201- memcpy(val, buf, sizeof(*val));
202+
203+ return buf;
204+}
205+
206+/**
207+ * nvmem_cell_read_variable_le_u32() - Read up to 32-bits of data as a little endian number.
208+ *
209+ * @dev: Device that requests the nvmem cell.
210+ * @cell_id: Name of nvmem cell to read.
211+ * @val: pointer to output value.
212+ *
213+ * Return: 0 on success or negative errno.
214+ */
215+int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id,
216+ u32 *val)
217+{
218+ size_t len;
219+ const u8 *buf;
220+ int i;
221+
222+ buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len);
223+ if (IS_ERR(buf))
224+ return PTR_ERR(buf);
225+
226+ /* Copy w/ implicit endian conversion */
227+ *val = 0;
228+ for (i = 0; i < len; i++)
229+ *val |= buf[i] << (8 * i);
230
231 kfree(buf);
232- nvmem_cell_put(cell);
233+
234 return 0;
235 }
236-EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
237+EXPORT_SYMBOL_GPL(nvmem_cell_read_variable_le_u32);
238+
239+/**
240+ * nvmem_cell_read_variable_le_u64() - Read up to 64-bits of data as a little endian number.
241+ *
242+ * @dev: Device that requests the nvmem cell.
243+ * @cell_id: Name of nvmem cell to read.
244+ * @val: pointer to output value.
245+ *
246+ * Return: 0 on success or negative errno.
247+ */
248+int nvmem_cell_read_variable_le_u64(struct device *dev, const char *cell_id,
249+ u64 *val)
250+{
251+ size_t len;
252+ const u8 *buf;
253+ int i;
254+
255+ buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len);
256+ if (IS_ERR(buf))
257+ return PTR_ERR(buf);
258+
259+ /* Copy w/ implicit endian conversion */
260+ *val = 0;
261+ for (i = 0; i < len; i++)
262+ *val |= (uint64_t)buf[i] << (8 * i);
263+
264+ kfree(buf);
265+
266+ return 0;
267+}
268+EXPORT_SYMBOL_GPL(nvmem_cell_read_variable_le_u64);
269
270 /**
271 * nvmem_device_cell_read() - Read a given nvmem device and cell
272diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
273index 5c17cb733224..e328c0f7eef3 100644
274--- a/include/linux/nvmem-consumer.h
275+++ b/include/linux/nvmem-consumer.h
276@@ -63,6 +63,10 @@ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
277 int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
278 int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val);
279 int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val);
280+int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id,
281+ u32 *val);
282+int nvmem_cell_read_variable_le_u64(struct device *dev, const char *cell_id,
283+ u64 *val);
284
285 /* direct nvmem device read/write interface */
286 struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
287@@ -134,6 +138,17 @@ static inline int nvmem_cell_read_u32(struct device *dev,
288 {
289 return -EOPNOTSUPP;
290 }
291+static inline int nvmem_cell_read_variable_le_u32(struct device *dev,
292+ const char *cell_id, u32 *val)
293+{
294+ return -ENOSYS;
295+}
296+
297+static inline int nvmem_cell_read_variable_le_u64(struct device *dev,
298+ const char *cell_id, u64 *val);
299+{
300+ return -ENOSYS;
301+}
302
303 static inline struct nvmem_device *nvmem_device_get(struct device *dev,
304 const char *name)
305--
3062.18.0
307