xref: /linux/drivers/nvmem/core.c (revision f7d8d7dcd978382dd1dd36e240dcddbfa6697796)
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);
75eace75cfSSrinivas Kandagatla 	kfree(nvmem);
76eace75cfSSrinivas Kandagatla }
77eace75cfSSrinivas Kandagatla 
78eace75cfSSrinivas Kandagatla static const struct device_type nvmem_provider_type = {
79eace75cfSSrinivas Kandagatla 	.release	= nvmem_release,
80eace75cfSSrinivas Kandagatla };
81eace75cfSSrinivas Kandagatla 
82eace75cfSSrinivas Kandagatla static struct bus_type nvmem_bus_type = {
83eace75cfSSrinivas Kandagatla 	.name		= "nvmem",
84eace75cfSSrinivas Kandagatla };
85eace75cfSSrinivas Kandagatla 
86eace75cfSSrinivas Kandagatla static void nvmem_cell_drop(struct nvmem_cell *cell)
87eace75cfSSrinivas Kandagatla {
88bee1138bSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
89c7235ee3SBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
90eace75cfSSrinivas Kandagatla 	list_del(&cell->node);
91c7235ee3SBartosz Golaszewski 	mutex_unlock(&nvmem_mutex);
920749aa25SSrinivas Kandagatla 	of_node_put(cell->np);
9316bb7abcSBitan Biswas 	kfree_const(cell->name);
94eace75cfSSrinivas Kandagatla 	kfree(cell);
95eace75cfSSrinivas Kandagatla }
96eace75cfSSrinivas Kandagatla 
97eace75cfSSrinivas Kandagatla static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
98eace75cfSSrinivas Kandagatla {
991852183eSBartosz Golaszewski 	struct nvmem_cell *cell, *p;
100eace75cfSSrinivas Kandagatla 
101c7235ee3SBartosz Golaszewski 	list_for_each_entry_safe(cell, p, &nvmem->cells, node)
102eace75cfSSrinivas Kandagatla 		nvmem_cell_drop(cell);
103eace75cfSSrinivas Kandagatla }
104eace75cfSSrinivas Kandagatla 
105eace75cfSSrinivas Kandagatla static void nvmem_cell_add(struct nvmem_cell *cell)
106eace75cfSSrinivas Kandagatla {
107c7235ee3SBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
108c7235ee3SBartosz Golaszewski 	list_add_tail(&cell->node, &cell->nvmem->cells);
109c7235ee3SBartosz Golaszewski 	mutex_unlock(&nvmem_mutex);
110bee1138bSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
111eace75cfSSrinivas Kandagatla }
112eace75cfSSrinivas Kandagatla 
113eace75cfSSrinivas Kandagatla static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
114eace75cfSSrinivas Kandagatla 				   const struct nvmem_cell_info *info,
115eace75cfSSrinivas Kandagatla 				   struct nvmem_cell *cell)
116eace75cfSSrinivas Kandagatla {
117eace75cfSSrinivas Kandagatla 	cell->nvmem = nvmem;
118eace75cfSSrinivas Kandagatla 	cell->offset = info->offset;
119eace75cfSSrinivas Kandagatla 	cell->bytes = info->bytes;
12016bb7abcSBitan Biswas 	cell->name = kstrdup_const(info->name, GFP_KERNEL);
12116bb7abcSBitan Biswas 	if (!cell->name)
12216bb7abcSBitan Biswas 		return -ENOMEM;
123eace75cfSSrinivas Kandagatla 
124eace75cfSSrinivas Kandagatla 	cell->bit_offset = info->bit_offset;
125eace75cfSSrinivas Kandagatla 	cell->nbits = info->nbits;
126eace75cfSSrinivas Kandagatla 
127eace75cfSSrinivas Kandagatla 	if (cell->nbits)
128eace75cfSSrinivas Kandagatla 		cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
129eace75cfSSrinivas Kandagatla 					   BITS_PER_BYTE);
130eace75cfSSrinivas Kandagatla 
131eace75cfSSrinivas Kandagatla 	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
132eace75cfSSrinivas Kandagatla 		dev_err(&nvmem->dev,
133eace75cfSSrinivas Kandagatla 			"cell %s unaligned to nvmem stride %d\n",
134eace75cfSSrinivas Kandagatla 			cell->name, nvmem->stride);
135eace75cfSSrinivas Kandagatla 		return -EINVAL;
136eace75cfSSrinivas Kandagatla 	}
137eace75cfSSrinivas Kandagatla 
138eace75cfSSrinivas Kandagatla 	return 0;
139eace75cfSSrinivas Kandagatla }
140eace75cfSSrinivas Kandagatla 
141b3db17e4SAndrew Lunn /**
142b3db17e4SAndrew Lunn  * nvmem_add_cells() - Add cell information to an nvmem device
143b3db17e4SAndrew Lunn  *
144b3db17e4SAndrew Lunn  * @nvmem: nvmem device to add cells to.
145b3db17e4SAndrew Lunn  * @info: nvmem cell info to add to the device
146b3db17e4SAndrew Lunn  * @ncells: number of cells in info
147b3db17e4SAndrew Lunn  *
148b3db17e4SAndrew Lunn  * Return: 0 or negative error code on failure.
149b3db17e4SAndrew Lunn  */
150ef92ab30SSrinivas Kandagatla static int nvmem_add_cells(struct nvmem_device *nvmem,
151b3db17e4SAndrew Lunn 		    const struct nvmem_cell_info *info,
152b3db17e4SAndrew Lunn 		    int ncells)
153eace75cfSSrinivas Kandagatla {
154eace75cfSSrinivas Kandagatla 	struct nvmem_cell **cells;
155eace75cfSSrinivas Kandagatla 	int i, rval;
156eace75cfSSrinivas Kandagatla 
157b3db17e4SAndrew Lunn 	cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
158eace75cfSSrinivas Kandagatla 	if (!cells)
159eace75cfSSrinivas Kandagatla 		return -ENOMEM;
160eace75cfSSrinivas Kandagatla 
161b3db17e4SAndrew Lunn 	for (i = 0; i < ncells; i++) {
162eace75cfSSrinivas Kandagatla 		cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
163eace75cfSSrinivas Kandagatla 		if (!cells[i]) {
164eace75cfSSrinivas Kandagatla 			rval = -ENOMEM;
165eace75cfSSrinivas Kandagatla 			goto err;
166eace75cfSSrinivas Kandagatla 		}
167eace75cfSSrinivas Kandagatla 
168eace75cfSSrinivas Kandagatla 		rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
169287980e4SArnd Bergmann 		if (rval) {
170eace75cfSSrinivas Kandagatla 			kfree(cells[i]);
171eace75cfSSrinivas Kandagatla 			goto err;
172eace75cfSSrinivas Kandagatla 		}
173eace75cfSSrinivas Kandagatla 
174eace75cfSSrinivas Kandagatla 		nvmem_cell_add(cells[i]);
175eace75cfSSrinivas Kandagatla 	}
176eace75cfSSrinivas Kandagatla 
177eace75cfSSrinivas Kandagatla 	/* remove tmp array */
178eace75cfSSrinivas Kandagatla 	kfree(cells);
179eace75cfSSrinivas Kandagatla 
180eace75cfSSrinivas Kandagatla 	return 0;
181eace75cfSSrinivas Kandagatla err:
182dfdf1414SRasmus Villemoes 	while (i--)
183eace75cfSSrinivas Kandagatla 		nvmem_cell_drop(cells[i]);
184eace75cfSSrinivas Kandagatla 
185dfdf1414SRasmus Villemoes 	kfree(cells);
186dfdf1414SRasmus Villemoes 
187eace75cfSSrinivas Kandagatla 	return rval;
188eace75cfSSrinivas Kandagatla }
189eace75cfSSrinivas Kandagatla 
190bee1138bSBartosz Golaszewski /**
191bee1138bSBartosz Golaszewski  * nvmem_register_notifier() - Register a notifier block for nvmem events.
192bee1138bSBartosz Golaszewski  *
193bee1138bSBartosz Golaszewski  * @nb: notifier block to be called on nvmem events.
194bee1138bSBartosz Golaszewski  *
195bee1138bSBartosz Golaszewski  * Return: 0 on success, negative error number on failure.
196bee1138bSBartosz Golaszewski  */
197bee1138bSBartosz Golaszewski int nvmem_register_notifier(struct notifier_block *nb)
198bee1138bSBartosz Golaszewski {
199bee1138bSBartosz Golaszewski 	return blocking_notifier_chain_register(&nvmem_notifier, nb);
200bee1138bSBartosz Golaszewski }
201bee1138bSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_register_notifier);
202bee1138bSBartosz Golaszewski 
203bee1138bSBartosz Golaszewski /**
204bee1138bSBartosz Golaszewski  * nvmem_unregister_notifier() - Unregister a notifier block for nvmem events.
205bee1138bSBartosz Golaszewski  *
206bee1138bSBartosz Golaszewski  * @nb: notifier block to be unregistered.
207bee1138bSBartosz Golaszewski  *
208bee1138bSBartosz Golaszewski  * Return: 0 on success, negative error number on failure.
209bee1138bSBartosz Golaszewski  */
210bee1138bSBartosz Golaszewski int nvmem_unregister_notifier(struct notifier_block *nb)
211bee1138bSBartosz Golaszewski {
212bee1138bSBartosz Golaszewski 	return blocking_notifier_chain_unregister(&nvmem_notifier, nb);
213bee1138bSBartosz Golaszewski }
214bee1138bSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_unregister_notifier);
215bee1138bSBartosz Golaszewski 
216b985f4cbSBartosz Golaszewski static int nvmem_add_cells_from_table(struct nvmem_device *nvmem)
217b985f4cbSBartosz Golaszewski {
218b985f4cbSBartosz Golaszewski 	const struct nvmem_cell_info *info;
219b985f4cbSBartosz Golaszewski 	struct nvmem_cell_table *table;
220b985f4cbSBartosz Golaszewski 	struct nvmem_cell *cell;
221b985f4cbSBartosz Golaszewski 	int rval = 0, i;
222b985f4cbSBartosz Golaszewski 
223b985f4cbSBartosz Golaszewski 	mutex_lock(&nvmem_cell_mutex);
224b985f4cbSBartosz Golaszewski 	list_for_each_entry(table, &nvmem_cell_tables, node) {
225b985f4cbSBartosz Golaszewski 		if (strcmp(nvmem_dev_name(nvmem), table->nvmem_name) == 0) {
226b985f4cbSBartosz Golaszewski 			for (i = 0; i < table->ncells; i++) {
227b985f4cbSBartosz Golaszewski 				info = &table->cells[i];
228b985f4cbSBartosz Golaszewski 
229b985f4cbSBartosz Golaszewski 				cell = kzalloc(sizeof(*cell), GFP_KERNEL);
230b985f4cbSBartosz Golaszewski 				if (!cell) {
231b985f4cbSBartosz Golaszewski 					rval = -ENOMEM;
232b985f4cbSBartosz Golaszewski 					goto out;
233b985f4cbSBartosz Golaszewski 				}
234b985f4cbSBartosz Golaszewski 
235b985f4cbSBartosz Golaszewski 				rval = nvmem_cell_info_to_nvmem_cell(nvmem,
236b985f4cbSBartosz Golaszewski 								     info,
237b985f4cbSBartosz Golaszewski 								     cell);
238b985f4cbSBartosz Golaszewski 				if (rval) {
239b985f4cbSBartosz Golaszewski 					kfree(cell);
240b985f4cbSBartosz Golaszewski 					goto out;
241b985f4cbSBartosz Golaszewski 				}
242b985f4cbSBartosz Golaszewski 
243b985f4cbSBartosz Golaszewski 				nvmem_cell_add(cell);
244b985f4cbSBartosz Golaszewski 			}
245b985f4cbSBartosz Golaszewski 		}
246b985f4cbSBartosz Golaszewski 	}
247b985f4cbSBartosz Golaszewski 
248b985f4cbSBartosz Golaszewski out:
249b985f4cbSBartosz Golaszewski 	mutex_unlock(&nvmem_cell_mutex);
250b985f4cbSBartosz Golaszewski 	return rval;
251b985f4cbSBartosz Golaszewski }
252b985f4cbSBartosz Golaszewski 
253e888d445SBartosz Golaszewski static struct nvmem_cell *
254506157beSBartosz Golaszewski nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
255506157beSBartosz Golaszewski {
2561c832674SAlban Bedel 	struct nvmem_cell *iter, *cell = NULL;
257506157beSBartosz Golaszewski 
258506157beSBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
2591c832674SAlban Bedel 	list_for_each_entry(iter, &nvmem->cells, node) {
2601c832674SAlban Bedel 		if (strcmp(cell_id, iter->name) == 0) {
2611c832674SAlban Bedel 			cell = iter;
262506157beSBartosz Golaszewski 			break;
263506157beSBartosz Golaszewski 		}
2641c832674SAlban Bedel 	}
265506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_mutex);
266506157beSBartosz Golaszewski 
267506157beSBartosz Golaszewski 	return cell;
268506157beSBartosz Golaszewski }
269506157beSBartosz Golaszewski 
270e888d445SBartosz Golaszewski static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
271e888d445SBartosz Golaszewski {
272e888d445SBartosz Golaszewski 	struct device_node *parent, *child;
273e888d445SBartosz Golaszewski 	struct device *dev = &nvmem->dev;
274e888d445SBartosz Golaszewski 	struct nvmem_cell *cell;
275e888d445SBartosz Golaszewski 	const __be32 *addr;
276e888d445SBartosz Golaszewski 	int len;
277e888d445SBartosz Golaszewski 
278e888d445SBartosz Golaszewski 	parent = dev->of_node;
279e888d445SBartosz Golaszewski 
280e888d445SBartosz Golaszewski 	for_each_child_of_node(parent, child) {
281e888d445SBartosz Golaszewski 		addr = of_get_property(child, "reg", &len);
282e888d445SBartosz Golaszewski 		if (!addr || (len < 2 * sizeof(u32))) {
283e888d445SBartosz Golaszewski 			dev_err(dev, "nvmem: invalid reg on %pOF\n", child);
284e888d445SBartosz Golaszewski 			return -EINVAL;
285e888d445SBartosz Golaszewski 		}
286e888d445SBartosz Golaszewski 
287e888d445SBartosz Golaszewski 		cell = kzalloc(sizeof(*cell), GFP_KERNEL);
288e888d445SBartosz Golaszewski 		if (!cell)
289e888d445SBartosz Golaszewski 			return -ENOMEM;
290e888d445SBartosz Golaszewski 
291e888d445SBartosz Golaszewski 		cell->nvmem = nvmem;
2920749aa25SSrinivas Kandagatla 		cell->np = of_node_get(child);
293e888d445SBartosz Golaszewski 		cell->offset = be32_to_cpup(addr++);
294e888d445SBartosz Golaszewski 		cell->bytes = be32_to_cpup(addr);
295badcdff1SRob Herring 		cell->name = kasprintf(GFP_KERNEL, "%pOFn", child);
296e888d445SBartosz Golaszewski 
297e888d445SBartosz Golaszewski 		addr = of_get_property(child, "bits", &len);
298e888d445SBartosz Golaszewski 		if (addr && len == (2 * sizeof(u32))) {
299e888d445SBartosz Golaszewski 			cell->bit_offset = be32_to_cpup(addr++);
300e888d445SBartosz Golaszewski 			cell->nbits = be32_to_cpup(addr);
301e888d445SBartosz Golaszewski 		}
302e888d445SBartosz Golaszewski 
303e888d445SBartosz Golaszewski 		if (cell->nbits)
304e888d445SBartosz Golaszewski 			cell->bytes = DIV_ROUND_UP(
305e888d445SBartosz Golaszewski 					cell->nbits + cell->bit_offset,
306e888d445SBartosz Golaszewski 					BITS_PER_BYTE);
307e888d445SBartosz Golaszewski 
308e888d445SBartosz Golaszewski 		if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
309e888d445SBartosz Golaszewski 			dev_err(dev, "cell %s unaligned to nvmem stride %d\n",
310e888d445SBartosz Golaszewski 				cell->name, nvmem->stride);
311e888d445SBartosz Golaszewski 			/* Cells already added will be freed later. */
31216bb7abcSBitan Biswas 			kfree_const(cell->name);
313e888d445SBartosz Golaszewski 			kfree(cell);
314e888d445SBartosz Golaszewski 			return -EINVAL;
315e888d445SBartosz Golaszewski 		}
316e888d445SBartosz Golaszewski 
317e888d445SBartosz Golaszewski 		nvmem_cell_add(cell);
318e888d445SBartosz Golaszewski 	}
319e888d445SBartosz Golaszewski 
320e888d445SBartosz Golaszewski 	return 0;
321e888d445SBartosz Golaszewski }
322e888d445SBartosz Golaszewski 
323eace75cfSSrinivas Kandagatla /**
324eace75cfSSrinivas Kandagatla  * nvmem_register() - Register a nvmem device for given nvmem_config.
325eace75cfSSrinivas Kandagatla  * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
326eace75cfSSrinivas Kandagatla  *
327eace75cfSSrinivas Kandagatla  * @config: nvmem device configuration with which nvmem device is created.
328eace75cfSSrinivas Kandagatla  *
329eace75cfSSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
330eace75cfSSrinivas Kandagatla  * on success.
331eace75cfSSrinivas Kandagatla  */
332eace75cfSSrinivas Kandagatla 
333eace75cfSSrinivas Kandagatla struct nvmem_device *nvmem_register(const struct nvmem_config *config)
334eace75cfSSrinivas Kandagatla {
335eace75cfSSrinivas Kandagatla 	struct nvmem_device *nvmem;
336eace75cfSSrinivas Kandagatla 	int rval;
337eace75cfSSrinivas Kandagatla 
338eace75cfSSrinivas Kandagatla 	if (!config->dev)
339eace75cfSSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
340eace75cfSSrinivas Kandagatla 
341eace75cfSSrinivas Kandagatla 	nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
342eace75cfSSrinivas Kandagatla 	if (!nvmem)
343eace75cfSSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
344eace75cfSSrinivas Kandagatla 
345eace75cfSSrinivas Kandagatla 	rval  = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
346eace75cfSSrinivas Kandagatla 	if (rval < 0) {
347eace75cfSSrinivas Kandagatla 		kfree(nvmem);
348eace75cfSSrinivas Kandagatla 		return ERR_PTR(rval);
349eace75cfSSrinivas Kandagatla 	}
35031c6ff51SBartosz Golaszewski 
3512a127da4SKhouloud Touil 	if (config->wp_gpio)
3522a127da4SKhouloud Touil 		nvmem->wp_gpio = config->wp_gpio;
3532a127da4SKhouloud Touil 	else
3542a127da4SKhouloud Touil 		nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp",
3552a127da4SKhouloud Touil 						    GPIOD_OUT_HIGH);
356*f7d8d7dcSBartosz Golaszewski 	if (IS_ERR(nvmem->wp_gpio)) {
357*f7d8d7dcSBartosz Golaszewski 		ida_simple_remove(&nvmem_ida, nvmem->id);
358*f7d8d7dcSBartosz Golaszewski 		rval = PTR_ERR(nvmem->wp_gpio);
359*f7d8d7dcSBartosz Golaszewski 		kfree(nvmem);
360*f7d8d7dcSBartosz Golaszewski 		return ERR_PTR(rval);
361*f7d8d7dcSBartosz Golaszewski 	}
3622a127da4SKhouloud Touil 
363c1de7f43SBartosz Golaszewski 	kref_init(&nvmem->refcnt);
364c7235ee3SBartosz Golaszewski 	INIT_LIST_HEAD(&nvmem->cells);
365c1de7f43SBartosz Golaszewski 
366eace75cfSSrinivas Kandagatla 	nvmem->id = rval;
367eace75cfSSrinivas Kandagatla 	nvmem->owner = config->owner;
36817eb18d6SMasahiro Yamada 	if (!nvmem->owner && config->dev->driver)
36917eb18d6SMasahiro Yamada 		nvmem->owner = config->dev->driver->owner;
37099897efdSHeiner Kallweit 	nvmem->stride = config->stride ?: 1;
37199897efdSHeiner Kallweit 	nvmem->word_size = config->word_size ?: 1;
372795ddd18SSrinivas Kandagatla 	nvmem->size = config->size;
373eace75cfSSrinivas Kandagatla 	nvmem->dev.type = &nvmem_provider_type;
374eace75cfSSrinivas Kandagatla 	nvmem->dev.bus = &nvmem_bus_type;
375eace75cfSSrinivas Kandagatla 	nvmem->dev.parent = config->dev;
376795ddd18SSrinivas Kandagatla 	nvmem->priv = config->priv;
37716688453SAlexandre Belloni 	nvmem->type = config->type;
378795ddd18SSrinivas Kandagatla 	nvmem->reg_read = config->reg_read;
379795ddd18SSrinivas Kandagatla 	nvmem->reg_write = config->reg_write;
380517f14d9SBartosz Golaszewski 	if (!config->no_of_node)
381fc2f9970SHeiner Kallweit 		nvmem->dev.of_node = config->dev->of_node;
382fd0f4906SAndrey Smirnov 
383fd0f4906SAndrey Smirnov 	if (config->id == -1 && config->name) {
384fd0f4906SAndrey Smirnov 		dev_set_name(&nvmem->dev, "%s", config->name);
385fd0f4906SAndrey Smirnov 	} else {
386eace75cfSSrinivas Kandagatla 		dev_set_name(&nvmem->dev, "%s%d",
3875253193dSAban Bedel 			     config->name ? : "nvmem",
3885253193dSAban Bedel 			     config->name ? config->id : nvmem->id);
389fd0f4906SAndrey Smirnov 	}
390eace75cfSSrinivas Kandagatla 
3911716cfe8SAlban Bedel 	nvmem->read_only = device_property_present(config->dev, "read-only") ||
3921716cfe8SAlban Bedel 			   config->read_only || !nvmem->reg_write;
393eace75cfSSrinivas Kandagatla 
394ae0c2d72SSrinivas Kandagatla 	nvmem->dev.groups = nvmem_sysfs_get_groups(nvmem, config);
395eace75cfSSrinivas Kandagatla 
396eace75cfSSrinivas Kandagatla 	device_initialize(&nvmem->dev);
397eace75cfSSrinivas Kandagatla 
398eace75cfSSrinivas Kandagatla 	dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
399eace75cfSSrinivas Kandagatla 
400eace75cfSSrinivas Kandagatla 	rval = device_add(&nvmem->dev);
401b6c217abSAndrew Lunn 	if (rval)
4023360acdfSJohan Hovold 		goto err_put_device;
403b6c217abSAndrew Lunn 
404b6c217abSAndrew Lunn 	if (config->compat) {
405ae0c2d72SSrinivas Kandagatla 		rval = nvmem_sysfs_setup_compat(nvmem, config);
406b6c217abSAndrew Lunn 		if (rval)
4073360acdfSJohan Hovold 			goto err_device_del;
408eace75cfSSrinivas Kandagatla 	}
409eace75cfSSrinivas Kandagatla 
410fa72d847SBartosz Golaszewski 	if (config->cells) {
411fa72d847SBartosz Golaszewski 		rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
412fa72d847SBartosz Golaszewski 		if (rval)
413fa72d847SBartosz Golaszewski 			goto err_teardown_compat;
414fa72d847SBartosz Golaszewski 	}
415eace75cfSSrinivas Kandagatla 
416b985f4cbSBartosz Golaszewski 	rval = nvmem_add_cells_from_table(nvmem);
417b985f4cbSBartosz Golaszewski 	if (rval)
418b985f4cbSBartosz Golaszewski 		goto err_remove_cells;
419b985f4cbSBartosz Golaszewski 
420e888d445SBartosz Golaszewski 	rval = nvmem_add_cells_from_of(nvmem);
421e888d445SBartosz Golaszewski 	if (rval)
422e888d445SBartosz Golaszewski 		goto err_remove_cells;
423e888d445SBartosz Golaszewski 
424f4853e1cSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
425bee1138bSBartosz Golaszewski 
426eace75cfSSrinivas Kandagatla 	return nvmem;
4273360acdfSJohan Hovold 
428b985f4cbSBartosz Golaszewski err_remove_cells:
429b985f4cbSBartosz Golaszewski 	nvmem_device_remove_all_cells(nvmem);
430fa72d847SBartosz Golaszewski err_teardown_compat:
431fa72d847SBartosz Golaszewski 	if (config->compat)
432ae0c2d72SSrinivas Kandagatla 		nvmem_sysfs_remove_compat(nvmem, config);
4333360acdfSJohan Hovold err_device_del:
4343360acdfSJohan Hovold 	device_del(&nvmem->dev);
4353360acdfSJohan Hovold err_put_device:
4363360acdfSJohan Hovold 	put_device(&nvmem->dev);
4373360acdfSJohan Hovold 
438b6c217abSAndrew Lunn 	return ERR_PTR(rval);
439eace75cfSSrinivas Kandagatla }
440eace75cfSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_register);
441eace75cfSSrinivas Kandagatla 
442c1de7f43SBartosz Golaszewski static void nvmem_device_release(struct kref *kref)
443c1de7f43SBartosz Golaszewski {
444c1de7f43SBartosz Golaszewski 	struct nvmem_device *nvmem;
445c1de7f43SBartosz Golaszewski 
446c1de7f43SBartosz Golaszewski 	nvmem = container_of(kref, struct nvmem_device, refcnt);
447c1de7f43SBartosz Golaszewski 
448bee1138bSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_REMOVE, nvmem);
449bee1138bSBartosz Golaszewski 
450c1de7f43SBartosz Golaszewski 	if (nvmem->flags & FLAG_COMPAT)
451c1de7f43SBartosz Golaszewski 		device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
452c1de7f43SBartosz Golaszewski 
453c1de7f43SBartosz Golaszewski 	nvmem_device_remove_all_cells(nvmem);
454c1de7f43SBartosz Golaszewski 	device_del(&nvmem->dev);
455c1de7f43SBartosz Golaszewski 	put_device(&nvmem->dev);
456c1de7f43SBartosz Golaszewski }
457c1de7f43SBartosz Golaszewski 
458eace75cfSSrinivas Kandagatla /**
459eace75cfSSrinivas Kandagatla  * nvmem_unregister() - Unregister previously registered nvmem device
460eace75cfSSrinivas Kandagatla  *
461eace75cfSSrinivas Kandagatla  * @nvmem: Pointer to previously registered nvmem device.
462eace75cfSSrinivas Kandagatla  */
463bf58e882SBartosz Golaszewski void nvmem_unregister(struct nvmem_device *nvmem)
464eace75cfSSrinivas Kandagatla {
465c1de7f43SBartosz Golaszewski 	kref_put(&nvmem->refcnt, nvmem_device_release);
466eace75cfSSrinivas Kandagatla }
467eace75cfSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_unregister);
468eace75cfSSrinivas Kandagatla 
469f1f50ecaSAndrey Smirnov static void devm_nvmem_release(struct device *dev, void *res)
470f1f50ecaSAndrey Smirnov {
471bf58e882SBartosz Golaszewski 	nvmem_unregister(*(struct nvmem_device **)res);
472f1f50ecaSAndrey Smirnov }
473f1f50ecaSAndrey Smirnov 
474f1f50ecaSAndrey Smirnov /**
475f1f50ecaSAndrey Smirnov  * devm_nvmem_register() - Register a managed nvmem device for given
476f1f50ecaSAndrey Smirnov  * nvmem_config.
477f1f50ecaSAndrey Smirnov  * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
478f1f50ecaSAndrey Smirnov  *
479b378c779SSrinivas Kandagatla  * @dev: Device that uses the nvmem device.
480f1f50ecaSAndrey Smirnov  * @config: nvmem device configuration with which nvmem device is created.
481f1f50ecaSAndrey Smirnov  *
482f1f50ecaSAndrey Smirnov  * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
483f1f50ecaSAndrey Smirnov  * on success.
484f1f50ecaSAndrey Smirnov  */
485f1f50ecaSAndrey Smirnov struct nvmem_device *devm_nvmem_register(struct device *dev,
486f1f50ecaSAndrey Smirnov 					 const struct nvmem_config *config)
487f1f50ecaSAndrey Smirnov {
488f1f50ecaSAndrey Smirnov 	struct nvmem_device **ptr, *nvmem;
489f1f50ecaSAndrey Smirnov 
490f1f50ecaSAndrey Smirnov 	ptr = devres_alloc(devm_nvmem_release, sizeof(*ptr), GFP_KERNEL);
491f1f50ecaSAndrey Smirnov 	if (!ptr)
492f1f50ecaSAndrey Smirnov 		return ERR_PTR(-ENOMEM);
493f1f50ecaSAndrey Smirnov 
494f1f50ecaSAndrey Smirnov 	nvmem = nvmem_register(config);
495f1f50ecaSAndrey Smirnov 
496f1f50ecaSAndrey Smirnov 	if (!IS_ERR(nvmem)) {
497f1f50ecaSAndrey Smirnov 		*ptr = nvmem;
498f1f50ecaSAndrey Smirnov 		devres_add(dev, ptr);
499f1f50ecaSAndrey Smirnov 	} else {
500f1f50ecaSAndrey Smirnov 		devres_free(ptr);
501f1f50ecaSAndrey Smirnov 	}
502f1f50ecaSAndrey Smirnov 
503f1f50ecaSAndrey Smirnov 	return nvmem;
504f1f50ecaSAndrey Smirnov }
505f1f50ecaSAndrey Smirnov EXPORT_SYMBOL_GPL(devm_nvmem_register);
506f1f50ecaSAndrey Smirnov 
507f1f50ecaSAndrey Smirnov static int devm_nvmem_match(struct device *dev, void *res, void *data)
508f1f50ecaSAndrey Smirnov {
509f1f50ecaSAndrey Smirnov 	struct nvmem_device **r = res;
510f1f50ecaSAndrey Smirnov 
511f1f50ecaSAndrey Smirnov 	return *r == data;
512f1f50ecaSAndrey Smirnov }
513f1f50ecaSAndrey Smirnov 
514f1f50ecaSAndrey Smirnov /**
515f1f50ecaSAndrey Smirnov  * devm_nvmem_unregister() - Unregister previously registered managed nvmem
516f1f50ecaSAndrey Smirnov  * device.
517f1f50ecaSAndrey Smirnov  *
518b378c779SSrinivas Kandagatla  * @dev: Device that uses the nvmem device.
519f1f50ecaSAndrey Smirnov  * @nvmem: Pointer to previously registered nvmem device.
520f1f50ecaSAndrey Smirnov  *
521f1f50ecaSAndrey Smirnov  * Return: Will be an negative on error or a zero on success.
522f1f50ecaSAndrey Smirnov  */
523f1f50ecaSAndrey Smirnov int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
524f1f50ecaSAndrey Smirnov {
525f1f50ecaSAndrey Smirnov 	return devres_release(dev, devm_nvmem_release, devm_nvmem_match, nvmem);
526f1f50ecaSAndrey Smirnov }
527f1f50ecaSAndrey Smirnov EXPORT_SYMBOL(devm_nvmem_unregister);
528f1f50ecaSAndrey Smirnov 
5298c2a2b8cSThomas Bogendoerfer static struct nvmem_device *__nvmem_device_get(void *data,
5308c2a2b8cSThomas Bogendoerfer 			int (*match)(struct device *dev, const void *data))
53169aba794SSrinivas Kandagatla {
53269aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = NULL;
5338c2a2b8cSThomas Bogendoerfer 	struct device *dev;
53469aba794SSrinivas Kandagatla 
535c7235ee3SBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
5368c2a2b8cSThomas Bogendoerfer 	dev = bus_find_device(&nvmem_bus_type, NULL, data, match);
5378c2a2b8cSThomas Bogendoerfer 	if (dev)
5388c2a2b8cSThomas Bogendoerfer 		nvmem = to_nvmem_device(dev);
53969aba794SSrinivas Kandagatla 	mutex_unlock(&nvmem_mutex);
540c7235ee3SBartosz Golaszewski 	if (!nvmem)
541c7235ee3SBartosz Golaszewski 		return ERR_PTR(-EPROBE_DEFER);
54269aba794SSrinivas Kandagatla 
54369aba794SSrinivas Kandagatla 	if (!try_module_get(nvmem->owner)) {
54469aba794SSrinivas Kandagatla 		dev_err(&nvmem->dev,
54569aba794SSrinivas Kandagatla 			"could not increase module refcount for cell %s\n",
5465db652c9SBartosz Golaszewski 			nvmem_dev_name(nvmem));
54769aba794SSrinivas Kandagatla 
54873e9dc4dSAlban Bedel 		put_device(&nvmem->dev);
54969aba794SSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
55069aba794SSrinivas Kandagatla 	}
55169aba794SSrinivas Kandagatla 
552c1de7f43SBartosz Golaszewski 	kref_get(&nvmem->refcnt);
553c1de7f43SBartosz Golaszewski 
55469aba794SSrinivas Kandagatla 	return nvmem;
55569aba794SSrinivas Kandagatla }
55669aba794SSrinivas Kandagatla 
55769aba794SSrinivas Kandagatla static void __nvmem_device_put(struct nvmem_device *nvmem)
55869aba794SSrinivas Kandagatla {
55973e9dc4dSAlban Bedel 	put_device(&nvmem->dev);
56069aba794SSrinivas Kandagatla 	module_put(nvmem->owner);
561c1de7f43SBartosz Golaszewski 	kref_put(&nvmem->refcnt, nvmem_device_release);
56269aba794SSrinivas Kandagatla }
56369aba794SSrinivas Kandagatla 
564e701c67cSMasahiro Yamada #if IS_ENABLED(CONFIG_OF)
565e2a5402eSSrinivas Kandagatla /**
566e2a5402eSSrinivas Kandagatla  * of_nvmem_device_get() - Get nvmem device from a given id
567e2a5402eSSrinivas Kandagatla  *
56829143268SVivek Gautam  * @np: Device tree node that uses the nvmem device.
569e2a5402eSSrinivas Kandagatla  * @id: nvmem name from nvmem-names property.
570e2a5402eSSrinivas Kandagatla  *
571e2a5402eSSrinivas Kandagatla  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
572e2a5402eSSrinivas Kandagatla  * on success.
573e2a5402eSSrinivas Kandagatla  */
574e2a5402eSSrinivas Kandagatla struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
575e2a5402eSSrinivas Kandagatla {
576e2a5402eSSrinivas Kandagatla 
577e2a5402eSSrinivas Kandagatla 	struct device_node *nvmem_np;
578d4e7fef1SAlban Bedel 	int index = 0;
579e2a5402eSSrinivas Kandagatla 
580d4e7fef1SAlban Bedel 	if (id)
581e2a5402eSSrinivas Kandagatla 		index = of_property_match_string(np, "nvmem-names", id);
582e2a5402eSSrinivas Kandagatla 
583e2a5402eSSrinivas Kandagatla 	nvmem_np = of_parse_phandle(np, "nvmem", index);
584e2a5402eSSrinivas Kandagatla 	if (!nvmem_np)
585d4e7fef1SAlban Bedel 		return ERR_PTR(-ENOENT);
586e2a5402eSSrinivas Kandagatla 
5878c2a2b8cSThomas Bogendoerfer 	return __nvmem_device_get(nvmem_np, device_match_of_node);
588e2a5402eSSrinivas Kandagatla }
589e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(of_nvmem_device_get);
590e2a5402eSSrinivas Kandagatla #endif
591e2a5402eSSrinivas Kandagatla 
592e2a5402eSSrinivas Kandagatla /**
593e2a5402eSSrinivas Kandagatla  * nvmem_device_get() - Get nvmem device from a given id
594e2a5402eSSrinivas Kandagatla  *
59529143268SVivek Gautam  * @dev: Device that uses the nvmem device.
59629143268SVivek Gautam  * @dev_name: name of the requested nvmem device.
597e2a5402eSSrinivas Kandagatla  *
598e2a5402eSSrinivas Kandagatla  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
599e2a5402eSSrinivas Kandagatla  * on success.
600e2a5402eSSrinivas Kandagatla  */
601e2a5402eSSrinivas Kandagatla struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
602e2a5402eSSrinivas Kandagatla {
603e2a5402eSSrinivas Kandagatla 	if (dev->of_node) { /* try dt first */
604e2a5402eSSrinivas Kandagatla 		struct nvmem_device *nvmem;
605e2a5402eSSrinivas Kandagatla 
606e2a5402eSSrinivas Kandagatla 		nvmem = of_nvmem_device_get(dev->of_node, dev_name);
607e2a5402eSSrinivas Kandagatla 
608e2a5402eSSrinivas Kandagatla 		if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
609e2a5402eSSrinivas Kandagatla 			return nvmem;
610e2a5402eSSrinivas Kandagatla 
611e2a5402eSSrinivas Kandagatla 	}
612e2a5402eSSrinivas Kandagatla 
6138c2a2b8cSThomas Bogendoerfer 	return __nvmem_device_get((void *)dev_name, device_match_name);
614e2a5402eSSrinivas Kandagatla }
615e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_get);
616e2a5402eSSrinivas Kandagatla 
6178c2a2b8cSThomas Bogendoerfer /**
6188c2a2b8cSThomas Bogendoerfer  * nvmem_device_find() - Find nvmem device with matching function
6198c2a2b8cSThomas Bogendoerfer  *
6208c2a2b8cSThomas Bogendoerfer  * @data: Data to pass to match function
6218c2a2b8cSThomas Bogendoerfer  * @match: Callback function to check device
6228c2a2b8cSThomas Bogendoerfer  *
6238c2a2b8cSThomas Bogendoerfer  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
6248c2a2b8cSThomas Bogendoerfer  * on success.
6258c2a2b8cSThomas Bogendoerfer  */
6268c2a2b8cSThomas Bogendoerfer struct nvmem_device *nvmem_device_find(void *data,
6278c2a2b8cSThomas Bogendoerfer 			int (*match)(struct device *dev, const void *data))
6288c2a2b8cSThomas Bogendoerfer {
6298c2a2b8cSThomas Bogendoerfer 	return __nvmem_device_get(data, match);
6308c2a2b8cSThomas Bogendoerfer }
6318c2a2b8cSThomas Bogendoerfer EXPORT_SYMBOL_GPL(nvmem_device_find);
6328c2a2b8cSThomas Bogendoerfer 
633e2a5402eSSrinivas Kandagatla static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
634e2a5402eSSrinivas Kandagatla {
635e2a5402eSSrinivas Kandagatla 	struct nvmem_device **nvmem = res;
636e2a5402eSSrinivas Kandagatla 
637e2a5402eSSrinivas Kandagatla 	if (WARN_ON(!nvmem || !*nvmem))
638e2a5402eSSrinivas Kandagatla 		return 0;
639e2a5402eSSrinivas Kandagatla 
640e2a5402eSSrinivas Kandagatla 	return *nvmem == data;
641e2a5402eSSrinivas Kandagatla }
642e2a5402eSSrinivas Kandagatla 
643e2a5402eSSrinivas Kandagatla static void devm_nvmem_device_release(struct device *dev, void *res)
644e2a5402eSSrinivas Kandagatla {
645e2a5402eSSrinivas Kandagatla 	nvmem_device_put(*(struct nvmem_device **)res);
646e2a5402eSSrinivas Kandagatla }
647e2a5402eSSrinivas Kandagatla 
648e2a5402eSSrinivas Kandagatla /**
649e2a5402eSSrinivas Kandagatla  * devm_nvmem_device_put() - put alredy got nvmem device
650e2a5402eSSrinivas Kandagatla  *
65129143268SVivek Gautam  * @dev: Device that uses the nvmem device.
652e2a5402eSSrinivas Kandagatla  * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
653e2a5402eSSrinivas Kandagatla  * that needs to be released.
654e2a5402eSSrinivas Kandagatla  */
655e2a5402eSSrinivas Kandagatla void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
656e2a5402eSSrinivas Kandagatla {
657e2a5402eSSrinivas Kandagatla 	int ret;
658e2a5402eSSrinivas Kandagatla 
659e2a5402eSSrinivas Kandagatla 	ret = devres_release(dev, devm_nvmem_device_release,
660e2a5402eSSrinivas Kandagatla 			     devm_nvmem_device_match, nvmem);
661e2a5402eSSrinivas Kandagatla 
662e2a5402eSSrinivas Kandagatla 	WARN_ON(ret);
663e2a5402eSSrinivas Kandagatla }
664e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
665e2a5402eSSrinivas Kandagatla 
666e2a5402eSSrinivas Kandagatla /**
667e2a5402eSSrinivas Kandagatla  * nvmem_device_put() - put alredy got nvmem device
668e2a5402eSSrinivas Kandagatla  *
669e2a5402eSSrinivas Kandagatla  * @nvmem: pointer to nvmem device that needs to be released.
670e2a5402eSSrinivas Kandagatla  */
671e2a5402eSSrinivas Kandagatla void nvmem_device_put(struct nvmem_device *nvmem)
672e2a5402eSSrinivas Kandagatla {
673e2a5402eSSrinivas Kandagatla 	__nvmem_device_put(nvmem);
674e2a5402eSSrinivas Kandagatla }
675e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_put);
676e2a5402eSSrinivas Kandagatla 
677e2a5402eSSrinivas Kandagatla /**
678e2a5402eSSrinivas Kandagatla  * devm_nvmem_device_get() - Get nvmem cell of device form a given id
679e2a5402eSSrinivas Kandagatla  *
68029143268SVivek Gautam  * @dev: Device that requests the nvmem device.
68129143268SVivek Gautam  * @id: name id for the requested nvmem device.
682e2a5402eSSrinivas Kandagatla  *
683e2a5402eSSrinivas Kandagatla  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell
684e2a5402eSSrinivas Kandagatla  * on success.  The nvmem_cell will be freed by the automatically once the
685e2a5402eSSrinivas Kandagatla  * device is freed.
686e2a5402eSSrinivas Kandagatla  */
687e2a5402eSSrinivas Kandagatla struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
688e2a5402eSSrinivas Kandagatla {
689e2a5402eSSrinivas Kandagatla 	struct nvmem_device **ptr, *nvmem;
690e2a5402eSSrinivas Kandagatla 
691e2a5402eSSrinivas Kandagatla 	ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
692e2a5402eSSrinivas Kandagatla 	if (!ptr)
693e2a5402eSSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
694e2a5402eSSrinivas Kandagatla 
695e2a5402eSSrinivas Kandagatla 	nvmem = nvmem_device_get(dev, id);
696e2a5402eSSrinivas Kandagatla 	if (!IS_ERR(nvmem)) {
697e2a5402eSSrinivas Kandagatla 		*ptr = nvmem;
698e2a5402eSSrinivas Kandagatla 		devres_add(dev, ptr);
699e2a5402eSSrinivas Kandagatla 	} else {
700e2a5402eSSrinivas Kandagatla 		devres_free(ptr);
701e2a5402eSSrinivas Kandagatla 	}
702e2a5402eSSrinivas Kandagatla 
703e2a5402eSSrinivas Kandagatla 	return nvmem;
704e2a5402eSSrinivas Kandagatla }
705e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
706e2a5402eSSrinivas Kandagatla 
707506157beSBartosz Golaszewski static struct nvmem_cell *
708506157beSBartosz Golaszewski nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
70969aba794SSrinivas Kandagatla {
710506157beSBartosz Golaszewski 	struct nvmem_cell *cell = ERR_PTR(-ENOENT);
711506157beSBartosz Golaszewski 	struct nvmem_cell_lookup *lookup;
71269aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem;
713506157beSBartosz Golaszewski 	const char *dev_id;
71469aba794SSrinivas Kandagatla 
715506157beSBartosz Golaszewski 	if (!dev)
716506157beSBartosz Golaszewski 		return ERR_PTR(-EINVAL);
71769aba794SSrinivas Kandagatla 
718506157beSBartosz Golaszewski 	dev_id = dev_name(dev);
719506157beSBartosz Golaszewski 
720506157beSBartosz Golaszewski 	mutex_lock(&nvmem_lookup_mutex);
721506157beSBartosz Golaszewski 
722506157beSBartosz Golaszewski 	list_for_each_entry(lookup, &nvmem_lookup_list, node) {
723506157beSBartosz Golaszewski 		if ((strcmp(lookup->dev_id, dev_id) == 0) &&
724506157beSBartosz Golaszewski 		    (strcmp(lookup->con_id, con_id) == 0)) {
725506157beSBartosz Golaszewski 			/* This is the right entry. */
7268c2a2b8cSThomas Bogendoerfer 			nvmem = __nvmem_device_get((void *)lookup->nvmem_name,
7278c2a2b8cSThomas Bogendoerfer 						   device_match_name);
728cccb3b19SBartosz Golaszewski 			if (IS_ERR(nvmem)) {
729506157beSBartosz Golaszewski 				/* Provider may not be registered yet. */
730cccb3b19SBartosz Golaszewski 				cell = ERR_CAST(nvmem);
7319bfd8198SAlban Bedel 				break;
732506157beSBartosz Golaszewski 			}
733506157beSBartosz Golaszewski 
734506157beSBartosz Golaszewski 			cell = nvmem_find_cell_by_name(nvmem,
735506157beSBartosz Golaszewski 						       lookup->cell_name);
736506157beSBartosz Golaszewski 			if (!cell) {
737506157beSBartosz Golaszewski 				__nvmem_device_put(nvmem);
738cccb3b19SBartosz Golaszewski 				cell = ERR_PTR(-ENOENT);
739506157beSBartosz Golaszewski 			}
7409bfd8198SAlban Bedel 			break;
741506157beSBartosz Golaszewski 		}
742506157beSBartosz Golaszewski 	}
743506157beSBartosz Golaszewski 
744506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_lookup_mutex);
74569aba794SSrinivas Kandagatla 	return cell;
74669aba794SSrinivas Kandagatla }
74769aba794SSrinivas Kandagatla 
748e701c67cSMasahiro Yamada #if IS_ENABLED(CONFIG_OF)
7493c53e235SArnd Bergmann static struct nvmem_cell *
7500749aa25SSrinivas Kandagatla nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
7513c53e235SArnd Bergmann {
7521c832674SAlban Bedel 	struct nvmem_cell *iter, *cell = NULL;
7533c53e235SArnd Bergmann 
7543c53e235SArnd Bergmann 	mutex_lock(&nvmem_mutex);
7551c832674SAlban Bedel 	list_for_each_entry(iter, &nvmem->cells, node) {
7561c832674SAlban Bedel 		if (np == iter->np) {
7571c832674SAlban Bedel 			cell = iter;
7583c53e235SArnd Bergmann 			break;
7593c53e235SArnd Bergmann 		}
7601c832674SAlban Bedel 	}
7613c53e235SArnd Bergmann 	mutex_unlock(&nvmem_mutex);
7623c53e235SArnd Bergmann 
7633c53e235SArnd Bergmann 	return cell;
7643c53e235SArnd Bergmann }
7653c53e235SArnd Bergmann 
76669aba794SSrinivas Kandagatla /**
76769aba794SSrinivas Kandagatla  * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
76869aba794SSrinivas Kandagatla  *
76929143268SVivek Gautam  * @np: Device tree node that uses the nvmem cell.
770165589f0SBartosz Golaszewski  * @id: nvmem cell name from nvmem-cell-names property, or NULL
771fd0c478cSVivek Gautam  *      for the cell at index 0 (the lone cell with no accompanying
772fd0c478cSVivek Gautam  *      nvmem-cell-names property).
77369aba794SSrinivas Kandagatla  *
77469aba794SSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer
77569aba794SSrinivas Kandagatla  * to a struct nvmem_cell.  The nvmem_cell will be freed by the
77669aba794SSrinivas Kandagatla  * nvmem_cell_put().
77769aba794SSrinivas Kandagatla  */
778165589f0SBartosz Golaszewski struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
77969aba794SSrinivas Kandagatla {
78069aba794SSrinivas Kandagatla 	struct device_node *cell_np, *nvmem_np;
78169aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem;
782e888d445SBartosz Golaszewski 	struct nvmem_cell *cell;
783fd0c478cSVivek Gautam 	int index = 0;
78469aba794SSrinivas Kandagatla 
785fd0c478cSVivek Gautam 	/* if cell name exists, find index to the name */
786165589f0SBartosz Golaszewski 	if (id)
787165589f0SBartosz Golaszewski 		index = of_property_match_string(np, "nvmem-cell-names", id);
78869aba794SSrinivas Kandagatla 
78969aba794SSrinivas Kandagatla 	cell_np = of_parse_phandle(np, "nvmem-cells", index);
79069aba794SSrinivas Kandagatla 	if (!cell_np)
7915087cc19SAlban Bedel 		return ERR_PTR(-ENOENT);
79269aba794SSrinivas Kandagatla 
79369aba794SSrinivas Kandagatla 	nvmem_np = of_get_next_parent(cell_np);
79469aba794SSrinivas Kandagatla 	if (!nvmem_np)
79569aba794SSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
79669aba794SSrinivas Kandagatla 
7978c2a2b8cSThomas Bogendoerfer 	nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
798aad8d097SMasahiro Yamada 	of_node_put(nvmem_np);
79969aba794SSrinivas Kandagatla 	if (IS_ERR(nvmem))
80069aba794SSrinivas Kandagatla 		return ERR_CAST(nvmem);
80169aba794SSrinivas Kandagatla 
8020749aa25SSrinivas Kandagatla 	cell = nvmem_find_cell_by_node(nvmem, cell_np);
80369aba794SSrinivas Kandagatla 	if (!cell) {
804e888d445SBartosz Golaszewski 		__nvmem_device_put(nvmem);
805e888d445SBartosz Golaszewski 		return ERR_PTR(-ENOENT);
80669aba794SSrinivas Kandagatla 	}
80769aba794SSrinivas Kandagatla 
80869aba794SSrinivas Kandagatla 	return cell;
80969aba794SSrinivas Kandagatla }
81069aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
81169aba794SSrinivas Kandagatla #endif
81269aba794SSrinivas Kandagatla 
81369aba794SSrinivas Kandagatla /**
81469aba794SSrinivas Kandagatla  * nvmem_cell_get() - Get nvmem cell of device form a given cell name
81569aba794SSrinivas Kandagatla  *
81629143268SVivek Gautam  * @dev: Device that requests the nvmem cell.
817165589f0SBartosz Golaszewski  * @id: nvmem cell name to get (this corresponds with the name from the
818165589f0SBartosz Golaszewski  *      nvmem-cell-names property for DT systems and with the con_id from
819165589f0SBartosz Golaszewski  *      the lookup entry for non-DT systems).
82069aba794SSrinivas Kandagatla  *
82169aba794SSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer
82269aba794SSrinivas Kandagatla  * to a struct nvmem_cell.  The nvmem_cell will be freed by the
82369aba794SSrinivas Kandagatla  * nvmem_cell_put().
82469aba794SSrinivas Kandagatla  */
825165589f0SBartosz Golaszewski struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *id)
82669aba794SSrinivas Kandagatla {
82769aba794SSrinivas Kandagatla 	struct nvmem_cell *cell;
82869aba794SSrinivas Kandagatla 
82969aba794SSrinivas Kandagatla 	if (dev->of_node) { /* try dt first */
830165589f0SBartosz Golaszewski 		cell = of_nvmem_cell_get(dev->of_node, id);
83169aba794SSrinivas Kandagatla 		if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
83269aba794SSrinivas Kandagatla 			return cell;
83369aba794SSrinivas Kandagatla 	}
83469aba794SSrinivas Kandagatla 
835165589f0SBartosz Golaszewski 	/* NULL cell id only allowed for device tree; invalid otherwise */
836165589f0SBartosz Golaszewski 	if (!id)
83787ed1405SDouglas Anderson 		return ERR_PTR(-EINVAL);
83887ed1405SDouglas Anderson 
839165589f0SBartosz Golaszewski 	return nvmem_cell_get_from_lookup(dev, id);
84069aba794SSrinivas Kandagatla }
84169aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_get);
84269aba794SSrinivas Kandagatla 
84369aba794SSrinivas Kandagatla static void devm_nvmem_cell_release(struct device *dev, void *res)
84469aba794SSrinivas Kandagatla {
84569aba794SSrinivas Kandagatla 	nvmem_cell_put(*(struct nvmem_cell **)res);
84669aba794SSrinivas Kandagatla }
84769aba794SSrinivas Kandagatla 
84869aba794SSrinivas Kandagatla /**
84969aba794SSrinivas Kandagatla  * devm_nvmem_cell_get() - Get nvmem cell of device form a given id
85069aba794SSrinivas Kandagatla  *
85129143268SVivek Gautam  * @dev: Device that requests the nvmem cell.
85229143268SVivek Gautam  * @id: nvmem cell name id to get.
85369aba794SSrinivas Kandagatla  *
85469aba794SSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer
85569aba794SSrinivas Kandagatla  * to a struct nvmem_cell.  The nvmem_cell will be freed by the
85669aba794SSrinivas Kandagatla  * automatically once the device is freed.
85769aba794SSrinivas Kandagatla  */
85869aba794SSrinivas Kandagatla struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id)
85969aba794SSrinivas Kandagatla {
86069aba794SSrinivas Kandagatla 	struct nvmem_cell **ptr, *cell;
86169aba794SSrinivas Kandagatla 
86269aba794SSrinivas Kandagatla 	ptr = devres_alloc(devm_nvmem_cell_release, sizeof(*ptr), GFP_KERNEL);
86369aba794SSrinivas Kandagatla 	if (!ptr)
86469aba794SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
86569aba794SSrinivas Kandagatla 
86669aba794SSrinivas Kandagatla 	cell = nvmem_cell_get(dev, id);
86769aba794SSrinivas Kandagatla 	if (!IS_ERR(cell)) {
86869aba794SSrinivas Kandagatla 		*ptr = cell;
86969aba794SSrinivas Kandagatla 		devres_add(dev, ptr);
87069aba794SSrinivas Kandagatla 	} else {
87169aba794SSrinivas Kandagatla 		devres_free(ptr);
87269aba794SSrinivas Kandagatla 	}
87369aba794SSrinivas Kandagatla 
87469aba794SSrinivas Kandagatla 	return cell;
87569aba794SSrinivas Kandagatla }
87669aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_nvmem_cell_get);
87769aba794SSrinivas Kandagatla 
87869aba794SSrinivas Kandagatla static int devm_nvmem_cell_match(struct device *dev, void *res, void *data)
87969aba794SSrinivas Kandagatla {
88069aba794SSrinivas Kandagatla 	struct nvmem_cell **c = res;
88169aba794SSrinivas Kandagatla 
88269aba794SSrinivas Kandagatla 	if (WARN_ON(!c || !*c))
88369aba794SSrinivas Kandagatla 		return 0;
88469aba794SSrinivas Kandagatla 
88569aba794SSrinivas Kandagatla 	return *c == data;
88669aba794SSrinivas Kandagatla }
88769aba794SSrinivas Kandagatla 
88869aba794SSrinivas Kandagatla /**
88969aba794SSrinivas Kandagatla  * devm_nvmem_cell_put() - Release previously allocated nvmem cell
89069aba794SSrinivas Kandagatla  * from devm_nvmem_cell_get.
89169aba794SSrinivas Kandagatla  *
89229143268SVivek Gautam  * @dev: Device that requests the nvmem cell.
89329143268SVivek Gautam  * @cell: Previously allocated nvmem cell by devm_nvmem_cell_get().
89469aba794SSrinivas Kandagatla  */
89569aba794SSrinivas Kandagatla void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell)
89669aba794SSrinivas Kandagatla {
89769aba794SSrinivas Kandagatla 	int ret;
89869aba794SSrinivas Kandagatla 
89969aba794SSrinivas Kandagatla 	ret = devres_release(dev, devm_nvmem_cell_release,
90069aba794SSrinivas Kandagatla 				devm_nvmem_cell_match, cell);
90169aba794SSrinivas Kandagatla 
90269aba794SSrinivas Kandagatla 	WARN_ON(ret);
90369aba794SSrinivas Kandagatla }
90469aba794SSrinivas Kandagatla EXPORT_SYMBOL(devm_nvmem_cell_put);
90569aba794SSrinivas Kandagatla 
90669aba794SSrinivas Kandagatla /**
90769aba794SSrinivas Kandagatla  * nvmem_cell_put() - Release previously allocated nvmem cell.
90869aba794SSrinivas Kandagatla  *
90929143268SVivek Gautam  * @cell: Previously allocated nvmem cell by nvmem_cell_get().
91069aba794SSrinivas Kandagatla  */
91169aba794SSrinivas Kandagatla void nvmem_cell_put(struct nvmem_cell *cell)
91269aba794SSrinivas Kandagatla {
91369aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
91469aba794SSrinivas Kandagatla 
91569aba794SSrinivas Kandagatla 	__nvmem_device_put(nvmem);
91669aba794SSrinivas Kandagatla }
91769aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_put);
91869aba794SSrinivas Kandagatla 
919f7c04f16SMasahiro Yamada static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)
92069aba794SSrinivas Kandagatla {
92169aba794SSrinivas Kandagatla 	u8 *p, *b;
9222fe518feSJorge Ramirez-Ortiz 	int i, extra, bit_offset = cell->bit_offset;
92369aba794SSrinivas Kandagatla 
92469aba794SSrinivas Kandagatla 	p = b = buf;
92569aba794SSrinivas Kandagatla 	if (bit_offset) {
92669aba794SSrinivas Kandagatla 		/* First shift */
92769aba794SSrinivas Kandagatla 		*b++ >>= bit_offset;
92869aba794SSrinivas Kandagatla 
92969aba794SSrinivas Kandagatla 		/* setup rest of the bytes if any */
93069aba794SSrinivas Kandagatla 		for (i = 1; i < cell->bytes; i++) {
93169aba794SSrinivas Kandagatla 			/* Get bits from next byte and shift them towards msb */
93269aba794SSrinivas Kandagatla 			*p |= *b << (BITS_PER_BYTE - bit_offset);
93369aba794SSrinivas Kandagatla 
93469aba794SSrinivas Kandagatla 			p = b;
93569aba794SSrinivas Kandagatla 			*b++ >>= bit_offset;
93669aba794SSrinivas Kandagatla 		}
9372fe518feSJorge Ramirez-Ortiz 	} else {
9382fe518feSJorge Ramirez-Ortiz 		/* point to the msb */
9392fe518feSJorge Ramirez-Ortiz 		p += cell->bytes - 1;
9402fe518feSJorge Ramirez-Ortiz 	}
94169aba794SSrinivas Kandagatla 
94269aba794SSrinivas Kandagatla 	/* result fits in less bytes */
9432fe518feSJorge Ramirez-Ortiz 	extra = cell->bytes - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);
9442fe518feSJorge Ramirez-Ortiz 	while (--extra >= 0)
94569aba794SSrinivas Kandagatla 		*p-- = 0;
9462fe518feSJorge Ramirez-Ortiz 
94769aba794SSrinivas Kandagatla 	/* clear msb bits if any leftover in the last byte */
94869aba794SSrinivas Kandagatla 	*p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
94969aba794SSrinivas Kandagatla }
95069aba794SSrinivas Kandagatla 
95169aba794SSrinivas Kandagatla static int __nvmem_cell_read(struct nvmem_device *nvmem,
95269aba794SSrinivas Kandagatla 		      struct nvmem_cell *cell,
95369aba794SSrinivas Kandagatla 		      void *buf, size_t *len)
95469aba794SSrinivas Kandagatla {
95569aba794SSrinivas Kandagatla 	int rc;
95669aba794SSrinivas Kandagatla 
957795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
95869aba794SSrinivas Kandagatla 
959287980e4SArnd Bergmann 	if (rc)
96069aba794SSrinivas Kandagatla 		return rc;
96169aba794SSrinivas Kandagatla 
96269aba794SSrinivas Kandagatla 	/* shift bits in-place */
963cbf854abSAxel Lin 	if (cell->bit_offset || cell->nbits)
96469aba794SSrinivas Kandagatla 		nvmem_shift_read_buffer_in_place(cell, buf);
96569aba794SSrinivas Kandagatla 
9663b4a6877SVivek Gautam 	if (len)
96769aba794SSrinivas Kandagatla 		*len = cell->bytes;
96869aba794SSrinivas Kandagatla 
96969aba794SSrinivas Kandagatla 	return 0;
97069aba794SSrinivas Kandagatla }
97169aba794SSrinivas Kandagatla 
97269aba794SSrinivas Kandagatla /**
97369aba794SSrinivas Kandagatla  * nvmem_cell_read() - Read a given nvmem cell
97469aba794SSrinivas Kandagatla  *
97569aba794SSrinivas Kandagatla  * @cell: nvmem cell to be read.
9763b4a6877SVivek Gautam  * @len: pointer to length of cell which will be populated on successful read;
9773b4a6877SVivek Gautam  *	 can be NULL.
97869aba794SSrinivas Kandagatla  *
979b577fafcSBrian Norris  * Return: ERR_PTR() on error or a valid pointer to a buffer on success. The
980b577fafcSBrian Norris  * buffer should be freed by the consumer with a kfree().
98169aba794SSrinivas Kandagatla  */
98269aba794SSrinivas Kandagatla void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
98369aba794SSrinivas Kandagatla {
98469aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
98569aba794SSrinivas Kandagatla 	u8 *buf;
98669aba794SSrinivas Kandagatla 	int rc;
98769aba794SSrinivas Kandagatla 
988795ddd18SSrinivas Kandagatla 	if (!nvmem)
98969aba794SSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
99069aba794SSrinivas Kandagatla 
99169aba794SSrinivas Kandagatla 	buf = kzalloc(cell->bytes, GFP_KERNEL);
99269aba794SSrinivas Kandagatla 	if (!buf)
99369aba794SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
99469aba794SSrinivas Kandagatla 
99569aba794SSrinivas Kandagatla 	rc = __nvmem_cell_read(nvmem, cell, buf, len);
996287980e4SArnd Bergmann 	if (rc) {
99769aba794SSrinivas Kandagatla 		kfree(buf);
99869aba794SSrinivas Kandagatla 		return ERR_PTR(rc);
99969aba794SSrinivas Kandagatla 	}
100069aba794SSrinivas Kandagatla 
100169aba794SSrinivas Kandagatla 	return buf;
100269aba794SSrinivas Kandagatla }
100369aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_read);
100469aba794SSrinivas Kandagatla 
1005f7c04f16SMasahiro Yamada static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
100669aba794SSrinivas Kandagatla 					     u8 *_buf, int len)
100769aba794SSrinivas Kandagatla {
100869aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
100969aba794SSrinivas Kandagatla 	int i, rc, nbits, bit_offset = cell->bit_offset;
101069aba794SSrinivas Kandagatla 	u8 v, *p, *buf, *b, pbyte, pbits;
101169aba794SSrinivas Kandagatla 
101269aba794SSrinivas Kandagatla 	nbits = cell->nbits;
101369aba794SSrinivas Kandagatla 	buf = kzalloc(cell->bytes, GFP_KERNEL);
101469aba794SSrinivas Kandagatla 	if (!buf)
101569aba794SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
101669aba794SSrinivas Kandagatla 
101769aba794SSrinivas Kandagatla 	memcpy(buf, _buf, len);
101869aba794SSrinivas Kandagatla 	p = b = buf;
101969aba794SSrinivas Kandagatla 
102069aba794SSrinivas Kandagatla 	if (bit_offset) {
102169aba794SSrinivas Kandagatla 		pbyte = *b;
102269aba794SSrinivas Kandagatla 		*b <<= bit_offset;
102369aba794SSrinivas Kandagatla 
102469aba794SSrinivas Kandagatla 		/* setup the first byte with lsb bits from nvmem */
1025795ddd18SSrinivas Kandagatla 		rc = nvmem_reg_read(nvmem, cell->offset, &v, 1);
102650808bfcSMathieu Malaterre 		if (rc)
102750808bfcSMathieu Malaterre 			goto err;
102869aba794SSrinivas Kandagatla 		*b++ |= GENMASK(bit_offset - 1, 0) & v;
102969aba794SSrinivas Kandagatla 
103069aba794SSrinivas Kandagatla 		/* setup rest of the byte if any */
103169aba794SSrinivas Kandagatla 		for (i = 1; i < cell->bytes; i++) {
103269aba794SSrinivas Kandagatla 			/* Get last byte bits and shift them towards lsb */
103369aba794SSrinivas Kandagatla 			pbits = pbyte >> (BITS_PER_BYTE - 1 - bit_offset);
103469aba794SSrinivas Kandagatla 			pbyte = *b;
103569aba794SSrinivas Kandagatla 			p = b;
103669aba794SSrinivas Kandagatla 			*b <<= bit_offset;
103769aba794SSrinivas Kandagatla 			*b++ |= pbits;
103869aba794SSrinivas Kandagatla 		}
103969aba794SSrinivas Kandagatla 	}
104069aba794SSrinivas Kandagatla 
104169aba794SSrinivas Kandagatla 	/* if it's not end on byte boundary */
104269aba794SSrinivas Kandagatla 	if ((nbits + bit_offset) % BITS_PER_BYTE) {
104369aba794SSrinivas Kandagatla 		/* setup the last byte with msb bits from nvmem */
1044795ddd18SSrinivas Kandagatla 		rc = nvmem_reg_read(nvmem,
104569aba794SSrinivas Kandagatla 				    cell->offset + cell->bytes - 1, &v, 1);
104650808bfcSMathieu Malaterre 		if (rc)
104750808bfcSMathieu Malaterre 			goto err;
104869aba794SSrinivas Kandagatla 		*p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
104969aba794SSrinivas Kandagatla 
105069aba794SSrinivas Kandagatla 	}
105169aba794SSrinivas Kandagatla 
105269aba794SSrinivas Kandagatla 	return buf;
105350808bfcSMathieu Malaterre err:
105450808bfcSMathieu Malaterre 	kfree(buf);
105550808bfcSMathieu Malaterre 	return ERR_PTR(rc);
105669aba794SSrinivas Kandagatla }
105769aba794SSrinivas Kandagatla 
105869aba794SSrinivas Kandagatla /**
105969aba794SSrinivas Kandagatla  * nvmem_cell_write() - Write to a given nvmem cell
106069aba794SSrinivas Kandagatla  *
106169aba794SSrinivas Kandagatla  * @cell: nvmem cell to be written.
106269aba794SSrinivas Kandagatla  * @buf: Buffer to be written.
106369aba794SSrinivas Kandagatla  * @len: length of buffer to be written to nvmem cell.
106469aba794SSrinivas Kandagatla  *
106569aba794SSrinivas Kandagatla  * Return: length of bytes written or negative on failure.
106669aba794SSrinivas Kandagatla  */
106769aba794SSrinivas Kandagatla int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
106869aba794SSrinivas Kandagatla {
106969aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
107069aba794SSrinivas Kandagatla 	int rc;
107169aba794SSrinivas Kandagatla 
1072795ddd18SSrinivas Kandagatla 	if (!nvmem || nvmem->read_only ||
107369aba794SSrinivas Kandagatla 	    (cell->bit_offset == 0 && len != cell->bytes))
107469aba794SSrinivas Kandagatla 		return -EINVAL;
107569aba794SSrinivas Kandagatla 
107669aba794SSrinivas Kandagatla 	if (cell->bit_offset || cell->nbits) {
107769aba794SSrinivas Kandagatla 		buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
107869aba794SSrinivas Kandagatla 		if (IS_ERR(buf))
107969aba794SSrinivas Kandagatla 			return PTR_ERR(buf);
108069aba794SSrinivas Kandagatla 	}
108169aba794SSrinivas Kandagatla 
1082795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_write(nvmem, cell->offset, buf, cell->bytes);
108369aba794SSrinivas Kandagatla 
108469aba794SSrinivas Kandagatla 	/* free the tmp buffer */
1085ace22170SAxel Lin 	if (cell->bit_offset || cell->nbits)
108669aba794SSrinivas Kandagatla 		kfree(buf);
108769aba794SSrinivas Kandagatla 
1088287980e4SArnd Bergmann 	if (rc)
108969aba794SSrinivas Kandagatla 		return rc;
109069aba794SSrinivas Kandagatla 
109169aba794SSrinivas Kandagatla 	return len;
109269aba794SSrinivas Kandagatla }
109369aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_write);
109469aba794SSrinivas Kandagatla 
10956bb317ceSYangtao Li static int nvmem_cell_read_common(struct device *dev, const char *cell_id,
10966bb317ceSYangtao Li 				  void *val, size_t count)
10970a9b2d1cSFabrice Gasnier {
10980a9b2d1cSFabrice Gasnier 	struct nvmem_cell *cell;
10990a9b2d1cSFabrice Gasnier 	void *buf;
11000a9b2d1cSFabrice Gasnier 	size_t len;
11010a9b2d1cSFabrice Gasnier 
11020a9b2d1cSFabrice Gasnier 	cell = nvmem_cell_get(dev, cell_id);
11030a9b2d1cSFabrice Gasnier 	if (IS_ERR(cell))
11040a9b2d1cSFabrice Gasnier 		return PTR_ERR(cell);
11050a9b2d1cSFabrice Gasnier 
11060a9b2d1cSFabrice Gasnier 	buf = nvmem_cell_read(cell, &len);
11070a9b2d1cSFabrice Gasnier 	if (IS_ERR(buf)) {
11080a9b2d1cSFabrice Gasnier 		nvmem_cell_put(cell);
11090a9b2d1cSFabrice Gasnier 		return PTR_ERR(buf);
11100a9b2d1cSFabrice Gasnier 	}
11116bb317ceSYangtao Li 	if (len != count) {
11120a9b2d1cSFabrice Gasnier 		kfree(buf);
11130a9b2d1cSFabrice Gasnier 		nvmem_cell_put(cell);
11140a9b2d1cSFabrice Gasnier 		return -EINVAL;
11150a9b2d1cSFabrice Gasnier 	}
11166bb317ceSYangtao Li 	memcpy(val, buf, count);
11170a9b2d1cSFabrice Gasnier 	kfree(buf);
11180a9b2d1cSFabrice Gasnier 	nvmem_cell_put(cell);
11190a9b2d1cSFabrice Gasnier 
11200a9b2d1cSFabrice Gasnier 	return 0;
11210a9b2d1cSFabrice Gasnier }
11226bb317ceSYangtao Li 
11236bb317ceSYangtao Li /**
11246bb317ceSYangtao Li  * nvmem_cell_read_u16() - Read a cell value as an u16
11256bb317ceSYangtao Li  *
11266bb317ceSYangtao Li  * @dev: Device that requests the nvmem cell.
11276bb317ceSYangtao Li  * @cell_id: Name of nvmem cell to read.
11286bb317ceSYangtao Li  * @val: pointer to output value.
11296bb317ceSYangtao Li  *
11306bb317ceSYangtao Li  * Return: 0 on success or negative errno.
11316bb317ceSYangtao Li  */
11326bb317ceSYangtao Li int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
11336bb317ceSYangtao Li {
11346bb317ceSYangtao Li 	return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
11356bb317ceSYangtao Li }
11360a9b2d1cSFabrice Gasnier EXPORT_SYMBOL_GPL(nvmem_cell_read_u16);
11370a9b2d1cSFabrice Gasnier 
11380a9b2d1cSFabrice Gasnier /**
1139d026d70aSLeonard Crestez  * nvmem_cell_read_u32() - Read a cell value as an u32
1140d026d70aSLeonard Crestez  *
1141d026d70aSLeonard Crestez  * @dev: Device that requests the nvmem cell.
1142d026d70aSLeonard Crestez  * @cell_id: Name of nvmem cell to read.
1143d026d70aSLeonard Crestez  * @val: pointer to output value.
1144d026d70aSLeonard Crestez  *
1145d026d70aSLeonard Crestez  * Return: 0 on success or negative errno.
1146d026d70aSLeonard Crestez  */
1147d026d70aSLeonard Crestez int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val)
1148d026d70aSLeonard Crestez {
11496bb317ceSYangtao Li 	return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
1150d026d70aSLeonard Crestez }
1151d026d70aSLeonard Crestez EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
1152d026d70aSLeonard Crestez 
1153d026d70aSLeonard Crestez /**
11548b977c54SYangtao Li  * nvmem_cell_read_u64() - Read a cell value as an u64
11558b977c54SYangtao Li  *
11568b977c54SYangtao Li  * @dev: Device that requests the nvmem cell.
11578b977c54SYangtao Li  * @cell_id: Name of nvmem cell to read.
11588b977c54SYangtao Li  * @val: pointer to output value.
11598b977c54SYangtao Li  *
11608b977c54SYangtao Li  * Return: 0 on success or negative errno.
11618b977c54SYangtao Li  */
11628b977c54SYangtao Li int nvmem_cell_read_u64(struct device *dev, const char *cell_id, u64 *val)
11638b977c54SYangtao Li {
11648b977c54SYangtao Li 	return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
11658b977c54SYangtao Li }
11668b977c54SYangtao Li EXPORT_SYMBOL_GPL(nvmem_cell_read_u64);
11678b977c54SYangtao Li 
11688b977c54SYangtao Li /**
1169e2a5402eSSrinivas Kandagatla  * nvmem_device_cell_read() - Read a given nvmem device and cell
1170e2a5402eSSrinivas Kandagatla  *
1171e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to read from.
1172e2a5402eSSrinivas Kandagatla  * @info: nvmem cell info to be read.
1173e2a5402eSSrinivas Kandagatla  * @buf: buffer pointer which will be populated on successful read.
1174e2a5402eSSrinivas Kandagatla  *
1175e2a5402eSSrinivas Kandagatla  * Return: length of successful bytes read on success and negative
1176e2a5402eSSrinivas Kandagatla  * error code on error.
1177e2a5402eSSrinivas Kandagatla  */
1178e2a5402eSSrinivas Kandagatla ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
1179e2a5402eSSrinivas Kandagatla 			   struct nvmem_cell_info *info, void *buf)
1180e2a5402eSSrinivas Kandagatla {
1181e2a5402eSSrinivas Kandagatla 	struct nvmem_cell cell;
1182e2a5402eSSrinivas Kandagatla 	int rc;
1183e2a5402eSSrinivas Kandagatla 	ssize_t len;
1184e2a5402eSSrinivas Kandagatla 
1185795ddd18SSrinivas Kandagatla 	if (!nvmem)
1186e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1187e2a5402eSSrinivas Kandagatla 
1188e2a5402eSSrinivas Kandagatla 	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
1189287980e4SArnd Bergmann 	if (rc)
1190e2a5402eSSrinivas Kandagatla 		return rc;
1191e2a5402eSSrinivas Kandagatla 
1192e2a5402eSSrinivas Kandagatla 	rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
1193287980e4SArnd Bergmann 	if (rc)
1194e2a5402eSSrinivas Kandagatla 		return rc;
1195e2a5402eSSrinivas Kandagatla 
1196e2a5402eSSrinivas Kandagatla 	return len;
1197e2a5402eSSrinivas Kandagatla }
1198e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
1199e2a5402eSSrinivas Kandagatla 
1200e2a5402eSSrinivas Kandagatla /**
1201e2a5402eSSrinivas Kandagatla  * nvmem_device_cell_write() - Write cell to a given nvmem device
1202e2a5402eSSrinivas Kandagatla  *
1203e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to be written to.
120429143268SVivek Gautam  * @info: nvmem cell info to be written.
1205e2a5402eSSrinivas Kandagatla  * @buf: buffer to be written to cell.
1206e2a5402eSSrinivas Kandagatla  *
1207e2a5402eSSrinivas Kandagatla  * Return: length of bytes written or negative error code on failure.
120848f63a2cSBartosz Golaszewski  */
1209e2a5402eSSrinivas Kandagatla int nvmem_device_cell_write(struct nvmem_device *nvmem,
1210e2a5402eSSrinivas Kandagatla 			    struct nvmem_cell_info *info, void *buf)
1211e2a5402eSSrinivas Kandagatla {
1212e2a5402eSSrinivas Kandagatla 	struct nvmem_cell cell;
1213e2a5402eSSrinivas Kandagatla 	int rc;
1214e2a5402eSSrinivas Kandagatla 
1215795ddd18SSrinivas Kandagatla 	if (!nvmem)
1216e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1217e2a5402eSSrinivas Kandagatla 
1218e2a5402eSSrinivas Kandagatla 	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
1219287980e4SArnd Bergmann 	if (rc)
1220e2a5402eSSrinivas Kandagatla 		return rc;
1221e2a5402eSSrinivas Kandagatla 
1222e2a5402eSSrinivas Kandagatla 	return nvmem_cell_write(&cell, buf, cell.bytes);
1223e2a5402eSSrinivas Kandagatla }
1224e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
1225e2a5402eSSrinivas Kandagatla 
1226e2a5402eSSrinivas Kandagatla /**
1227e2a5402eSSrinivas Kandagatla  * nvmem_device_read() - Read from a given nvmem device
1228e2a5402eSSrinivas Kandagatla  *
1229e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to read from.
1230e2a5402eSSrinivas Kandagatla  * @offset: offset in nvmem device.
1231e2a5402eSSrinivas Kandagatla  * @bytes: number of bytes to read.
1232e2a5402eSSrinivas Kandagatla  * @buf: buffer pointer which will be populated on successful read.
1233e2a5402eSSrinivas Kandagatla  *
1234e2a5402eSSrinivas Kandagatla  * Return: length of successful bytes read on success and negative
1235e2a5402eSSrinivas Kandagatla  * error code on error.
1236e2a5402eSSrinivas Kandagatla  */
1237e2a5402eSSrinivas Kandagatla int nvmem_device_read(struct nvmem_device *nvmem,
1238e2a5402eSSrinivas Kandagatla 		      unsigned int offset,
1239e2a5402eSSrinivas Kandagatla 		      size_t bytes, void *buf)
1240e2a5402eSSrinivas Kandagatla {
1241e2a5402eSSrinivas Kandagatla 	int rc;
1242e2a5402eSSrinivas Kandagatla 
1243795ddd18SSrinivas Kandagatla 	if (!nvmem)
1244e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1245e2a5402eSSrinivas Kandagatla 
1246795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_read(nvmem, offset, buf, bytes);
1247e2a5402eSSrinivas Kandagatla 
1248287980e4SArnd Bergmann 	if (rc)
1249e2a5402eSSrinivas Kandagatla 		return rc;
1250e2a5402eSSrinivas Kandagatla 
1251e2a5402eSSrinivas Kandagatla 	return bytes;
1252e2a5402eSSrinivas Kandagatla }
1253e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_read);
1254e2a5402eSSrinivas Kandagatla 
1255e2a5402eSSrinivas Kandagatla /**
1256e2a5402eSSrinivas Kandagatla  * nvmem_device_write() - Write cell to a given nvmem device
1257e2a5402eSSrinivas Kandagatla  *
1258e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to be written to.
1259e2a5402eSSrinivas Kandagatla  * @offset: offset in nvmem device.
1260e2a5402eSSrinivas Kandagatla  * @bytes: number of bytes to write.
1261e2a5402eSSrinivas Kandagatla  * @buf: buffer to be written.
1262e2a5402eSSrinivas Kandagatla  *
1263e2a5402eSSrinivas Kandagatla  * Return: length of bytes written or negative error code on failure.
126448f63a2cSBartosz Golaszewski  */
1265e2a5402eSSrinivas Kandagatla int nvmem_device_write(struct nvmem_device *nvmem,
1266e2a5402eSSrinivas Kandagatla 		       unsigned int offset,
1267e2a5402eSSrinivas Kandagatla 		       size_t bytes, void *buf)
1268e2a5402eSSrinivas Kandagatla {
1269e2a5402eSSrinivas Kandagatla 	int rc;
1270e2a5402eSSrinivas Kandagatla 
1271795ddd18SSrinivas Kandagatla 	if (!nvmem)
1272e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1273e2a5402eSSrinivas Kandagatla 
1274795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_write(nvmem, offset, buf, bytes);
1275e2a5402eSSrinivas Kandagatla 
1276287980e4SArnd Bergmann 	if (rc)
1277e2a5402eSSrinivas Kandagatla 		return rc;
1278e2a5402eSSrinivas Kandagatla 
1279e2a5402eSSrinivas Kandagatla 
1280e2a5402eSSrinivas Kandagatla 	return bytes;
1281e2a5402eSSrinivas Kandagatla }
1282e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_write);
1283e2a5402eSSrinivas Kandagatla 
1284d7b9fd16SBartosz Golaszewski /**
1285b985f4cbSBartosz Golaszewski  * nvmem_add_cell_table() - register a table of cell info entries
1286b985f4cbSBartosz Golaszewski  *
1287b985f4cbSBartosz Golaszewski  * @table: table of cell info entries
1288b985f4cbSBartosz Golaszewski  */
1289b985f4cbSBartosz Golaszewski void nvmem_add_cell_table(struct nvmem_cell_table *table)
1290b985f4cbSBartosz Golaszewski {
1291b985f4cbSBartosz Golaszewski 	mutex_lock(&nvmem_cell_mutex);
1292b985f4cbSBartosz Golaszewski 	list_add_tail(&table->node, &nvmem_cell_tables);
1293b985f4cbSBartosz Golaszewski 	mutex_unlock(&nvmem_cell_mutex);
1294b985f4cbSBartosz Golaszewski }
1295b985f4cbSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_add_cell_table);
1296b985f4cbSBartosz Golaszewski 
1297b985f4cbSBartosz Golaszewski /**
1298b985f4cbSBartosz Golaszewski  * nvmem_del_cell_table() - remove a previously registered cell info table
1299b985f4cbSBartosz Golaszewski  *
1300b985f4cbSBartosz Golaszewski  * @table: table of cell info entries
1301b985f4cbSBartosz Golaszewski  */
1302b985f4cbSBartosz Golaszewski void nvmem_del_cell_table(struct nvmem_cell_table *table)
1303b985f4cbSBartosz Golaszewski {
1304b985f4cbSBartosz Golaszewski 	mutex_lock(&nvmem_cell_mutex);
1305b985f4cbSBartosz Golaszewski 	list_del(&table->node);
1306b985f4cbSBartosz Golaszewski 	mutex_unlock(&nvmem_cell_mutex);
1307b985f4cbSBartosz Golaszewski }
1308b985f4cbSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_del_cell_table);
1309b985f4cbSBartosz Golaszewski 
1310b985f4cbSBartosz Golaszewski /**
1311506157beSBartosz Golaszewski  * nvmem_add_cell_lookups() - register a list of cell lookup entries
1312506157beSBartosz Golaszewski  *
1313506157beSBartosz Golaszewski  * @entries: array of cell lookup entries
1314506157beSBartosz Golaszewski  * @nentries: number of cell lookup entries in the array
1315506157beSBartosz Golaszewski  */
1316506157beSBartosz Golaszewski void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
1317506157beSBartosz Golaszewski {
1318506157beSBartosz Golaszewski 	int i;
1319506157beSBartosz Golaszewski 
1320506157beSBartosz Golaszewski 	mutex_lock(&nvmem_lookup_mutex);
1321506157beSBartosz Golaszewski 	for (i = 0; i < nentries; i++)
1322506157beSBartosz Golaszewski 		list_add_tail(&entries[i].node, &nvmem_lookup_list);
1323506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_lookup_mutex);
1324506157beSBartosz Golaszewski }
1325506157beSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_add_cell_lookups);
1326506157beSBartosz Golaszewski 
1327506157beSBartosz Golaszewski /**
1328506157beSBartosz Golaszewski  * nvmem_del_cell_lookups() - remove a list of previously added cell lookup
1329506157beSBartosz Golaszewski  *                            entries
1330506157beSBartosz Golaszewski  *
1331506157beSBartosz Golaszewski  * @entries: array of cell lookup entries
1332506157beSBartosz Golaszewski  * @nentries: number of cell lookup entries in the array
1333506157beSBartosz Golaszewski  */
1334506157beSBartosz Golaszewski void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
1335506157beSBartosz Golaszewski {
1336506157beSBartosz Golaszewski 	int i;
1337506157beSBartosz Golaszewski 
1338506157beSBartosz Golaszewski 	mutex_lock(&nvmem_lookup_mutex);
1339506157beSBartosz Golaszewski 	for (i = 0; i < nentries; i++)
1340506157beSBartosz Golaszewski 		list_del(&entries[i].node);
1341506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_lookup_mutex);
1342506157beSBartosz Golaszewski }
1343506157beSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_del_cell_lookups);
1344506157beSBartosz Golaszewski 
1345506157beSBartosz Golaszewski /**
1346d7b9fd16SBartosz Golaszewski  * nvmem_dev_name() - Get the name of a given nvmem device.
1347d7b9fd16SBartosz Golaszewski  *
1348d7b9fd16SBartosz Golaszewski  * @nvmem: nvmem device.
1349d7b9fd16SBartosz Golaszewski  *
1350d7b9fd16SBartosz Golaszewski  * Return: name of the nvmem device.
1351d7b9fd16SBartosz Golaszewski  */
1352d7b9fd16SBartosz Golaszewski const char *nvmem_dev_name(struct nvmem_device *nvmem)
1353d7b9fd16SBartosz Golaszewski {
1354d7b9fd16SBartosz Golaszewski 	return dev_name(&nvmem->dev);
1355d7b9fd16SBartosz Golaszewski }
1356d7b9fd16SBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_dev_name);
1357d7b9fd16SBartosz Golaszewski 
1358eace75cfSSrinivas Kandagatla static int __init nvmem_init(void)
1359eace75cfSSrinivas Kandagatla {
1360eace75cfSSrinivas Kandagatla 	return bus_register(&nvmem_bus_type);
1361eace75cfSSrinivas Kandagatla }
1362eace75cfSSrinivas Kandagatla 
1363eace75cfSSrinivas Kandagatla static void __exit nvmem_exit(void)
1364eace75cfSSrinivas Kandagatla {
1365eace75cfSSrinivas Kandagatla 	bus_unregister(&nvmem_bus_type);
1366eace75cfSSrinivas Kandagatla }
1367eace75cfSSrinivas Kandagatla 
1368eace75cfSSrinivas Kandagatla subsys_initcall(nvmem_init);
1369eace75cfSSrinivas Kandagatla module_exit(nvmem_exit);
1370eace75cfSSrinivas Kandagatla 
1371eace75cfSSrinivas Kandagatla MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
1372eace75cfSSrinivas Kandagatla MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
1373eace75cfSSrinivas Kandagatla MODULE_DESCRIPTION("nvmem Driver Core");
1374eace75cfSSrinivas Kandagatla MODULE_LICENSE("GPL v2");
1375