xref: /linux/drivers/nvmem/core.c (revision f60442ddc40c21a99720ee990d5924c80a24728d)
1b1c1db98SBartosz Golaszewski // SPDX-License-Identifier: GPL-2.0
2eace75cfSSrinivas Kandagatla /*
3eace75cfSSrinivas Kandagatla  * nvmem framework core.
4eace75cfSSrinivas Kandagatla  *
5eace75cfSSrinivas Kandagatla  * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
6eace75cfSSrinivas Kandagatla  * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
7eace75cfSSrinivas Kandagatla  */
8eace75cfSSrinivas Kandagatla 
9eace75cfSSrinivas Kandagatla #include <linux/device.h>
10eace75cfSSrinivas Kandagatla #include <linux/export.h>
11eace75cfSSrinivas Kandagatla #include <linux/fs.h>
12eace75cfSSrinivas Kandagatla #include <linux/idr.h>
13eace75cfSSrinivas Kandagatla #include <linux/init.h>
14c1de7f43SBartosz Golaszewski #include <linux/kref.h>
15eace75cfSSrinivas Kandagatla #include <linux/module.h>
16eace75cfSSrinivas Kandagatla #include <linux/nvmem-consumer.h>
17eace75cfSSrinivas Kandagatla #include <linux/nvmem-provider.h>
182a127da4SKhouloud Touil #include <linux/gpio/consumer.h>
19eace75cfSSrinivas Kandagatla #include <linux/of.h>
20eace75cfSSrinivas Kandagatla #include <linux/slab.h>
21ae0c2d72SSrinivas Kandagatla #include "nvmem.h"
22b6c217abSAndrew Lunn 
23eace75cfSSrinivas Kandagatla struct nvmem_cell {
24eace75cfSSrinivas Kandagatla 	const char		*name;
25eace75cfSSrinivas Kandagatla 	int			offset;
26eace75cfSSrinivas Kandagatla 	int			bytes;
27eace75cfSSrinivas Kandagatla 	int			bit_offset;
28eace75cfSSrinivas Kandagatla 	int			nbits;
290749aa25SSrinivas Kandagatla 	struct device_node	*np;
30eace75cfSSrinivas Kandagatla 	struct nvmem_device	*nvmem;
31eace75cfSSrinivas Kandagatla 	struct list_head	node;
32eace75cfSSrinivas Kandagatla };
33eace75cfSSrinivas Kandagatla 
34eace75cfSSrinivas Kandagatla static DEFINE_MUTEX(nvmem_mutex);
35eace75cfSSrinivas Kandagatla static DEFINE_IDA(nvmem_ida);
36eace75cfSSrinivas Kandagatla 
37b985f4cbSBartosz Golaszewski static DEFINE_MUTEX(nvmem_cell_mutex);
38b985f4cbSBartosz Golaszewski static LIST_HEAD(nvmem_cell_tables);
39b985f4cbSBartosz Golaszewski 
40506157beSBartosz Golaszewski static DEFINE_MUTEX(nvmem_lookup_mutex);
41506157beSBartosz Golaszewski static LIST_HEAD(nvmem_lookup_list);
42506157beSBartosz Golaszewski 
43bee1138bSBartosz Golaszewski static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
44bee1138bSBartosz Golaszewski 
45a8b44d5dSAndy Shevchenko 
46795ddd18SSrinivas Kandagatla static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
47795ddd18SSrinivas Kandagatla 			  void *val, size_t bytes)
48795ddd18SSrinivas Kandagatla {
49795ddd18SSrinivas Kandagatla 	if (nvmem->reg_read)
50795ddd18SSrinivas Kandagatla 		return nvmem->reg_read(nvmem->priv, offset, val, bytes);
51795ddd18SSrinivas Kandagatla 
52795ddd18SSrinivas Kandagatla 	return -EINVAL;
53795ddd18SSrinivas Kandagatla }
54795ddd18SSrinivas Kandagatla 
55795ddd18SSrinivas Kandagatla static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
56795ddd18SSrinivas Kandagatla 			   void *val, size_t bytes)
57795ddd18SSrinivas Kandagatla {
582a127da4SKhouloud Touil 	int ret;
592a127da4SKhouloud Touil 
602a127da4SKhouloud Touil 	if (nvmem->reg_write) {
612a127da4SKhouloud Touil 		gpiod_set_value_cansleep(nvmem->wp_gpio, 0);
622a127da4SKhouloud Touil 		ret = nvmem->reg_write(nvmem->priv, offset, val, bytes);
632a127da4SKhouloud Touil 		gpiod_set_value_cansleep(nvmem->wp_gpio, 1);
642a127da4SKhouloud Touil 		return ret;
652a127da4SKhouloud Touil 	}
66795ddd18SSrinivas Kandagatla 
67795ddd18SSrinivas Kandagatla 	return -EINVAL;
68795ddd18SSrinivas Kandagatla }
69eace75cfSSrinivas Kandagatla 
70eace75cfSSrinivas Kandagatla static void nvmem_release(struct device *dev)
71eace75cfSSrinivas Kandagatla {
72eace75cfSSrinivas Kandagatla 	struct nvmem_device *nvmem = to_nvmem_device(dev);
73eace75cfSSrinivas Kandagatla 
74eace75cfSSrinivas Kandagatla 	ida_simple_remove(&nvmem_ida, nvmem->id);
75a9c3766cSKhouloud Touil 	gpiod_put(nvmem->wp_gpio);
76eace75cfSSrinivas Kandagatla 	kfree(nvmem);
77eace75cfSSrinivas Kandagatla }
78eace75cfSSrinivas Kandagatla 
79eace75cfSSrinivas Kandagatla static const struct device_type nvmem_provider_type = {
80eace75cfSSrinivas Kandagatla 	.release	= nvmem_release,
81eace75cfSSrinivas Kandagatla };
82eace75cfSSrinivas Kandagatla 
83eace75cfSSrinivas Kandagatla static struct bus_type nvmem_bus_type = {
84eace75cfSSrinivas Kandagatla 	.name		= "nvmem",
85eace75cfSSrinivas Kandagatla };
86eace75cfSSrinivas Kandagatla 
87eace75cfSSrinivas Kandagatla static void nvmem_cell_drop(struct nvmem_cell *cell)
88eace75cfSSrinivas Kandagatla {
89bee1138bSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
90c7235ee3SBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
91eace75cfSSrinivas Kandagatla 	list_del(&cell->node);
92c7235ee3SBartosz Golaszewski 	mutex_unlock(&nvmem_mutex);
930749aa25SSrinivas Kandagatla 	of_node_put(cell->np);
9416bb7abcSBitan Biswas 	kfree_const(cell->name);
95eace75cfSSrinivas Kandagatla 	kfree(cell);
96eace75cfSSrinivas Kandagatla }
97eace75cfSSrinivas Kandagatla 
98eace75cfSSrinivas Kandagatla static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
99eace75cfSSrinivas Kandagatla {
1001852183eSBartosz Golaszewski 	struct nvmem_cell *cell, *p;
101eace75cfSSrinivas Kandagatla 
102c7235ee3SBartosz Golaszewski 	list_for_each_entry_safe(cell, p, &nvmem->cells, node)
103eace75cfSSrinivas Kandagatla 		nvmem_cell_drop(cell);
104eace75cfSSrinivas Kandagatla }
105eace75cfSSrinivas Kandagatla 
106eace75cfSSrinivas Kandagatla static void nvmem_cell_add(struct nvmem_cell *cell)
107eace75cfSSrinivas Kandagatla {
108c7235ee3SBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
109c7235ee3SBartosz Golaszewski 	list_add_tail(&cell->node, &cell->nvmem->cells);
110c7235ee3SBartosz Golaszewski 	mutex_unlock(&nvmem_mutex);
111bee1138bSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
112eace75cfSSrinivas Kandagatla }
113eace75cfSSrinivas Kandagatla 
114eace75cfSSrinivas Kandagatla static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
115eace75cfSSrinivas Kandagatla 				   const struct nvmem_cell_info *info,
116eace75cfSSrinivas Kandagatla 				   struct nvmem_cell *cell)
117eace75cfSSrinivas Kandagatla {
118eace75cfSSrinivas Kandagatla 	cell->nvmem = nvmem;
119eace75cfSSrinivas Kandagatla 	cell->offset = info->offset;
120eace75cfSSrinivas Kandagatla 	cell->bytes = info->bytes;
12116bb7abcSBitan Biswas 	cell->name = kstrdup_const(info->name, GFP_KERNEL);
12216bb7abcSBitan Biswas 	if (!cell->name)
12316bb7abcSBitan Biswas 		return -ENOMEM;
124eace75cfSSrinivas Kandagatla 
125eace75cfSSrinivas Kandagatla 	cell->bit_offset = info->bit_offset;
126eace75cfSSrinivas Kandagatla 	cell->nbits = info->nbits;
127eace75cfSSrinivas Kandagatla 
128eace75cfSSrinivas Kandagatla 	if (cell->nbits)
129eace75cfSSrinivas Kandagatla 		cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
130eace75cfSSrinivas Kandagatla 					   BITS_PER_BYTE);
131eace75cfSSrinivas Kandagatla 
132eace75cfSSrinivas Kandagatla 	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
133eace75cfSSrinivas Kandagatla 		dev_err(&nvmem->dev,
134eace75cfSSrinivas Kandagatla 			"cell %s unaligned to nvmem stride %d\n",
135eace75cfSSrinivas Kandagatla 			cell->name, nvmem->stride);
136eace75cfSSrinivas Kandagatla 		return -EINVAL;
137eace75cfSSrinivas Kandagatla 	}
138eace75cfSSrinivas Kandagatla 
139eace75cfSSrinivas Kandagatla 	return 0;
140eace75cfSSrinivas Kandagatla }
141eace75cfSSrinivas Kandagatla 
142b3db17e4SAndrew Lunn /**
143b3db17e4SAndrew Lunn  * nvmem_add_cells() - Add cell information to an nvmem device
144b3db17e4SAndrew Lunn  *
145b3db17e4SAndrew Lunn  * @nvmem: nvmem device to add cells to.
146b3db17e4SAndrew Lunn  * @info: nvmem cell info to add to the device
147b3db17e4SAndrew Lunn  * @ncells: number of cells in info
148b3db17e4SAndrew Lunn  *
149b3db17e4SAndrew Lunn  * Return: 0 or negative error code on failure.
150b3db17e4SAndrew Lunn  */
151ef92ab30SSrinivas Kandagatla static int nvmem_add_cells(struct nvmem_device *nvmem,
152b3db17e4SAndrew Lunn 		    const struct nvmem_cell_info *info,
153b3db17e4SAndrew Lunn 		    int ncells)
154eace75cfSSrinivas Kandagatla {
155eace75cfSSrinivas Kandagatla 	struct nvmem_cell **cells;
156eace75cfSSrinivas Kandagatla 	int i, rval;
157eace75cfSSrinivas Kandagatla 
158b3db17e4SAndrew Lunn 	cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
159eace75cfSSrinivas Kandagatla 	if (!cells)
160eace75cfSSrinivas Kandagatla 		return -ENOMEM;
161eace75cfSSrinivas Kandagatla 
162b3db17e4SAndrew Lunn 	for (i = 0; i < ncells; i++) {
163eace75cfSSrinivas Kandagatla 		cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
164eace75cfSSrinivas Kandagatla 		if (!cells[i]) {
165eace75cfSSrinivas Kandagatla 			rval = -ENOMEM;
166eace75cfSSrinivas Kandagatla 			goto err;
167eace75cfSSrinivas Kandagatla 		}
168eace75cfSSrinivas Kandagatla 
169eace75cfSSrinivas Kandagatla 		rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
170287980e4SArnd Bergmann 		if (rval) {
171eace75cfSSrinivas Kandagatla 			kfree(cells[i]);
172eace75cfSSrinivas Kandagatla 			goto err;
173eace75cfSSrinivas Kandagatla 		}
174eace75cfSSrinivas Kandagatla 
175eace75cfSSrinivas Kandagatla 		nvmem_cell_add(cells[i]);
176eace75cfSSrinivas Kandagatla 	}
177eace75cfSSrinivas Kandagatla 
178eace75cfSSrinivas Kandagatla 	/* remove tmp array */
179eace75cfSSrinivas Kandagatla 	kfree(cells);
180eace75cfSSrinivas Kandagatla 
181eace75cfSSrinivas Kandagatla 	return 0;
182eace75cfSSrinivas Kandagatla err:
183dfdf1414SRasmus Villemoes 	while (i--)
184eace75cfSSrinivas Kandagatla 		nvmem_cell_drop(cells[i]);
185eace75cfSSrinivas Kandagatla 
186dfdf1414SRasmus Villemoes 	kfree(cells);
187dfdf1414SRasmus Villemoes 
188eace75cfSSrinivas Kandagatla 	return rval;
189eace75cfSSrinivas Kandagatla }
190eace75cfSSrinivas Kandagatla 
191bee1138bSBartosz Golaszewski /**
192bee1138bSBartosz Golaszewski  * nvmem_register_notifier() - Register a notifier block for nvmem events.
193bee1138bSBartosz Golaszewski  *
194bee1138bSBartosz Golaszewski  * @nb: notifier block to be called on nvmem events.
195bee1138bSBartosz Golaszewski  *
196bee1138bSBartosz Golaszewski  * Return: 0 on success, negative error number on failure.
197bee1138bSBartosz Golaszewski  */
198bee1138bSBartosz Golaszewski int nvmem_register_notifier(struct notifier_block *nb)
199bee1138bSBartosz Golaszewski {
200bee1138bSBartosz Golaszewski 	return blocking_notifier_chain_register(&nvmem_notifier, nb);
201bee1138bSBartosz Golaszewski }
202bee1138bSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_register_notifier);
203bee1138bSBartosz Golaszewski 
204bee1138bSBartosz Golaszewski /**
205bee1138bSBartosz Golaszewski  * nvmem_unregister_notifier() - Unregister a notifier block for nvmem events.
206bee1138bSBartosz Golaszewski  *
207bee1138bSBartosz Golaszewski  * @nb: notifier block to be unregistered.
208bee1138bSBartosz Golaszewski  *
209bee1138bSBartosz Golaszewski  * Return: 0 on success, negative error number on failure.
210bee1138bSBartosz Golaszewski  */
211bee1138bSBartosz Golaszewski int nvmem_unregister_notifier(struct notifier_block *nb)
212bee1138bSBartosz Golaszewski {
213bee1138bSBartosz Golaszewski 	return blocking_notifier_chain_unregister(&nvmem_notifier, nb);
214bee1138bSBartosz Golaszewski }
215bee1138bSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_unregister_notifier);
216bee1138bSBartosz Golaszewski 
217b985f4cbSBartosz Golaszewski static int nvmem_add_cells_from_table(struct nvmem_device *nvmem)
218b985f4cbSBartosz Golaszewski {
219b985f4cbSBartosz Golaszewski 	const struct nvmem_cell_info *info;
220b985f4cbSBartosz Golaszewski 	struct nvmem_cell_table *table;
221b985f4cbSBartosz Golaszewski 	struct nvmem_cell *cell;
222b985f4cbSBartosz Golaszewski 	int rval = 0, i;
223b985f4cbSBartosz Golaszewski 
224b985f4cbSBartosz Golaszewski 	mutex_lock(&nvmem_cell_mutex);
225b985f4cbSBartosz Golaszewski 	list_for_each_entry(table, &nvmem_cell_tables, node) {
226b985f4cbSBartosz Golaszewski 		if (strcmp(nvmem_dev_name(nvmem), table->nvmem_name) == 0) {
227b985f4cbSBartosz Golaszewski 			for (i = 0; i < table->ncells; i++) {
228b985f4cbSBartosz Golaszewski 				info = &table->cells[i];
229b985f4cbSBartosz Golaszewski 
230b985f4cbSBartosz Golaszewski 				cell = kzalloc(sizeof(*cell), GFP_KERNEL);
231b985f4cbSBartosz Golaszewski 				if (!cell) {
232b985f4cbSBartosz Golaszewski 					rval = -ENOMEM;
233b985f4cbSBartosz Golaszewski 					goto out;
234b985f4cbSBartosz Golaszewski 				}
235b985f4cbSBartosz Golaszewski 
236b985f4cbSBartosz Golaszewski 				rval = nvmem_cell_info_to_nvmem_cell(nvmem,
237b985f4cbSBartosz Golaszewski 								     info,
238b985f4cbSBartosz Golaszewski 								     cell);
239b985f4cbSBartosz Golaszewski 				if (rval) {
240b985f4cbSBartosz Golaszewski 					kfree(cell);
241b985f4cbSBartosz Golaszewski 					goto out;
242b985f4cbSBartosz Golaszewski 				}
243b985f4cbSBartosz Golaszewski 
244b985f4cbSBartosz Golaszewski 				nvmem_cell_add(cell);
245b985f4cbSBartosz Golaszewski 			}
246b985f4cbSBartosz Golaszewski 		}
247b985f4cbSBartosz Golaszewski 	}
248b985f4cbSBartosz Golaszewski 
249b985f4cbSBartosz Golaszewski out:
250b985f4cbSBartosz Golaszewski 	mutex_unlock(&nvmem_cell_mutex);
251b985f4cbSBartosz Golaszewski 	return rval;
252b985f4cbSBartosz Golaszewski }
253b985f4cbSBartosz Golaszewski 
254e888d445SBartosz Golaszewski static struct nvmem_cell *
255506157beSBartosz Golaszewski nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
256506157beSBartosz Golaszewski {
2571c832674SAlban Bedel 	struct nvmem_cell *iter, *cell = NULL;
258506157beSBartosz Golaszewski 
259506157beSBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
2601c832674SAlban Bedel 	list_for_each_entry(iter, &nvmem->cells, node) {
2611c832674SAlban Bedel 		if (strcmp(cell_id, iter->name) == 0) {
2621c832674SAlban Bedel 			cell = iter;
263506157beSBartosz Golaszewski 			break;
264506157beSBartosz Golaszewski 		}
2651c832674SAlban Bedel 	}
266506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_mutex);
267506157beSBartosz Golaszewski 
268506157beSBartosz Golaszewski 	return cell;
269506157beSBartosz Golaszewski }
270506157beSBartosz Golaszewski 
271e888d445SBartosz Golaszewski static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
272e888d445SBartosz Golaszewski {
273e888d445SBartosz Golaszewski 	struct device_node *parent, *child;
274e888d445SBartosz Golaszewski 	struct device *dev = &nvmem->dev;
275e888d445SBartosz Golaszewski 	struct nvmem_cell *cell;
276e888d445SBartosz Golaszewski 	const __be32 *addr;
277e888d445SBartosz Golaszewski 	int len;
278e888d445SBartosz Golaszewski 
279e888d445SBartosz Golaszewski 	parent = dev->of_node;
280e888d445SBartosz Golaszewski 
281e888d445SBartosz Golaszewski 	for_each_child_of_node(parent, child) {
282e888d445SBartosz Golaszewski 		addr = of_get_property(child, "reg", &len);
283e888d445SBartosz Golaszewski 		if (!addr || (len < 2 * sizeof(u32))) {
284e888d445SBartosz Golaszewski 			dev_err(dev, "nvmem: invalid reg on %pOF\n", child);
285e888d445SBartosz Golaszewski 			return -EINVAL;
286e888d445SBartosz Golaszewski 		}
287e888d445SBartosz Golaszewski 
288e888d445SBartosz Golaszewski 		cell = kzalloc(sizeof(*cell), GFP_KERNEL);
289e888d445SBartosz Golaszewski 		if (!cell)
290e888d445SBartosz Golaszewski 			return -ENOMEM;
291e888d445SBartosz Golaszewski 
292e888d445SBartosz Golaszewski 		cell->nvmem = nvmem;
2930749aa25SSrinivas Kandagatla 		cell->np = of_node_get(child);
294e888d445SBartosz Golaszewski 		cell->offset = be32_to_cpup(addr++);
295e888d445SBartosz Golaszewski 		cell->bytes = be32_to_cpup(addr);
296badcdff1SRob Herring 		cell->name = kasprintf(GFP_KERNEL, "%pOFn", child);
297e888d445SBartosz Golaszewski 
298e888d445SBartosz Golaszewski 		addr = of_get_property(child, "bits", &len);
299e888d445SBartosz Golaszewski 		if (addr && len == (2 * sizeof(u32))) {
300e888d445SBartosz Golaszewski 			cell->bit_offset = be32_to_cpup(addr++);
301e888d445SBartosz Golaszewski 			cell->nbits = be32_to_cpup(addr);
302e888d445SBartosz Golaszewski 		}
303e888d445SBartosz Golaszewski 
304e888d445SBartosz Golaszewski 		if (cell->nbits)
305e888d445SBartosz Golaszewski 			cell->bytes = DIV_ROUND_UP(
306e888d445SBartosz Golaszewski 					cell->nbits + cell->bit_offset,
307e888d445SBartosz Golaszewski 					BITS_PER_BYTE);
308e888d445SBartosz Golaszewski 
309e888d445SBartosz Golaszewski 		if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
310e888d445SBartosz Golaszewski 			dev_err(dev, "cell %s unaligned to nvmem stride %d\n",
311e888d445SBartosz Golaszewski 				cell->name, nvmem->stride);
312e888d445SBartosz Golaszewski 			/* Cells already added will be freed later. */
31316bb7abcSBitan Biswas 			kfree_const(cell->name);
314e888d445SBartosz Golaszewski 			kfree(cell);
315e888d445SBartosz Golaszewski 			return -EINVAL;
316e888d445SBartosz Golaszewski 		}
317e888d445SBartosz Golaszewski 
318e888d445SBartosz Golaszewski 		nvmem_cell_add(cell);
319e888d445SBartosz Golaszewski 	}
320e888d445SBartosz Golaszewski 
321e888d445SBartosz Golaszewski 	return 0;
322e888d445SBartosz Golaszewski }
323e888d445SBartosz Golaszewski 
324eace75cfSSrinivas Kandagatla /**
325eace75cfSSrinivas Kandagatla  * nvmem_register() - Register a nvmem device for given nvmem_config.
326eace75cfSSrinivas Kandagatla  * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
327eace75cfSSrinivas Kandagatla  *
328eace75cfSSrinivas Kandagatla  * @config: nvmem device configuration with which nvmem device is created.
329eace75cfSSrinivas Kandagatla  *
330eace75cfSSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
331eace75cfSSrinivas Kandagatla  * on success.
332eace75cfSSrinivas Kandagatla  */
333eace75cfSSrinivas Kandagatla 
334eace75cfSSrinivas Kandagatla struct nvmem_device *nvmem_register(const struct nvmem_config *config)
335eace75cfSSrinivas Kandagatla {
336eace75cfSSrinivas Kandagatla 	struct nvmem_device *nvmem;
337eace75cfSSrinivas Kandagatla 	int rval;
338eace75cfSSrinivas Kandagatla 
339eace75cfSSrinivas Kandagatla 	if (!config->dev)
340eace75cfSSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
341eace75cfSSrinivas Kandagatla 
342061a320bSSrinivas Kandagatla 	if (!config->reg_read && !config->reg_write)
343061a320bSSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
344061a320bSSrinivas Kandagatla 
345eace75cfSSrinivas Kandagatla 	nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
346eace75cfSSrinivas Kandagatla 	if (!nvmem)
347eace75cfSSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
348eace75cfSSrinivas Kandagatla 
349eace75cfSSrinivas Kandagatla 	rval  = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
350eace75cfSSrinivas Kandagatla 	if (rval < 0) {
351eace75cfSSrinivas Kandagatla 		kfree(nvmem);
352eace75cfSSrinivas Kandagatla 		return ERR_PTR(rval);
353eace75cfSSrinivas Kandagatla 	}
35431c6ff51SBartosz Golaszewski 
3552a127da4SKhouloud Touil 	if (config->wp_gpio)
3562a127da4SKhouloud Touil 		nvmem->wp_gpio = config->wp_gpio;
3572a127da4SKhouloud Touil 	else
3582a127da4SKhouloud Touil 		nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp",
3592a127da4SKhouloud Touil 						    GPIOD_OUT_HIGH);
360f7d8d7dcSBartosz Golaszewski 	if (IS_ERR(nvmem->wp_gpio)) {
361f7d8d7dcSBartosz Golaszewski 		ida_simple_remove(&nvmem_ida, nvmem->id);
362f7d8d7dcSBartosz Golaszewski 		rval = PTR_ERR(nvmem->wp_gpio);
363f7d8d7dcSBartosz Golaszewski 		kfree(nvmem);
364f7d8d7dcSBartosz Golaszewski 		return ERR_PTR(rval);
365f7d8d7dcSBartosz Golaszewski 	}
3662a127da4SKhouloud Touil 
367c1de7f43SBartosz Golaszewski 	kref_init(&nvmem->refcnt);
368c7235ee3SBartosz Golaszewski 	INIT_LIST_HEAD(&nvmem->cells);
369c1de7f43SBartosz Golaszewski 
370eace75cfSSrinivas Kandagatla 	nvmem->id = rval;
371eace75cfSSrinivas Kandagatla 	nvmem->owner = config->owner;
37217eb18d6SMasahiro Yamada 	if (!nvmem->owner && config->dev->driver)
37317eb18d6SMasahiro Yamada 		nvmem->owner = config->dev->driver->owner;
37499897efdSHeiner Kallweit 	nvmem->stride = config->stride ?: 1;
37599897efdSHeiner Kallweit 	nvmem->word_size = config->word_size ?: 1;
376795ddd18SSrinivas Kandagatla 	nvmem->size = config->size;
377eace75cfSSrinivas Kandagatla 	nvmem->dev.type = &nvmem_provider_type;
378eace75cfSSrinivas Kandagatla 	nvmem->dev.bus = &nvmem_bus_type;
379eace75cfSSrinivas Kandagatla 	nvmem->dev.parent = config->dev;
380e6de179dSSrinivas Kandagatla 	nvmem->root_only = config->root_only;
381795ddd18SSrinivas Kandagatla 	nvmem->priv = config->priv;
38216688453SAlexandre Belloni 	nvmem->type = config->type;
383795ddd18SSrinivas Kandagatla 	nvmem->reg_read = config->reg_read;
384795ddd18SSrinivas Kandagatla 	nvmem->reg_write = config->reg_write;
385517f14d9SBartosz Golaszewski 	if (!config->no_of_node)
386fc2f9970SHeiner Kallweit 		nvmem->dev.of_node = config->dev->of_node;
387fd0f4906SAndrey Smirnov 
388fd0f4906SAndrey Smirnov 	if (config->id == -1 && config->name) {
389fd0f4906SAndrey Smirnov 		dev_set_name(&nvmem->dev, "%s", config->name);
390fd0f4906SAndrey Smirnov 	} else {
391eace75cfSSrinivas Kandagatla 		dev_set_name(&nvmem->dev, "%s%d",
3925253193dSAban Bedel 			     config->name ? : "nvmem",
3935253193dSAban Bedel 			     config->name ? config->id : nvmem->id);
394fd0f4906SAndrey Smirnov 	}
395eace75cfSSrinivas Kandagatla 
3961716cfe8SAlban Bedel 	nvmem->read_only = device_property_present(config->dev, "read-only") ||
3971716cfe8SAlban Bedel 			   config->read_only || !nvmem->reg_write;
398eace75cfSSrinivas Kandagatla 
399ae0c2d72SSrinivas Kandagatla 	nvmem->dev.groups = nvmem_sysfs_get_groups(nvmem, config);
400eace75cfSSrinivas Kandagatla 
401eace75cfSSrinivas Kandagatla 	dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
402eace75cfSSrinivas Kandagatla 
403*f60442ddSSrinivas Kandagatla 	rval = device_register(&nvmem->dev);
404b6c217abSAndrew Lunn 	if (rval)
4053360acdfSJohan Hovold 		goto err_put_device;
406b6c217abSAndrew Lunn 
407b6c217abSAndrew Lunn 	if (config->compat) {
408ae0c2d72SSrinivas Kandagatla 		rval = nvmem_sysfs_setup_compat(nvmem, config);
409b6c217abSAndrew Lunn 		if (rval)
4103360acdfSJohan Hovold 			goto err_device_del;
411eace75cfSSrinivas Kandagatla 	}
412eace75cfSSrinivas Kandagatla 
413fa72d847SBartosz Golaszewski 	if (config->cells) {
414fa72d847SBartosz Golaszewski 		rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
415fa72d847SBartosz Golaszewski 		if (rval)
416fa72d847SBartosz Golaszewski 			goto err_teardown_compat;
417fa72d847SBartosz Golaszewski 	}
418eace75cfSSrinivas Kandagatla 
419b985f4cbSBartosz Golaszewski 	rval = nvmem_add_cells_from_table(nvmem);
420b985f4cbSBartosz Golaszewski 	if (rval)
421b985f4cbSBartosz Golaszewski 		goto err_remove_cells;
422b985f4cbSBartosz Golaszewski 
423e888d445SBartosz Golaszewski 	rval = nvmem_add_cells_from_of(nvmem);
424e888d445SBartosz Golaszewski 	if (rval)
425e888d445SBartosz Golaszewski 		goto err_remove_cells;
426e888d445SBartosz Golaszewski 
427f4853e1cSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
428bee1138bSBartosz Golaszewski 
429eace75cfSSrinivas Kandagatla 	return nvmem;
4303360acdfSJohan Hovold 
431b985f4cbSBartosz Golaszewski err_remove_cells:
432b985f4cbSBartosz Golaszewski 	nvmem_device_remove_all_cells(nvmem);
433fa72d847SBartosz Golaszewski err_teardown_compat:
434fa72d847SBartosz Golaszewski 	if (config->compat)
435ae0c2d72SSrinivas Kandagatla 		nvmem_sysfs_remove_compat(nvmem, config);
4363360acdfSJohan Hovold err_device_del:
4373360acdfSJohan Hovold 	device_del(&nvmem->dev);
4383360acdfSJohan Hovold err_put_device:
4393360acdfSJohan Hovold 	put_device(&nvmem->dev);
4403360acdfSJohan Hovold 
441b6c217abSAndrew Lunn 	return ERR_PTR(rval);
442eace75cfSSrinivas Kandagatla }
443eace75cfSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_register);
444eace75cfSSrinivas Kandagatla 
445c1de7f43SBartosz Golaszewski static void nvmem_device_release(struct kref *kref)
446c1de7f43SBartosz Golaszewski {
447c1de7f43SBartosz Golaszewski 	struct nvmem_device *nvmem;
448c1de7f43SBartosz Golaszewski 
449c1de7f43SBartosz Golaszewski 	nvmem = container_of(kref, struct nvmem_device, refcnt);
450c1de7f43SBartosz Golaszewski 
451bee1138bSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_REMOVE, nvmem);
452bee1138bSBartosz Golaszewski 
453c1de7f43SBartosz Golaszewski 	if (nvmem->flags & FLAG_COMPAT)
454c1de7f43SBartosz Golaszewski 		device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
455c1de7f43SBartosz Golaszewski 
456c1de7f43SBartosz Golaszewski 	nvmem_device_remove_all_cells(nvmem);
457*f60442ddSSrinivas Kandagatla 	device_unregister(&nvmem->dev);
458c1de7f43SBartosz Golaszewski }
459c1de7f43SBartosz Golaszewski 
460eace75cfSSrinivas Kandagatla /**
461eace75cfSSrinivas Kandagatla  * nvmem_unregister() - Unregister previously registered nvmem device
462eace75cfSSrinivas Kandagatla  *
463eace75cfSSrinivas Kandagatla  * @nvmem: Pointer to previously registered nvmem device.
464eace75cfSSrinivas Kandagatla  */
465bf58e882SBartosz Golaszewski void nvmem_unregister(struct nvmem_device *nvmem)
466eace75cfSSrinivas Kandagatla {
467c1de7f43SBartosz Golaszewski 	kref_put(&nvmem->refcnt, nvmem_device_release);
468eace75cfSSrinivas Kandagatla }
469eace75cfSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_unregister);
470eace75cfSSrinivas Kandagatla 
471f1f50ecaSAndrey Smirnov static void devm_nvmem_release(struct device *dev, void *res)
472f1f50ecaSAndrey Smirnov {
473bf58e882SBartosz Golaszewski 	nvmem_unregister(*(struct nvmem_device **)res);
474f1f50ecaSAndrey Smirnov }
475f1f50ecaSAndrey Smirnov 
476f1f50ecaSAndrey Smirnov /**
477f1f50ecaSAndrey Smirnov  * devm_nvmem_register() - Register a managed nvmem device for given
478f1f50ecaSAndrey Smirnov  * nvmem_config.
479f1f50ecaSAndrey Smirnov  * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
480f1f50ecaSAndrey Smirnov  *
481b378c779SSrinivas Kandagatla  * @dev: Device that uses the nvmem device.
482f1f50ecaSAndrey Smirnov  * @config: nvmem device configuration with which nvmem device is created.
483f1f50ecaSAndrey Smirnov  *
484f1f50ecaSAndrey Smirnov  * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
485f1f50ecaSAndrey Smirnov  * on success.
486f1f50ecaSAndrey Smirnov  */
487f1f50ecaSAndrey Smirnov struct nvmem_device *devm_nvmem_register(struct device *dev,
488f1f50ecaSAndrey Smirnov 					 const struct nvmem_config *config)
489f1f50ecaSAndrey Smirnov {
490f1f50ecaSAndrey Smirnov 	struct nvmem_device **ptr, *nvmem;
491f1f50ecaSAndrey Smirnov 
492f1f50ecaSAndrey Smirnov 	ptr = devres_alloc(devm_nvmem_release, sizeof(*ptr), GFP_KERNEL);
493f1f50ecaSAndrey Smirnov 	if (!ptr)
494f1f50ecaSAndrey Smirnov 		return ERR_PTR(-ENOMEM);
495f1f50ecaSAndrey Smirnov 
496f1f50ecaSAndrey Smirnov 	nvmem = nvmem_register(config);
497f1f50ecaSAndrey Smirnov 
498f1f50ecaSAndrey Smirnov 	if (!IS_ERR(nvmem)) {
499f1f50ecaSAndrey Smirnov 		*ptr = nvmem;
500f1f50ecaSAndrey Smirnov 		devres_add(dev, ptr);
501f1f50ecaSAndrey Smirnov 	} else {
502f1f50ecaSAndrey Smirnov 		devres_free(ptr);
503f1f50ecaSAndrey Smirnov 	}
504f1f50ecaSAndrey Smirnov 
505f1f50ecaSAndrey Smirnov 	return nvmem;
506f1f50ecaSAndrey Smirnov }
507f1f50ecaSAndrey Smirnov EXPORT_SYMBOL_GPL(devm_nvmem_register);
508f1f50ecaSAndrey Smirnov 
509f1f50ecaSAndrey Smirnov static int devm_nvmem_match(struct device *dev, void *res, void *data)
510f1f50ecaSAndrey Smirnov {
511f1f50ecaSAndrey Smirnov 	struct nvmem_device **r = res;
512f1f50ecaSAndrey Smirnov 
513f1f50ecaSAndrey Smirnov 	return *r == data;
514f1f50ecaSAndrey Smirnov }
515f1f50ecaSAndrey Smirnov 
516f1f50ecaSAndrey Smirnov /**
517f1f50ecaSAndrey Smirnov  * devm_nvmem_unregister() - Unregister previously registered managed nvmem
518f1f50ecaSAndrey Smirnov  * device.
519f1f50ecaSAndrey Smirnov  *
520b378c779SSrinivas Kandagatla  * @dev: Device that uses the nvmem device.
521f1f50ecaSAndrey Smirnov  * @nvmem: Pointer to previously registered nvmem device.
522f1f50ecaSAndrey Smirnov  *
523f1f50ecaSAndrey Smirnov  * Return: Will be an negative on error or a zero on success.
524f1f50ecaSAndrey Smirnov  */
525f1f50ecaSAndrey Smirnov int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
526f1f50ecaSAndrey Smirnov {
527f1f50ecaSAndrey Smirnov 	return devres_release(dev, devm_nvmem_release, devm_nvmem_match, nvmem);
528f1f50ecaSAndrey Smirnov }
529f1f50ecaSAndrey Smirnov EXPORT_SYMBOL(devm_nvmem_unregister);
530f1f50ecaSAndrey Smirnov 
5318c2a2b8cSThomas Bogendoerfer static struct nvmem_device *__nvmem_device_get(void *data,
5328c2a2b8cSThomas Bogendoerfer 			int (*match)(struct device *dev, const void *data))
53369aba794SSrinivas Kandagatla {
53469aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = NULL;
5358c2a2b8cSThomas Bogendoerfer 	struct device *dev;
53669aba794SSrinivas Kandagatla 
537c7235ee3SBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
5388c2a2b8cSThomas Bogendoerfer 	dev = bus_find_device(&nvmem_bus_type, NULL, data, match);
5398c2a2b8cSThomas Bogendoerfer 	if (dev)
5408c2a2b8cSThomas Bogendoerfer 		nvmem = to_nvmem_device(dev);
54169aba794SSrinivas Kandagatla 	mutex_unlock(&nvmem_mutex);
542c7235ee3SBartosz Golaszewski 	if (!nvmem)
543c7235ee3SBartosz Golaszewski 		return ERR_PTR(-EPROBE_DEFER);
54469aba794SSrinivas Kandagatla 
54569aba794SSrinivas Kandagatla 	if (!try_module_get(nvmem->owner)) {
54669aba794SSrinivas Kandagatla 		dev_err(&nvmem->dev,
54769aba794SSrinivas Kandagatla 			"could not increase module refcount for cell %s\n",
5485db652c9SBartosz Golaszewski 			nvmem_dev_name(nvmem));
54969aba794SSrinivas Kandagatla 
55073e9dc4dSAlban Bedel 		put_device(&nvmem->dev);
55169aba794SSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
55269aba794SSrinivas Kandagatla 	}
55369aba794SSrinivas Kandagatla 
554c1de7f43SBartosz Golaszewski 	kref_get(&nvmem->refcnt);
555c1de7f43SBartosz Golaszewski 
55669aba794SSrinivas Kandagatla 	return nvmem;
55769aba794SSrinivas Kandagatla }
55869aba794SSrinivas Kandagatla 
55969aba794SSrinivas Kandagatla static void __nvmem_device_put(struct nvmem_device *nvmem)
56069aba794SSrinivas Kandagatla {
56173e9dc4dSAlban Bedel 	put_device(&nvmem->dev);
56269aba794SSrinivas Kandagatla 	module_put(nvmem->owner);
563c1de7f43SBartosz Golaszewski 	kref_put(&nvmem->refcnt, nvmem_device_release);
56469aba794SSrinivas Kandagatla }
56569aba794SSrinivas Kandagatla 
566e701c67cSMasahiro Yamada #if IS_ENABLED(CONFIG_OF)
567e2a5402eSSrinivas Kandagatla /**
568e2a5402eSSrinivas Kandagatla  * of_nvmem_device_get() - Get nvmem device from a given id
569e2a5402eSSrinivas Kandagatla  *
57029143268SVivek Gautam  * @np: Device tree node that uses the nvmem device.
571e2a5402eSSrinivas Kandagatla  * @id: nvmem name from nvmem-names property.
572e2a5402eSSrinivas Kandagatla  *
573e2a5402eSSrinivas Kandagatla  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
574e2a5402eSSrinivas Kandagatla  * on success.
575e2a5402eSSrinivas Kandagatla  */
576e2a5402eSSrinivas Kandagatla struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
577e2a5402eSSrinivas Kandagatla {
578e2a5402eSSrinivas Kandagatla 
579e2a5402eSSrinivas Kandagatla 	struct device_node *nvmem_np;
580d4e7fef1SAlban Bedel 	int index = 0;
581e2a5402eSSrinivas Kandagatla 
582d4e7fef1SAlban Bedel 	if (id)
583e2a5402eSSrinivas Kandagatla 		index = of_property_match_string(np, "nvmem-names", id);
584e2a5402eSSrinivas Kandagatla 
585e2a5402eSSrinivas Kandagatla 	nvmem_np = of_parse_phandle(np, "nvmem", index);
586e2a5402eSSrinivas Kandagatla 	if (!nvmem_np)
587d4e7fef1SAlban Bedel 		return ERR_PTR(-ENOENT);
588e2a5402eSSrinivas Kandagatla 
5898c2a2b8cSThomas Bogendoerfer 	return __nvmem_device_get(nvmem_np, device_match_of_node);
590e2a5402eSSrinivas Kandagatla }
591e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(of_nvmem_device_get);
592e2a5402eSSrinivas Kandagatla #endif
593e2a5402eSSrinivas Kandagatla 
594e2a5402eSSrinivas Kandagatla /**
595e2a5402eSSrinivas Kandagatla  * nvmem_device_get() - Get nvmem device from a given id
596e2a5402eSSrinivas Kandagatla  *
59729143268SVivek Gautam  * @dev: Device that uses the nvmem device.
59829143268SVivek Gautam  * @dev_name: name of the requested nvmem device.
599e2a5402eSSrinivas Kandagatla  *
600e2a5402eSSrinivas Kandagatla  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
601e2a5402eSSrinivas Kandagatla  * on success.
602e2a5402eSSrinivas Kandagatla  */
603e2a5402eSSrinivas Kandagatla struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
604e2a5402eSSrinivas Kandagatla {
605e2a5402eSSrinivas Kandagatla 	if (dev->of_node) { /* try dt first */
606e2a5402eSSrinivas Kandagatla 		struct nvmem_device *nvmem;
607e2a5402eSSrinivas Kandagatla 
608e2a5402eSSrinivas Kandagatla 		nvmem = of_nvmem_device_get(dev->of_node, dev_name);
609e2a5402eSSrinivas Kandagatla 
610e2a5402eSSrinivas Kandagatla 		if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
611e2a5402eSSrinivas Kandagatla 			return nvmem;
612e2a5402eSSrinivas Kandagatla 
613e2a5402eSSrinivas Kandagatla 	}
614e2a5402eSSrinivas Kandagatla 
6158c2a2b8cSThomas Bogendoerfer 	return __nvmem_device_get((void *)dev_name, device_match_name);
616e2a5402eSSrinivas Kandagatla }
617e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_get);
618e2a5402eSSrinivas Kandagatla 
6198c2a2b8cSThomas Bogendoerfer /**
6208c2a2b8cSThomas Bogendoerfer  * nvmem_device_find() - Find nvmem device with matching function
6218c2a2b8cSThomas Bogendoerfer  *
6228c2a2b8cSThomas Bogendoerfer  * @data: Data to pass to match function
6238c2a2b8cSThomas Bogendoerfer  * @match: Callback function to check device
6248c2a2b8cSThomas Bogendoerfer  *
6258c2a2b8cSThomas Bogendoerfer  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
6268c2a2b8cSThomas Bogendoerfer  * on success.
6278c2a2b8cSThomas Bogendoerfer  */
6288c2a2b8cSThomas Bogendoerfer struct nvmem_device *nvmem_device_find(void *data,
6298c2a2b8cSThomas Bogendoerfer 			int (*match)(struct device *dev, const void *data))
6308c2a2b8cSThomas Bogendoerfer {
6318c2a2b8cSThomas Bogendoerfer 	return __nvmem_device_get(data, match);
6328c2a2b8cSThomas Bogendoerfer }
6338c2a2b8cSThomas Bogendoerfer EXPORT_SYMBOL_GPL(nvmem_device_find);
6348c2a2b8cSThomas Bogendoerfer 
635e2a5402eSSrinivas Kandagatla static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
636e2a5402eSSrinivas Kandagatla {
637e2a5402eSSrinivas Kandagatla 	struct nvmem_device **nvmem = res;
638e2a5402eSSrinivas Kandagatla 
639e2a5402eSSrinivas Kandagatla 	if (WARN_ON(!nvmem || !*nvmem))
640e2a5402eSSrinivas Kandagatla 		return 0;
641e2a5402eSSrinivas Kandagatla 
642e2a5402eSSrinivas Kandagatla 	return *nvmem == data;
643e2a5402eSSrinivas Kandagatla }
644e2a5402eSSrinivas Kandagatla 
645e2a5402eSSrinivas Kandagatla static void devm_nvmem_device_release(struct device *dev, void *res)
646e2a5402eSSrinivas Kandagatla {
647e2a5402eSSrinivas Kandagatla 	nvmem_device_put(*(struct nvmem_device **)res);
648e2a5402eSSrinivas Kandagatla }
649e2a5402eSSrinivas Kandagatla 
650e2a5402eSSrinivas Kandagatla /**
651e2a5402eSSrinivas Kandagatla  * devm_nvmem_device_put() - put alredy got nvmem device
652e2a5402eSSrinivas Kandagatla  *
65329143268SVivek Gautam  * @dev: Device that uses the nvmem device.
654e2a5402eSSrinivas Kandagatla  * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
655e2a5402eSSrinivas Kandagatla  * that needs to be released.
656e2a5402eSSrinivas Kandagatla  */
657e2a5402eSSrinivas Kandagatla void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
658e2a5402eSSrinivas Kandagatla {
659e2a5402eSSrinivas Kandagatla 	int ret;
660e2a5402eSSrinivas Kandagatla 
661e2a5402eSSrinivas Kandagatla 	ret = devres_release(dev, devm_nvmem_device_release,
662e2a5402eSSrinivas Kandagatla 			     devm_nvmem_device_match, nvmem);
663e2a5402eSSrinivas Kandagatla 
664e2a5402eSSrinivas Kandagatla 	WARN_ON(ret);
665e2a5402eSSrinivas Kandagatla }
666e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
667e2a5402eSSrinivas Kandagatla 
668e2a5402eSSrinivas Kandagatla /**
669e2a5402eSSrinivas Kandagatla  * nvmem_device_put() - put alredy got nvmem device
670e2a5402eSSrinivas Kandagatla  *
671e2a5402eSSrinivas Kandagatla  * @nvmem: pointer to nvmem device that needs to be released.
672e2a5402eSSrinivas Kandagatla  */
673e2a5402eSSrinivas Kandagatla void nvmem_device_put(struct nvmem_device *nvmem)
674e2a5402eSSrinivas Kandagatla {
675e2a5402eSSrinivas Kandagatla 	__nvmem_device_put(nvmem);
676e2a5402eSSrinivas Kandagatla }
677e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_put);
678e2a5402eSSrinivas Kandagatla 
679e2a5402eSSrinivas Kandagatla /**
680e2a5402eSSrinivas Kandagatla  * devm_nvmem_device_get() - Get nvmem cell of device form a given id
681e2a5402eSSrinivas Kandagatla  *
68229143268SVivek Gautam  * @dev: Device that requests the nvmem device.
68329143268SVivek Gautam  * @id: name id for the requested nvmem device.
684e2a5402eSSrinivas Kandagatla  *
685e2a5402eSSrinivas Kandagatla  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell
686e2a5402eSSrinivas Kandagatla  * on success.  The nvmem_cell will be freed by the automatically once the
687e2a5402eSSrinivas Kandagatla  * device is freed.
688e2a5402eSSrinivas Kandagatla  */
689e2a5402eSSrinivas Kandagatla struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
690e2a5402eSSrinivas Kandagatla {
691e2a5402eSSrinivas Kandagatla 	struct nvmem_device **ptr, *nvmem;
692e2a5402eSSrinivas Kandagatla 
693e2a5402eSSrinivas Kandagatla 	ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
694e2a5402eSSrinivas Kandagatla 	if (!ptr)
695e2a5402eSSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
696e2a5402eSSrinivas Kandagatla 
697e2a5402eSSrinivas Kandagatla 	nvmem = nvmem_device_get(dev, id);
698e2a5402eSSrinivas Kandagatla 	if (!IS_ERR(nvmem)) {
699e2a5402eSSrinivas Kandagatla 		*ptr = nvmem;
700e2a5402eSSrinivas Kandagatla 		devres_add(dev, ptr);
701e2a5402eSSrinivas Kandagatla 	} else {
702e2a5402eSSrinivas Kandagatla 		devres_free(ptr);
703e2a5402eSSrinivas Kandagatla 	}
704e2a5402eSSrinivas Kandagatla 
705e2a5402eSSrinivas Kandagatla 	return nvmem;
706e2a5402eSSrinivas Kandagatla }
707e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
708e2a5402eSSrinivas Kandagatla 
709506157beSBartosz Golaszewski static struct nvmem_cell *
710506157beSBartosz Golaszewski nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
71169aba794SSrinivas Kandagatla {
712506157beSBartosz Golaszewski 	struct nvmem_cell *cell = ERR_PTR(-ENOENT);
713506157beSBartosz Golaszewski 	struct nvmem_cell_lookup *lookup;
71469aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem;
715506157beSBartosz Golaszewski 	const char *dev_id;
71669aba794SSrinivas Kandagatla 
717506157beSBartosz Golaszewski 	if (!dev)
718506157beSBartosz Golaszewski 		return ERR_PTR(-EINVAL);
71969aba794SSrinivas Kandagatla 
720506157beSBartosz Golaszewski 	dev_id = dev_name(dev);
721506157beSBartosz Golaszewski 
722506157beSBartosz Golaszewski 	mutex_lock(&nvmem_lookup_mutex);
723506157beSBartosz Golaszewski 
724506157beSBartosz Golaszewski 	list_for_each_entry(lookup, &nvmem_lookup_list, node) {
725506157beSBartosz Golaszewski 		if ((strcmp(lookup->dev_id, dev_id) == 0) &&
726506157beSBartosz Golaszewski 		    (strcmp(lookup->con_id, con_id) == 0)) {
727506157beSBartosz Golaszewski 			/* This is the right entry. */
7288c2a2b8cSThomas Bogendoerfer 			nvmem = __nvmem_device_get((void *)lookup->nvmem_name,
7298c2a2b8cSThomas Bogendoerfer 						   device_match_name);
730cccb3b19SBartosz Golaszewski 			if (IS_ERR(nvmem)) {
731506157beSBartosz Golaszewski 				/* Provider may not be registered yet. */
732cccb3b19SBartosz Golaszewski 				cell = ERR_CAST(nvmem);
7339bfd8198SAlban Bedel 				break;
734506157beSBartosz Golaszewski 			}
735506157beSBartosz Golaszewski 
736506157beSBartosz Golaszewski 			cell = nvmem_find_cell_by_name(nvmem,
737506157beSBartosz Golaszewski 						       lookup->cell_name);
738506157beSBartosz Golaszewski 			if (!cell) {
739506157beSBartosz Golaszewski 				__nvmem_device_put(nvmem);
740cccb3b19SBartosz Golaszewski 				cell = ERR_PTR(-ENOENT);
741506157beSBartosz Golaszewski 			}
7429bfd8198SAlban Bedel 			break;
743506157beSBartosz Golaszewski 		}
744506157beSBartosz Golaszewski 	}
745506157beSBartosz Golaszewski 
746506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_lookup_mutex);
74769aba794SSrinivas Kandagatla 	return cell;
74869aba794SSrinivas Kandagatla }
74969aba794SSrinivas Kandagatla 
750e701c67cSMasahiro Yamada #if IS_ENABLED(CONFIG_OF)
7513c53e235SArnd Bergmann static struct nvmem_cell *
7520749aa25SSrinivas Kandagatla nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
7533c53e235SArnd Bergmann {
7541c832674SAlban Bedel 	struct nvmem_cell *iter, *cell = NULL;
7553c53e235SArnd Bergmann 
7563c53e235SArnd Bergmann 	mutex_lock(&nvmem_mutex);
7571c832674SAlban Bedel 	list_for_each_entry(iter, &nvmem->cells, node) {
7581c832674SAlban Bedel 		if (np == iter->np) {
7591c832674SAlban Bedel 			cell = iter;
7603c53e235SArnd Bergmann 			break;
7613c53e235SArnd Bergmann 		}
7621c832674SAlban Bedel 	}
7633c53e235SArnd Bergmann 	mutex_unlock(&nvmem_mutex);
7643c53e235SArnd Bergmann 
7653c53e235SArnd Bergmann 	return cell;
7663c53e235SArnd Bergmann }
7673c53e235SArnd Bergmann 
76869aba794SSrinivas Kandagatla /**
76969aba794SSrinivas Kandagatla  * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
77069aba794SSrinivas Kandagatla  *
77129143268SVivek Gautam  * @np: Device tree node that uses the nvmem cell.
772165589f0SBartosz Golaszewski  * @id: nvmem cell name from nvmem-cell-names property, or NULL
773fd0c478cSVivek Gautam  *      for the cell at index 0 (the lone cell with no accompanying
774fd0c478cSVivek Gautam  *      nvmem-cell-names property).
77569aba794SSrinivas Kandagatla  *
77669aba794SSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer
77769aba794SSrinivas Kandagatla  * to a struct nvmem_cell.  The nvmem_cell will be freed by the
77869aba794SSrinivas Kandagatla  * nvmem_cell_put().
77969aba794SSrinivas Kandagatla  */
780165589f0SBartosz Golaszewski struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
78169aba794SSrinivas Kandagatla {
78269aba794SSrinivas Kandagatla 	struct device_node *cell_np, *nvmem_np;
78369aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem;
784e888d445SBartosz Golaszewski 	struct nvmem_cell *cell;
785fd0c478cSVivek Gautam 	int index = 0;
78669aba794SSrinivas Kandagatla 
787fd0c478cSVivek Gautam 	/* if cell name exists, find index to the name */
788165589f0SBartosz Golaszewski 	if (id)
789165589f0SBartosz Golaszewski 		index = of_property_match_string(np, "nvmem-cell-names", id);
79069aba794SSrinivas Kandagatla 
79169aba794SSrinivas Kandagatla 	cell_np = of_parse_phandle(np, "nvmem-cells", index);
79269aba794SSrinivas Kandagatla 	if (!cell_np)
7935087cc19SAlban Bedel 		return ERR_PTR(-ENOENT);
79469aba794SSrinivas Kandagatla 
79569aba794SSrinivas Kandagatla 	nvmem_np = of_get_next_parent(cell_np);
79669aba794SSrinivas Kandagatla 	if (!nvmem_np)
79769aba794SSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
79869aba794SSrinivas Kandagatla 
7998c2a2b8cSThomas Bogendoerfer 	nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
800aad8d097SMasahiro Yamada 	of_node_put(nvmem_np);
80169aba794SSrinivas Kandagatla 	if (IS_ERR(nvmem))
80269aba794SSrinivas Kandagatla 		return ERR_CAST(nvmem);
80369aba794SSrinivas Kandagatla 
8040749aa25SSrinivas Kandagatla 	cell = nvmem_find_cell_by_node(nvmem, cell_np);
80569aba794SSrinivas Kandagatla 	if (!cell) {
806e888d445SBartosz Golaszewski 		__nvmem_device_put(nvmem);
807e888d445SBartosz Golaszewski 		return ERR_PTR(-ENOENT);
80869aba794SSrinivas Kandagatla 	}
80969aba794SSrinivas Kandagatla 
81069aba794SSrinivas Kandagatla 	return cell;
81169aba794SSrinivas Kandagatla }
81269aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
81369aba794SSrinivas Kandagatla #endif
81469aba794SSrinivas Kandagatla 
81569aba794SSrinivas Kandagatla /**
81669aba794SSrinivas Kandagatla  * nvmem_cell_get() - Get nvmem cell of device form a given cell name
81769aba794SSrinivas Kandagatla  *
81829143268SVivek Gautam  * @dev: Device that requests the nvmem cell.
819165589f0SBartosz Golaszewski  * @id: nvmem cell name to get (this corresponds with the name from the
820165589f0SBartosz Golaszewski  *      nvmem-cell-names property for DT systems and with the con_id from
821165589f0SBartosz Golaszewski  *      the lookup entry for non-DT systems).
82269aba794SSrinivas Kandagatla  *
82369aba794SSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer
82469aba794SSrinivas Kandagatla  * to a struct nvmem_cell.  The nvmem_cell will be freed by the
82569aba794SSrinivas Kandagatla  * nvmem_cell_put().
82669aba794SSrinivas Kandagatla  */
827165589f0SBartosz Golaszewski struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *id)
82869aba794SSrinivas Kandagatla {
82969aba794SSrinivas Kandagatla 	struct nvmem_cell *cell;
83069aba794SSrinivas Kandagatla 
83169aba794SSrinivas Kandagatla 	if (dev->of_node) { /* try dt first */
832165589f0SBartosz Golaszewski 		cell = of_nvmem_cell_get(dev->of_node, id);
83369aba794SSrinivas Kandagatla 		if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
83469aba794SSrinivas Kandagatla 			return cell;
83569aba794SSrinivas Kandagatla 	}
83669aba794SSrinivas Kandagatla 
837165589f0SBartosz Golaszewski 	/* NULL cell id only allowed for device tree; invalid otherwise */
838165589f0SBartosz Golaszewski 	if (!id)
83987ed1405SDouglas Anderson 		return ERR_PTR(-EINVAL);
84087ed1405SDouglas Anderson 
841165589f0SBartosz Golaszewski 	return nvmem_cell_get_from_lookup(dev, id);
84269aba794SSrinivas Kandagatla }
84369aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_get);
84469aba794SSrinivas Kandagatla 
84569aba794SSrinivas Kandagatla static void devm_nvmem_cell_release(struct device *dev, void *res)
84669aba794SSrinivas Kandagatla {
84769aba794SSrinivas Kandagatla 	nvmem_cell_put(*(struct nvmem_cell **)res);
84869aba794SSrinivas Kandagatla }
84969aba794SSrinivas Kandagatla 
85069aba794SSrinivas Kandagatla /**
85169aba794SSrinivas Kandagatla  * devm_nvmem_cell_get() - Get nvmem cell of device form a given id
85269aba794SSrinivas Kandagatla  *
85329143268SVivek Gautam  * @dev: Device that requests the nvmem cell.
85429143268SVivek Gautam  * @id: nvmem cell name id to get.
85569aba794SSrinivas Kandagatla  *
85669aba794SSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer
85769aba794SSrinivas Kandagatla  * to a struct nvmem_cell.  The nvmem_cell will be freed by the
85869aba794SSrinivas Kandagatla  * automatically once the device is freed.
85969aba794SSrinivas Kandagatla  */
86069aba794SSrinivas Kandagatla struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id)
86169aba794SSrinivas Kandagatla {
86269aba794SSrinivas Kandagatla 	struct nvmem_cell **ptr, *cell;
86369aba794SSrinivas Kandagatla 
86469aba794SSrinivas Kandagatla 	ptr = devres_alloc(devm_nvmem_cell_release, sizeof(*ptr), GFP_KERNEL);
86569aba794SSrinivas Kandagatla 	if (!ptr)
86669aba794SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
86769aba794SSrinivas Kandagatla 
86869aba794SSrinivas Kandagatla 	cell = nvmem_cell_get(dev, id);
86969aba794SSrinivas Kandagatla 	if (!IS_ERR(cell)) {
87069aba794SSrinivas Kandagatla 		*ptr = cell;
87169aba794SSrinivas Kandagatla 		devres_add(dev, ptr);
87269aba794SSrinivas Kandagatla 	} else {
87369aba794SSrinivas Kandagatla 		devres_free(ptr);
87469aba794SSrinivas Kandagatla 	}
87569aba794SSrinivas Kandagatla 
87669aba794SSrinivas Kandagatla 	return cell;
87769aba794SSrinivas Kandagatla }
87869aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_nvmem_cell_get);
87969aba794SSrinivas Kandagatla 
88069aba794SSrinivas Kandagatla static int devm_nvmem_cell_match(struct device *dev, void *res, void *data)
88169aba794SSrinivas Kandagatla {
88269aba794SSrinivas Kandagatla 	struct nvmem_cell **c = res;
88369aba794SSrinivas Kandagatla 
88469aba794SSrinivas Kandagatla 	if (WARN_ON(!c || !*c))
88569aba794SSrinivas Kandagatla 		return 0;
88669aba794SSrinivas Kandagatla 
88769aba794SSrinivas Kandagatla 	return *c == data;
88869aba794SSrinivas Kandagatla }
88969aba794SSrinivas Kandagatla 
89069aba794SSrinivas Kandagatla /**
89169aba794SSrinivas Kandagatla  * devm_nvmem_cell_put() - Release previously allocated nvmem cell
89269aba794SSrinivas Kandagatla  * from devm_nvmem_cell_get.
89369aba794SSrinivas Kandagatla  *
89429143268SVivek Gautam  * @dev: Device that requests the nvmem cell.
89529143268SVivek Gautam  * @cell: Previously allocated nvmem cell by devm_nvmem_cell_get().
89669aba794SSrinivas Kandagatla  */
89769aba794SSrinivas Kandagatla void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell)
89869aba794SSrinivas Kandagatla {
89969aba794SSrinivas Kandagatla 	int ret;
90069aba794SSrinivas Kandagatla 
90169aba794SSrinivas Kandagatla 	ret = devres_release(dev, devm_nvmem_cell_release,
90269aba794SSrinivas Kandagatla 				devm_nvmem_cell_match, cell);
90369aba794SSrinivas Kandagatla 
90469aba794SSrinivas Kandagatla 	WARN_ON(ret);
90569aba794SSrinivas Kandagatla }
90669aba794SSrinivas Kandagatla EXPORT_SYMBOL(devm_nvmem_cell_put);
90769aba794SSrinivas Kandagatla 
90869aba794SSrinivas Kandagatla /**
90969aba794SSrinivas Kandagatla  * nvmem_cell_put() - Release previously allocated nvmem cell.
91069aba794SSrinivas Kandagatla  *
91129143268SVivek Gautam  * @cell: Previously allocated nvmem cell by nvmem_cell_get().
91269aba794SSrinivas Kandagatla  */
91369aba794SSrinivas Kandagatla void nvmem_cell_put(struct nvmem_cell *cell)
91469aba794SSrinivas Kandagatla {
91569aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
91669aba794SSrinivas Kandagatla 
91769aba794SSrinivas Kandagatla 	__nvmem_device_put(nvmem);
91869aba794SSrinivas Kandagatla }
91969aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_put);
92069aba794SSrinivas Kandagatla 
921f7c04f16SMasahiro Yamada static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)
92269aba794SSrinivas Kandagatla {
92369aba794SSrinivas Kandagatla 	u8 *p, *b;
9242fe518feSJorge Ramirez-Ortiz 	int i, extra, bit_offset = cell->bit_offset;
92569aba794SSrinivas Kandagatla 
92669aba794SSrinivas Kandagatla 	p = b = buf;
92769aba794SSrinivas Kandagatla 	if (bit_offset) {
92869aba794SSrinivas Kandagatla 		/* First shift */
92969aba794SSrinivas Kandagatla 		*b++ >>= bit_offset;
93069aba794SSrinivas Kandagatla 
93169aba794SSrinivas Kandagatla 		/* setup rest of the bytes if any */
93269aba794SSrinivas Kandagatla 		for (i = 1; i < cell->bytes; i++) {
93369aba794SSrinivas Kandagatla 			/* Get bits from next byte and shift them towards msb */
93469aba794SSrinivas Kandagatla 			*p |= *b << (BITS_PER_BYTE - bit_offset);
93569aba794SSrinivas Kandagatla 
93669aba794SSrinivas Kandagatla 			p = b;
93769aba794SSrinivas Kandagatla 			*b++ >>= bit_offset;
93869aba794SSrinivas Kandagatla 		}
9392fe518feSJorge Ramirez-Ortiz 	} else {
9402fe518feSJorge Ramirez-Ortiz 		/* point to the msb */
9412fe518feSJorge Ramirez-Ortiz 		p += cell->bytes - 1;
9422fe518feSJorge Ramirez-Ortiz 	}
94369aba794SSrinivas Kandagatla 
94469aba794SSrinivas Kandagatla 	/* result fits in less bytes */
9452fe518feSJorge Ramirez-Ortiz 	extra = cell->bytes - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);
9462fe518feSJorge Ramirez-Ortiz 	while (--extra >= 0)
94769aba794SSrinivas Kandagatla 		*p-- = 0;
9482fe518feSJorge Ramirez-Ortiz 
94969aba794SSrinivas Kandagatla 	/* clear msb bits if any leftover in the last byte */
95069aba794SSrinivas Kandagatla 	*p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
95169aba794SSrinivas Kandagatla }
95269aba794SSrinivas Kandagatla 
95369aba794SSrinivas Kandagatla static int __nvmem_cell_read(struct nvmem_device *nvmem,
95469aba794SSrinivas Kandagatla 		      struct nvmem_cell *cell,
95569aba794SSrinivas Kandagatla 		      void *buf, size_t *len)
95669aba794SSrinivas Kandagatla {
95769aba794SSrinivas Kandagatla 	int rc;
95869aba794SSrinivas Kandagatla 
959795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
96069aba794SSrinivas Kandagatla 
961287980e4SArnd Bergmann 	if (rc)
96269aba794SSrinivas Kandagatla 		return rc;
96369aba794SSrinivas Kandagatla 
96469aba794SSrinivas Kandagatla 	/* shift bits in-place */
965cbf854abSAxel Lin 	if (cell->bit_offset || cell->nbits)
96669aba794SSrinivas Kandagatla 		nvmem_shift_read_buffer_in_place(cell, buf);
96769aba794SSrinivas Kandagatla 
9683b4a6877SVivek Gautam 	if (len)
96969aba794SSrinivas Kandagatla 		*len = cell->bytes;
97069aba794SSrinivas Kandagatla 
97169aba794SSrinivas Kandagatla 	return 0;
97269aba794SSrinivas Kandagatla }
97369aba794SSrinivas Kandagatla 
97469aba794SSrinivas Kandagatla /**
97569aba794SSrinivas Kandagatla  * nvmem_cell_read() - Read a given nvmem cell
97669aba794SSrinivas Kandagatla  *
97769aba794SSrinivas Kandagatla  * @cell: nvmem cell to be read.
9783b4a6877SVivek Gautam  * @len: pointer to length of cell which will be populated on successful read;
9793b4a6877SVivek Gautam  *	 can be NULL.
98069aba794SSrinivas Kandagatla  *
981b577fafcSBrian Norris  * Return: ERR_PTR() on error or a valid pointer to a buffer on success. The
982b577fafcSBrian Norris  * buffer should be freed by the consumer with a kfree().
98369aba794SSrinivas Kandagatla  */
98469aba794SSrinivas Kandagatla void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
98569aba794SSrinivas Kandagatla {
98669aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
98769aba794SSrinivas Kandagatla 	u8 *buf;
98869aba794SSrinivas Kandagatla 	int rc;
98969aba794SSrinivas Kandagatla 
990795ddd18SSrinivas Kandagatla 	if (!nvmem)
99169aba794SSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
99269aba794SSrinivas Kandagatla 
99369aba794SSrinivas Kandagatla 	buf = kzalloc(cell->bytes, GFP_KERNEL);
99469aba794SSrinivas Kandagatla 	if (!buf)
99569aba794SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
99669aba794SSrinivas Kandagatla 
99769aba794SSrinivas Kandagatla 	rc = __nvmem_cell_read(nvmem, cell, buf, len);
998287980e4SArnd Bergmann 	if (rc) {
99969aba794SSrinivas Kandagatla 		kfree(buf);
100069aba794SSrinivas Kandagatla 		return ERR_PTR(rc);
100169aba794SSrinivas Kandagatla 	}
100269aba794SSrinivas Kandagatla 
100369aba794SSrinivas Kandagatla 	return buf;
100469aba794SSrinivas Kandagatla }
100569aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_read);
100669aba794SSrinivas Kandagatla 
1007f7c04f16SMasahiro Yamada static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
100869aba794SSrinivas Kandagatla 					     u8 *_buf, int len)
100969aba794SSrinivas Kandagatla {
101069aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
101169aba794SSrinivas Kandagatla 	int i, rc, nbits, bit_offset = cell->bit_offset;
101269aba794SSrinivas Kandagatla 	u8 v, *p, *buf, *b, pbyte, pbits;
101369aba794SSrinivas Kandagatla 
101469aba794SSrinivas Kandagatla 	nbits = cell->nbits;
101569aba794SSrinivas Kandagatla 	buf = kzalloc(cell->bytes, GFP_KERNEL);
101669aba794SSrinivas Kandagatla 	if (!buf)
101769aba794SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
101869aba794SSrinivas Kandagatla 
101969aba794SSrinivas Kandagatla 	memcpy(buf, _buf, len);
102069aba794SSrinivas Kandagatla 	p = b = buf;
102169aba794SSrinivas Kandagatla 
102269aba794SSrinivas Kandagatla 	if (bit_offset) {
102369aba794SSrinivas Kandagatla 		pbyte = *b;
102469aba794SSrinivas Kandagatla 		*b <<= bit_offset;
102569aba794SSrinivas Kandagatla 
102669aba794SSrinivas Kandagatla 		/* setup the first byte with lsb bits from nvmem */
1027795ddd18SSrinivas Kandagatla 		rc = nvmem_reg_read(nvmem, cell->offset, &v, 1);
102850808bfcSMathieu Malaterre 		if (rc)
102950808bfcSMathieu Malaterre 			goto err;
103069aba794SSrinivas Kandagatla 		*b++ |= GENMASK(bit_offset - 1, 0) & v;
103169aba794SSrinivas Kandagatla 
103269aba794SSrinivas Kandagatla 		/* setup rest of the byte if any */
103369aba794SSrinivas Kandagatla 		for (i = 1; i < cell->bytes; i++) {
103469aba794SSrinivas Kandagatla 			/* Get last byte bits and shift them towards lsb */
103569aba794SSrinivas Kandagatla 			pbits = pbyte >> (BITS_PER_BYTE - 1 - bit_offset);
103669aba794SSrinivas Kandagatla 			pbyte = *b;
103769aba794SSrinivas Kandagatla 			p = b;
103869aba794SSrinivas Kandagatla 			*b <<= bit_offset;
103969aba794SSrinivas Kandagatla 			*b++ |= pbits;
104069aba794SSrinivas Kandagatla 		}
104169aba794SSrinivas Kandagatla 	}
104269aba794SSrinivas Kandagatla 
104369aba794SSrinivas Kandagatla 	/* if it's not end on byte boundary */
104469aba794SSrinivas Kandagatla 	if ((nbits + bit_offset) % BITS_PER_BYTE) {
104569aba794SSrinivas Kandagatla 		/* setup the last byte with msb bits from nvmem */
1046795ddd18SSrinivas Kandagatla 		rc = nvmem_reg_read(nvmem,
104769aba794SSrinivas Kandagatla 				    cell->offset + cell->bytes - 1, &v, 1);
104850808bfcSMathieu Malaterre 		if (rc)
104950808bfcSMathieu Malaterre 			goto err;
105069aba794SSrinivas Kandagatla 		*p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
105169aba794SSrinivas Kandagatla 
105269aba794SSrinivas Kandagatla 	}
105369aba794SSrinivas Kandagatla 
105469aba794SSrinivas Kandagatla 	return buf;
105550808bfcSMathieu Malaterre err:
105650808bfcSMathieu Malaterre 	kfree(buf);
105750808bfcSMathieu Malaterre 	return ERR_PTR(rc);
105869aba794SSrinivas Kandagatla }
105969aba794SSrinivas Kandagatla 
106069aba794SSrinivas Kandagatla /**
106169aba794SSrinivas Kandagatla  * nvmem_cell_write() - Write to a given nvmem cell
106269aba794SSrinivas Kandagatla  *
106369aba794SSrinivas Kandagatla  * @cell: nvmem cell to be written.
106469aba794SSrinivas Kandagatla  * @buf: Buffer to be written.
106569aba794SSrinivas Kandagatla  * @len: length of buffer to be written to nvmem cell.
106669aba794SSrinivas Kandagatla  *
106769aba794SSrinivas Kandagatla  * Return: length of bytes written or negative on failure.
106869aba794SSrinivas Kandagatla  */
106969aba794SSrinivas Kandagatla int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
107069aba794SSrinivas Kandagatla {
107169aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
107269aba794SSrinivas Kandagatla 	int rc;
107369aba794SSrinivas Kandagatla 
1074795ddd18SSrinivas Kandagatla 	if (!nvmem || nvmem->read_only ||
107569aba794SSrinivas Kandagatla 	    (cell->bit_offset == 0 && len != cell->bytes))
107669aba794SSrinivas Kandagatla 		return -EINVAL;
107769aba794SSrinivas Kandagatla 
107869aba794SSrinivas Kandagatla 	if (cell->bit_offset || cell->nbits) {
107969aba794SSrinivas Kandagatla 		buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
108069aba794SSrinivas Kandagatla 		if (IS_ERR(buf))
108169aba794SSrinivas Kandagatla 			return PTR_ERR(buf);
108269aba794SSrinivas Kandagatla 	}
108369aba794SSrinivas Kandagatla 
1084795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_write(nvmem, cell->offset, buf, cell->bytes);
108569aba794SSrinivas Kandagatla 
108669aba794SSrinivas Kandagatla 	/* free the tmp buffer */
1087ace22170SAxel Lin 	if (cell->bit_offset || cell->nbits)
108869aba794SSrinivas Kandagatla 		kfree(buf);
108969aba794SSrinivas Kandagatla 
1090287980e4SArnd Bergmann 	if (rc)
109169aba794SSrinivas Kandagatla 		return rc;
109269aba794SSrinivas Kandagatla 
109369aba794SSrinivas Kandagatla 	return len;
109469aba794SSrinivas Kandagatla }
109569aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_write);
109669aba794SSrinivas Kandagatla 
10976bb317ceSYangtao Li static int nvmem_cell_read_common(struct device *dev, const char *cell_id,
10986bb317ceSYangtao Li 				  void *val, size_t count)
10990a9b2d1cSFabrice Gasnier {
11000a9b2d1cSFabrice Gasnier 	struct nvmem_cell *cell;
11010a9b2d1cSFabrice Gasnier 	void *buf;
11020a9b2d1cSFabrice Gasnier 	size_t len;
11030a9b2d1cSFabrice Gasnier 
11040a9b2d1cSFabrice Gasnier 	cell = nvmem_cell_get(dev, cell_id);
11050a9b2d1cSFabrice Gasnier 	if (IS_ERR(cell))
11060a9b2d1cSFabrice Gasnier 		return PTR_ERR(cell);
11070a9b2d1cSFabrice Gasnier 
11080a9b2d1cSFabrice Gasnier 	buf = nvmem_cell_read(cell, &len);
11090a9b2d1cSFabrice Gasnier 	if (IS_ERR(buf)) {
11100a9b2d1cSFabrice Gasnier 		nvmem_cell_put(cell);
11110a9b2d1cSFabrice Gasnier 		return PTR_ERR(buf);
11120a9b2d1cSFabrice Gasnier 	}
11136bb317ceSYangtao Li 	if (len != count) {
11140a9b2d1cSFabrice Gasnier 		kfree(buf);
11150a9b2d1cSFabrice Gasnier 		nvmem_cell_put(cell);
11160a9b2d1cSFabrice Gasnier 		return -EINVAL;
11170a9b2d1cSFabrice Gasnier 	}
11186bb317ceSYangtao Li 	memcpy(val, buf, count);
11190a9b2d1cSFabrice Gasnier 	kfree(buf);
11200a9b2d1cSFabrice Gasnier 	nvmem_cell_put(cell);
11210a9b2d1cSFabrice Gasnier 
11220a9b2d1cSFabrice Gasnier 	return 0;
11230a9b2d1cSFabrice Gasnier }
11246bb317ceSYangtao Li 
11256bb317ceSYangtao Li /**
11266bb317ceSYangtao Li  * nvmem_cell_read_u16() - Read a cell value as an u16
11276bb317ceSYangtao Li  *
11286bb317ceSYangtao Li  * @dev: Device that requests the nvmem cell.
11296bb317ceSYangtao Li  * @cell_id: Name of nvmem cell to read.
11306bb317ceSYangtao Li  * @val: pointer to output value.
11316bb317ceSYangtao Li  *
11326bb317ceSYangtao Li  * Return: 0 on success or negative errno.
11336bb317ceSYangtao Li  */
11346bb317ceSYangtao Li int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
11356bb317ceSYangtao Li {
11366bb317ceSYangtao Li 	return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
11376bb317ceSYangtao Li }
11380a9b2d1cSFabrice Gasnier EXPORT_SYMBOL_GPL(nvmem_cell_read_u16);
11390a9b2d1cSFabrice Gasnier 
11400a9b2d1cSFabrice Gasnier /**
1141d026d70aSLeonard Crestez  * nvmem_cell_read_u32() - Read a cell value as an u32
1142d026d70aSLeonard Crestez  *
1143d026d70aSLeonard Crestez  * @dev: Device that requests the nvmem cell.
1144d026d70aSLeonard Crestez  * @cell_id: Name of nvmem cell to read.
1145d026d70aSLeonard Crestez  * @val: pointer to output value.
1146d026d70aSLeonard Crestez  *
1147d026d70aSLeonard Crestez  * Return: 0 on success or negative errno.
1148d026d70aSLeonard Crestez  */
1149d026d70aSLeonard Crestez int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val)
1150d026d70aSLeonard Crestez {
11516bb317ceSYangtao Li 	return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
1152d026d70aSLeonard Crestez }
1153d026d70aSLeonard Crestez EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
1154d026d70aSLeonard Crestez 
1155d026d70aSLeonard Crestez /**
11568b977c54SYangtao Li  * nvmem_cell_read_u64() - Read a cell value as an u64
11578b977c54SYangtao Li  *
11588b977c54SYangtao Li  * @dev: Device that requests the nvmem cell.
11598b977c54SYangtao Li  * @cell_id: Name of nvmem cell to read.
11608b977c54SYangtao Li  * @val: pointer to output value.
11618b977c54SYangtao Li  *
11628b977c54SYangtao Li  * Return: 0 on success or negative errno.
11638b977c54SYangtao Li  */
11648b977c54SYangtao Li int nvmem_cell_read_u64(struct device *dev, const char *cell_id, u64 *val)
11658b977c54SYangtao Li {
11668b977c54SYangtao Li 	return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
11678b977c54SYangtao Li }
11688b977c54SYangtao Li EXPORT_SYMBOL_GPL(nvmem_cell_read_u64);
11698b977c54SYangtao Li 
11708b977c54SYangtao Li /**
1171e2a5402eSSrinivas Kandagatla  * nvmem_device_cell_read() - Read a given nvmem device and cell
1172e2a5402eSSrinivas Kandagatla  *
1173e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to read from.
1174e2a5402eSSrinivas Kandagatla  * @info: nvmem cell info to be read.
1175e2a5402eSSrinivas Kandagatla  * @buf: buffer pointer which will be populated on successful read.
1176e2a5402eSSrinivas Kandagatla  *
1177e2a5402eSSrinivas Kandagatla  * Return: length of successful bytes read on success and negative
1178e2a5402eSSrinivas Kandagatla  * error code on error.
1179e2a5402eSSrinivas Kandagatla  */
1180e2a5402eSSrinivas Kandagatla ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
1181e2a5402eSSrinivas Kandagatla 			   struct nvmem_cell_info *info, void *buf)
1182e2a5402eSSrinivas Kandagatla {
1183e2a5402eSSrinivas Kandagatla 	struct nvmem_cell cell;
1184e2a5402eSSrinivas Kandagatla 	int rc;
1185e2a5402eSSrinivas Kandagatla 	ssize_t len;
1186e2a5402eSSrinivas Kandagatla 
1187795ddd18SSrinivas Kandagatla 	if (!nvmem)
1188e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1189e2a5402eSSrinivas Kandagatla 
1190e2a5402eSSrinivas Kandagatla 	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
1191287980e4SArnd Bergmann 	if (rc)
1192e2a5402eSSrinivas Kandagatla 		return rc;
1193e2a5402eSSrinivas Kandagatla 
1194e2a5402eSSrinivas Kandagatla 	rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
1195287980e4SArnd Bergmann 	if (rc)
1196e2a5402eSSrinivas Kandagatla 		return rc;
1197e2a5402eSSrinivas Kandagatla 
1198e2a5402eSSrinivas Kandagatla 	return len;
1199e2a5402eSSrinivas Kandagatla }
1200e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
1201e2a5402eSSrinivas Kandagatla 
1202e2a5402eSSrinivas Kandagatla /**
1203e2a5402eSSrinivas Kandagatla  * nvmem_device_cell_write() - Write cell to a given nvmem device
1204e2a5402eSSrinivas Kandagatla  *
1205e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to be written to.
120629143268SVivek Gautam  * @info: nvmem cell info to be written.
1207e2a5402eSSrinivas Kandagatla  * @buf: buffer to be written to cell.
1208e2a5402eSSrinivas Kandagatla  *
1209e2a5402eSSrinivas Kandagatla  * Return: length of bytes written or negative error code on failure.
121048f63a2cSBartosz Golaszewski  */
1211e2a5402eSSrinivas Kandagatla int nvmem_device_cell_write(struct nvmem_device *nvmem,
1212e2a5402eSSrinivas Kandagatla 			    struct nvmem_cell_info *info, void *buf)
1213e2a5402eSSrinivas Kandagatla {
1214e2a5402eSSrinivas Kandagatla 	struct nvmem_cell cell;
1215e2a5402eSSrinivas Kandagatla 	int rc;
1216e2a5402eSSrinivas Kandagatla 
1217795ddd18SSrinivas Kandagatla 	if (!nvmem)
1218e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1219e2a5402eSSrinivas Kandagatla 
1220e2a5402eSSrinivas Kandagatla 	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
1221287980e4SArnd Bergmann 	if (rc)
1222e2a5402eSSrinivas Kandagatla 		return rc;
1223e2a5402eSSrinivas Kandagatla 
1224e2a5402eSSrinivas Kandagatla 	return nvmem_cell_write(&cell, buf, cell.bytes);
1225e2a5402eSSrinivas Kandagatla }
1226e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
1227e2a5402eSSrinivas Kandagatla 
1228e2a5402eSSrinivas Kandagatla /**
1229e2a5402eSSrinivas Kandagatla  * nvmem_device_read() - Read from a given nvmem device
1230e2a5402eSSrinivas Kandagatla  *
1231e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to read from.
1232e2a5402eSSrinivas Kandagatla  * @offset: offset in nvmem device.
1233e2a5402eSSrinivas Kandagatla  * @bytes: number of bytes to read.
1234e2a5402eSSrinivas Kandagatla  * @buf: buffer pointer which will be populated on successful read.
1235e2a5402eSSrinivas Kandagatla  *
1236e2a5402eSSrinivas Kandagatla  * Return: length of successful bytes read on success and negative
1237e2a5402eSSrinivas Kandagatla  * error code on error.
1238e2a5402eSSrinivas Kandagatla  */
1239e2a5402eSSrinivas Kandagatla int nvmem_device_read(struct nvmem_device *nvmem,
1240e2a5402eSSrinivas Kandagatla 		      unsigned int offset,
1241e2a5402eSSrinivas Kandagatla 		      size_t bytes, void *buf)
1242e2a5402eSSrinivas Kandagatla {
1243e2a5402eSSrinivas Kandagatla 	int rc;
1244e2a5402eSSrinivas Kandagatla 
1245795ddd18SSrinivas Kandagatla 	if (!nvmem)
1246e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1247e2a5402eSSrinivas Kandagatla 
1248795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_read(nvmem, offset, buf, bytes);
1249e2a5402eSSrinivas Kandagatla 
1250287980e4SArnd Bergmann 	if (rc)
1251e2a5402eSSrinivas Kandagatla 		return rc;
1252e2a5402eSSrinivas Kandagatla 
1253e2a5402eSSrinivas Kandagatla 	return bytes;
1254e2a5402eSSrinivas Kandagatla }
1255e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_read);
1256e2a5402eSSrinivas Kandagatla 
1257e2a5402eSSrinivas Kandagatla /**
1258e2a5402eSSrinivas Kandagatla  * nvmem_device_write() - Write cell to a given nvmem device
1259e2a5402eSSrinivas Kandagatla  *
1260e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to be written to.
1261e2a5402eSSrinivas Kandagatla  * @offset: offset in nvmem device.
1262e2a5402eSSrinivas Kandagatla  * @bytes: number of bytes to write.
1263e2a5402eSSrinivas Kandagatla  * @buf: buffer to be written.
1264e2a5402eSSrinivas Kandagatla  *
1265e2a5402eSSrinivas Kandagatla  * Return: length of bytes written or negative error code on failure.
126648f63a2cSBartosz Golaszewski  */
1267e2a5402eSSrinivas Kandagatla int nvmem_device_write(struct nvmem_device *nvmem,
1268e2a5402eSSrinivas Kandagatla 		       unsigned int offset,
1269e2a5402eSSrinivas Kandagatla 		       size_t bytes, void *buf)
1270e2a5402eSSrinivas Kandagatla {
1271e2a5402eSSrinivas Kandagatla 	int rc;
1272e2a5402eSSrinivas Kandagatla 
1273795ddd18SSrinivas Kandagatla 	if (!nvmem)
1274e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1275e2a5402eSSrinivas Kandagatla 
1276795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_write(nvmem, offset, buf, bytes);
1277e2a5402eSSrinivas Kandagatla 
1278287980e4SArnd Bergmann 	if (rc)
1279e2a5402eSSrinivas Kandagatla 		return rc;
1280e2a5402eSSrinivas Kandagatla 
1281e2a5402eSSrinivas Kandagatla 
1282e2a5402eSSrinivas Kandagatla 	return bytes;
1283e2a5402eSSrinivas Kandagatla }
1284e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_write);
1285e2a5402eSSrinivas Kandagatla 
1286d7b9fd16SBartosz Golaszewski /**
1287b985f4cbSBartosz Golaszewski  * nvmem_add_cell_table() - register a table of cell info entries
1288b985f4cbSBartosz Golaszewski  *
1289b985f4cbSBartosz Golaszewski  * @table: table of cell info entries
1290b985f4cbSBartosz Golaszewski  */
1291b985f4cbSBartosz Golaszewski void nvmem_add_cell_table(struct nvmem_cell_table *table)
1292b985f4cbSBartosz Golaszewski {
1293b985f4cbSBartosz Golaszewski 	mutex_lock(&nvmem_cell_mutex);
1294b985f4cbSBartosz Golaszewski 	list_add_tail(&table->node, &nvmem_cell_tables);
1295b985f4cbSBartosz Golaszewski 	mutex_unlock(&nvmem_cell_mutex);
1296b985f4cbSBartosz Golaszewski }
1297b985f4cbSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_add_cell_table);
1298b985f4cbSBartosz Golaszewski 
1299b985f4cbSBartosz Golaszewski /**
1300b985f4cbSBartosz Golaszewski  * nvmem_del_cell_table() - remove a previously registered cell info table
1301b985f4cbSBartosz Golaszewski  *
1302b985f4cbSBartosz Golaszewski  * @table: table of cell info entries
1303b985f4cbSBartosz Golaszewski  */
1304b985f4cbSBartosz Golaszewski void nvmem_del_cell_table(struct nvmem_cell_table *table)
1305b985f4cbSBartosz Golaszewski {
1306b985f4cbSBartosz Golaszewski 	mutex_lock(&nvmem_cell_mutex);
1307b985f4cbSBartosz Golaszewski 	list_del(&table->node);
1308b985f4cbSBartosz Golaszewski 	mutex_unlock(&nvmem_cell_mutex);
1309b985f4cbSBartosz Golaszewski }
1310b985f4cbSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_del_cell_table);
1311b985f4cbSBartosz Golaszewski 
1312b985f4cbSBartosz Golaszewski /**
1313506157beSBartosz Golaszewski  * nvmem_add_cell_lookups() - register a list of cell lookup entries
1314506157beSBartosz Golaszewski  *
1315506157beSBartosz Golaszewski  * @entries: array of cell lookup entries
1316506157beSBartosz Golaszewski  * @nentries: number of cell lookup entries in the array
1317506157beSBartosz Golaszewski  */
1318506157beSBartosz Golaszewski void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
1319506157beSBartosz Golaszewski {
1320506157beSBartosz Golaszewski 	int i;
1321506157beSBartosz Golaszewski 
1322506157beSBartosz Golaszewski 	mutex_lock(&nvmem_lookup_mutex);
1323506157beSBartosz Golaszewski 	for (i = 0; i < nentries; i++)
1324506157beSBartosz Golaszewski 		list_add_tail(&entries[i].node, &nvmem_lookup_list);
1325506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_lookup_mutex);
1326506157beSBartosz Golaszewski }
1327506157beSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_add_cell_lookups);
1328506157beSBartosz Golaszewski 
1329506157beSBartosz Golaszewski /**
1330506157beSBartosz Golaszewski  * nvmem_del_cell_lookups() - remove a list of previously added cell lookup
1331506157beSBartosz Golaszewski  *                            entries
1332506157beSBartosz Golaszewski  *
1333506157beSBartosz Golaszewski  * @entries: array of cell lookup entries
1334506157beSBartosz Golaszewski  * @nentries: number of cell lookup entries in the array
1335506157beSBartosz Golaszewski  */
1336506157beSBartosz Golaszewski void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
1337506157beSBartosz Golaszewski {
1338506157beSBartosz Golaszewski 	int i;
1339506157beSBartosz Golaszewski 
1340506157beSBartosz Golaszewski 	mutex_lock(&nvmem_lookup_mutex);
1341506157beSBartosz Golaszewski 	for (i = 0; i < nentries; i++)
1342506157beSBartosz Golaszewski 		list_del(&entries[i].node);
1343506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_lookup_mutex);
1344506157beSBartosz Golaszewski }
1345506157beSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_del_cell_lookups);
1346506157beSBartosz Golaszewski 
1347506157beSBartosz Golaszewski /**
1348d7b9fd16SBartosz Golaszewski  * nvmem_dev_name() - Get the name of a given nvmem device.
1349d7b9fd16SBartosz Golaszewski  *
1350d7b9fd16SBartosz Golaszewski  * @nvmem: nvmem device.
1351d7b9fd16SBartosz Golaszewski  *
1352d7b9fd16SBartosz Golaszewski  * Return: name of the nvmem device.
1353d7b9fd16SBartosz Golaszewski  */
1354d7b9fd16SBartosz Golaszewski const char *nvmem_dev_name(struct nvmem_device *nvmem)
1355d7b9fd16SBartosz Golaszewski {
1356d7b9fd16SBartosz Golaszewski 	return dev_name(&nvmem->dev);
1357d7b9fd16SBartosz Golaszewski }
1358d7b9fd16SBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_dev_name);
1359d7b9fd16SBartosz Golaszewski 
1360eace75cfSSrinivas Kandagatla static int __init nvmem_init(void)
1361eace75cfSSrinivas Kandagatla {
1362eace75cfSSrinivas Kandagatla 	return bus_register(&nvmem_bus_type);
1363eace75cfSSrinivas Kandagatla }
1364eace75cfSSrinivas Kandagatla 
1365eace75cfSSrinivas Kandagatla static void __exit nvmem_exit(void)
1366eace75cfSSrinivas Kandagatla {
1367eace75cfSSrinivas Kandagatla 	bus_unregister(&nvmem_bus_type);
1368eace75cfSSrinivas Kandagatla }
1369eace75cfSSrinivas Kandagatla 
1370eace75cfSSrinivas Kandagatla subsys_initcall(nvmem_init);
1371eace75cfSSrinivas Kandagatla module_exit(nvmem_exit);
1372eace75cfSSrinivas Kandagatla 
1373eace75cfSSrinivas Kandagatla MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
1374eace75cfSSrinivas Kandagatla MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
1375eace75cfSSrinivas Kandagatla MODULE_DESCRIPTION("nvmem Driver Core");
1376eace75cfSSrinivas Kandagatla MODULE_LICENSE("GPL v2");
1377