Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * nvmem framework core.
4 : : *
5 : : * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
6 : : * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
7 : : */
8 : :
9 : : #include <linux/device.h>
10 : : #include <linux/export.h>
11 : : #include <linux/fs.h>
12 : : #include <linux/idr.h>
13 : : #include <linux/init.h>
14 : : #include <linux/kref.h>
15 : : #include <linux/module.h>
16 : : #include <linux/nvmem-consumer.h>
17 : : #include <linux/nvmem-provider.h>
18 : : #include <linux/gpio/consumer.h>
19 : : #include <linux/of.h>
20 : : #include <linux/slab.h>
21 : : #include "nvmem.h"
22 : :
23 : : struct nvmem_cell {
24 : : const char *name;
25 : : int offset;
26 : : int bytes;
27 : : int bit_offset;
28 : : int nbits;
29 : : struct device_node *np;
30 : : struct nvmem_device *nvmem;
31 : : struct list_head node;
32 : : };
33 : :
34 : : static DEFINE_MUTEX(nvmem_mutex);
35 : : static DEFINE_IDA(nvmem_ida);
36 : :
37 : : static DEFINE_MUTEX(nvmem_cell_mutex);
38 : : static LIST_HEAD(nvmem_cell_tables);
39 : :
40 : : static DEFINE_MUTEX(nvmem_lookup_mutex);
41 : : static LIST_HEAD(nvmem_lookup_list);
42 : :
43 : : static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
44 : :
45 : :
46 : 0 : static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
47 : : void *val, size_t bytes)
48 : : {
49 : 0 : if (nvmem->reg_read)
50 : 0 : return nvmem->reg_read(nvmem->priv, offset, val, bytes);
51 : :
52 : : return -EINVAL;
53 : : }
54 : :
55 : 0 : static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
56 : : void *val, size_t bytes)
57 : : {
58 : 0 : int ret;
59 : :
60 [ # # ]: 0 : if (nvmem->reg_write) {
61 [ # # ]: 0 : gpiod_set_value_cansleep(nvmem->wp_gpio, 0);
62 : 0 : ret = nvmem->reg_write(nvmem->priv, offset, val, bytes);
63 [ # # ]: 0 : gpiod_set_value_cansleep(nvmem->wp_gpio, 1);
64 : : return ret;
65 : : }
66 : :
67 : : return -EINVAL;
68 : : }
69 : :
70 : 0 : static void nvmem_release(struct device *dev)
71 : : {
72 : 0 : struct nvmem_device *nvmem = to_nvmem_device(dev);
73 : :
74 : 0 : ida_simple_remove(&nvmem_ida, nvmem->id);
75 : 0 : kfree(nvmem);
76 : 0 : }
77 : :
78 : : static const struct device_type nvmem_provider_type = {
79 : : .release = nvmem_release,
80 : : };
81 : :
82 : : static struct bus_type nvmem_bus_type = {
83 : : .name = "nvmem",
84 : : };
85 : :
86 : 0 : static void nvmem_cell_drop(struct nvmem_cell *cell)
87 : : {
88 : 0 : blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
89 : 0 : mutex_lock(&nvmem_mutex);
90 : 0 : list_del(&cell->node);
91 : 0 : mutex_unlock(&nvmem_mutex);
92 : 0 : of_node_put(cell->np);
93 : 0 : kfree_const(cell->name);
94 : 0 : kfree(cell);
95 : 0 : }
96 : :
97 : 0 : static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
98 : : {
99 : 0 : struct nvmem_cell *cell, *p;
100 : :
101 [ # # ]: 0 : list_for_each_entry_safe(cell, p, &nvmem->cells, node)
102 : 0 : nvmem_cell_drop(cell);
103 : 0 : }
104 : :
105 : 0 : static void nvmem_cell_add(struct nvmem_cell *cell)
106 : : {
107 : 0 : mutex_lock(&nvmem_mutex);
108 : 0 : list_add_tail(&cell->node, &cell->nvmem->cells);
109 : 0 : mutex_unlock(&nvmem_mutex);
110 : 0 : blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
111 : 0 : }
112 : :
113 : 0 : static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
114 : : const struct nvmem_cell_info *info,
115 : : struct nvmem_cell *cell)
116 : : {
117 : 0 : cell->nvmem = nvmem;
118 : 0 : cell->offset = info->offset;
119 : 0 : cell->bytes = info->bytes;
120 : 0 : cell->name = kstrdup_const(info->name, GFP_KERNEL);
121 [ # # ]: 0 : if (!cell->name)
122 : : return -ENOMEM;
123 : :
124 : 0 : cell->bit_offset = info->bit_offset;
125 : 0 : cell->nbits = info->nbits;
126 : :
127 [ # # ]: 0 : if (cell->nbits)
128 : 0 : cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
129 : : BITS_PER_BYTE);
130 : :
131 [ # # ]: 0 : if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
132 : 0 : dev_err(&nvmem->dev,
133 : : "cell %s unaligned to nvmem stride %d\n",
134 : : cell->name, nvmem->stride);
135 : 0 : return -EINVAL;
136 : : }
137 : :
138 : : return 0;
139 : : }
140 : :
141 : : /**
142 : : * nvmem_add_cells() - Add cell information to an nvmem device
143 : : *
144 : : * @nvmem: nvmem device to add cells to.
145 : : * @info: nvmem cell info to add to the device
146 : : * @ncells: number of cells in info
147 : : *
148 : : * Return: 0 or negative error code on failure.
149 : : */
150 : 0 : static int nvmem_add_cells(struct nvmem_device *nvmem,
151 : : const struct nvmem_cell_info *info,
152 : : int ncells)
153 : : {
154 : 0 : struct nvmem_cell **cells;
155 : 0 : int i, rval;
156 : :
157 : 0 : cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
158 [ # # ]: 0 : if (!cells)
159 : : return -ENOMEM;
160 : :
161 [ # # ]: 0 : for (i = 0; i < ncells; i++) {
162 : 0 : cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
163 [ # # ]: 0 : if (!cells[i]) {
164 : 0 : rval = -ENOMEM;
165 : 0 : goto err;
166 : : }
167 : :
168 : 0 : rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
169 [ # # ]: 0 : if (rval) {
170 : 0 : kfree(cells[i]);
171 : 0 : goto err;
172 : : }
173 : :
174 : 0 : nvmem_cell_add(cells[i]);
175 : : }
176 : :
177 : : /* remove tmp array */
178 : 0 : kfree(cells);
179 : :
180 : 0 : return 0;
181 : 0 : err:
182 [ # # ]: 0 : while (i--)
183 : 0 : nvmem_cell_drop(cells[i]);
184 : :
185 : 0 : kfree(cells);
186 : :
187 : 0 : return rval;
188 : : }
189 : :
190 : : /**
191 : : * nvmem_register_notifier() - Register a notifier block for nvmem events.
192 : : *
193 : : * @nb: notifier block to be called on nvmem events.
194 : : *
195 : : * Return: 0 on success, negative error number on failure.
196 : : */
197 : 0 : int nvmem_register_notifier(struct notifier_block *nb)
198 : : {
199 : 0 : return blocking_notifier_chain_register(&nvmem_notifier, nb);
200 : : }
201 : : EXPORT_SYMBOL_GPL(nvmem_register_notifier);
202 : :
203 : : /**
204 : : * nvmem_unregister_notifier() - Unregister a notifier block for nvmem events.
205 : : *
206 : : * @nb: notifier block to be unregistered.
207 : : *
208 : : * Return: 0 on success, negative error number on failure.
209 : : */
210 : 0 : int nvmem_unregister_notifier(struct notifier_block *nb)
211 : : {
212 : 0 : return blocking_notifier_chain_unregister(&nvmem_notifier, nb);
213 : : }
214 : : EXPORT_SYMBOL_GPL(nvmem_unregister_notifier);
215 : :
216 : 13 : static int nvmem_add_cells_from_table(struct nvmem_device *nvmem)
217 : : {
218 : 13 : const struct nvmem_cell_info *info;
219 : 13 : struct nvmem_cell_table *table;
220 : 13 : struct nvmem_cell *cell;
221 : 13 : int rval = 0, i;
222 : :
223 : 13 : mutex_lock(&nvmem_cell_mutex);
224 [ - + ]: 13 : list_for_each_entry(table, &nvmem_cell_tables, node) {
225 [ # # ]: 0 : if (strcmp(nvmem_dev_name(nvmem), table->nvmem_name) == 0) {
226 [ # # ]: 0 : for (i = 0; i < table->ncells; i++) {
227 : 0 : info = &table->cells[i];
228 : :
229 : 0 : cell = kzalloc(sizeof(*cell), GFP_KERNEL);
230 [ # # ]: 0 : if (!cell) {
231 : 0 : rval = -ENOMEM;
232 : 0 : goto out;
233 : : }
234 : :
235 : 0 : rval = nvmem_cell_info_to_nvmem_cell(nvmem,
236 : : info,
237 : : cell);
238 [ # # ]: 0 : if (rval) {
239 : 0 : kfree(cell);
240 : 0 : goto out;
241 : : }
242 : :
243 : 0 : nvmem_cell_add(cell);
244 : : }
245 : : }
246 : : }
247 : :
248 : 13 : out:
249 : 13 : mutex_unlock(&nvmem_cell_mutex);
250 : 13 : return rval;
251 : : }
252 : :
253 : : static struct nvmem_cell *
254 : 0 : nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
255 : : {
256 : 0 : struct nvmem_cell *iter, *cell = NULL;
257 : :
258 : 0 : mutex_lock(&nvmem_mutex);
259 [ # # ]: 0 : list_for_each_entry(iter, &nvmem->cells, node) {
260 [ # # ]: 0 : if (strcmp(cell_id, iter->name) == 0) {
261 : : cell = iter;
262 : : break;
263 : : }
264 : : }
265 : 0 : mutex_unlock(&nvmem_mutex);
266 : :
267 : 0 : return cell;
268 : : }
269 : :
270 : 13 : static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
271 : : {
272 : 13 : struct device_node *parent, *child;
273 : 13 : struct device *dev = &nvmem->dev;
274 : 13 : struct nvmem_cell *cell;
275 : 13 : const __be32 *addr;
276 : 13 : int len;
277 : :
278 : 13 : parent = dev->of_node;
279 : :
280 : 13 : for_each_child_of_node(parent, child) {
281 : : addr = of_get_property(child, "reg", &len);
282 : : if (!addr || (len < 2 * sizeof(u32))) {
283 : : dev_err(dev, "nvmem: invalid reg on %pOF\n", child);
284 : : return -EINVAL;
285 : : }
286 : :
287 : : cell = kzalloc(sizeof(*cell), GFP_KERNEL);
288 : : if (!cell)
289 : : return -ENOMEM;
290 : :
291 : : cell->nvmem = nvmem;
292 : : cell->np = of_node_get(child);
293 : : cell->offset = be32_to_cpup(addr++);
294 : : cell->bytes = be32_to_cpup(addr);
295 : : cell->name = kasprintf(GFP_KERNEL, "%pOFn", child);
296 : :
297 : : addr = of_get_property(child, "bits", &len);
298 : : if (addr && len == (2 * sizeof(u32))) {
299 : : cell->bit_offset = be32_to_cpup(addr++);
300 : : cell->nbits = be32_to_cpup(addr);
301 : : }
302 : :
303 : : if (cell->nbits)
304 : : cell->bytes = DIV_ROUND_UP(
305 : : cell->nbits + cell->bit_offset,
306 : : BITS_PER_BYTE);
307 : :
308 : : if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
309 : : dev_err(dev, "cell %s unaligned to nvmem stride %d\n",
310 : : cell->name, nvmem->stride);
311 : : /* Cells already added will be freed later. */
312 : : kfree_const(cell->name);
313 : : kfree(cell);
314 : : return -EINVAL;
315 : : }
316 : :
317 : : nvmem_cell_add(cell);
318 : : }
319 : :
320 : 13 : return 0;
321 : : }
322 : :
323 : : /**
324 : : * nvmem_register() - Register a nvmem device for given nvmem_config.
325 : : * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
326 : : *
327 : : * @config: nvmem device configuration with which nvmem device is created.
328 : : *
329 : : * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
330 : : * on success.
331 : : */
332 : :
333 : 13 : struct nvmem_device *nvmem_register(const struct nvmem_config *config)
334 : : {
335 : 13 : struct nvmem_device *nvmem;
336 : 13 : int rval;
337 : :
338 [ + - ]: 13 : if (!config->dev)
339 : : return ERR_PTR(-EINVAL);
340 : :
341 : 13 : nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
342 [ + - ]: 13 : if (!nvmem)
343 : : return ERR_PTR(-ENOMEM);
344 : :
345 : 13 : rval = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
346 [ - + ]: 13 : if (rval < 0) {
347 : 0 : kfree(nvmem);
348 : 0 : return ERR_PTR(rval);
349 : : }
350 [ - + ]: 13 : if (config->wp_gpio)
351 : 0 : nvmem->wp_gpio = config->wp_gpio;
352 : : else
353 : 13 : nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp",
354 : : GPIOD_OUT_HIGH);
355 [ + - ]: 13 : if (IS_ERR(nvmem->wp_gpio))
356 : : return ERR_CAST(nvmem->wp_gpio);
357 : :
358 : :
359 : 13 : kref_init(&nvmem->refcnt);
360 [ + - ]: 13 : INIT_LIST_HEAD(&nvmem->cells);
361 : :
362 : 13 : nvmem->id = rval;
363 : 13 : nvmem->owner = config->owner;
364 [ + - + - ]: 13 : if (!nvmem->owner && config->dev->driver)
365 : 13 : nvmem->owner = config->dev->driver->owner;
366 [ + - ]: 13 : nvmem->stride = config->stride ?: 1;
367 [ + - ]: 13 : nvmem->word_size = config->word_size ?: 1;
368 : 13 : nvmem->size = config->size;
369 : 13 : nvmem->dev.type = &nvmem_provider_type;
370 : 13 : nvmem->dev.bus = &nvmem_bus_type;
371 : 13 : nvmem->dev.parent = config->dev;
372 : 13 : nvmem->priv = config->priv;
373 : 13 : nvmem->type = config->type;
374 : 13 : nvmem->reg_read = config->reg_read;
375 : 13 : nvmem->reg_write = config->reg_write;
376 [ + - ]: 13 : if (!config->no_of_node)
377 : 13 : nvmem->dev.of_node = config->dev->of_node;
378 : :
379 [ - + - - ]: 13 : if (config->id == -1 && config->name) {
380 : 0 : dev_set_name(&nvmem->dev, "%s", config->name);
381 : : } else {
382 [ + - ]: 26 : dev_set_name(&nvmem->dev, "%s%d",
383 : : config->name ? : "nvmem",
384 [ - + ]: 13 : config->name ? config->id : nvmem->id);
385 : : }
386 : :
387 : 13 : nvmem->read_only = device_property_present(config->dev, "read-only") ||
388 [ + - + - : 13 : config->read_only || !nvmem->reg_write;
+ - ]
389 : :
390 : 13 : nvmem->dev.groups = nvmem_sysfs_get_groups(nvmem, config);
391 : :
392 : 13 : device_initialize(&nvmem->dev);
393 : :
394 : 13 : dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
395 : :
396 : 13 : rval = device_add(&nvmem->dev);
397 [ - + ]: 13 : if (rval)
398 : 0 : goto err_put_device;
399 : :
400 [ - + ]: 13 : if (config->compat) {
401 : 0 : rval = nvmem_sysfs_setup_compat(nvmem, config);
402 [ # # ]: 0 : if (rval)
403 : 0 : goto err_device_del;
404 : : }
405 : :
406 [ - + ]: 13 : if (config->cells) {
407 : 0 : rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
408 [ # # ]: 0 : if (rval)
409 : 0 : goto err_teardown_compat;
410 : : }
411 : :
412 : 13 : rval = nvmem_add_cells_from_table(nvmem);
413 [ - + ]: 13 : if (rval)
414 : 0 : goto err_remove_cells;
415 : :
416 : 13 : rval = nvmem_add_cells_from_of(nvmem);
417 : 13 : if (rval)
418 : : goto err_remove_cells;
419 : :
420 : 13 : blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
421 : :
422 : 13 : return nvmem;
423 : :
424 : : err_remove_cells:
425 : 0 : nvmem_device_remove_all_cells(nvmem);
426 : 0 : err_teardown_compat:
427 [ # # ]: 0 : if (config->compat)
428 : 0 : nvmem_sysfs_remove_compat(nvmem, config);
429 : 0 : err_device_del:
430 : 0 : device_del(&nvmem->dev);
431 : 0 : err_put_device:
432 : 0 : put_device(&nvmem->dev);
433 : :
434 : 0 : return ERR_PTR(rval);
435 : : }
436 : : EXPORT_SYMBOL_GPL(nvmem_register);
437 : :
438 : 0 : static void nvmem_device_release(struct kref *kref)
439 : : {
440 : 0 : struct nvmem_device *nvmem;
441 : :
442 : 0 : nvmem = container_of(kref, struct nvmem_device, refcnt);
443 : :
444 : 0 : blocking_notifier_call_chain(&nvmem_notifier, NVMEM_REMOVE, nvmem);
445 : :
446 [ # # ]: 0 : if (nvmem->flags & FLAG_COMPAT)
447 : 0 : device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
448 : :
449 : 0 : nvmem_device_remove_all_cells(nvmem);
450 : 0 : device_del(&nvmem->dev);
451 : 0 : put_device(&nvmem->dev);
452 : 0 : }
453 : :
454 : : /**
455 : : * nvmem_unregister() - Unregister previously registered nvmem device
456 : : *
457 : : * @nvmem: Pointer to previously registered nvmem device.
458 : : */
459 : 0 : void nvmem_unregister(struct nvmem_device *nvmem)
460 : : {
461 : 0 : kref_put(&nvmem->refcnt, nvmem_device_release);
462 : 0 : }
463 : : EXPORT_SYMBOL_GPL(nvmem_unregister);
464 : :
465 : 0 : static void devm_nvmem_release(struct device *dev, void *res)
466 : : {
467 : 0 : nvmem_unregister(*(struct nvmem_device **)res);
468 : 0 : }
469 : :
470 : : /**
471 : : * devm_nvmem_register() - Register a managed nvmem device for given
472 : : * nvmem_config.
473 : : * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
474 : : *
475 : : * @dev: Device that uses the nvmem device.
476 : : * @config: nvmem device configuration with which nvmem device is created.
477 : : *
478 : : * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
479 : : * on success.
480 : : */
481 : 13 : struct nvmem_device *devm_nvmem_register(struct device *dev,
482 : : const struct nvmem_config *config)
483 : : {
484 : 13 : struct nvmem_device **ptr, *nvmem;
485 : :
486 : 13 : ptr = devres_alloc(devm_nvmem_release, sizeof(*ptr), GFP_KERNEL);
487 [ + - ]: 13 : if (!ptr)
488 : : return ERR_PTR(-ENOMEM);
489 : :
490 : 13 : nvmem = nvmem_register(config);
491 : :
492 [ + - ]: 13 : if (!IS_ERR(nvmem)) {
493 : 13 : *ptr = nvmem;
494 : 13 : devres_add(dev, ptr);
495 : : } else {
496 : 0 : devres_free(ptr);
497 : : }
498 : :
499 : : return nvmem;
500 : : }
501 : : EXPORT_SYMBOL_GPL(devm_nvmem_register);
502 : :
503 : 0 : static int devm_nvmem_match(struct device *dev, void *res, void *data)
504 : : {
505 : 0 : struct nvmem_device **r = res;
506 : :
507 : 0 : return *r == data;
508 : : }
509 : :
510 : : /**
511 : : * devm_nvmem_unregister() - Unregister previously registered managed nvmem
512 : : * device.
513 : : *
514 : : * @dev: Device that uses the nvmem device.
515 : : * @nvmem: Pointer to previously registered nvmem device.
516 : : *
517 : : * Return: Will be an negative on error or a zero on success.
518 : : */
519 : 0 : int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
520 : : {
521 : 0 : return devres_release(dev, devm_nvmem_release, devm_nvmem_match, nvmem);
522 : : }
523 : : EXPORT_SYMBOL(devm_nvmem_unregister);
524 : :
525 : 0 : static struct nvmem_device *__nvmem_device_get(void *data,
526 : : int (*match)(struct device *dev, const void *data))
527 : : {
528 : 0 : struct nvmem_device *nvmem = NULL;
529 : 0 : struct device *dev;
530 : :
531 : 0 : mutex_lock(&nvmem_mutex);
532 : 0 : dev = bus_find_device(&nvmem_bus_type, NULL, data, match);
533 [ # # ]: 0 : if (dev)
534 : 0 : nvmem = to_nvmem_device(dev);
535 : 0 : mutex_unlock(&nvmem_mutex);
536 [ # # ]: 0 : if (!nvmem)
537 : : return ERR_PTR(-EPROBE_DEFER);
538 : :
539 [ # # ]: 0 : if (!try_module_get(nvmem->owner)) {
540 : 0 : dev_err(&nvmem->dev,
541 : : "could not increase module refcount for cell %s\n",
542 : : nvmem_dev_name(nvmem));
543 : :
544 : 0 : put_device(&nvmem->dev);
545 : 0 : return ERR_PTR(-EINVAL);
546 : : }
547 : :
548 : 0 : kref_get(&nvmem->refcnt);
549 : :
550 : 0 : return nvmem;
551 : : }
552 : :
553 : 0 : static void __nvmem_device_put(struct nvmem_device *nvmem)
554 : : {
555 : 0 : put_device(&nvmem->dev);
556 : 0 : module_put(nvmem->owner);
557 : 0 : kref_put(&nvmem->refcnt, nvmem_device_release);
558 : 0 : }
559 : :
560 : : #if IS_ENABLED(CONFIG_OF)
561 : : /**
562 : : * of_nvmem_device_get() - Get nvmem device from a given id
563 : : *
564 : : * @np: Device tree node that uses the nvmem device.
565 : : * @id: nvmem name from nvmem-names property.
566 : : *
567 : : * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
568 : : * on success.
569 : : */
570 : : struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
571 : : {
572 : :
573 : : struct device_node *nvmem_np;
574 : : int index = 0;
575 : :
576 : : if (id)
577 : : index = of_property_match_string(np, "nvmem-names", id);
578 : :
579 : : nvmem_np = of_parse_phandle(np, "nvmem", index);
580 : : if (!nvmem_np)
581 : : return ERR_PTR(-ENOENT);
582 : :
583 : : return __nvmem_device_get(nvmem_np, device_match_of_node);
584 : : }
585 : : EXPORT_SYMBOL_GPL(of_nvmem_device_get);
586 : : #endif
587 : :
588 : : /**
589 : : * nvmem_device_get() - Get nvmem device from a given id
590 : : *
591 : : * @dev: Device that uses the nvmem device.
592 : : * @dev_name: name of the requested nvmem device.
593 : : *
594 : : * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
595 : : * on success.
596 : : */
597 : 0 : struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
598 : : {
599 : 0 : if (dev->of_node) { /* try dt first */
600 : : struct nvmem_device *nvmem;
601 : :
602 : : nvmem = of_nvmem_device_get(dev->of_node, dev_name);
603 : :
604 : : if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
605 : : return nvmem;
606 : :
607 : : }
608 : :
609 : 0 : return __nvmem_device_get((void *)dev_name, device_match_name);
610 : : }
611 : : EXPORT_SYMBOL_GPL(nvmem_device_get);
612 : :
613 : : /**
614 : : * nvmem_device_find() - Find nvmem device with matching function
615 : : *
616 : : * @data: Data to pass to match function
617 : : * @match: Callback function to check device
618 : : *
619 : : * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
620 : : * on success.
621 : : */
622 : 0 : struct nvmem_device *nvmem_device_find(void *data,
623 : : int (*match)(struct device *dev, const void *data))
624 : : {
625 : 0 : return __nvmem_device_get(data, match);
626 : : }
627 : : EXPORT_SYMBOL_GPL(nvmem_device_find);
628 : :
629 : 0 : static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
630 : : {
631 : 0 : struct nvmem_device **nvmem = res;
632 : :
633 [ # # # # : 0 : if (WARN_ON(!nvmem || !*nvmem))
# # # # ]
634 : : return 0;
635 : :
636 : 0 : return *nvmem == data;
637 : : }
638 : :
639 : 0 : static void devm_nvmem_device_release(struct device *dev, void *res)
640 : : {
641 : 0 : nvmem_device_put(*(struct nvmem_device **)res);
642 : 0 : }
643 : :
644 : : /**
645 : : * devm_nvmem_device_put() - put alredy got nvmem device
646 : : *
647 : : * @dev: Device that uses the nvmem device.
648 : : * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
649 : : * that needs to be released.
650 : : */
651 : 0 : void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
652 : : {
653 : 0 : int ret;
654 : :
655 : 0 : ret = devres_release(dev, devm_nvmem_device_release,
656 : : devm_nvmem_device_match, nvmem);
657 : :
658 [ # # ]: 0 : WARN_ON(ret);
659 : 0 : }
660 : : EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
661 : :
662 : : /**
663 : : * nvmem_device_put() - put alredy got nvmem device
664 : : *
665 : : * @nvmem: pointer to nvmem device that needs to be released.
666 : : */
667 : 0 : void nvmem_device_put(struct nvmem_device *nvmem)
668 : : {
669 : 0 : __nvmem_device_put(nvmem);
670 : 0 : }
671 : : EXPORT_SYMBOL_GPL(nvmem_device_put);
672 : :
673 : : /**
674 : : * devm_nvmem_device_get() - Get nvmem cell of device form a given id
675 : : *
676 : : * @dev: Device that requests the nvmem device.
677 : : * @id: name id for the requested nvmem device.
678 : : *
679 : : * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell
680 : : * on success. The nvmem_cell will be freed by the automatically once the
681 : : * device is freed.
682 : : */
683 : 0 : struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
684 : : {
685 : 0 : struct nvmem_device **ptr, *nvmem;
686 : :
687 : 0 : ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
688 [ # # ]: 0 : if (!ptr)
689 : : return ERR_PTR(-ENOMEM);
690 : :
691 : 0 : nvmem = nvmem_device_get(dev, id);
692 [ # # ]: 0 : if (!IS_ERR(nvmem)) {
693 : 0 : *ptr = nvmem;
694 : 0 : devres_add(dev, ptr);
695 : : } else {
696 : 0 : devres_free(ptr);
697 : : }
698 : :
699 : : return nvmem;
700 : : }
701 : : EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
702 : :
703 : : static struct nvmem_cell *
704 : 0 : nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
705 : : {
706 [ # # ]: 0 : struct nvmem_cell *cell = ERR_PTR(-ENOENT);
707 : 0 : struct nvmem_cell_lookup *lookup;
708 : 0 : struct nvmem_device *nvmem;
709 : 0 : const char *dev_id;
710 : :
711 [ # # ]: 0 : if (!dev)
712 : : return ERR_PTR(-EINVAL);
713 : :
714 [ # # ]: 0 : dev_id = dev_name(dev);
715 : :
716 : 0 : mutex_lock(&nvmem_lookup_mutex);
717 : :
718 [ # # ]: 0 : list_for_each_entry(lookup, &nvmem_lookup_list, node) {
719 [ # # ]: 0 : if ((strcmp(lookup->dev_id, dev_id) == 0) &&
720 [ # # ]: 0 : (strcmp(lookup->con_id, con_id) == 0)) {
721 : : /* This is the right entry. */
722 : 0 : nvmem = __nvmem_device_get((void *)lookup->nvmem_name,
723 : : device_match_name);
724 [ # # ]: 0 : if (IS_ERR(nvmem)) {
725 : : /* Provider may not be registered yet. */
726 : : cell = ERR_CAST(nvmem);
727 : : break;
728 : : }
729 : :
730 : 0 : cell = nvmem_find_cell_by_name(nvmem,
731 : : lookup->cell_name);
732 [ # # ]: 0 : if (!cell) {
733 : 0 : __nvmem_device_put(nvmem);
734 : 0 : cell = ERR_PTR(-ENOENT);
735 : : }
736 : : break;
737 : : }
738 : : }
739 : :
740 : 0 : mutex_unlock(&nvmem_lookup_mutex);
741 : 0 : return cell;
742 : : }
743 : :
744 : : #if IS_ENABLED(CONFIG_OF)
745 : : static struct nvmem_cell *
746 : : nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
747 : : {
748 : : struct nvmem_cell *iter, *cell = NULL;
749 : :
750 : : mutex_lock(&nvmem_mutex);
751 : : list_for_each_entry(iter, &nvmem->cells, node) {
752 : : if (np == iter->np) {
753 : : cell = iter;
754 : : break;
755 : : }
756 : : }
757 : : mutex_unlock(&nvmem_mutex);
758 : :
759 : : return cell;
760 : : }
761 : :
762 : : /**
763 : : * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
764 : : *
765 : : * @np: Device tree node that uses the nvmem cell.
766 : : * @id: nvmem cell name from nvmem-cell-names property, or NULL
767 : : * for the cell at index 0 (the lone cell with no accompanying
768 : : * nvmem-cell-names property).
769 : : *
770 : : * Return: Will be an ERR_PTR() on error or a valid pointer
771 : : * to a struct nvmem_cell. The nvmem_cell will be freed by the
772 : : * nvmem_cell_put().
773 : : */
774 : : struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
775 : : {
776 : : struct device_node *cell_np, *nvmem_np;
777 : : struct nvmem_device *nvmem;
778 : : struct nvmem_cell *cell;
779 : : int index = 0;
780 : :
781 : : /* if cell name exists, find index to the name */
782 : : if (id)
783 : : index = of_property_match_string(np, "nvmem-cell-names", id);
784 : :
785 : : cell_np = of_parse_phandle(np, "nvmem-cells", index);
786 : : if (!cell_np)
787 : : return ERR_PTR(-ENOENT);
788 : :
789 : : nvmem_np = of_get_next_parent(cell_np);
790 : : if (!nvmem_np)
791 : : return ERR_PTR(-EINVAL);
792 : :
793 : : nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
794 : : of_node_put(nvmem_np);
795 : : if (IS_ERR(nvmem))
796 : : return ERR_CAST(nvmem);
797 : :
798 : : cell = nvmem_find_cell_by_node(nvmem, cell_np);
799 : : if (!cell) {
800 : : __nvmem_device_put(nvmem);
801 : : return ERR_PTR(-ENOENT);
802 : : }
803 : :
804 : : return cell;
805 : : }
806 : : EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
807 : : #endif
808 : :
809 : : /**
810 : : * nvmem_cell_get() - Get nvmem cell of device form a given cell name
811 : : *
812 : : * @dev: Device that requests the nvmem cell.
813 : : * @id: nvmem cell name to get (this corresponds with the name from the
814 : : * nvmem-cell-names property for DT systems and with the con_id from
815 : : * the lookup entry for non-DT systems).
816 : : *
817 : : * Return: Will be an ERR_PTR() on error or a valid pointer
818 : : * to a struct nvmem_cell. The nvmem_cell will be freed by the
819 : : * nvmem_cell_put().
820 : : */
821 : 0 : struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *id)
822 : : {
823 : 0 : struct nvmem_cell *cell;
824 : :
825 : 0 : if (dev->of_node) { /* try dt first */
826 : : cell = of_nvmem_cell_get(dev->of_node, id);
827 : : if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
828 : : return cell;
829 : : }
830 : :
831 : : /* NULL cell id only allowed for device tree; invalid otherwise */
832 [ # # ]: 0 : if (!id)
833 : : return ERR_PTR(-EINVAL);
834 : :
835 : 0 : return nvmem_cell_get_from_lookup(dev, id);
836 : : }
837 : : EXPORT_SYMBOL_GPL(nvmem_cell_get);
838 : :
839 : 0 : static void devm_nvmem_cell_release(struct device *dev, void *res)
840 : : {
841 : 0 : nvmem_cell_put(*(struct nvmem_cell **)res);
842 : 0 : }
843 : :
844 : : /**
845 : : * devm_nvmem_cell_get() - Get nvmem cell of device form a given id
846 : : *
847 : : * @dev: Device that requests the nvmem cell.
848 : : * @id: nvmem cell name id to get.
849 : : *
850 : : * Return: Will be an ERR_PTR() on error or a valid pointer
851 : : * to a struct nvmem_cell. The nvmem_cell will be freed by the
852 : : * automatically once the device is freed.
853 : : */
854 : 0 : struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id)
855 : : {
856 : 0 : struct nvmem_cell **ptr, *cell;
857 : :
858 : 0 : ptr = devres_alloc(devm_nvmem_cell_release, sizeof(*ptr), GFP_KERNEL);
859 [ # # ]: 0 : if (!ptr)
860 : : return ERR_PTR(-ENOMEM);
861 : :
862 [ # # ]: 0 : cell = nvmem_cell_get(dev, id);
863 [ # # ]: 0 : if (!IS_ERR(cell)) {
864 : 0 : *ptr = cell;
865 : 0 : devres_add(dev, ptr);
866 : : } else {
867 : 0 : devres_free(ptr);
868 : : }
869 : :
870 : : return cell;
871 : : }
872 : : EXPORT_SYMBOL_GPL(devm_nvmem_cell_get);
873 : :
874 : 0 : static int devm_nvmem_cell_match(struct device *dev, void *res, void *data)
875 : : {
876 : 0 : struct nvmem_cell **c = res;
877 : :
878 [ # # # # : 0 : if (WARN_ON(!c || !*c))
# # # # ]
879 : : return 0;
880 : :
881 : 0 : return *c == data;
882 : : }
883 : :
884 : : /**
885 : : * devm_nvmem_cell_put() - Release previously allocated nvmem cell
886 : : * from devm_nvmem_cell_get.
887 : : *
888 : : * @dev: Device that requests the nvmem cell.
889 : : * @cell: Previously allocated nvmem cell by devm_nvmem_cell_get().
890 : : */
891 : 0 : void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell)
892 : : {
893 : 0 : int ret;
894 : :
895 : 0 : ret = devres_release(dev, devm_nvmem_cell_release,
896 : : devm_nvmem_cell_match, cell);
897 : :
898 [ # # ]: 0 : WARN_ON(ret);
899 : 0 : }
900 : : EXPORT_SYMBOL(devm_nvmem_cell_put);
901 : :
902 : : /**
903 : : * nvmem_cell_put() - Release previously allocated nvmem cell.
904 : : *
905 : : * @cell: Previously allocated nvmem cell by nvmem_cell_get().
906 : : */
907 : 0 : void nvmem_cell_put(struct nvmem_cell *cell)
908 : : {
909 : 0 : struct nvmem_device *nvmem = cell->nvmem;
910 : :
911 : 0 : __nvmem_device_put(nvmem);
912 : 0 : }
913 : : EXPORT_SYMBOL_GPL(nvmem_cell_put);
914 : :
915 : 0 : static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)
916 : : {
917 : 0 : u8 *p, *b;
918 : 0 : int i, extra, bit_offset = cell->bit_offset;
919 : :
920 : 0 : p = b = buf;
921 [ # # ]: 0 : if (bit_offset) {
922 : : /* First shift */
923 : 0 : *b++ >>= bit_offset;
924 : :
925 : : /* setup rest of the bytes if any */
926 [ # # ]: 0 : for (i = 1; i < cell->bytes; i++) {
927 : : /* Get bits from next byte and shift them towards msb */
928 : 0 : *p |= *b << (BITS_PER_BYTE - bit_offset);
929 : :
930 : 0 : p = b;
931 : 0 : *b++ >>= bit_offset;
932 : : }
933 : : } else {
934 : : /* point to the msb */
935 : 0 : p += cell->bytes - 1;
936 : : }
937 : :
938 : : /* result fits in less bytes */
939 : 0 : extra = cell->bytes - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);
940 [ # # ]: 0 : while (--extra >= 0)
941 : 0 : *p-- = 0;
942 : :
943 : : /* clear msb bits if any leftover in the last byte */
944 : 0 : *p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
945 : 0 : }
946 : :
947 : 0 : static int __nvmem_cell_read(struct nvmem_device *nvmem,
948 : : struct nvmem_cell *cell,
949 : : void *buf, size_t *len)
950 : : {
951 : 0 : int rc;
952 : :
953 [ # # ]: 0 : rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
954 : :
955 [ # # ]: 0 : if (rc)
956 : 0 : return rc;
957 : :
958 : : /* shift bits in-place */
959 [ # # ]: 0 : if (cell->bit_offset || cell->nbits)
960 : 0 : nvmem_shift_read_buffer_in_place(cell, buf);
961 : :
962 [ # # ]: 0 : if (len)
963 : 0 : *len = cell->bytes;
964 : :
965 : : return 0;
966 : : }
967 : :
968 : : /**
969 : : * nvmem_cell_read() - Read a given nvmem cell
970 : : *
971 : : * @cell: nvmem cell to be read.
972 : : * @len: pointer to length of cell which will be populated on successful read;
973 : : * can be NULL.
974 : : *
975 : : * Return: ERR_PTR() on error or a valid pointer to a buffer on success. The
976 : : * buffer should be freed by the consumer with a kfree().
977 : : */
978 : 0 : void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
979 : : {
980 : 0 : struct nvmem_device *nvmem = cell->nvmem;
981 : 0 : u8 *buf;
982 : 0 : int rc;
983 : :
984 [ # # ]: 0 : if (!nvmem)
985 : : return ERR_PTR(-EINVAL);
986 : :
987 : 0 : buf = kzalloc(cell->bytes, GFP_KERNEL);
988 [ # # ]: 0 : if (!buf)
989 : : return ERR_PTR(-ENOMEM);
990 : :
991 : 0 : rc = __nvmem_cell_read(nvmem, cell, buf, len);
992 [ # # ]: 0 : if (rc) {
993 : 0 : kfree(buf);
994 : 0 : return ERR_PTR(rc);
995 : : }
996 : :
997 : : return buf;
998 : : }
999 : : EXPORT_SYMBOL_GPL(nvmem_cell_read);
1000 : :
1001 : 0 : static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
1002 : : u8 *_buf, int len)
1003 : : {
1004 : 0 : struct nvmem_device *nvmem = cell->nvmem;
1005 : 0 : int i, rc, nbits, bit_offset = cell->bit_offset;
1006 : 0 : u8 v, *p, *buf, *b, pbyte, pbits;
1007 : :
1008 : 0 : nbits = cell->nbits;
1009 : 0 : buf = kzalloc(cell->bytes, GFP_KERNEL);
1010 [ # # ]: 0 : if (!buf)
1011 : : return ERR_PTR(-ENOMEM);
1012 : :
1013 : 0 : memcpy(buf, _buf, len);
1014 : 0 : p = b = buf;
1015 : :
1016 [ # # ]: 0 : if (bit_offset) {
1017 : 0 : pbyte = *b;
1018 : 0 : *b <<= bit_offset;
1019 : :
1020 : : /* setup the first byte with lsb bits from nvmem */
1021 [ # # ]: 0 : rc = nvmem_reg_read(nvmem, cell->offset, &v, 1);
1022 [ # # ]: 0 : if (rc)
1023 : 0 : goto err;
1024 : 0 : *b++ |= GENMASK(bit_offset - 1, 0) & v;
1025 : :
1026 : : /* setup rest of the byte if any */
1027 [ # # ]: 0 : for (i = 1; i < cell->bytes; i++) {
1028 : : /* Get last byte bits and shift them towards lsb */
1029 : 0 : pbits = pbyte >> (BITS_PER_BYTE - 1 - bit_offset);
1030 : 0 : pbyte = *b;
1031 : 0 : p = b;
1032 : 0 : *b <<= bit_offset;
1033 : 0 : *b++ |= pbits;
1034 : : }
1035 : : }
1036 : :
1037 : : /* if it's not end on byte boundary */
1038 [ # # ]: 0 : if ((nbits + bit_offset) % BITS_PER_BYTE) {
1039 : : /* setup the last byte with msb bits from nvmem */
1040 : 0 : rc = nvmem_reg_read(nvmem,
1041 [ # # ]: 0 : cell->offset + cell->bytes - 1, &v, 1);
1042 [ # # ]: 0 : if (rc)
1043 : 0 : goto err;
1044 : 0 : *p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
1045 : :
1046 : : }
1047 : :
1048 : : return buf;
1049 : 0 : err:
1050 : 0 : kfree(buf);
1051 : 0 : return ERR_PTR(rc);
1052 : : }
1053 : :
1054 : : /**
1055 : : * nvmem_cell_write() - Write to a given nvmem cell
1056 : : *
1057 : : * @cell: nvmem cell to be written.
1058 : : * @buf: Buffer to be written.
1059 : : * @len: length of buffer to be written to nvmem cell.
1060 : : *
1061 : : * Return: length of bytes written or negative on failure.
1062 : : */
1063 : 0 : int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
1064 : : {
1065 : 0 : struct nvmem_device *nvmem = cell->nvmem;
1066 : 0 : int rc;
1067 : :
1068 [ # # # # ]: 0 : if (!nvmem || nvmem->read_only ||
1069 [ # # # # ]: 0 : (cell->bit_offset == 0 && len != cell->bytes))
1070 : : return -EINVAL;
1071 : :
1072 [ # # ]: 0 : if (cell->bit_offset || cell->nbits) {
1073 : 0 : buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
1074 [ # # ]: 0 : if (IS_ERR(buf))
1075 : 0 : return PTR_ERR(buf);
1076 : : }
1077 : :
1078 : 0 : rc = nvmem_reg_write(nvmem, cell->offset, buf, cell->bytes);
1079 : :
1080 : : /* free the tmp buffer */
1081 [ # # ]: 0 : if (cell->bit_offset || cell->nbits)
1082 : 0 : kfree(buf);
1083 : :
1084 [ # # ]: 0 : if (rc)
1085 : : return rc;
1086 : :
1087 : 0 : return len;
1088 : : }
1089 : : EXPORT_SYMBOL_GPL(nvmem_cell_write);
1090 : :
1091 : : /**
1092 : : * nvmem_cell_read_u16() - Read a cell value as an u16
1093 : : *
1094 : : * @dev: Device that requests the nvmem cell.
1095 : : * @cell_id: Name of nvmem cell to read.
1096 : : * @val: pointer to output value.
1097 : : *
1098 : : * Return: 0 on success or negative errno.
1099 : : */
1100 : 0 : int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
1101 : : {
1102 : 0 : struct nvmem_cell *cell;
1103 : 0 : void *buf;
1104 : 0 : size_t len;
1105 : :
1106 [ # # ]: 0 : cell = nvmem_cell_get(dev, cell_id);
1107 [ # # ]: 0 : if (IS_ERR(cell))
1108 : 0 : return PTR_ERR(cell);
1109 : :
1110 : 0 : buf = nvmem_cell_read(cell, &len);
1111 [ # # ]: 0 : if (IS_ERR(buf)) {
1112 : 0 : nvmem_cell_put(cell);
1113 : 0 : return PTR_ERR(buf);
1114 : : }
1115 [ # # ]: 0 : if (len != sizeof(*val)) {
1116 : 0 : kfree(buf);
1117 : 0 : nvmem_cell_put(cell);
1118 : 0 : return -EINVAL;
1119 : : }
1120 : 0 : memcpy(val, buf, sizeof(*val));
1121 : 0 : kfree(buf);
1122 : 0 : nvmem_cell_put(cell);
1123 : :
1124 : 0 : return 0;
1125 : : }
1126 : : EXPORT_SYMBOL_GPL(nvmem_cell_read_u16);
1127 : :
1128 : : /**
1129 : : * nvmem_cell_read_u32() - Read a cell value as an u32
1130 : : *
1131 : : * @dev: Device that requests the nvmem cell.
1132 : : * @cell_id: Name of nvmem cell to read.
1133 : : * @val: pointer to output value.
1134 : : *
1135 : : * Return: 0 on success or negative errno.
1136 : : */
1137 : 0 : int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val)
1138 : : {
1139 : 0 : struct nvmem_cell *cell;
1140 : 0 : void *buf;
1141 : 0 : size_t len;
1142 : :
1143 [ # # ]: 0 : cell = nvmem_cell_get(dev, cell_id);
1144 [ # # ]: 0 : if (IS_ERR(cell))
1145 : 0 : return PTR_ERR(cell);
1146 : :
1147 : 0 : buf = nvmem_cell_read(cell, &len);
1148 [ # # ]: 0 : if (IS_ERR(buf)) {
1149 : 0 : nvmem_cell_put(cell);
1150 : 0 : return PTR_ERR(buf);
1151 : : }
1152 [ # # ]: 0 : if (len != sizeof(*val)) {
1153 : 0 : kfree(buf);
1154 : 0 : nvmem_cell_put(cell);
1155 : 0 : return -EINVAL;
1156 : : }
1157 : 0 : memcpy(val, buf, sizeof(*val));
1158 : :
1159 : 0 : kfree(buf);
1160 : 0 : nvmem_cell_put(cell);
1161 : 0 : return 0;
1162 : : }
1163 : : EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
1164 : :
1165 : : /**
1166 : : * nvmem_device_cell_read() - Read a given nvmem device and cell
1167 : : *
1168 : : * @nvmem: nvmem device to read from.
1169 : : * @info: nvmem cell info to be read.
1170 : : * @buf: buffer pointer which will be populated on successful read.
1171 : : *
1172 : : * Return: length of successful bytes read on success and negative
1173 : : * error code on error.
1174 : : */
1175 : 0 : ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
1176 : : struct nvmem_cell_info *info, void *buf)
1177 : : {
1178 : 0 : struct nvmem_cell cell;
1179 : 0 : int rc;
1180 : 0 : ssize_t len;
1181 : :
1182 [ # # ]: 0 : if (!nvmem)
1183 : : return -EINVAL;
1184 : :
1185 : 0 : rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
1186 [ # # ]: 0 : if (rc)
1187 : 0 : return rc;
1188 : :
1189 : 0 : rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
1190 [ # # ]: 0 : if (rc)
1191 : 0 : return rc;
1192 : :
1193 : 0 : return len;
1194 : : }
1195 : : EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
1196 : :
1197 : : /**
1198 : : * nvmem_device_cell_write() - Write cell to a given nvmem device
1199 : : *
1200 : : * @nvmem: nvmem device to be written to.
1201 : : * @info: nvmem cell info to be written.
1202 : : * @buf: buffer to be written to cell.
1203 : : *
1204 : : * Return: length of bytes written or negative error code on failure.
1205 : : */
1206 : 0 : int nvmem_device_cell_write(struct nvmem_device *nvmem,
1207 : : struct nvmem_cell_info *info, void *buf)
1208 : : {
1209 : 0 : struct nvmem_cell cell;
1210 : 0 : int rc;
1211 : :
1212 [ # # ]: 0 : if (!nvmem)
1213 : : return -EINVAL;
1214 : :
1215 : 0 : rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
1216 [ # # ]: 0 : if (rc)
1217 : : return rc;
1218 : :
1219 : 0 : return nvmem_cell_write(&cell, buf, cell.bytes);
1220 : : }
1221 : : EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
1222 : :
1223 : : /**
1224 : : * nvmem_device_read() - Read from a given nvmem device
1225 : : *
1226 : : * @nvmem: nvmem device to read from.
1227 : : * @offset: offset in nvmem device.
1228 : : * @bytes: number of bytes to read.
1229 : : * @buf: buffer pointer which will be populated on successful read.
1230 : : *
1231 : : * Return: length of successful bytes read on success and negative
1232 : : * error code on error.
1233 : : */
1234 : 0 : int nvmem_device_read(struct nvmem_device *nvmem,
1235 : : unsigned int offset,
1236 : : size_t bytes, void *buf)
1237 : : {
1238 : 0 : int rc;
1239 : :
1240 [ # # ]: 0 : if (!nvmem)
1241 : : return -EINVAL;
1242 : :
1243 [ # # ]: 0 : rc = nvmem_reg_read(nvmem, offset, buf, bytes);
1244 : :
1245 [ # # ]: 0 : if (rc)
1246 : 0 : return rc;
1247 : :
1248 : 0 : return bytes;
1249 : : }
1250 : : EXPORT_SYMBOL_GPL(nvmem_device_read);
1251 : :
1252 : : /**
1253 : : * nvmem_device_write() - Write cell to a given nvmem device
1254 : : *
1255 : : * @nvmem: nvmem device to be written to.
1256 : : * @offset: offset in nvmem device.
1257 : : * @bytes: number of bytes to write.
1258 : : * @buf: buffer to be written.
1259 : : *
1260 : : * Return: length of bytes written or negative error code on failure.
1261 : : */
1262 : 0 : int nvmem_device_write(struct nvmem_device *nvmem,
1263 : : unsigned int offset,
1264 : : size_t bytes, void *buf)
1265 : : {
1266 : 0 : int rc;
1267 : :
1268 [ # # ]: 0 : if (!nvmem)
1269 : : return -EINVAL;
1270 : :
1271 : 0 : rc = nvmem_reg_write(nvmem, offset, buf, bytes);
1272 : :
1273 [ # # ]: 0 : if (rc)
1274 : : return rc;
1275 : :
1276 : :
1277 : 0 : return bytes;
1278 : : }
1279 : : EXPORT_SYMBOL_GPL(nvmem_device_write);
1280 : :
1281 : : /**
1282 : : * nvmem_add_cell_table() - register a table of cell info entries
1283 : : *
1284 : : * @table: table of cell info entries
1285 : : */
1286 : 0 : void nvmem_add_cell_table(struct nvmem_cell_table *table)
1287 : : {
1288 : 0 : mutex_lock(&nvmem_cell_mutex);
1289 : 0 : list_add_tail(&table->node, &nvmem_cell_tables);
1290 : 0 : mutex_unlock(&nvmem_cell_mutex);
1291 : 0 : }
1292 : : EXPORT_SYMBOL_GPL(nvmem_add_cell_table);
1293 : :
1294 : : /**
1295 : : * nvmem_del_cell_table() - remove a previously registered cell info table
1296 : : *
1297 : : * @table: table of cell info entries
1298 : : */
1299 : 0 : void nvmem_del_cell_table(struct nvmem_cell_table *table)
1300 : : {
1301 : 0 : mutex_lock(&nvmem_cell_mutex);
1302 : 0 : list_del(&table->node);
1303 : 0 : mutex_unlock(&nvmem_cell_mutex);
1304 : 0 : }
1305 : : EXPORT_SYMBOL_GPL(nvmem_del_cell_table);
1306 : :
1307 : : /**
1308 : : * nvmem_add_cell_lookups() - register a list of cell lookup entries
1309 : : *
1310 : : * @entries: array of cell lookup entries
1311 : : * @nentries: number of cell lookup entries in the array
1312 : : */
1313 : 0 : void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
1314 : : {
1315 : 0 : int i;
1316 : :
1317 : 0 : mutex_lock(&nvmem_lookup_mutex);
1318 [ # # ]: 0 : for (i = 0; i < nentries; i++)
1319 : 0 : list_add_tail(&entries[i].node, &nvmem_lookup_list);
1320 : 0 : mutex_unlock(&nvmem_lookup_mutex);
1321 : 0 : }
1322 : : EXPORT_SYMBOL_GPL(nvmem_add_cell_lookups);
1323 : :
1324 : : /**
1325 : : * nvmem_del_cell_lookups() - remove a list of previously added cell lookup
1326 : : * entries
1327 : : *
1328 : : * @entries: array of cell lookup entries
1329 : : * @nentries: number of cell lookup entries in the array
1330 : : */
1331 : 0 : void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
1332 : : {
1333 : 0 : int i;
1334 : :
1335 : 0 : mutex_lock(&nvmem_lookup_mutex);
1336 [ # # ]: 0 : for (i = 0; i < nentries; i++)
1337 : 0 : list_del(&entries[i].node);
1338 : 0 : mutex_unlock(&nvmem_lookup_mutex);
1339 : 0 : }
1340 : : EXPORT_SYMBOL_GPL(nvmem_del_cell_lookups);
1341 : :
1342 : : /**
1343 : : * nvmem_dev_name() - Get the name of a given nvmem device.
1344 : : *
1345 : : * @nvmem: nvmem device.
1346 : : *
1347 : : * Return: name of the nvmem device.
1348 : : */
1349 : 0 : const char *nvmem_dev_name(struct nvmem_device *nvmem)
1350 : : {
1351 [ # # # # : 0 : return dev_name(&nvmem->dev);
# # ]
1352 : : }
1353 : : EXPORT_SYMBOL_GPL(nvmem_dev_name);
1354 : :
1355 : 13 : static int __init nvmem_init(void)
1356 : : {
1357 : 13 : return bus_register(&nvmem_bus_type);
1358 : : }
1359 : :
1360 : 0 : static void __exit nvmem_exit(void)
1361 : : {
1362 : 0 : bus_unregister(&nvmem_bus_type);
1363 : 0 : }
1364 : :
1365 : : subsys_initcall(nvmem_init);
1366 : : module_exit(nvmem_exit);
1367 : :
1368 : : MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
1369 : : MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
1370 : : MODULE_DESCRIPTION("nvmem Driver Core");
1371 : : MODULE_LICENSE("GPL v2");
|