blob: a4147dd3b27035fa56c0000a7fd358ad1a95846c [file] [log] [blame]
developer5d148cb2023-06-02 13:08:11 +08001From 21a99150a566b69edc7f3b9bc369bb4525e04acd Mon Sep 17 00:00:00 2001
2From: Sam Shih <sam.shih@mediatek.com>
3Date: Fri, 2 Jun 2023 13:06:17 +0800
4Subject: [PATCH]
5 [spi-and-storage][999-2350-nvmem-core-Add-functions-to-make-number-reading-easy.patch]
developer44e1bbf2022-01-28 17:20:00 +08006
developer44e1bbf2022-01-28 17:20:00 +08007---
8 drivers/nvmem/core.c | 161 +++++++++++++++++++++++++++------
9 include/linux/nvmem-consumer.h | 15 +++
10 2 files changed, 150 insertions(+), 26 deletions(-)
11
12diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
developer5d148cb2023-06-02 13:08:11 +080013index 19ac0d055..f65305b6d 100644
developer44e1bbf2022-01-28 17:20:00 +080014--- a/drivers/nvmem/core.c
15+++ b/drivers/nvmem/core.c
16@@ -1102,16 +1102,8 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
17 }
18 EXPORT_SYMBOL_GPL(nvmem_cell_write);
19
20-/**
21- * nvmem_cell_read_u16() - Read a cell value as an u16
22- *
23- * @dev: Device that requests the nvmem cell.
24- * @cell_id: Name of nvmem cell to read.
25- * @val: pointer to output value.
26- *
27- * Return: 0 on success or negative errno.
28- */
29-int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
30+static int nvmem_cell_read_common(struct device *dev, const char *cell_id,
31+ void *val, size_t count)
32 {
33 struct nvmem_cell *cell;
34 void *buf;
35@@ -1126,21 +1118,50 @@ int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
36 nvmem_cell_put(cell);
37 return PTR_ERR(buf);
38 }
39- if (len != sizeof(*val)) {
40+ if (len != count) {
41 kfree(buf);
42 nvmem_cell_put(cell);
43 return -EINVAL;
44 }
45- memcpy(val, buf, sizeof(*val));
46+ memcpy(val, buf, count);
47 kfree(buf);
48 nvmem_cell_put(cell);
49
50 return 0;
51 }
52+
53+/**
54+ * nvmem_cell_read_u8() - Read a cell value as a u8
55+ *
56+ * @dev: Device that requests the nvmem cell.
57+ * @cell_id: Name of nvmem cell to read.
58+ * @val: pointer to output value.
59+ *
60+ * Return: 0 on success or negative errno.
61+ */
62+int nvmem_cell_read_u8(struct device *dev, const char *cell_id, u8 *val)
63+{
64+ return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
65+}
66+EXPORT_SYMBOL_GPL(nvmem_cell_read_u8);
67+
68+/**
69+ * nvmem_cell_read_u16() - Read a cell value as a u16
70+ *
71+ * @dev: Device that requests the nvmem cell.
72+ * @cell_id: Name of nvmem cell to read.
73+ * @val: pointer to output value.
74+ *
75+ * Return: 0 on success or negative errno.
76+ */
77+int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
78+{
79+ return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
80+}
81 EXPORT_SYMBOL_GPL(nvmem_cell_read_u16);
82
83 /**
84- * nvmem_cell_read_u32() - Read a cell value as an u32
85+ * nvmem_cell_read_u32() - Read a cell value as a u32
86 *
87 * @dev: Device that requests the nvmem cell.
88 * @cell_id: Name of nvmem cell to read.
89@@ -1149,32 +1170,120 @@ EXPORT_SYMBOL_GPL(nvmem_cell_read_u16);
90 * Return: 0 on success or negative errno.
91 */
92 int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val)
93+{
94+ return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
95+}
96+EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
97+
98+/**
99+ * nvmem_cell_read_u64() - Read a cell value as a u64
100+ *
101+ * @dev: Device that requests the nvmem cell.
102+ * @cell_id: Name of nvmem cell to read.
103+ * @val: pointer to output value.
104+ *
105+ * Return: 0 on success or negative errno.
106+ */
107+int nvmem_cell_read_u64(struct device *dev, const char *cell_id, u64 *val)
108+{
109+ return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
110+}
111+EXPORT_SYMBOL_GPL(nvmem_cell_read_u64);
112+
113+static const void *nvmem_cell_read_variable_common(struct device *dev,
114+ const char *cell_id,
115+ size_t max_len, size_t *len)
116 {
117 struct nvmem_cell *cell;
118+ int nbits;
119 void *buf;
120- size_t len;
121
122 cell = nvmem_cell_get(dev, cell_id);
123 if (IS_ERR(cell))
124- return PTR_ERR(cell);
125+ return cell;
126
127- buf = nvmem_cell_read(cell, &len);
128- if (IS_ERR(buf)) {
129- nvmem_cell_put(cell);
130- return PTR_ERR(buf);
131- }
132- if (len != sizeof(*val)) {
133+ nbits = cell->nbits;
134+ buf = nvmem_cell_read(cell, len);
135+ nvmem_cell_put(cell);
136+ if (IS_ERR(buf))
137+ return buf;
138+
139+ /*
140+ * If nbits is set then nvmem_cell_read() can significantly exaggerate
141+ * the length of the real data. Throw away the extra junk.
142+ */
143+ if (nbits)
144+ *len = DIV_ROUND_UP(nbits, 8);
145+
146+ if (*len > max_len) {
147 kfree(buf);
148- nvmem_cell_put(cell);
149- return -EINVAL;
150+ return ERR_PTR(-ERANGE);
151 }
152- memcpy(val, buf, sizeof(*val));
153+
154+ return buf;
155+}
156+
157+/**
158+ * nvmem_cell_read_variable_le_u32() - Read up to 32-bits of data as a little endian number.
159+ *
160+ * @dev: Device that requests the nvmem cell.
161+ * @cell_id: Name of nvmem cell to read.
162+ * @val: pointer to output value.
163+ *
164+ * Return: 0 on success or negative errno.
165+ */
166+int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id,
167+ u32 *val)
168+{
169+ size_t len;
170+ const u8 *buf;
171+ int i;
172+
173+ buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len);
174+ if (IS_ERR(buf))
175+ return PTR_ERR(buf);
176+
177+ /* Copy w/ implicit endian conversion */
178+ *val = 0;
179+ for (i = 0; i < len; i++)
180+ *val |= buf[i] << (8 * i);
181
182 kfree(buf);
183- nvmem_cell_put(cell);
184+
185 return 0;
186 }
187-EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
188+EXPORT_SYMBOL_GPL(nvmem_cell_read_variable_le_u32);
189+
190+/**
191+ * nvmem_cell_read_variable_le_u64() - Read up to 64-bits of data as a little endian number.
192+ *
193+ * @dev: Device that requests the nvmem cell.
194+ * @cell_id: Name of nvmem cell to read.
195+ * @val: pointer to output value.
196+ *
197+ * Return: 0 on success or negative errno.
198+ */
199+int nvmem_cell_read_variable_le_u64(struct device *dev, const char *cell_id,
200+ u64 *val)
201+{
202+ size_t len;
203+ const u8 *buf;
204+ int i;
205+
206+ buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len);
207+ if (IS_ERR(buf))
208+ return PTR_ERR(buf);
209+
210+ /* Copy w/ implicit endian conversion */
211+ *val = 0;
212+ for (i = 0; i < len; i++)
213+ *val |= (uint64_t)buf[i] << (8 * i);
214+
215+ kfree(buf);
216+
217+ return 0;
218+}
219+EXPORT_SYMBOL_GPL(nvmem_cell_read_variable_le_u64);
220
221 /**
222 * nvmem_device_cell_read() - Read a given nvmem device and cell
223diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
developer5d148cb2023-06-02 13:08:11 +0800224index 0f490b288..227b93158 100644
developer44e1bbf2022-01-28 17:20:00 +0800225--- a/include/linux/nvmem-consumer.h
226+++ b/include/linux/nvmem-consumer.h
developer5d148cb2023-06-02 13:08:11 +0800227@@ -64,6 +64,10 @@ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
developer44e1bbf2022-01-28 17:20:00 +0800228 int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
229 int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val);
230 int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val);
231+int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id,
232+ u32 *val);
233+int nvmem_cell_read_variable_le_u64(struct device *dev, const char *cell_id,
234+ u64 *val);
235
236 /* direct nvmem device read/write interface */
237 struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
developer5d148cb2023-06-02 13:08:11 +0800238@@ -135,6 +139,17 @@ static inline int nvmem_cell_read_u32(struct device *dev,
developer44e1bbf2022-01-28 17:20:00 +0800239 {
240 return -EOPNOTSUPP;
241 }
242+static inline int nvmem_cell_read_variable_le_u32(struct device *dev,
243+ const char *cell_id, u32 *val)
244+{
245+ return -ENOSYS;
246+}
247+
248+static inline int nvmem_cell_read_variable_le_u64(struct device *dev,
249+ const char *cell_id, u64 *val);
250+{
251+ return -ENOSYS;
252+}
253
254 static inline struct nvmem_device *nvmem_device_get(struct device *dev,
255 const char *name)
256--
developer5d148cb2023-06-02 13:08:11 +08002572.34.1
developer44e1bbf2022-01-28 17:20:00 +0800258