xref: /linux/drivers/nvmem/core.c (revision 844003052719375bad24a740fed5d32c5a18efaf)
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>
21*84400305SSrinivas Kandagatla 
22*84400305SSrinivas Kandagatla struct nvmem_device {
23*84400305SSrinivas Kandagatla 	struct module		*owner;
24*84400305SSrinivas Kandagatla 	struct device		dev;
25*84400305SSrinivas Kandagatla 	int			stride;
26*84400305SSrinivas Kandagatla 	int			word_size;
27*84400305SSrinivas Kandagatla 	int			id;
28*84400305SSrinivas Kandagatla 	struct kref		refcnt;
29*84400305SSrinivas Kandagatla 	size_t			size;
30*84400305SSrinivas Kandagatla 	bool			read_only;
31*84400305SSrinivas Kandagatla 	bool			root_only;
32*84400305SSrinivas Kandagatla 	int			flags;
33*84400305SSrinivas Kandagatla 	enum nvmem_type		type;
34*84400305SSrinivas Kandagatla 	struct bin_attribute	eeprom;
35*84400305SSrinivas Kandagatla 	struct device		*base_dev;
36*84400305SSrinivas Kandagatla 	struct list_head	cells;
37*84400305SSrinivas Kandagatla 	nvmem_reg_read_t	reg_read;
38*84400305SSrinivas Kandagatla 	nvmem_reg_write_t	reg_write;
39*84400305SSrinivas Kandagatla 	struct gpio_desc	*wp_gpio;
40*84400305SSrinivas Kandagatla 	void *priv;
41*84400305SSrinivas Kandagatla };
42*84400305SSrinivas Kandagatla 
43*84400305SSrinivas Kandagatla #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
44*84400305SSrinivas Kandagatla 
45*84400305SSrinivas Kandagatla #define FLAG_COMPAT		BIT(0)
46b6c217abSAndrew Lunn 
47eace75cfSSrinivas Kandagatla struct nvmem_cell {
48eace75cfSSrinivas Kandagatla 	const char		*name;
49eace75cfSSrinivas Kandagatla 	int			offset;
50eace75cfSSrinivas Kandagatla 	int			bytes;
51eace75cfSSrinivas Kandagatla 	int			bit_offset;
52eace75cfSSrinivas Kandagatla 	int			nbits;
530749aa25SSrinivas Kandagatla 	struct device_node	*np;
54eace75cfSSrinivas Kandagatla 	struct nvmem_device	*nvmem;
55eace75cfSSrinivas Kandagatla 	struct list_head	node;
56eace75cfSSrinivas Kandagatla };
57eace75cfSSrinivas Kandagatla 
58eace75cfSSrinivas Kandagatla static DEFINE_MUTEX(nvmem_mutex);
59eace75cfSSrinivas Kandagatla static DEFINE_IDA(nvmem_ida);
60eace75cfSSrinivas Kandagatla 
61b985f4cbSBartosz Golaszewski static DEFINE_MUTEX(nvmem_cell_mutex);
62b985f4cbSBartosz Golaszewski static LIST_HEAD(nvmem_cell_tables);
63b985f4cbSBartosz Golaszewski 
64506157beSBartosz Golaszewski static DEFINE_MUTEX(nvmem_lookup_mutex);
65506157beSBartosz Golaszewski static LIST_HEAD(nvmem_lookup_list);
66506157beSBartosz Golaszewski 
67bee1138bSBartosz Golaszewski static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
68bee1138bSBartosz Golaszewski 
69*84400305SSrinivas Kandagatla #ifdef CONFIG_NVMEM_SYSFS
70*84400305SSrinivas Kandagatla static const char * const nvmem_type_str[] = {
71*84400305SSrinivas Kandagatla 	[NVMEM_TYPE_UNKNOWN] = "Unknown",
72*84400305SSrinivas Kandagatla 	[NVMEM_TYPE_EEPROM] = "EEPROM",
73*84400305SSrinivas Kandagatla 	[NVMEM_TYPE_OTP] = "OTP",
74*84400305SSrinivas Kandagatla 	[NVMEM_TYPE_BATTERY_BACKED] = "Battery backed",
75*84400305SSrinivas Kandagatla };
76*84400305SSrinivas Kandagatla 
77*84400305SSrinivas Kandagatla #ifdef CONFIG_DEBUG_LOCK_ALLOC
78*84400305SSrinivas Kandagatla static struct lock_class_key eeprom_lock_key;
79*84400305SSrinivas Kandagatla #endif
80*84400305SSrinivas Kandagatla 
81*84400305SSrinivas Kandagatla static ssize_t type_show(struct device *dev,
82*84400305SSrinivas Kandagatla 			 struct device_attribute *attr, char *buf)
83*84400305SSrinivas Kandagatla {
84*84400305SSrinivas Kandagatla 	struct nvmem_device *nvmem = to_nvmem_device(dev);
85*84400305SSrinivas Kandagatla 
86*84400305SSrinivas Kandagatla 	return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]);
87*84400305SSrinivas Kandagatla }
88*84400305SSrinivas Kandagatla 
89*84400305SSrinivas Kandagatla static DEVICE_ATTR_RO(type);
90*84400305SSrinivas Kandagatla 
91*84400305SSrinivas Kandagatla static struct attribute *nvmem_attrs[] = {
92*84400305SSrinivas Kandagatla 	&dev_attr_type.attr,
93*84400305SSrinivas Kandagatla 	NULL,
94*84400305SSrinivas Kandagatla };
95*84400305SSrinivas Kandagatla 
96*84400305SSrinivas Kandagatla static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
97*84400305SSrinivas Kandagatla 				   struct bin_attribute *attr, char *buf,
98*84400305SSrinivas Kandagatla 				   loff_t pos, size_t count)
99*84400305SSrinivas Kandagatla {
100*84400305SSrinivas Kandagatla 	struct device *dev;
101*84400305SSrinivas Kandagatla 	struct nvmem_device *nvmem;
102*84400305SSrinivas Kandagatla 	int rc;
103*84400305SSrinivas Kandagatla 
104*84400305SSrinivas Kandagatla 	if (attr->private)
105*84400305SSrinivas Kandagatla 		dev = attr->private;
106*84400305SSrinivas Kandagatla 	else
107*84400305SSrinivas Kandagatla 		dev = container_of(kobj, struct device, kobj);
108*84400305SSrinivas Kandagatla 	nvmem = to_nvmem_device(dev);
109*84400305SSrinivas Kandagatla 
110*84400305SSrinivas Kandagatla 	/* Stop the user from reading */
111*84400305SSrinivas Kandagatla 	if (pos >= nvmem->size)
112*84400305SSrinivas Kandagatla 		return 0;
113*84400305SSrinivas Kandagatla 
114*84400305SSrinivas Kandagatla 	if (count < nvmem->word_size)
115*84400305SSrinivas Kandagatla 		return -EINVAL;
116*84400305SSrinivas Kandagatla 
117*84400305SSrinivas Kandagatla 	if (pos + count > nvmem->size)
118*84400305SSrinivas Kandagatla 		count = nvmem->size - pos;
119*84400305SSrinivas Kandagatla 
120*84400305SSrinivas Kandagatla 	count = round_down(count, nvmem->word_size);
121*84400305SSrinivas Kandagatla 
122*84400305SSrinivas Kandagatla 	if (!nvmem->reg_read)
123*84400305SSrinivas Kandagatla 		return -EPERM;
124*84400305SSrinivas Kandagatla 
125*84400305SSrinivas Kandagatla 	rc = nvmem->reg_read(nvmem->priv, pos, buf, count);
126*84400305SSrinivas Kandagatla 
127*84400305SSrinivas Kandagatla 	if (rc)
128*84400305SSrinivas Kandagatla 		return rc;
129*84400305SSrinivas Kandagatla 
130*84400305SSrinivas Kandagatla 	return count;
131*84400305SSrinivas Kandagatla }
132*84400305SSrinivas Kandagatla 
133*84400305SSrinivas Kandagatla static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
134*84400305SSrinivas Kandagatla 				    struct bin_attribute *attr, char *buf,
135*84400305SSrinivas Kandagatla 				    loff_t pos, size_t count)
136*84400305SSrinivas Kandagatla {
137*84400305SSrinivas Kandagatla 	struct device *dev;
138*84400305SSrinivas Kandagatla 	struct nvmem_device *nvmem;
139*84400305SSrinivas Kandagatla 	int rc;
140*84400305SSrinivas Kandagatla 
141*84400305SSrinivas Kandagatla 	if (attr->private)
142*84400305SSrinivas Kandagatla 		dev = attr->private;
143*84400305SSrinivas Kandagatla 	else
144*84400305SSrinivas Kandagatla 		dev = container_of(kobj, struct device, kobj);
145*84400305SSrinivas Kandagatla 	nvmem = to_nvmem_device(dev);
146*84400305SSrinivas Kandagatla 
147*84400305SSrinivas Kandagatla 	/* Stop the user from writing */
148*84400305SSrinivas Kandagatla 	if (pos >= nvmem->size)
149*84400305SSrinivas Kandagatla 		return -EFBIG;
150*84400305SSrinivas Kandagatla 
151*84400305SSrinivas Kandagatla 	if (count < nvmem->word_size)
152*84400305SSrinivas Kandagatla 		return -EINVAL;
153*84400305SSrinivas Kandagatla 
154*84400305SSrinivas Kandagatla 	if (pos + count > nvmem->size)
155*84400305SSrinivas Kandagatla 		count = nvmem->size - pos;
156*84400305SSrinivas Kandagatla 
157*84400305SSrinivas Kandagatla 	count = round_down(count, nvmem->word_size);
158*84400305SSrinivas Kandagatla 
159*84400305SSrinivas Kandagatla 	if (!nvmem->reg_write)
160*84400305SSrinivas Kandagatla 		return -EPERM;
161*84400305SSrinivas Kandagatla 
162*84400305SSrinivas Kandagatla 	rc = nvmem->reg_write(nvmem->priv, pos, buf, count);
163*84400305SSrinivas Kandagatla 
164*84400305SSrinivas Kandagatla 	if (rc)
165*84400305SSrinivas Kandagatla 		return rc;
166*84400305SSrinivas Kandagatla 
167*84400305SSrinivas Kandagatla 	return count;
168*84400305SSrinivas Kandagatla }
169*84400305SSrinivas Kandagatla 
170*84400305SSrinivas Kandagatla static umode_t nvmem_bin_attr_is_visible(struct kobject *kobj,
171*84400305SSrinivas Kandagatla 					 struct bin_attribute *attr, int i)
172*84400305SSrinivas Kandagatla {
173*84400305SSrinivas Kandagatla 	struct device *dev = container_of(kobj, struct device, kobj);
174*84400305SSrinivas Kandagatla 	struct nvmem_device *nvmem = to_nvmem_device(dev);
175*84400305SSrinivas Kandagatla 	umode_t mode = 0400;
176*84400305SSrinivas Kandagatla 
177*84400305SSrinivas Kandagatla 	if (!nvmem->root_only)
178*84400305SSrinivas Kandagatla 		mode |= 0044;
179*84400305SSrinivas Kandagatla 
180*84400305SSrinivas Kandagatla 	if (!nvmem->read_only)
181*84400305SSrinivas Kandagatla 		mode |= 0200;
182*84400305SSrinivas Kandagatla 
183*84400305SSrinivas Kandagatla 	if (!nvmem->reg_write)
184*84400305SSrinivas Kandagatla 		mode &= ~0200;
185*84400305SSrinivas Kandagatla 
186*84400305SSrinivas Kandagatla 	if (!nvmem->reg_read)
187*84400305SSrinivas Kandagatla 		mode &= ~0444;
188*84400305SSrinivas Kandagatla 
189*84400305SSrinivas Kandagatla 	return mode;
190*84400305SSrinivas Kandagatla }
191*84400305SSrinivas Kandagatla 
192*84400305SSrinivas Kandagatla /* default read/write permissions */
193*84400305SSrinivas Kandagatla static struct bin_attribute bin_attr_rw_nvmem = {
194*84400305SSrinivas Kandagatla 	.attr	= {
195*84400305SSrinivas Kandagatla 		.name	= "nvmem",
196*84400305SSrinivas Kandagatla 		.mode	= 0644,
197*84400305SSrinivas Kandagatla 	},
198*84400305SSrinivas Kandagatla 	.read	= bin_attr_nvmem_read,
199*84400305SSrinivas Kandagatla 	.write	= bin_attr_nvmem_write,
200*84400305SSrinivas Kandagatla };
201*84400305SSrinivas Kandagatla 
202*84400305SSrinivas Kandagatla static struct bin_attribute *nvmem_bin_attributes[] = {
203*84400305SSrinivas Kandagatla 	&bin_attr_rw_nvmem,
204*84400305SSrinivas Kandagatla 	NULL,
205*84400305SSrinivas Kandagatla };
206*84400305SSrinivas Kandagatla 
207*84400305SSrinivas Kandagatla static const struct attribute_group nvmem_bin_group = {
208*84400305SSrinivas Kandagatla 	.bin_attrs	= nvmem_bin_attributes,
209*84400305SSrinivas Kandagatla 	.attrs		= nvmem_attrs,
210*84400305SSrinivas Kandagatla 	.is_bin_visible = nvmem_bin_attr_is_visible,
211*84400305SSrinivas Kandagatla };
212*84400305SSrinivas Kandagatla 
213*84400305SSrinivas Kandagatla static const struct attribute_group *nvmem_dev_groups[] = {
214*84400305SSrinivas Kandagatla 	&nvmem_bin_group,
215*84400305SSrinivas Kandagatla 	NULL,
216*84400305SSrinivas Kandagatla };
217*84400305SSrinivas Kandagatla 
218*84400305SSrinivas Kandagatla /* read only permission */
219*84400305SSrinivas Kandagatla static struct bin_attribute bin_attr_ro_nvmem = {
220*84400305SSrinivas Kandagatla 	.attr	= {
221*84400305SSrinivas Kandagatla 		.name	= "nvmem",
222*84400305SSrinivas Kandagatla 		.mode	= 0444,
223*84400305SSrinivas Kandagatla 	},
224*84400305SSrinivas Kandagatla 	.read	= bin_attr_nvmem_read,
225*84400305SSrinivas Kandagatla };
226*84400305SSrinivas Kandagatla 
227*84400305SSrinivas Kandagatla /* default read/write permissions, root only */
228*84400305SSrinivas Kandagatla static struct bin_attribute bin_attr_rw_root_nvmem = {
229*84400305SSrinivas Kandagatla 	.attr	= {
230*84400305SSrinivas Kandagatla 		.name	= "nvmem",
231*84400305SSrinivas Kandagatla 		.mode	= 0600,
232*84400305SSrinivas Kandagatla 	},
233*84400305SSrinivas Kandagatla 	.read	= bin_attr_nvmem_read,
234*84400305SSrinivas Kandagatla 	.write	= bin_attr_nvmem_write,
235*84400305SSrinivas Kandagatla };
236*84400305SSrinivas Kandagatla 
237*84400305SSrinivas Kandagatla /* read only permission, root only */
238*84400305SSrinivas Kandagatla static struct bin_attribute bin_attr_ro_root_nvmem = {
239*84400305SSrinivas Kandagatla 	.attr	= {
240*84400305SSrinivas Kandagatla 		.name	= "nvmem",
241*84400305SSrinivas Kandagatla 		.mode	= 0400,
242*84400305SSrinivas Kandagatla 	},
243*84400305SSrinivas Kandagatla 	.read	= bin_attr_nvmem_read,
244*84400305SSrinivas Kandagatla };
245*84400305SSrinivas Kandagatla 
246*84400305SSrinivas Kandagatla /*
247*84400305SSrinivas Kandagatla  * nvmem_setup_compat() - Create an additional binary entry in
248*84400305SSrinivas Kandagatla  * drivers sys directory, to be backwards compatible with the older
249*84400305SSrinivas Kandagatla  * drivers/misc/eeprom drivers.
250*84400305SSrinivas Kandagatla  */
251*84400305SSrinivas Kandagatla static int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
252*84400305SSrinivas Kandagatla 				    const struct nvmem_config *config)
253*84400305SSrinivas Kandagatla {
254*84400305SSrinivas Kandagatla 	int rval;
255*84400305SSrinivas Kandagatla 
256*84400305SSrinivas Kandagatla 	if (!config->compat)
257*84400305SSrinivas Kandagatla 		return 0;
258*84400305SSrinivas Kandagatla 
259*84400305SSrinivas Kandagatla 	if (!config->base_dev)
260*84400305SSrinivas Kandagatla 		return -EINVAL;
261*84400305SSrinivas Kandagatla 
262*84400305SSrinivas Kandagatla 	if (nvmem->read_only) {
263*84400305SSrinivas Kandagatla 		if (config->root_only)
264*84400305SSrinivas Kandagatla 			nvmem->eeprom = bin_attr_ro_root_nvmem;
265*84400305SSrinivas Kandagatla 		else
266*84400305SSrinivas Kandagatla 			nvmem->eeprom = bin_attr_ro_nvmem;
267*84400305SSrinivas Kandagatla 	} else {
268*84400305SSrinivas Kandagatla 		if (config->root_only)
269*84400305SSrinivas Kandagatla 			nvmem->eeprom = bin_attr_rw_root_nvmem;
270*84400305SSrinivas Kandagatla 		else
271*84400305SSrinivas Kandagatla 			nvmem->eeprom = bin_attr_rw_nvmem;
272*84400305SSrinivas Kandagatla 	}
273*84400305SSrinivas Kandagatla 	nvmem->eeprom.attr.name = "eeprom";
274*84400305SSrinivas Kandagatla 	nvmem->eeprom.size = nvmem->size;
275*84400305SSrinivas Kandagatla #ifdef CONFIG_DEBUG_LOCK_ALLOC
276*84400305SSrinivas Kandagatla 	nvmem->eeprom.attr.key = &eeprom_lock_key;
277*84400305SSrinivas Kandagatla #endif
278*84400305SSrinivas Kandagatla 	nvmem->eeprom.private = &nvmem->dev;
279*84400305SSrinivas Kandagatla 	nvmem->base_dev = config->base_dev;
280*84400305SSrinivas Kandagatla 
281*84400305SSrinivas Kandagatla 	rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
282*84400305SSrinivas Kandagatla 	if (rval) {
283*84400305SSrinivas Kandagatla 		dev_err(&nvmem->dev,
284*84400305SSrinivas Kandagatla 			"Failed to create eeprom binary file %d\n", rval);
285*84400305SSrinivas Kandagatla 		return rval;
286*84400305SSrinivas Kandagatla 	}
287*84400305SSrinivas Kandagatla 
288*84400305SSrinivas Kandagatla 	nvmem->flags |= FLAG_COMPAT;
289*84400305SSrinivas Kandagatla 
290*84400305SSrinivas Kandagatla 	return 0;
291*84400305SSrinivas Kandagatla }
292*84400305SSrinivas Kandagatla 
293*84400305SSrinivas Kandagatla static void nvmem_sysfs_remove_compat(struct nvmem_device *nvmem,
294*84400305SSrinivas Kandagatla 			      const struct nvmem_config *config)
295*84400305SSrinivas Kandagatla {
296*84400305SSrinivas Kandagatla 	if (config->compat)
297*84400305SSrinivas Kandagatla 		device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
298*84400305SSrinivas Kandagatla }
299*84400305SSrinivas Kandagatla 
300*84400305SSrinivas Kandagatla #else /* CONFIG_NVMEM_SYSFS */
301*84400305SSrinivas Kandagatla 
302*84400305SSrinivas Kandagatla static int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
303*84400305SSrinivas Kandagatla 				    const struct nvmem_config *config)
304*84400305SSrinivas Kandagatla {
305*84400305SSrinivas Kandagatla 	return -ENOSYS;
306*84400305SSrinivas Kandagatla }
307*84400305SSrinivas Kandagatla static void nvmem_sysfs_remove_compat(struct nvmem_device *nvmem,
308*84400305SSrinivas Kandagatla 				      const struct nvmem_config *config)
309*84400305SSrinivas Kandagatla {
310*84400305SSrinivas Kandagatla }
311*84400305SSrinivas Kandagatla 
312*84400305SSrinivas Kandagatla #endif /* CONFIG_NVMEM_SYSFS */
313a8b44d5dSAndy Shevchenko 
314795ddd18SSrinivas Kandagatla static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
315795ddd18SSrinivas Kandagatla 			  void *val, size_t bytes)
316795ddd18SSrinivas Kandagatla {
317795ddd18SSrinivas Kandagatla 	if (nvmem->reg_read)
318795ddd18SSrinivas Kandagatla 		return nvmem->reg_read(nvmem->priv, offset, val, bytes);
319795ddd18SSrinivas Kandagatla 
320795ddd18SSrinivas Kandagatla 	return -EINVAL;
321795ddd18SSrinivas Kandagatla }
322795ddd18SSrinivas Kandagatla 
323795ddd18SSrinivas Kandagatla static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
324795ddd18SSrinivas Kandagatla 			   void *val, size_t bytes)
325795ddd18SSrinivas Kandagatla {
3262a127da4SKhouloud Touil 	int ret;
3272a127da4SKhouloud Touil 
3282a127da4SKhouloud Touil 	if (nvmem->reg_write) {
3292a127da4SKhouloud Touil 		gpiod_set_value_cansleep(nvmem->wp_gpio, 0);
3302a127da4SKhouloud Touil 		ret = nvmem->reg_write(nvmem->priv, offset, val, bytes);
3312a127da4SKhouloud Touil 		gpiod_set_value_cansleep(nvmem->wp_gpio, 1);
3322a127da4SKhouloud Touil 		return ret;
3332a127da4SKhouloud Touil 	}
334795ddd18SSrinivas Kandagatla 
335795ddd18SSrinivas Kandagatla 	return -EINVAL;
336795ddd18SSrinivas Kandagatla }
337eace75cfSSrinivas Kandagatla 
338eace75cfSSrinivas Kandagatla static void nvmem_release(struct device *dev)
339eace75cfSSrinivas Kandagatla {
340eace75cfSSrinivas Kandagatla 	struct nvmem_device *nvmem = to_nvmem_device(dev);
341eace75cfSSrinivas Kandagatla 
342eace75cfSSrinivas Kandagatla 	ida_simple_remove(&nvmem_ida, nvmem->id);
343a9c3766cSKhouloud Touil 	gpiod_put(nvmem->wp_gpio);
344eace75cfSSrinivas Kandagatla 	kfree(nvmem);
345eace75cfSSrinivas Kandagatla }
346eace75cfSSrinivas Kandagatla 
347eace75cfSSrinivas Kandagatla static const struct device_type nvmem_provider_type = {
348eace75cfSSrinivas Kandagatla 	.release	= nvmem_release,
349eace75cfSSrinivas Kandagatla };
350eace75cfSSrinivas Kandagatla 
351eace75cfSSrinivas Kandagatla static struct bus_type nvmem_bus_type = {
352eace75cfSSrinivas Kandagatla 	.name		= "nvmem",
353eace75cfSSrinivas Kandagatla };
354eace75cfSSrinivas Kandagatla 
355eace75cfSSrinivas Kandagatla static void nvmem_cell_drop(struct nvmem_cell *cell)
356eace75cfSSrinivas Kandagatla {
357bee1138bSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
358c7235ee3SBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
359eace75cfSSrinivas Kandagatla 	list_del(&cell->node);
360c7235ee3SBartosz Golaszewski 	mutex_unlock(&nvmem_mutex);
3610749aa25SSrinivas Kandagatla 	of_node_put(cell->np);
36216bb7abcSBitan Biswas 	kfree_const(cell->name);
363eace75cfSSrinivas Kandagatla 	kfree(cell);
364eace75cfSSrinivas Kandagatla }
365eace75cfSSrinivas Kandagatla 
366eace75cfSSrinivas Kandagatla static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
367eace75cfSSrinivas Kandagatla {
3681852183eSBartosz Golaszewski 	struct nvmem_cell *cell, *p;
369eace75cfSSrinivas Kandagatla 
370c7235ee3SBartosz Golaszewski 	list_for_each_entry_safe(cell, p, &nvmem->cells, node)
371eace75cfSSrinivas Kandagatla 		nvmem_cell_drop(cell);
372eace75cfSSrinivas Kandagatla }
373eace75cfSSrinivas Kandagatla 
374eace75cfSSrinivas Kandagatla static void nvmem_cell_add(struct nvmem_cell *cell)
375eace75cfSSrinivas Kandagatla {
376c7235ee3SBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
377c7235ee3SBartosz Golaszewski 	list_add_tail(&cell->node, &cell->nvmem->cells);
378c7235ee3SBartosz Golaszewski 	mutex_unlock(&nvmem_mutex);
379bee1138bSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
380eace75cfSSrinivas Kandagatla }
381eace75cfSSrinivas Kandagatla 
382eace75cfSSrinivas Kandagatla static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
383eace75cfSSrinivas Kandagatla 				   const struct nvmem_cell_info *info,
384eace75cfSSrinivas Kandagatla 				   struct nvmem_cell *cell)
385eace75cfSSrinivas Kandagatla {
386eace75cfSSrinivas Kandagatla 	cell->nvmem = nvmem;
387eace75cfSSrinivas Kandagatla 	cell->offset = info->offset;
388eace75cfSSrinivas Kandagatla 	cell->bytes = info->bytes;
38916bb7abcSBitan Biswas 	cell->name = kstrdup_const(info->name, GFP_KERNEL);
39016bb7abcSBitan Biswas 	if (!cell->name)
39116bb7abcSBitan Biswas 		return -ENOMEM;
392eace75cfSSrinivas Kandagatla 
393eace75cfSSrinivas Kandagatla 	cell->bit_offset = info->bit_offset;
394eace75cfSSrinivas Kandagatla 	cell->nbits = info->nbits;
395eace75cfSSrinivas Kandagatla 
396eace75cfSSrinivas Kandagatla 	if (cell->nbits)
397eace75cfSSrinivas Kandagatla 		cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
398eace75cfSSrinivas Kandagatla 					   BITS_PER_BYTE);
399eace75cfSSrinivas Kandagatla 
400eace75cfSSrinivas Kandagatla 	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
401eace75cfSSrinivas Kandagatla 		dev_err(&nvmem->dev,
402eace75cfSSrinivas Kandagatla 			"cell %s unaligned to nvmem stride %d\n",
403eace75cfSSrinivas Kandagatla 			cell->name, nvmem->stride);
404eace75cfSSrinivas Kandagatla 		return -EINVAL;
405eace75cfSSrinivas Kandagatla 	}
406eace75cfSSrinivas Kandagatla 
407eace75cfSSrinivas Kandagatla 	return 0;
408eace75cfSSrinivas Kandagatla }
409eace75cfSSrinivas Kandagatla 
410b3db17e4SAndrew Lunn /**
411b3db17e4SAndrew Lunn  * nvmem_add_cells() - Add cell information to an nvmem device
412b3db17e4SAndrew Lunn  *
413b3db17e4SAndrew Lunn  * @nvmem: nvmem device to add cells to.
414b3db17e4SAndrew Lunn  * @info: nvmem cell info to add to the device
415b3db17e4SAndrew Lunn  * @ncells: number of cells in info
416b3db17e4SAndrew Lunn  *
417b3db17e4SAndrew Lunn  * Return: 0 or negative error code on failure.
418b3db17e4SAndrew Lunn  */
419ef92ab30SSrinivas Kandagatla static int nvmem_add_cells(struct nvmem_device *nvmem,
420b3db17e4SAndrew Lunn 		    const struct nvmem_cell_info *info,
421b3db17e4SAndrew Lunn 		    int ncells)
422eace75cfSSrinivas Kandagatla {
423eace75cfSSrinivas Kandagatla 	struct nvmem_cell **cells;
424eace75cfSSrinivas Kandagatla 	int i, rval;
425eace75cfSSrinivas Kandagatla 
426b3db17e4SAndrew Lunn 	cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
427eace75cfSSrinivas Kandagatla 	if (!cells)
428eace75cfSSrinivas Kandagatla 		return -ENOMEM;
429eace75cfSSrinivas Kandagatla 
430b3db17e4SAndrew Lunn 	for (i = 0; i < ncells; i++) {
431eace75cfSSrinivas Kandagatla 		cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
432eace75cfSSrinivas Kandagatla 		if (!cells[i]) {
433eace75cfSSrinivas Kandagatla 			rval = -ENOMEM;
434eace75cfSSrinivas Kandagatla 			goto err;
435eace75cfSSrinivas Kandagatla 		}
436eace75cfSSrinivas Kandagatla 
437eace75cfSSrinivas Kandagatla 		rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
438287980e4SArnd Bergmann 		if (rval) {
439eace75cfSSrinivas Kandagatla 			kfree(cells[i]);
440eace75cfSSrinivas Kandagatla 			goto err;
441eace75cfSSrinivas Kandagatla 		}
442eace75cfSSrinivas Kandagatla 
443eace75cfSSrinivas Kandagatla 		nvmem_cell_add(cells[i]);
444eace75cfSSrinivas Kandagatla 	}
445eace75cfSSrinivas Kandagatla 
446eace75cfSSrinivas Kandagatla 	/* remove tmp array */
447eace75cfSSrinivas Kandagatla 	kfree(cells);
448eace75cfSSrinivas Kandagatla 
449eace75cfSSrinivas Kandagatla 	return 0;
450eace75cfSSrinivas Kandagatla err:
451dfdf1414SRasmus Villemoes 	while (i--)
452eace75cfSSrinivas Kandagatla 		nvmem_cell_drop(cells[i]);
453eace75cfSSrinivas Kandagatla 
454dfdf1414SRasmus Villemoes 	kfree(cells);
455dfdf1414SRasmus Villemoes 
456eace75cfSSrinivas Kandagatla 	return rval;
457eace75cfSSrinivas Kandagatla }
458eace75cfSSrinivas Kandagatla 
459bee1138bSBartosz Golaszewski /**
460bee1138bSBartosz Golaszewski  * nvmem_register_notifier() - Register a notifier block for nvmem events.
461bee1138bSBartosz Golaszewski  *
462bee1138bSBartosz Golaszewski  * @nb: notifier block to be called on nvmem events.
463bee1138bSBartosz Golaszewski  *
464bee1138bSBartosz Golaszewski  * Return: 0 on success, negative error number on failure.
465bee1138bSBartosz Golaszewski  */
466bee1138bSBartosz Golaszewski int nvmem_register_notifier(struct notifier_block *nb)
467bee1138bSBartosz Golaszewski {
468bee1138bSBartosz Golaszewski 	return blocking_notifier_chain_register(&nvmem_notifier, nb);
469bee1138bSBartosz Golaszewski }
470bee1138bSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_register_notifier);
471bee1138bSBartosz Golaszewski 
472bee1138bSBartosz Golaszewski /**
473bee1138bSBartosz Golaszewski  * nvmem_unregister_notifier() - Unregister a notifier block for nvmem events.
474bee1138bSBartosz Golaszewski  *
475bee1138bSBartosz Golaszewski  * @nb: notifier block to be unregistered.
476bee1138bSBartosz Golaszewski  *
477bee1138bSBartosz Golaszewski  * Return: 0 on success, negative error number on failure.
478bee1138bSBartosz Golaszewski  */
479bee1138bSBartosz Golaszewski int nvmem_unregister_notifier(struct notifier_block *nb)
480bee1138bSBartosz Golaszewski {
481bee1138bSBartosz Golaszewski 	return blocking_notifier_chain_unregister(&nvmem_notifier, nb);
482bee1138bSBartosz Golaszewski }
483bee1138bSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_unregister_notifier);
484bee1138bSBartosz Golaszewski 
485b985f4cbSBartosz Golaszewski static int nvmem_add_cells_from_table(struct nvmem_device *nvmem)
486b985f4cbSBartosz Golaszewski {
487b985f4cbSBartosz Golaszewski 	const struct nvmem_cell_info *info;
488b985f4cbSBartosz Golaszewski 	struct nvmem_cell_table *table;
489b985f4cbSBartosz Golaszewski 	struct nvmem_cell *cell;
490b985f4cbSBartosz Golaszewski 	int rval = 0, i;
491b985f4cbSBartosz Golaszewski 
492b985f4cbSBartosz Golaszewski 	mutex_lock(&nvmem_cell_mutex);
493b985f4cbSBartosz Golaszewski 	list_for_each_entry(table, &nvmem_cell_tables, node) {
494b985f4cbSBartosz Golaszewski 		if (strcmp(nvmem_dev_name(nvmem), table->nvmem_name) == 0) {
495b985f4cbSBartosz Golaszewski 			for (i = 0; i < table->ncells; i++) {
496b985f4cbSBartosz Golaszewski 				info = &table->cells[i];
497b985f4cbSBartosz Golaszewski 
498b985f4cbSBartosz Golaszewski 				cell = kzalloc(sizeof(*cell), GFP_KERNEL);
499b985f4cbSBartosz Golaszewski 				if (!cell) {
500b985f4cbSBartosz Golaszewski 					rval = -ENOMEM;
501b985f4cbSBartosz Golaszewski 					goto out;
502b985f4cbSBartosz Golaszewski 				}
503b985f4cbSBartosz Golaszewski 
504b985f4cbSBartosz Golaszewski 				rval = nvmem_cell_info_to_nvmem_cell(nvmem,
505b985f4cbSBartosz Golaszewski 								     info,
506b985f4cbSBartosz Golaszewski 								     cell);
507b985f4cbSBartosz Golaszewski 				if (rval) {
508b985f4cbSBartosz Golaszewski 					kfree(cell);
509b985f4cbSBartosz Golaszewski 					goto out;
510b985f4cbSBartosz Golaszewski 				}
511b985f4cbSBartosz Golaszewski 
512b985f4cbSBartosz Golaszewski 				nvmem_cell_add(cell);
513b985f4cbSBartosz Golaszewski 			}
514b985f4cbSBartosz Golaszewski 		}
515b985f4cbSBartosz Golaszewski 	}
516b985f4cbSBartosz Golaszewski 
517b985f4cbSBartosz Golaszewski out:
518b985f4cbSBartosz Golaszewski 	mutex_unlock(&nvmem_cell_mutex);
519b985f4cbSBartosz Golaszewski 	return rval;
520b985f4cbSBartosz Golaszewski }
521b985f4cbSBartosz Golaszewski 
522e888d445SBartosz Golaszewski static struct nvmem_cell *
523506157beSBartosz Golaszewski nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
524506157beSBartosz Golaszewski {
5251c832674SAlban Bedel 	struct nvmem_cell *iter, *cell = NULL;
526506157beSBartosz Golaszewski 
527506157beSBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
5281c832674SAlban Bedel 	list_for_each_entry(iter, &nvmem->cells, node) {
5291c832674SAlban Bedel 		if (strcmp(cell_id, iter->name) == 0) {
5301c832674SAlban Bedel 			cell = iter;
531506157beSBartosz Golaszewski 			break;
532506157beSBartosz Golaszewski 		}
5331c832674SAlban Bedel 	}
534506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_mutex);
535506157beSBartosz Golaszewski 
536506157beSBartosz Golaszewski 	return cell;
537506157beSBartosz Golaszewski }
538506157beSBartosz Golaszewski 
539e888d445SBartosz Golaszewski static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
540e888d445SBartosz Golaszewski {
541e888d445SBartosz Golaszewski 	struct device_node *parent, *child;
542e888d445SBartosz Golaszewski 	struct device *dev = &nvmem->dev;
543e888d445SBartosz Golaszewski 	struct nvmem_cell *cell;
544e888d445SBartosz Golaszewski 	const __be32 *addr;
545e888d445SBartosz Golaszewski 	int len;
546e888d445SBartosz Golaszewski 
547e888d445SBartosz Golaszewski 	parent = dev->of_node;
548e888d445SBartosz Golaszewski 
549e888d445SBartosz Golaszewski 	for_each_child_of_node(parent, child) {
550e888d445SBartosz Golaszewski 		addr = of_get_property(child, "reg", &len);
551e888d445SBartosz Golaszewski 		if (!addr || (len < 2 * sizeof(u32))) {
552e888d445SBartosz Golaszewski 			dev_err(dev, "nvmem: invalid reg on %pOF\n", child);
553e888d445SBartosz Golaszewski 			return -EINVAL;
554e888d445SBartosz Golaszewski 		}
555e888d445SBartosz Golaszewski 
556e888d445SBartosz Golaszewski 		cell = kzalloc(sizeof(*cell), GFP_KERNEL);
557e888d445SBartosz Golaszewski 		if (!cell)
558e888d445SBartosz Golaszewski 			return -ENOMEM;
559e888d445SBartosz Golaszewski 
560e888d445SBartosz Golaszewski 		cell->nvmem = nvmem;
5610749aa25SSrinivas Kandagatla 		cell->np = of_node_get(child);
562e888d445SBartosz Golaszewski 		cell->offset = be32_to_cpup(addr++);
563e888d445SBartosz Golaszewski 		cell->bytes = be32_to_cpup(addr);
564badcdff1SRob Herring 		cell->name = kasprintf(GFP_KERNEL, "%pOFn", child);
565e888d445SBartosz Golaszewski 
566e888d445SBartosz Golaszewski 		addr = of_get_property(child, "bits", &len);
567e888d445SBartosz Golaszewski 		if (addr && len == (2 * sizeof(u32))) {
568e888d445SBartosz Golaszewski 			cell->bit_offset = be32_to_cpup(addr++);
569e888d445SBartosz Golaszewski 			cell->nbits = be32_to_cpup(addr);
570e888d445SBartosz Golaszewski 		}
571e888d445SBartosz Golaszewski 
572e888d445SBartosz Golaszewski 		if (cell->nbits)
573e888d445SBartosz Golaszewski 			cell->bytes = DIV_ROUND_UP(
574e888d445SBartosz Golaszewski 					cell->nbits + cell->bit_offset,
575e888d445SBartosz Golaszewski 					BITS_PER_BYTE);
576e888d445SBartosz Golaszewski 
577e888d445SBartosz Golaszewski 		if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
578e888d445SBartosz Golaszewski 			dev_err(dev, "cell %s unaligned to nvmem stride %d\n",
579e888d445SBartosz Golaszewski 				cell->name, nvmem->stride);
580e888d445SBartosz Golaszewski 			/* Cells already added will be freed later. */
58116bb7abcSBitan Biswas 			kfree_const(cell->name);
582e888d445SBartosz Golaszewski 			kfree(cell);
583e888d445SBartosz Golaszewski 			return -EINVAL;
584e888d445SBartosz Golaszewski 		}
585e888d445SBartosz Golaszewski 
586e888d445SBartosz Golaszewski 		nvmem_cell_add(cell);
587e888d445SBartosz Golaszewski 	}
588e888d445SBartosz Golaszewski 
589e888d445SBartosz Golaszewski 	return 0;
590e888d445SBartosz Golaszewski }
591e888d445SBartosz Golaszewski 
592eace75cfSSrinivas Kandagatla /**
593eace75cfSSrinivas Kandagatla  * nvmem_register() - Register a nvmem device for given nvmem_config.
594eace75cfSSrinivas Kandagatla  * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
595eace75cfSSrinivas Kandagatla  *
596eace75cfSSrinivas Kandagatla  * @config: nvmem device configuration with which nvmem device is created.
597eace75cfSSrinivas Kandagatla  *
598eace75cfSSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
599eace75cfSSrinivas Kandagatla  * on success.
600eace75cfSSrinivas Kandagatla  */
601eace75cfSSrinivas Kandagatla 
602eace75cfSSrinivas Kandagatla struct nvmem_device *nvmem_register(const struct nvmem_config *config)
603eace75cfSSrinivas Kandagatla {
604eace75cfSSrinivas Kandagatla 	struct nvmem_device *nvmem;
605eace75cfSSrinivas Kandagatla 	int rval;
606eace75cfSSrinivas Kandagatla 
607eace75cfSSrinivas Kandagatla 	if (!config->dev)
608eace75cfSSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
609eace75cfSSrinivas Kandagatla 
610061a320bSSrinivas Kandagatla 	if (!config->reg_read && !config->reg_write)
611061a320bSSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
612061a320bSSrinivas Kandagatla 
613eace75cfSSrinivas Kandagatla 	nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
614eace75cfSSrinivas Kandagatla 	if (!nvmem)
615eace75cfSSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
616eace75cfSSrinivas Kandagatla 
617eace75cfSSrinivas Kandagatla 	rval  = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
618eace75cfSSrinivas Kandagatla 	if (rval < 0) {
619eace75cfSSrinivas Kandagatla 		kfree(nvmem);
620eace75cfSSrinivas Kandagatla 		return ERR_PTR(rval);
621eace75cfSSrinivas Kandagatla 	}
62231c6ff51SBartosz Golaszewski 
6232a127da4SKhouloud Touil 	if (config->wp_gpio)
6242a127da4SKhouloud Touil 		nvmem->wp_gpio = config->wp_gpio;
6252a127da4SKhouloud Touil 	else
6262a127da4SKhouloud Touil 		nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp",
6272a127da4SKhouloud Touil 						    GPIOD_OUT_HIGH);
628f7d8d7dcSBartosz Golaszewski 	if (IS_ERR(nvmem->wp_gpio)) {
629f7d8d7dcSBartosz Golaszewski 		ida_simple_remove(&nvmem_ida, nvmem->id);
630f7d8d7dcSBartosz Golaszewski 		rval = PTR_ERR(nvmem->wp_gpio);
631f7d8d7dcSBartosz Golaszewski 		kfree(nvmem);
632f7d8d7dcSBartosz Golaszewski 		return ERR_PTR(rval);
633f7d8d7dcSBartosz Golaszewski 	}
6342a127da4SKhouloud Touil 
635c1de7f43SBartosz Golaszewski 	kref_init(&nvmem->refcnt);
636c7235ee3SBartosz Golaszewski 	INIT_LIST_HEAD(&nvmem->cells);
637c1de7f43SBartosz Golaszewski 
638eace75cfSSrinivas Kandagatla 	nvmem->id = rval;
639eace75cfSSrinivas Kandagatla 	nvmem->owner = config->owner;
64017eb18d6SMasahiro Yamada 	if (!nvmem->owner && config->dev->driver)
64117eb18d6SMasahiro Yamada 		nvmem->owner = config->dev->driver->owner;
64299897efdSHeiner Kallweit 	nvmem->stride = config->stride ?: 1;
64399897efdSHeiner Kallweit 	nvmem->word_size = config->word_size ?: 1;
644795ddd18SSrinivas Kandagatla 	nvmem->size = config->size;
645eace75cfSSrinivas Kandagatla 	nvmem->dev.type = &nvmem_provider_type;
646eace75cfSSrinivas Kandagatla 	nvmem->dev.bus = &nvmem_bus_type;
647eace75cfSSrinivas Kandagatla 	nvmem->dev.parent = config->dev;
648e6de179dSSrinivas Kandagatla 	nvmem->root_only = config->root_only;
649795ddd18SSrinivas Kandagatla 	nvmem->priv = config->priv;
65016688453SAlexandre Belloni 	nvmem->type = config->type;
651795ddd18SSrinivas Kandagatla 	nvmem->reg_read = config->reg_read;
652795ddd18SSrinivas Kandagatla 	nvmem->reg_write = config->reg_write;
653517f14d9SBartosz Golaszewski 	if (!config->no_of_node)
654fc2f9970SHeiner Kallweit 		nvmem->dev.of_node = config->dev->of_node;
655fd0f4906SAndrey Smirnov 
656fd0f4906SAndrey Smirnov 	if (config->id == -1 && config->name) {
657fd0f4906SAndrey Smirnov 		dev_set_name(&nvmem->dev, "%s", config->name);
658fd0f4906SAndrey Smirnov 	} else {
659eace75cfSSrinivas Kandagatla 		dev_set_name(&nvmem->dev, "%s%d",
6605253193dSAban Bedel 			     config->name ? : "nvmem",
6615253193dSAban Bedel 			     config->name ? config->id : nvmem->id);
662fd0f4906SAndrey Smirnov 	}
663eace75cfSSrinivas Kandagatla 
6641716cfe8SAlban Bedel 	nvmem->read_only = device_property_present(config->dev, "read-only") ||
6651716cfe8SAlban Bedel 			   config->read_only || !nvmem->reg_write;
666eace75cfSSrinivas Kandagatla 
667*84400305SSrinivas Kandagatla #ifdef CONFIG_NVMEM_SYSFS
668*84400305SSrinivas Kandagatla 	nvmem->dev.groups = nvmem_dev_groups;
669*84400305SSrinivas Kandagatla #endif
670eace75cfSSrinivas Kandagatla 
671eace75cfSSrinivas Kandagatla 	dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
672eace75cfSSrinivas Kandagatla 
673f60442ddSSrinivas Kandagatla 	rval = device_register(&nvmem->dev);
674b6c217abSAndrew Lunn 	if (rval)
6753360acdfSJohan Hovold 		goto err_put_device;
676b6c217abSAndrew Lunn 
677b6c217abSAndrew Lunn 	if (config->compat) {
678ae0c2d72SSrinivas Kandagatla 		rval = nvmem_sysfs_setup_compat(nvmem, config);
679b6c217abSAndrew Lunn 		if (rval)
6803360acdfSJohan Hovold 			goto err_device_del;
681eace75cfSSrinivas Kandagatla 	}
682eace75cfSSrinivas Kandagatla 
683fa72d847SBartosz Golaszewski 	if (config->cells) {
684fa72d847SBartosz Golaszewski 		rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
685fa72d847SBartosz Golaszewski 		if (rval)
686fa72d847SBartosz Golaszewski 			goto err_teardown_compat;
687fa72d847SBartosz Golaszewski 	}
688eace75cfSSrinivas Kandagatla 
689b985f4cbSBartosz Golaszewski 	rval = nvmem_add_cells_from_table(nvmem);
690b985f4cbSBartosz Golaszewski 	if (rval)
691b985f4cbSBartosz Golaszewski 		goto err_remove_cells;
692b985f4cbSBartosz Golaszewski 
693e888d445SBartosz Golaszewski 	rval = nvmem_add_cells_from_of(nvmem);
694e888d445SBartosz Golaszewski 	if (rval)
695e888d445SBartosz Golaszewski 		goto err_remove_cells;
696e888d445SBartosz Golaszewski 
697f4853e1cSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
698bee1138bSBartosz Golaszewski 
699eace75cfSSrinivas Kandagatla 	return nvmem;
7003360acdfSJohan Hovold 
701b985f4cbSBartosz Golaszewski err_remove_cells:
702b985f4cbSBartosz Golaszewski 	nvmem_device_remove_all_cells(nvmem);
703fa72d847SBartosz Golaszewski err_teardown_compat:
704fa72d847SBartosz Golaszewski 	if (config->compat)
705ae0c2d72SSrinivas Kandagatla 		nvmem_sysfs_remove_compat(nvmem, config);
7063360acdfSJohan Hovold err_device_del:
7073360acdfSJohan Hovold 	device_del(&nvmem->dev);
7083360acdfSJohan Hovold err_put_device:
7093360acdfSJohan Hovold 	put_device(&nvmem->dev);
7103360acdfSJohan Hovold 
711b6c217abSAndrew Lunn 	return ERR_PTR(rval);
712eace75cfSSrinivas Kandagatla }
713eace75cfSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_register);
714eace75cfSSrinivas Kandagatla 
715c1de7f43SBartosz Golaszewski static void nvmem_device_release(struct kref *kref)
716c1de7f43SBartosz Golaszewski {
717c1de7f43SBartosz Golaszewski 	struct nvmem_device *nvmem;
718c1de7f43SBartosz Golaszewski 
719c1de7f43SBartosz Golaszewski 	nvmem = container_of(kref, struct nvmem_device, refcnt);
720c1de7f43SBartosz Golaszewski 
721bee1138bSBartosz Golaszewski 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_REMOVE, nvmem);
722bee1138bSBartosz Golaszewski 
723c1de7f43SBartosz Golaszewski 	if (nvmem->flags & FLAG_COMPAT)
724c1de7f43SBartosz Golaszewski 		device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
725c1de7f43SBartosz Golaszewski 
726c1de7f43SBartosz Golaszewski 	nvmem_device_remove_all_cells(nvmem);
727f60442ddSSrinivas Kandagatla 	device_unregister(&nvmem->dev);
728c1de7f43SBartosz Golaszewski }
729c1de7f43SBartosz Golaszewski 
730eace75cfSSrinivas Kandagatla /**
731eace75cfSSrinivas Kandagatla  * nvmem_unregister() - Unregister previously registered nvmem device
732eace75cfSSrinivas Kandagatla  *
733eace75cfSSrinivas Kandagatla  * @nvmem: Pointer to previously registered nvmem device.
734eace75cfSSrinivas Kandagatla  */
735bf58e882SBartosz Golaszewski void nvmem_unregister(struct nvmem_device *nvmem)
736eace75cfSSrinivas Kandagatla {
737c1de7f43SBartosz Golaszewski 	kref_put(&nvmem->refcnt, nvmem_device_release);
738eace75cfSSrinivas Kandagatla }
739eace75cfSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_unregister);
740eace75cfSSrinivas Kandagatla 
741f1f50ecaSAndrey Smirnov static void devm_nvmem_release(struct device *dev, void *res)
742f1f50ecaSAndrey Smirnov {
743bf58e882SBartosz Golaszewski 	nvmem_unregister(*(struct nvmem_device **)res);
744f1f50ecaSAndrey Smirnov }
745f1f50ecaSAndrey Smirnov 
746f1f50ecaSAndrey Smirnov /**
747f1f50ecaSAndrey Smirnov  * devm_nvmem_register() - Register a managed nvmem device for given
748f1f50ecaSAndrey Smirnov  * nvmem_config.
749f1f50ecaSAndrey Smirnov  * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
750f1f50ecaSAndrey Smirnov  *
751b378c779SSrinivas Kandagatla  * @dev: Device that uses the nvmem device.
752f1f50ecaSAndrey Smirnov  * @config: nvmem device configuration with which nvmem device is created.
753f1f50ecaSAndrey Smirnov  *
754f1f50ecaSAndrey Smirnov  * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
755f1f50ecaSAndrey Smirnov  * on success.
756f1f50ecaSAndrey Smirnov  */
757f1f50ecaSAndrey Smirnov struct nvmem_device *devm_nvmem_register(struct device *dev,
758f1f50ecaSAndrey Smirnov 					 const struct nvmem_config *config)
759f1f50ecaSAndrey Smirnov {
760f1f50ecaSAndrey Smirnov 	struct nvmem_device **ptr, *nvmem;
761f1f50ecaSAndrey Smirnov 
762f1f50ecaSAndrey Smirnov 	ptr = devres_alloc(devm_nvmem_release, sizeof(*ptr), GFP_KERNEL);
763f1f50ecaSAndrey Smirnov 	if (!ptr)
764f1f50ecaSAndrey Smirnov 		return ERR_PTR(-ENOMEM);
765f1f50ecaSAndrey Smirnov 
766f1f50ecaSAndrey Smirnov 	nvmem = nvmem_register(config);
767f1f50ecaSAndrey Smirnov 
768f1f50ecaSAndrey Smirnov 	if (!IS_ERR(nvmem)) {
769f1f50ecaSAndrey Smirnov 		*ptr = nvmem;
770f1f50ecaSAndrey Smirnov 		devres_add(dev, ptr);
771f1f50ecaSAndrey Smirnov 	} else {
772f1f50ecaSAndrey Smirnov 		devres_free(ptr);
773f1f50ecaSAndrey Smirnov 	}
774f1f50ecaSAndrey Smirnov 
775f1f50ecaSAndrey Smirnov 	return nvmem;
776f1f50ecaSAndrey Smirnov }
777f1f50ecaSAndrey Smirnov EXPORT_SYMBOL_GPL(devm_nvmem_register);
778f1f50ecaSAndrey Smirnov 
779f1f50ecaSAndrey Smirnov static int devm_nvmem_match(struct device *dev, void *res, void *data)
780f1f50ecaSAndrey Smirnov {
781f1f50ecaSAndrey Smirnov 	struct nvmem_device **r = res;
782f1f50ecaSAndrey Smirnov 
783f1f50ecaSAndrey Smirnov 	return *r == data;
784f1f50ecaSAndrey Smirnov }
785f1f50ecaSAndrey Smirnov 
786f1f50ecaSAndrey Smirnov /**
787f1f50ecaSAndrey Smirnov  * devm_nvmem_unregister() - Unregister previously registered managed nvmem
788f1f50ecaSAndrey Smirnov  * device.
789f1f50ecaSAndrey Smirnov  *
790b378c779SSrinivas Kandagatla  * @dev: Device that uses the nvmem device.
791f1f50ecaSAndrey Smirnov  * @nvmem: Pointer to previously registered nvmem device.
792f1f50ecaSAndrey Smirnov  *
793f1f50ecaSAndrey Smirnov  * Return: Will be an negative on error or a zero on success.
794f1f50ecaSAndrey Smirnov  */
795f1f50ecaSAndrey Smirnov int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
796f1f50ecaSAndrey Smirnov {
797f1f50ecaSAndrey Smirnov 	return devres_release(dev, devm_nvmem_release, devm_nvmem_match, nvmem);
798f1f50ecaSAndrey Smirnov }
799f1f50ecaSAndrey Smirnov EXPORT_SYMBOL(devm_nvmem_unregister);
800f1f50ecaSAndrey Smirnov 
8018c2a2b8cSThomas Bogendoerfer static struct nvmem_device *__nvmem_device_get(void *data,
8028c2a2b8cSThomas Bogendoerfer 			int (*match)(struct device *dev, const void *data))
80369aba794SSrinivas Kandagatla {
80469aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = NULL;
8058c2a2b8cSThomas Bogendoerfer 	struct device *dev;
80669aba794SSrinivas Kandagatla 
807c7235ee3SBartosz Golaszewski 	mutex_lock(&nvmem_mutex);
8088c2a2b8cSThomas Bogendoerfer 	dev = bus_find_device(&nvmem_bus_type, NULL, data, match);
8098c2a2b8cSThomas Bogendoerfer 	if (dev)
8108c2a2b8cSThomas Bogendoerfer 		nvmem = to_nvmem_device(dev);
81169aba794SSrinivas Kandagatla 	mutex_unlock(&nvmem_mutex);
812c7235ee3SBartosz Golaszewski 	if (!nvmem)
813c7235ee3SBartosz Golaszewski 		return ERR_PTR(-EPROBE_DEFER);
81469aba794SSrinivas Kandagatla 
81569aba794SSrinivas Kandagatla 	if (!try_module_get(nvmem->owner)) {
81669aba794SSrinivas Kandagatla 		dev_err(&nvmem->dev,
81769aba794SSrinivas Kandagatla 			"could not increase module refcount for cell %s\n",
8185db652c9SBartosz Golaszewski 			nvmem_dev_name(nvmem));
81969aba794SSrinivas Kandagatla 
82073e9dc4dSAlban Bedel 		put_device(&nvmem->dev);
82169aba794SSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
82269aba794SSrinivas Kandagatla 	}
82369aba794SSrinivas Kandagatla 
824c1de7f43SBartosz Golaszewski 	kref_get(&nvmem->refcnt);
825c1de7f43SBartosz Golaszewski 
82669aba794SSrinivas Kandagatla 	return nvmem;
82769aba794SSrinivas Kandagatla }
82869aba794SSrinivas Kandagatla 
82969aba794SSrinivas Kandagatla static void __nvmem_device_put(struct nvmem_device *nvmem)
83069aba794SSrinivas Kandagatla {
83173e9dc4dSAlban Bedel 	put_device(&nvmem->dev);
83269aba794SSrinivas Kandagatla 	module_put(nvmem->owner);
833c1de7f43SBartosz Golaszewski 	kref_put(&nvmem->refcnt, nvmem_device_release);
83469aba794SSrinivas Kandagatla }
83569aba794SSrinivas Kandagatla 
836e701c67cSMasahiro Yamada #if IS_ENABLED(CONFIG_OF)
837e2a5402eSSrinivas Kandagatla /**
838e2a5402eSSrinivas Kandagatla  * of_nvmem_device_get() - Get nvmem device from a given id
839e2a5402eSSrinivas Kandagatla  *
84029143268SVivek Gautam  * @np: Device tree node that uses the nvmem device.
841e2a5402eSSrinivas Kandagatla  * @id: nvmem name from nvmem-names property.
842e2a5402eSSrinivas Kandagatla  *
843e2a5402eSSrinivas Kandagatla  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
844e2a5402eSSrinivas Kandagatla  * on success.
845e2a5402eSSrinivas Kandagatla  */
846e2a5402eSSrinivas Kandagatla struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
847e2a5402eSSrinivas Kandagatla {
848e2a5402eSSrinivas Kandagatla 
849e2a5402eSSrinivas Kandagatla 	struct device_node *nvmem_np;
850d4e7fef1SAlban Bedel 	int index = 0;
851e2a5402eSSrinivas Kandagatla 
852d4e7fef1SAlban Bedel 	if (id)
853e2a5402eSSrinivas Kandagatla 		index = of_property_match_string(np, "nvmem-names", id);
854e2a5402eSSrinivas Kandagatla 
855e2a5402eSSrinivas Kandagatla 	nvmem_np = of_parse_phandle(np, "nvmem", index);
856e2a5402eSSrinivas Kandagatla 	if (!nvmem_np)
857d4e7fef1SAlban Bedel 		return ERR_PTR(-ENOENT);
858e2a5402eSSrinivas Kandagatla 
8598c2a2b8cSThomas Bogendoerfer 	return __nvmem_device_get(nvmem_np, device_match_of_node);
860e2a5402eSSrinivas Kandagatla }
861e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(of_nvmem_device_get);
862e2a5402eSSrinivas Kandagatla #endif
863e2a5402eSSrinivas Kandagatla 
864e2a5402eSSrinivas Kandagatla /**
865e2a5402eSSrinivas Kandagatla  * nvmem_device_get() - Get nvmem device from a given id
866e2a5402eSSrinivas Kandagatla  *
86729143268SVivek Gautam  * @dev: Device that uses the nvmem device.
86829143268SVivek Gautam  * @dev_name: name of the requested nvmem device.
869e2a5402eSSrinivas Kandagatla  *
870e2a5402eSSrinivas Kandagatla  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
871e2a5402eSSrinivas Kandagatla  * on success.
872e2a5402eSSrinivas Kandagatla  */
873e2a5402eSSrinivas Kandagatla struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
874e2a5402eSSrinivas Kandagatla {
875e2a5402eSSrinivas Kandagatla 	if (dev->of_node) { /* try dt first */
876e2a5402eSSrinivas Kandagatla 		struct nvmem_device *nvmem;
877e2a5402eSSrinivas Kandagatla 
878e2a5402eSSrinivas Kandagatla 		nvmem = of_nvmem_device_get(dev->of_node, dev_name);
879e2a5402eSSrinivas Kandagatla 
880e2a5402eSSrinivas Kandagatla 		if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
881e2a5402eSSrinivas Kandagatla 			return nvmem;
882e2a5402eSSrinivas Kandagatla 
883e2a5402eSSrinivas Kandagatla 	}
884e2a5402eSSrinivas Kandagatla 
8858c2a2b8cSThomas Bogendoerfer 	return __nvmem_device_get((void *)dev_name, device_match_name);
886e2a5402eSSrinivas Kandagatla }
887e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_get);
888e2a5402eSSrinivas Kandagatla 
8898c2a2b8cSThomas Bogendoerfer /**
8908c2a2b8cSThomas Bogendoerfer  * nvmem_device_find() - Find nvmem device with matching function
8918c2a2b8cSThomas Bogendoerfer  *
8928c2a2b8cSThomas Bogendoerfer  * @data: Data to pass to match function
8938c2a2b8cSThomas Bogendoerfer  * @match: Callback function to check device
8948c2a2b8cSThomas Bogendoerfer  *
8958c2a2b8cSThomas Bogendoerfer  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
8968c2a2b8cSThomas Bogendoerfer  * on success.
8978c2a2b8cSThomas Bogendoerfer  */
8988c2a2b8cSThomas Bogendoerfer struct nvmem_device *nvmem_device_find(void *data,
8998c2a2b8cSThomas Bogendoerfer 			int (*match)(struct device *dev, const void *data))
9008c2a2b8cSThomas Bogendoerfer {
9018c2a2b8cSThomas Bogendoerfer 	return __nvmem_device_get(data, match);
9028c2a2b8cSThomas Bogendoerfer }
9038c2a2b8cSThomas Bogendoerfer EXPORT_SYMBOL_GPL(nvmem_device_find);
9048c2a2b8cSThomas Bogendoerfer 
905e2a5402eSSrinivas Kandagatla static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
906e2a5402eSSrinivas Kandagatla {
907e2a5402eSSrinivas Kandagatla 	struct nvmem_device **nvmem = res;
908e2a5402eSSrinivas Kandagatla 
909e2a5402eSSrinivas Kandagatla 	if (WARN_ON(!nvmem || !*nvmem))
910e2a5402eSSrinivas Kandagatla 		return 0;
911e2a5402eSSrinivas Kandagatla 
912e2a5402eSSrinivas Kandagatla 	return *nvmem == data;
913e2a5402eSSrinivas Kandagatla }
914e2a5402eSSrinivas Kandagatla 
915e2a5402eSSrinivas Kandagatla static void devm_nvmem_device_release(struct device *dev, void *res)
916e2a5402eSSrinivas Kandagatla {
917e2a5402eSSrinivas Kandagatla 	nvmem_device_put(*(struct nvmem_device **)res);
918e2a5402eSSrinivas Kandagatla }
919e2a5402eSSrinivas Kandagatla 
920e2a5402eSSrinivas Kandagatla /**
921e2a5402eSSrinivas Kandagatla  * devm_nvmem_device_put() - put alredy got nvmem device
922e2a5402eSSrinivas Kandagatla  *
92329143268SVivek Gautam  * @dev: Device that uses the nvmem device.
924e2a5402eSSrinivas Kandagatla  * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
925e2a5402eSSrinivas Kandagatla  * that needs to be released.
926e2a5402eSSrinivas Kandagatla  */
927e2a5402eSSrinivas Kandagatla void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
928e2a5402eSSrinivas Kandagatla {
929e2a5402eSSrinivas Kandagatla 	int ret;
930e2a5402eSSrinivas Kandagatla 
931e2a5402eSSrinivas Kandagatla 	ret = devres_release(dev, devm_nvmem_device_release,
932e2a5402eSSrinivas Kandagatla 			     devm_nvmem_device_match, nvmem);
933e2a5402eSSrinivas Kandagatla 
934e2a5402eSSrinivas Kandagatla 	WARN_ON(ret);
935e2a5402eSSrinivas Kandagatla }
936e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
937e2a5402eSSrinivas Kandagatla 
938e2a5402eSSrinivas Kandagatla /**
939e2a5402eSSrinivas Kandagatla  * nvmem_device_put() - put alredy got nvmem device
940e2a5402eSSrinivas Kandagatla  *
941e2a5402eSSrinivas Kandagatla  * @nvmem: pointer to nvmem device that needs to be released.
942e2a5402eSSrinivas Kandagatla  */
943e2a5402eSSrinivas Kandagatla void nvmem_device_put(struct nvmem_device *nvmem)
944e2a5402eSSrinivas Kandagatla {
945e2a5402eSSrinivas Kandagatla 	__nvmem_device_put(nvmem);
946e2a5402eSSrinivas Kandagatla }
947e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_put);
948e2a5402eSSrinivas Kandagatla 
949e2a5402eSSrinivas Kandagatla /**
950e2a5402eSSrinivas Kandagatla  * devm_nvmem_device_get() - Get nvmem cell of device form a given id
951e2a5402eSSrinivas Kandagatla  *
95229143268SVivek Gautam  * @dev: Device that requests the nvmem device.
95329143268SVivek Gautam  * @id: name id for the requested nvmem device.
954e2a5402eSSrinivas Kandagatla  *
955e2a5402eSSrinivas Kandagatla  * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell
956e2a5402eSSrinivas Kandagatla  * on success.  The nvmem_cell will be freed by the automatically once the
957e2a5402eSSrinivas Kandagatla  * device is freed.
958e2a5402eSSrinivas Kandagatla  */
959e2a5402eSSrinivas Kandagatla struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
960e2a5402eSSrinivas Kandagatla {
961e2a5402eSSrinivas Kandagatla 	struct nvmem_device **ptr, *nvmem;
962e2a5402eSSrinivas Kandagatla 
963e2a5402eSSrinivas Kandagatla 	ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
964e2a5402eSSrinivas Kandagatla 	if (!ptr)
965e2a5402eSSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
966e2a5402eSSrinivas Kandagatla 
967e2a5402eSSrinivas Kandagatla 	nvmem = nvmem_device_get(dev, id);
968e2a5402eSSrinivas Kandagatla 	if (!IS_ERR(nvmem)) {
969e2a5402eSSrinivas Kandagatla 		*ptr = nvmem;
970e2a5402eSSrinivas Kandagatla 		devres_add(dev, ptr);
971e2a5402eSSrinivas Kandagatla 	} else {
972e2a5402eSSrinivas Kandagatla 		devres_free(ptr);
973e2a5402eSSrinivas Kandagatla 	}
974e2a5402eSSrinivas Kandagatla 
975e2a5402eSSrinivas Kandagatla 	return nvmem;
976e2a5402eSSrinivas Kandagatla }
977e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
978e2a5402eSSrinivas Kandagatla 
979506157beSBartosz Golaszewski static struct nvmem_cell *
980506157beSBartosz Golaszewski nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
98169aba794SSrinivas Kandagatla {
982506157beSBartosz Golaszewski 	struct nvmem_cell *cell = ERR_PTR(-ENOENT);
983506157beSBartosz Golaszewski 	struct nvmem_cell_lookup *lookup;
98469aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem;
985506157beSBartosz Golaszewski 	const char *dev_id;
98669aba794SSrinivas Kandagatla 
987506157beSBartosz Golaszewski 	if (!dev)
988506157beSBartosz Golaszewski 		return ERR_PTR(-EINVAL);
98969aba794SSrinivas Kandagatla 
990506157beSBartosz Golaszewski 	dev_id = dev_name(dev);
991506157beSBartosz Golaszewski 
992506157beSBartosz Golaszewski 	mutex_lock(&nvmem_lookup_mutex);
993506157beSBartosz Golaszewski 
994506157beSBartosz Golaszewski 	list_for_each_entry(lookup, &nvmem_lookup_list, node) {
995506157beSBartosz Golaszewski 		if ((strcmp(lookup->dev_id, dev_id) == 0) &&
996506157beSBartosz Golaszewski 		    (strcmp(lookup->con_id, con_id) == 0)) {
997506157beSBartosz Golaszewski 			/* This is the right entry. */
9988c2a2b8cSThomas Bogendoerfer 			nvmem = __nvmem_device_get((void *)lookup->nvmem_name,
9998c2a2b8cSThomas Bogendoerfer 						   device_match_name);
1000cccb3b19SBartosz Golaszewski 			if (IS_ERR(nvmem)) {
1001506157beSBartosz Golaszewski 				/* Provider may not be registered yet. */
1002cccb3b19SBartosz Golaszewski 				cell = ERR_CAST(nvmem);
10039bfd8198SAlban Bedel 				break;
1004506157beSBartosz Golaszewski 			}
1005506157beSBartosz Golaszewski 
1006506157beSBartosz Golaszewski 			cell = nvmem_find_cell_by_name(nvmem,
1007506157beSBartosz Golaszewski 						       lookup->cell_name);
1008506157beSBartosz Golaszewski 			if (!cell) {
1009506157beSBartosz Golaszewski 				__nvmem_device_put(nvmem);
1010cccb3b19SBartosz Golaszewski 				cell = ERR_PTR(-ENOENT);
1011506157beSBartosz Golaszewski 			}
10129bfd8198SAlban Bedel 			break;
1013506157beSBartosz Golaszewski 		}
1014506157beSBartosz Golaszewski 	}
1015506157beSBartosz Golaszewski 
1016506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_lookup_mutex);
101769aba794SSrinivas Kandagatla 	return cell;
101869aba794SSrinivas Kandagatla }
101969aba794SSrinivas Kandagatla 
1020e701c67cSMasahiro Yamada #if IS_ENABLED(CONFIG_OF)
10213c53e235SArnd Bergmann static struct nvmem_cell *
10220749aa25SSrinivas Kandagatla nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
10233c53e235SArnd Bergmann {
10241c832674SAlban Bedel 	struct nvmem_cell *iter, *cell = NULL;
10253c53e235SArnd Bergmann 
10263c53e235SArnd Bergmann 	mutex_lock(&nvmem_mutex);
10271c832674SAlban Bedel 	list_for_each_entry(iter, &nvmem->cells, node) {
10281c832674SAlban Bedel 		if (np == iter->np) {
10291c832674SAlban Bedel 			cell = iter;
10303c53e235SArnd Bergmann 			break;
10313c53e235SArnd Bergmann 		}
10321c832674SAlban Bedel 	}
10333c53e235SArnd Bergmann 	mutex_unlock(&nvmem_mutex);
10343c53e235SArnd Bergmann 
10353c53e235SArnd Bergmann 	return cell;
10363c53e235SArnd Bergmann }
10373c53e235SArnd Bergmann 
103869aba794SSrinivas Kandagatla /**
103969aba794SSrinivas Kandagatla  * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
104069aba794SSrinivas Kandagatla  *
104129143268SVivek Gautam  * @np: Device tree node that uses the nvmem cell.
1042165589f0SBartosz Golaszewski  * @id: nvmem cell name from nvmem-cell-names property, or NULL
1043fd0c478cSVivek Gautam  *      for the cell at index 0 (the lone cell with no accompanying
1044fd0c478cSVivek Gautam  *      nvmem-cell-names property).
104569aba794SSrinivas Kandagatla  *
104669aba794SSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer
104769aba794SSrinivas Kandagatla  * to a struct nvmem_cell.  The nvmem_cell will be freed by the
104869aba794SSrinivas Kandagatla  * nvmem_cell_put().
104969aba794SSrinivas Kandagatla  */
1050165589f0SBartosz Golaszewski struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
105169aba794SSrinivas Kandagatla {
105269aba794SSrinivas Kandagatla 	struct device_node *cell_np, *nvmem_np;
105369aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem;
1054e888d445SBartosz Golaszewski 	struct nvmem_cell *cell;
1055fd0c478cSVivek Gautam 	int index = 0;
105669aba794SSrinivas Kandagatla 
1057fd0c478cSVivek Gautam 	/* if cell name exists, find index to the name */
1058165589f0SBartosz Golaszewski 	if (id)
1059165589f0SBartosz Golaszewski 		index = of_property_match_string(np, "nvmem-cell-names", id);
106069aba794SSrinivas Kandagatla 
106169aba794SSrinivas Kandagatla 	cell_np = of_parse_phandle(np, "nvmem-cells", index);
106269aba794SSrinivas Kandagatla 	if (!cell_np)
10635087cc19SAlban Bedel 		return ERR_PTR(-ENOENT);
106469aba794SSrinivas Kandagatla 
106569aba794SSrinivas Kandagatla 	nvmem_np = of_get_next_parent(cell_np);
106669aba794SSrinivas Kandagatla 	if (!nvmem_np)
106769aba794SSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
106869aba794SSrinivas Kandagatla 
10698c2a2b8cSThomas Bogendoerfer 	nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
1070aad8d097SMasahiro Yamada 	of_node_put(nvmem_np);
107169aba794SSrinivas Kandagatla 	if (IS_ERR(nvmem))
107269aba794SSrinivas Kandagatla 		return ERR_CAST(nvmem);
107369aba794SSrinivas Kandagatla 
10740749aa25SSrinivas Kandagatla 	cell = nvmem_find_cell_by_node(nvmem, cell_np);
107569aba794SSrinivas Kandagatla 	if (!cell) {
1076e888d445SBartosz Golaszewski 		__nvmem_device_put(nvmem);
1077e888d445SBartosz Golaszewski 		return ERR_PTR(-ENOENT);
107869aba794SSrinivas Kandagatla 	}
107969aba794SSrinivas Kandagatla 
108069aba794SSrinivas Kandagatla 	return cell;
108169aba794SSrinivas Kandagatla }
108269aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
108369aba794SSrinivas Kandagatla #endif
108469aba794SSrinivas Kandagatla 
108569aba794SSrinivas Kandagatla /**
108669aba794SSrinivas Kandagatla  * nvmem_cell_get() - Get nvmem cell of device form a given cell name
108769aba794SSrinivas Kandagatla  *
108829143268SVivek Gautam  * @dev: Device that requests the nvmem cell.
1089165589f0SBartosz Golaszewski  * @id: nvmem cell name to get (this corresponds with the name from the
1090165589f0SBartosz Golaszewski  *      nvmem-cell-names property for DT systems and with the con_id from
1091165589f0SBartosz Golaszewski  *      the lookup entry for non-DT systems).
109269aba794SSrinivas Kandagatla  *
109369aba794SSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer
109469aba794SSrinivas Kandagatla  * to a struct nvmem_cell.  The nvmem_cell will be freed by the
109569aba794SSrinivas Kandagatla  * nvmem_cell_put().
109669aba794SSrinivas Kandagatla  */
1097165589f0SBartosz Golaszewski struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *id)
109869aba794SSrinivas Kandagatla {
109969aba794SSrinivas Kandagatla 	struct nvmem_cell *cell;
110069aba794SSrinivas Kandagatla 
110169aba794SSrinivas Kandagatla 	if (dev->of_node) { /* try dt first */
1102165589f0SBartosz Golaszewski 		cell = of_nvmem_cell_get(dev->of_node, id);
110369aba794SSrinivas Kandagatla 		if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
110469aba794SSrinivas Kandagatla 			return cell;
110569aba794SSrinivas Kandagatla 	}
110669aba794SSrinivas Kandagatla 
1107165589f0SBartosz Golaszewski 	/* NULL cell id only allowed for device tree; invalid otherwise */
1108165589f0SBartosz Golaszewski 	if (!id)
110987ed1405SDouglas Anderson 		return ERR_PTR(-EINVAL);
111087ed1405SDouglas Anderson 
1111165589f0SBartosz Golaszewski 	return nvmem_cell_get_from_lookup(dev, id);
111269aba794SSrinivas Kandagatla }
111369aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_get);
111469aba794SSrinivas Kandagatla 
111569aba794SSrinivas Kandagatla static void devm_nvmem_cell_release(struct device *dev, void *res)
111669aba794SSrinivas Kandagatla {
111769aba794SSrinivas Kandagatla 	nvmem_cell_put(*(struct nvmem_cell **)res);
111869aba794SSrinivas Kandagatla }
111969aba794SSrinivas Kandagatla 
112069aba794SSrinivas Kandagatla /**
112169aba794SSrinivas Kandagatla  * devm_nvmem_cell_get() - Get nvmem cell of device form a given id
112269aba794SSrinivas Kandagatla  *
112329143268SVivek Gautam  * @dev: Device that requests the nvmem cell.
112429143268SVivek Gautam  * @id: nvmem cell name id to get.
112569aba794SSrinivas Kandagatla  *
112669aba794SSrinivas Kandagatla  * Return: Will be an ERR_PTR() on error or a valid pointer
112769aba794SSrinivas Kandagatla  * to a struct nvmem_cell.  The nvmem_cell will be freed by the
112869aba794SSrinivas Kandagatla  * automatically once the device is freed.
112969aba794SSrinivas Kandagatla  */
113069aba794SSrinivas Kandagatla struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id)
113169aba794SSrinivas Kandagatla {
113269aba794SSrinivas Kandagatla 	struct nvmem_cell **ptr, *cell;
113369aba794SSrinivas Kandagatla 
113469aba794SSrinivas Kandagatla 	ptr = devres_alloc(devm_nvmem_cell_release, sizeof(*ptr), GFP_KERNEL);
113569aba794SSrinivas Kandagatla 	if (!ptr)
113669aba794SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
113769aba794SSrinivas Kandagatla 
113869aba794SSrinivas Kandagatla 	cell = nvmem_cell_get(dev, id);
113969aba794SSrinivas Kandagatla 	if (!IS_ERR(cell)) {
114069aba794SSrinivas Kandagatla 		*ptr = cell;
114169aba794SSrinivas Kandagatla 		devres_add(dev, ptr);
114269aba794SSrinivas Kandagatla 	} else {
114369aba794SSrinivas Kandagatla 		devres_free(ptr);
114469aba794SSrinivas Kandagatla 	}
114569aba794SSrinivas Kandagatla 
114669aba794SSrinivas Kandagatla 	return cell;
114769aba794SSrinivas Kandagatla }
114869aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_nvmem_cell_get);
114969aba794SSrinivas Kandagatla 
115069aba794SSrinivas Kandagatla static int devm_nvmem_cell_match(struct device *dev, void *res, void *data)
115169aba794SSrinivas Kandagatla {
115269aba794SSrinivas Kandagatla 	struct nvmem_cell **c = res;
115369aba794SSrinivas Kandagatla 
115469aba794SSrinivas Kandagatla 	if (WARN_ON(!c || !*c))
115569aba794SSrinivas Kandagatla 		return 0;
115669aba794SSrinivas Kandagatla 
115769aba794SSrinivas Kandagatla 	return *c == data;
115869aba794SSrinivas Kandagatla }
115969aba794SSrinivas Kandagatla 
116069aba794SSrinivas Kandagatla /**
116169aba794SSrinivas Kandagatla  * devm_nvmem_cell_put() - Release previously allocated nvmem cell
116269aba794SSrinivas Kandagatla  * from devm_nvmem_cell_get.
116369aba794SSrinivas Kandagatla  *
116429143268SVivek Gautam  * @dev: Device that requests the nvmem cell.
116529143268SVivek Gautam  * @cell: Previously allocated nvmem cell by devm_nvmem_cell_get().
116669aba794SSrinivas Kandagatla  */
116769aba794SSrinivas Kandagatla void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell)
116869aba794SSrinivas Kandagatla {
116969aba794SSrinivas Kandagatla 	int ret;
117069aba794SSrinivas Kandagatla 
117169aba794SSrinivas Kandagatla 	ret = devres_release(dev, devm_nvmem_cell_release,
117269aba794SSrinivas Kandagatla 				devm_nvmem_cell_match, cell);
117369aba794SSrinivas Kandagatla 
117469aba794SSrinivas Kandagatla 	WARN_ON(ret);
117569aba794SSrinivas Kandagatla }
117669aba794SSrinivas Kandagatla EXPORT_SYMBOL(devm_nvmem_cell_put);
117769aba794SSrinivas Kandagatla 
117869aba794SSrinivas Kandagatla /**
117969aba794SSrinivas Kandagatla  * nvmem_cell_put() - Release previously allocated nvmem cell.
118069aba794SSrinivas Kandagatla  *
118129143268SVivek Gautam  * @cell: Previously allocated nvmem cell by nvmem_cell_get().
118269aba794SSrinivas Kandagatla  */
118369aba794SSrinivas Kandagatla void nvmem_cell_put(struct nvmem_cell *cell)
118469aba794SSrinivas Kandagatla {
118569aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
118669aba794SSrinivas Kandagatla 
118769aba794SSrinivas Kandagatla 	__nvmem_device_put(nvmem);
118869aba794SSrinivas Kandagatla }
118969aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_put);
119069aba794SSrinivas Kandagatla 
1191f7c04f16SMasahiro Yamada static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)
119269aba794SSrinivas Kandagatla {
119369aba794SSrinivas Kandagatla 	u8 *p, *b;
11942fe518feSJorge Ramirez-Ortiz 	int i, extra, bit_offset = cell->bit_offset;
119569aba794SSrinivas Kandagatla 
119669aba794SSrinivas Kandagatla 	p = b = buf;
119769aba794SSrinivas Kandagatla 	if (bit_offset) {
119869aba794SSrinivas Kandagatla 		/* First shift */
119969aba794SSrinivas Kandagatla 		*b++ >>= bit_offset;
120069aba794SSrinivas Kandagatla 
120169aba794SSrinivas Kandagatla 		/* setup rest of the bytes if any */
120269aba794SSrinivas Kandagatla 		for (i = 1; i < cell->bytes; i++) {
120369aba794SSrinivas Kandagatla 			/* Get bits from next byte and shift them towards msb */
120469aba794SSrinivas Kandagatla 			*p |= *b << (BITS_PER_BYTE - bit_offset);
120569aba794SSrinivas Kandagatla 
120669aba794SSrinivas Kandagatla 			p = b;
120769aba794SSrinivas Kandagatla 			*b++ >>= bit_offset;
120869aba794SSrinivas Kandagatla 		}
12092fe518feSJorge Ramirez-Ortiz 	} else {
12102fe518feSJorge Ramirez-Ortiz 		/* point to the msb */
12112fe518feSJorge Ramirez-Ortiz 		p += cell->bytes - 1;
12122fe518feSJorge Ramirez-Ortiz 	}
121369aba794SSrinivas Kandagatla 
121469aba794SSrinivas Kandagatla 	/* result fits in less bytes */
12152fe518feSJorge Ramirez-Ortiz 	extra = cell->bytes - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);
12162fe518feSJorge Ramirez-Ortiz 	while (--extra >= 0)
121769aba794SSrinivas Kandagatla 		*p-- = 0;
12182fe518feSJorge Ramirez-Ortiz 
121969aba794SSrinivas Kandagatla 	/* clear msb bits if any leftover in the last byte */
122069aba794SSrinivas Kandagatla 	*p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
122169aba794SSrinivas Kandagatla }
122269aba794SSrinivas Kandagatla 
122369aba794SSrinivas Kandagatla static int __nvmem_cell_read(struct nvmem_device *nvmem,
122469aba794SSrinivas Kandagatla 		      struct nvmem_cell *cell,
122569aba794SSrinivas Kandagatla 		      void *buf, size_t *len)
122669aba794SSrinivas Kandagatla {
122769aba794SSrinivas Kandagatla 	int rc;
122869aba794SSrinivas Kandagatla 
1229795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
123069aba794SSrinivas Kandagatla 
1231287980e4SArnd Bergmann 	if (rc)
123269aba794SSrinivas Kandagatla 		return rc;
123369aba794SSrinivas Kandagatla 
123469aba794SSrinivas Kandagatla 	/* shift bits in-place */
1235cbf854abSAxel Lin 	if (cell->bit_offset || cell->nbits)
123669aba794SSrinivas Kandagatla 		nvmem_shift_read_buffer_in_place(cell, buf);
123769aba794SSrinivas Kandagatla 
12383b4a6877SVivek Gautam 	if (len)
123969aba794SSrinivas Kandagatla 		*len = cell->bytes;
124069aba794SSrinivas Kandagatla 
124169aba794SSrinivas Kandagatla 	return 0;
124269aba794SSrinivas Kandagatla }
124369aba794SSrinivas Kandagatla 
124469aba794SSrinivas Kandagatla /**
124569aba794SSrinivas Kandagatla  * nvmem_cell_read() - Read a given nvmem cell
124669aba794SSrinivas Kandagatla  *
124769aba794SSrinivas Kandagatla  * @cell: nvmem cell to be read.
12483b4a6877SVivek Gautam  * @len: pointer to length of cell which will be populated on successful read;
12493b4a6877SVivek Gautam  *	 can be NULL.
125069aba794SSrinivas Kandagatla  *
1251b577fafcSBrian Norris  * Return: ERR_PTR() on error or a valid pointer to a buffer on success. The
1252b577fafcSBrian Norris  * buffer should be freed by the consumer with a kfree().
125369aba794SSrinivas Kandagatla  */
125469aba794SSrinivas Kandagatla void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
125569aba794SSrinivas Kandagatla {
125669aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
125769aba794SSrinivas Kandagatla 	u8 *buf;
125869aba794SSrinivas Kandagatla 	int rc;
125969aba794SSrinivas Kandagatla 
1260795ddd18SSrinivas Kandagatla 	if (!nvmem)
126169aba794SSrinivas Kandagatla 		return ERR_PTR(-EINVAL);
126269aba794SSrinivas Kandagatla 
126369aba794SSrinivas Kandagatla 	buf = kzalloc(cell->bytes, GFP_KERNEL);
126469aba794SSrinivas Kandagatla 	if (!buf)
126569aba794SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
126669aba794SSrinivas Kandagatla 
126769aba794SSrinivas Kandagatla 	rc = __nvmem_cell_read(nvmem, cell, buf, len);
1268287980e4SArnd Bergmann 	if (rc) {
126969aba794SSrinivas Kandagatla 		kfree(buf);
127069aba794SSrinivas Kandagatla 		return ERR_PTR(rc);
127169aba794SSrinivas Kandagatla 	}
127269aba794SSrinivas Kandagatla 
127369aba794SSrinivas Kandagatla 	return buf;
127469aba794SSrinivas Kandagatla }
127569aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_read);
127669aba794SSrinivas Kandagatla 
1277f7c04f16SMasahiro Yamada static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
127869aba794SSrinivas Kandagatla 					     u8 *_buf, int len)
127969aba794SSrinivas Kandagatla {
128069aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
128169aba794SSrinivas Kandagatla 	int i, rc, nbits, bit_offset = cell->bit_offset;
128269aba794SSrinivas Kandagatla 	u8 v, *p, *buf, *b, pbyte, pbits;
128369aba794SSrinivas Kandagatla 
128469aba794SSrinivas Kandagatla 	nbits = cell->nbits;
128569aba794SSrinivas Kandagatla 	buf = kzalloc(cell->bytes, GFP_KERNEL);
128669aba794SSrinivas Kandagatla 	if (!buf)
128769aba794SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
128869aba794SSrinivas Kandagatla 
128969aba794SSrinivas Kandagatla 	memcpy(buf, _buf, len);
129069aba794SSrinivas Kandagatla 	p = b = buf;
129169aba794SSrinivas Kandagatla 
129269aba794SSrinivas Kandagatla 	if (bit_offset) {
129369aba794SSrinivas Kandagatla 		pbyte = *b;
129469aba794SSrinivas Kandagatla 		*b <<= bit_offset;
129569aba794SSrinivas Kandagatla 
129669aba794SSrinivas Kandagatla 		/* setup the first byte with lsb bits from nvmem */
1297795ddd18SSrinivas Kandagatla 		rc = nvmem_reg_read(nvmem, cell->offset, &v, 1);
129850808bfcSMathieu Malaterre 		if (rc)
129950808bfcSMathieu Malaterre 			goto err;
130069aba794SSrinivas Kandagatla 		*b++ |= GENMASK(bit_offset - 1, 0) & v;
130169aba794SSrinivas Kandagatla 
130269aba794SSrinivas Kandagatla 		/* setup rest of the byte if any */
130369aba794SSrinivas Kandagatla 		for (i = 1; i < cell->bytes; i++) {
130469aba794SSrinivas Kandagatla 			/* Get last byte bits and shift them towards lsb */
130569aba794SSrinivas Kandagatla 			pbits = pbyte >> (BITS_PER_BYTE - 1 - bit_offset);
130669aba794SSrinivas Kandagatla 			pbyte = *b;
130769aba794SSrinivas Kandagatla 			p = b;
130869aba794SSrinivas Kandagatla 			*b <<= bit_offset;
130969aba794SSrinivas Kandagatla 			*b++ |= pbits;
131069aba794SSrinivas Kandagatla 		}
131169aba794SSrinivas Kandagatla 	}
131269aba794SSrinivas Kandagatla 
131369aba794SSrinivas Kandagatla 	/* if it's not end on byte boundary */
131469aba794SSrinivas Kandagatla 	if ((nbits + bit_offset) % BITS_PER_BYTE) {
131569aba794SSrinivas Kandagatla 		/* setup the last byte with msb bits from nvmem */
1316795ddd18SSrinivas Kandagatla 		rc = nvmem_reg_read(nvmem,
131769aba794SSrinivas Kandagatla 				    cell->offset + cell->bytes - 1, &v, 1);
131850808bfcSMathieu Malaterre 		if (rc)
131950808bfcSMathieu Malaterre 			goto err;
132069aba794SSrinivas Kandagatla 		*p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
132169aba794SSrinivas Kandagatla 
132269aba794SSrinivas Kandagatla 	}
132369aba794SSrinivas Kandagatla 
132469aba794SSrinivas Kandagatla 	return buf;
132550808bfcSMathieu Malaterre err:
132650808bfcSMathieu Malaterre 	kfree(buf);
132750808bfcSMathieu Malaterre 	return ERR_PTR(rc);
132869aba794SSrinivas Kandagatla }
132969aba794SSrinivas Kandagatla 
133069aba794SSrinivas Kandagatla /**
133169aba794SSrinivas Kandagatla  * nvmem_cell_write() - Write to a given nvmem cell
133269aba794SSrinivas Kandagatla  *
133369aba794SSrinivas Kandagatla  * @cell: nvmem cell to be written.
133469aba794SSrinivas Kandagatla  * @buf: Buffer to be written.
133569aba794SSrinivas Kandagatla  * @len: length of buffer to be written to nvmem cell.
133669aba794SSrinivas Kandagatla  *
133769aba794SSrinivas Kandagatla  * Return: length of bytes written or negative on failure.
133869aba794SSrinivas Kandagatla  */
133969aba794SSrinivas Kandagatla int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
134069aba794SSrinivas Kandagatla {
134169aba794SSrinivas Kandagatla 	struct nvmem_device *nvmem = cell->nvmem;
134269aba794SSrinivas Kandagatla 	int rc;
134369aba794SSrinivas Kandagatla 
1344795ddd18SSrinivas Kandagatla 	if (!nvmem || nvmem->read_only ||
134569aba794SSrinivas Kandagatla 	    (cell->bit_offset == 0 && len != cell->bytes))
134669aba794SSrinivas Kandagatla 		return -EINVAL;
134769aba794SSrinivas Kandagatla 
134869aba794SSrinivas Kandagatla 	if (cell->bit_offset || cell->nbits) {
134969aba794SSrinivas Kandagatla 		buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
135069aba794SSrinivas Kandagatla 		if (IS_ERR(buf))
135169aba794SSrinivas Kandagatla 			return PTR_ERR(buf);
135269aba794SSrinivas Kandagatla 	}
135369aba794SSrinivas Kandagatla 
1354795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_write(nvmem, cell->offset, buf, cell->bytes);
135569aba794SSrinivas Kandagatla 
135669aba794SSrinivas Kandagatla 	/* free the tmp buffer */
1357ace22170SAxel Lin 	if (cell->bit_offset || cell->nbits)
135869aba794SSrinivas Kandagatla 		kfree(buf);
135969aba794SSrinivas Kandagatla 
1360287980e4SArnd Bergmann 	if (rc)
136169aba794SSrinivas Kandagatla 		return rc;
136269aba794SSrinivas Kandagatla 
136369aba794SSrinivas Kandagatla 	return len;
136469aba794SSrinivas Kandagatla }
136569aba794SSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_cell_write);
136669aba794SSrinivas Kandagatla 
13676bb317ceSYangtao Li static int nvmem_cell_read_common(struct device *dev, const char *cell_id,
13686bb317ceSYangtao Li 				  void *val, size_t count)
13690a9b2d1cSFabrice Gasnier {
13700a9b2d1cSFabrice Gasnier 	struct nvmem_cell *cell;
13710a9b2d1cSFabrice Gasnier 	void *buf;
13720a9b2d1cSFabrice Gasnier 	size_t len;
13730a9b2d1cSFabrice Gasnier 
13740a9b2d1cSFabrice Gasnier 	cell = nvmem_cell_get(dev, cell_id);
13750a9b2d1cSFabrice Gasnier 	if (IS_ERR(cell))
13760a9b2d1cSFabrice Gasnier 		return PTR_ERR(cell);
13770a9b2d1cSFabrice Gasnier 
13780a9b2d1cSFabrice Gasnier 	buf = nvmem_cell_read(cell, &len);
13790a9b2d1cSFabrice Gasnier 	if (IS_ERR(buf)) {
13800a9b2d1cSFabrice Gasnier 		nvmem_cell_put(cell);
13810a9b2d1cSFabrice Gasnier 		return PTR_ERR(buf);
13820a9b2d1cSFabrice Gasnier 	}
13836bb317ceSYangtao Li 	if (len != count) {
13840a9b2d1cSFabrice Gasnier 		kfree(buf);
13850a9b2d1cSFabrice Gasnier 		nvmem_cell_put(cell);
13860a9b2d1cSFabrice Gasnier 		return -EINVAL;
13870a9b2d1cSFabrice Gasnier 	}
13886bb317ceSYangtao Li 	memcpy(val, buf, count);
13890a9b2d1cSFabrice Gasnier 	kfree(buf);
13900a9b2d1cSFabrice Gasnier 	nvmem_cell_put(cell);
13910a9b2d1cSFabrice Gasnier 
13920a9b2d1cSFabrice Gasnier 	return 0;
13930a9b2d1cSFabrice Gasnier }
13946bb317ceSYangtao Li 
13956bb317ceSYangtao Li /**
13966bb317ceSYangtao Li  * nvmem_cell_read_u16() - Read a cell value as an u16
13976bb317ceSYangtao Li  *
13986bb317ceSYangtao Li  * @dev: Device that requests the nvmem cell.
13996bb317ceSYangtao Li  * @cell_id: Name of nvmem cell to read.
14006bb317ceSYangtao Li  * @val: pointer to output value.
14016bb317ceSYangtao Li  *
14026bb317ceSYangtao Li  * Return: 0 on success or negative errno.
14036bb317ceSYangtao Li  */
14046bb317ceSYangtao Li int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val)
14056bb317ceSYangtao Li {
14066bb317ceSYangtao Li 	return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
14076bb317ceSYangtao Li }
14080a9b2d1cSFabrice Gasnier EXPORT_SYMBOL_GPL(nvmem_cell_read_u16);
14090a9b2d1cSFabrice Gasnier 
14100a9b2d1cSFabrice Gasnier /**
1411d026d70aSLeonard Crestez  * nvmem_cell_read_u32() - Read a cell value as an u32
1412d026d70aSLeonard Crestez  *
1413d026d70aSLeonard Crestez  * @dev: Device that requests the nvmem cell.
1414d026d70aSLeonard Crestez  * @cell_id: Name of nvmem cell to read.
1415d026d70aSLeonard Crestez  * @val: pointer to output value.
1416d026d70aSLeonard Crestez  *
1417d026d70aSLeonard Crestez  * Return: 0 on success or negative errno.
1418d026d70aSLeonard Crestez  */
1419d026d70aSLeonard Crestez int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val)
1420d026d70aSLeonard Crestez {
14216bb317ceSYangtao Li 	return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
1422d026d70aSLeonard Crestez }
1423d026d70aSLeonard Crestez EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
1424d026d70aSLeonard Crestez 
1425d026d70aSLeonard Crestez /**
14268b977c54SYangtao Li  * nvmem_cell_read_u64() - Read a cell value as an u64
14278b977c54SYangtao Li  *
14288b977c54SYangtao Li  * @dev: Device that requests the nvmem cell.
14298b977c54SYangtao Li  * @cell_id: Name of nvmem cell to read.
14308b977c54SYangtao Li  * @val: pointer to output value.
14318b977c54SYangtao Li  *
14328b977c54SYangtao Li  * Return: 0 on success or negative errno.
14338b977c54SYangtao Li  */
14348b977c54SYangtao Li int nvmem_cell_read_u64(struct device *dev, const char *cell_id, u64 *val)
14358b977c54SYangtao Li {
14368b977c54SYangtao Li 	return nvmem_cell_read_common(dev, cell_id, val, sizeof(*val));
14378b977c54SYangtao Li }
14388b977c54SYangtao Li EXPORT_SYMBOL_GPL(nvmem_cell_read_u64);
14398b977c54SYangtao Li 
14408b977c54SYangtao Li /**
1441e2a5402eSSrinivas Kandagatla  * nvmem_device_cell_read() - Read a given nvmem device and cell
1442e2a5402eSSrinivas Kandagatla  *
1443e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to read from.
1444e2a5402eSSrinivas Kandagatla  * @info: nvmem cell info to be read.
1445e2a5402eSSrinivas Kandagatla  * @buf: buffer pointer which will be populated on successful read.
1446e2a5402eSSrinivas Kandagatla  *
1447e2a5402eSSrinivas Kandagatla  * Return: length of successful bytes read on success and negative
1448e2a5402eSSrinivas Kandagatla  * error code on error.
1449e2a5402eSSrinivas Kandagatla  */
1450e2a5402eSSrinivas Kandagatla ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
1451e2a5402eSSrinivas Kandagatla 			   struct nvmem_cell_info *info, void *buf)
1452e2a5402eSSrinivas Kandagatla {
1453e2a5402eSSrinivas Kandagatla 	struct nvmem_cell cell;
1454e2a5402eSSrinivas Kandagatla 	int rc;
1455e2a5402eSSrinivas Kandagatla 	ssize_t len;
1456e2a5402eSSrinivas Kandagatla 
1457795ddd18SSrinivas Kandagatla 	if (!nvmem)
1458e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1459e2a5402eSSrinivas Kandagatla 
1460e2a5402eSSrinivas Kandagatla 	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
1461287980e4SArnd Bergmann 	if (rc)
1462e2a5402eSSrinivas Kandagatla 		return rc;
1463e2a5402eSSrinivas Kandagatla 
1464e2a5402eSSrinivas Kandagatla 	rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
1465287980e4SArnd Bergmann 	if (rc)
1466e2a5402eSSrinivas Kandagatla 		return rc;
1467e2a5402eSSrinivas Kandagatla 
1468e2a5402eSSrinivas Kandagatla 	return len;
1469e2a5402eSSrinivas Kandagatla }
1470e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
1471e2a5402eSSrinivas Kandagatla 
1472e2a5402eSSrinivas Kandagatla /**
1473e2a5402eSSrinivas Kandagatla  * nvmem_device_cell_write() - Write cell to a given nvmem device
1474e2a5402eSSrinivas Kandagatla  *
1475e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to be written to.
147629143268SVivek Gautam  * @info: nvmem cell info to be written.
1477e2a5402eSSrinivas Kandagatla  * @buf: buffer to be written to cell.
1478e2a5402eSSrinivas Kandagatla  *
1479e2a5402eSSrinivas Kandagatla  * Return: length of bytes written or negative error code on failure.
148048f63a2cSBartosz Golaszewski  */
1481e2a5402eSSrinivas Kandagatla int nvmem_device_cell_write(struct nvmem_device *nvmem,
1482e2a5402eSSrinivas Kandagatla 			    struct nvmem_cell_info *info, void *buf)
1483e2a5402eSSrinivas Kandagatla {
1484e2a5402eSSrinivas Kandagatla 	struct nvmem_cell cell;
1485e2a5402eSSrinivas Kandagatla 	int rc;
1486e2a5402eSSrinivas Kandagatla 
1487795ddd18SSrinivas Kandagatla 	if (!nvmem)
1488e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1489e2a5402eSSrinivas Kandagatla 
1490e2a5402eSSrinivas Kandagatla 	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
1491287980e4SArnd Bergmann 	if (rc)
1492e2a5402eSSrinivas Kandagatla 		return rc;
1493e2a5402eSSrinivas Kandagatla 
1494e2a5402eSSrinivas Kandagatla 	return nvmem_cell_write(&cell, buf, cell.bytes);
1495e2a5402eSSrinivas Kandagatla }
1496e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
1497e2a5402eSSrinivas Kandagatla 
1498e2a5402eSSrinivas Kandagatla /**
1499e2a5402eSSrinivas Kandagatla  * nvmem_device_read() - Read from a given nvmem device
1500e2a5402eSSrinivas Kandagatla  *
1501e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to read from.
1502e2a5402eSSrinivas Kandagatla  * @offset: offset in nvmem device.
1503e2a5402eSSrinivas Kandagatla  * @bytes: number of bytes to read.
1504e2a5402eSSrinivas Kandagatla  * @buf: buffer pointer which will be populated on successful read.
1505e2a5402eSSrinivas Kandagatla  *
1506e2a5402eSSrinivas Kandagatla  * Return: length of successful bytes read on success and negative
1507e2a5402eSSrinivas Kandagatla  * error code on error.
1508e2a5402eSSrinivas Kandagatla  */
1509e2a5402eSSrinivas Kandagatla int nvmem_device_read(struct nvmem_device *nvmem,
1510e2a5402eSSrinivas Kandagatla 		      unsigned int offset,
1511e2a5402eSSrinivas Kandagatla 		      size_t bytes, void *buf)
1512e2a5402eSSrinivas Kandagatla {
1513e2a5402eSSrinivas Kandagatla 	int rc;
1514e2a5402eSSrinivas Kandagatla 
1515795ddd18SSrinivas Kandagatla 	if (!nvmem)
1516e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1517e2a5402eSSrinivas Kandagatla 
1518795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_read(nvmem, offset, buf, bytes);
1519e2a5402eSSrinivas Kandagatla 
1520287980e4SArnd Bergmann 	if (rc)
1521e2a5402eSSrinivas Kandagatla 		return rc;
1522e2a5402eSSrinivas Kandagatla 
1523e2a5402eSSrinivas Kandagatla 	return bytes;
1524e2a5402eSSrinivas Kandagatla }
1525e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_read);
1526e2a5402eSSrinivas Kandagatla 
1527e2a5402eSSrinivas Kandagatla /**
1528e2a5402eSSrinivas Kandagatla  * nvmem_device_write() - Write cell to a given nvmem device
1529e2a5402eSSrinivas Kandagatla  *
1530e2a5402eSSrinivas Kandagatla  * @nvmem: nvmem device to be written to.
1531e2a5402eSSrinivas Kandagatla  * @offset: offset in nvmem device.
1532e2a5402eSSrinivas Kandagatla  * @bytes: number of bytes to write.
1533e2a5402eSSrinivas Kandagatla  * @buf: buffer to be written.
1534e2a5402eSSrinivas Kandagatla  *
1535e2a5402eSSrinivas Kandagatla  * Return: length of bytes written or negative error code on failure.
153648f63a2cSBartosz Golaszewski  */
1537e2a5402eSSrinivas Kandagatla int nvmem_device_write(struct nvmem_device *nvmem,
1538e2a5402eSSrinivas Kandagatla 		       unsigned int offset,
1539e2a5402eSSrinivas Kandagatla 		       size_t bytes, void *buf)
1540e2a5402eSSrinivas Kandagatla {
1541e2a5402eSSrinivas Kandagatla 	int rc;
1542e2a5402eSSrinivas Kandagatla 
1543795ddd18SSrinivas Kandagatla 	if (!nvmem)
1544e2a5402eSSrinivas Kandagatla 		return -EINVAL;
1545e2a5402eSSrinivas Kandagatla 
1546795ddd18SSrinivas Kandagatla 	rc = nvmem_reg_write(nvmem, offset, buf, bytes);
1547e2a5402eSSrinivas Kandagatla 
1548287980e4SArnd Bergmann 	if (rc)
1549e2a5402eSSrinivas Kandagatla 		return rc;
1550e2a5402eSSrinivas Kandagatla 
1551e2a5402eSSrinivas Kandagatla 
1552e2a5402eSSrinivas Kandagatla 	return bytes;
1553e2a5402eSSrinivas Kandagatla }
1554e2a5402eSSrinivas Kandagatla EXPORT_SYMBOL_GPL(nvmem_device_write);
1555e2a5402eSSrinivas Kandagatla 
1556d7b9fd16SBartosz Golaszewski /**
1557b985f4cbSBartosz Golaszewski  * nvmem_add_cell_table() - register a table of cell info entries
1558b985f4cbSBartosz Golaszewski  *
1559b985f4cbSBartosz Golaszewski  * @table: table of cell info entries
1560b985f4cbSBartosz Golaszewski  */
1561b985f4cbSBartosz Golaszewski void nvmem_add_cell_table(struct nvmem_cell_table *table)
1562b985f4cbSBartosz Golaszewski {
1563b985f4cbSBartosz Golaszewski 	mutex_lock(&nvmem_cell_mutex);
1564b985f4cbSBartosz Golaszewski 	list_add_tail(&table->node, &nvmem_cell_tables);
1565b985f4cbSBartosz Golaszewski 	mutex_unlock(&nvmem_cell_mutex);
1566b985f4cbSBartosz Golaszewski }
1567b985f4cbSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_add_cell_table);
1568b985f4cbSBartosz Golaszewski 
1569b985f4cbSBartosz Golaszewski /**
1570b985f4cbSBartosz Golaszewski  * nvmem_del_cell_table() - remove a previously registered cell info table
1571b985f4cbSBartosz Golaszewski  *
1572b985f4cbSBartosz Golaszewski  * @table: table of cell info entries
1573b985f4cbSBartosz Golaszewski  */
1574b985f4cbSBartosz Golaszewski void nvmem_del_cell_table(struct nvmem_cell_table *table)
1575b985f4cbSBartosz Golaszewski {
1576b985f4cbSBartosz Golaszewski 	mutex_lock(&nvmem_cell_mutex);
1577b985f4cbSBartosz Golaszewski 	list_del(&table->node);
1578b985f4cbSBartosz Golaszewski 	mutex_unlock(&nvmem_cell_mutex);
1579b985f4cbSBartosz Golaszewski }
1580b985f4cbSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_del_cell_table);
1581b985f4cbSBartosz Golaszewski 
1582b985f4cbSBartosz Golaszewski /**
1583506157beSBartosz Golaszewski  * nvmem_add_cell_lookups() - register a list of cell lookup entries
1584506157beSBartosz Golaszewski  *
1585506157beSBartosz Golaszewski  * @entries: array of cell lookup entries
1586506157beSBartosz Golaszewski  * @nentries: number of cell lookup entries in the array
1587506157beSBartosz Golaszewski  */
1588506157beSBartosz Golaszewski void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
1589506157beSBartosz Golaszewski {
1590506157beSBartosz Golaszewski 	int i;
1591506157beSBartosz Golaszewski 
1592506157beSBartosz Golaszewski 	mutex_lock(&nvmem_lookup_mutex);
1593506157beSBartosz Golaszewski 	for (i = 0; i < nentries; i++)
1594506157beSBartosz Golaszewski 		list_add_tail(&entries[i].node, &nvmem_lookup_list);
1595506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_lookup_mutex);
1596506157beSBartosz Golaszewski }
1597506157beSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_add_cell_lookups);
1598506157beSBartosz Golaszewski 
1599506157beSBartosz Golaszewski /**
1600506157beSBartosz Golaszewski  * nvmem_del_cell_lookups() - remove a list of previously added cell lookup
1601506157beSBartosz Golaszewski  *                            entries
1602506157beSBartosz Golaszewski  *
1603506157beSBartosz Golaszewski  * @entries: array of cell lookup entries
1604506157beSBartosz Golaszewski  * @nentries: number of cell lookup entries in the array
1605506157beSBartosz Golaszewski  */
1606506157beSBartosz Golaszewski void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
1607506157beSBartosz Golaszewski {
1608506157beSBartosz Golaszewski 	int i;
1609506157beSBartosz Golaszewski 
1610506157beSBartosz Golaszewski 	mutex_lock(&nvmem_lookup_mutex);
1611506157beSBartosz Golaszewski 	for (i = 0; i < nentries; i++)
1612506157beSBartosz Golaszewski 		list_del(&entries[i].node);
1613506157beSBartosz Golaszewski 	mutex_unlock(&nvmem_lookup_mutex);
1614506157beSBartosz Golaszewski }
1615506157beSBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_del_cell_lookups);
1616506157beSBartosz Golaszewski 
1617506157beSBartosz Golaszewski /**
1618d7b9fd16SBartosz Golaszewski  * nvmem_dev_name() - Get the name of a given nvmem device.
1619d7b9fd16SBartosz Golaszewski  *
1620d7b9fd16SBartosz Golaszewski  * @nvmem: nvmem device.
1621d7b9fd16SBartosz Golaszewski  *
1622d7b9fd16SBartosz Golaszewski  * Return: name of the nvmem device.
1623d7b9fd16SBartosz Golaszewski  */
1624d7b9fd16SBartosz Golaszewski const char *nvmem_dev_name(struct nvmem_device *nvmem)
1625d7b9fd16SBartosz Golaszewski {
1626d7b9fd16SBartosz Golaszewski 	return dev_name(&nvmem->dev);
1627d7b9fd16SBartosz Golaszewski }
1628d7b9fd16SBartosz Golaszewski EXPORT_SYMBOL_GPL(nvmem_dev_name);
1629d7b9fd16SBartosz Golaszewski 
1630eace75cfSSrinivas Kandagatla static int __init nvmem_init(void)
1631eace75cfSSrinivas Kandagatla {
1632eace75cfSSrinivas Kandagatla 	return bus_register(&nvmem_bus_type);
1633eace75cfSSrinivas Kandagatla }
1634eace75cfSSrinivas Kandagatla 
1635eace75cfSSrinivas Kandagatla static void __exit nvmem_exit(void)
1636eace75cfSSrinivas Kandagatla {
1637eace75cfSSrinivas Kandagatla 	bus_unregister(&nvmem_bus_type);
1638eace75cfSSrinivas Kandagatla }
1639eace75cfSSrinivas Kandagatla 
1640eace75cfSSrinivas Kandagatla subsys_initcall(nvmem_init);
1641eace75cfSSrinivas Kandagatla module_exit(nvmem_exit);
1642eace75cfSSrinivas Kandagatla 
1643eace75cfSSrinivas Kandagatla MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
1644eace75cfSSrinivas Kandagatla MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
1645eace75cfSSrinivas Kandagatla MODULE_DESCRIPTION("nvmem Driver Core");
1646eace75cfSSrinivas Kandagatla MODULE_LICENSE("GPL v2");
1647