xref: /linux-6.15/drivers/base/regmap/regmap.c (revision 052d2cd1)
1b83a313bSMark Brown /*
2b83a313bSMark Brown  * Register map access API
3b83a313bSMark Brown  *
4b83a313bSMark Brown  * Copyright 2011 Wolfson Microelectronics plc
5b83a313bSMark Brown  *
6b83a313bSMark Brown  * Author: Mark Brown <[email protected]>
7b83a313bSMark Brown  *
8b83a313bSMark Brown  * This program is free software; you can redistribute it and/or modify
9b83a313bSMark Brown  * it under the terms of the GNU General Public License version 2 as
10b83a313bSMark Brown  * published by the Free Software Foundation.
11b83a313bSMark Brown  */
12b83a313bSMark Brown 
13b83a313bSMark Brown #include <linux/slab.h>
14b83a313bSMark Brown #include <linux/module.h>
15b83a313bSMark Brown #include <linux/mutex.h>
16b83a313bSMark Brown #include <linux/err.h>
17b83a313bSMark Brown 
18fb2736bbSMark Brown #define CREATE_TRACE_POINTS
19fb2736bbSMark Brown #include <trace/events/regmap.h>
20fb2736bbSMark Brown 
2193de9124SMark Brown #include "internal.h"
22b83a313bSMark Brown 
238de2f081SMark Brown bool regmap_writeable(struct regmap *map, unsigned int reg)
248de2f081SMark Brown {
258de2f081SMark Brown 	if (map->max_register && reg > map->max_register)
268de2f081SMark Brown 		return false;
278de2f081SMark Brown 
288de2f081SMark Brown 	if (map->writeable_reg)
298de2f081SMark Brown 		return map->writeable_reg(map->dev, reg);
308de2f081SMark Brown 
318de2f081SMark Brown 	return true;
328de2f081SMark Brown }
338de2f081SMark Brown 
348de2f081SMark Brown bool regmap_readable(struct regmap *map, unsigned int reg)
358de2f081SMark Brown {
368de2f081SMark Brown 	if (map->max_register && reg > map->max_register)
378de2f081SMark Brown 		return false;
388de2f081SMark Brown 
398de2f081SMark Brown 	if (map->readable_reg)
408de2f081SMark Brown 		return map->readable_reg(map->dev, reg);
418de2f081SMark Brown 
428de2f081SMark Brown 	return true;
438de2f081SMark Brown }
448de2f081SMark Brown 
458de2f081SMark Brown bool regmap_volatile(struct regmap *map, unsigned int reg)
468de2f081SMark Brown {
478de2f081SMark Brown 	if (map->max_register && reg > map->max_register)
488de2f081SMark Brown 		return false;
498de2f081SMark Brown 
508de2f081SMark Brown 	if (map->volatile_reg)
518de2f081SMark Brown 		return map->volatile_reg(map->dev, reg);
528de2f081SMark Brown 
538de2f081SMark Brown 	return true;
548de2f081SMark Brown }
558de2f081SMark Brown 
568de2f081SMark Brown bool regmap_precious(struct regmap *map, unsigned int reg)
578de2f081SMark Brown {
588de2f081SMark Brown 	if (map->max_register && reg > map->max_register)
598de2f081SMark Brown 		return false;
608de2f081SMark Brown 
618de2f081SMark Brown 	if (map->precious_reg)
628de2f081SMark Brown 		return map->precious_reg(map->dev, reg);
638de2f081SMark Brown 
648de2f081SMark Brown 	return false;
658de2f081SMark Brown }
668de2f081SMark Brown 
6782cd9965SLars-Peter Clausen static bool regmap_volatile_range(struct regmap *map, unsigned int reg,
6882cd9965SLars-Peter Clausen 	unsigned int num)
6982cd9965SLars-Peter Clausen {
7082cd9965SLars-Peter Clausen 	unsigned int i;
7182cd9965SLars-Peter Clausen 
7282cd9965SLars-Peter Clausen 	for (i = 0; i < num; i++)
7382cd9965SLars-Peter Clausen 		if (!regmap_volatile(map, reg + i))
7482cd9965SLars-Peter Clausen 			return false;
7582cd9965SLars-Peter Clausen 
7682cd9965SLars-Peter Clausen 	return true;
7782cd9965SLars-Peter Clausen }
7882cd9965SLars-Peter Clausen 
79b83a313bSMark Brown static void regmap_format_4_12_write(struct regmap *map,
80b83a313bSMark Brown 				     unsigned int reg, unsigned int val)
81b83a313bSMark Brown {
82b83a313bSMark Brown 	__be16 *out = map->work_buf;
83b83a313bSMark Brown 	*out = cpu_to_be16((reg << 12) | val);
84b83a313bSMark Brown }
85b83a313bSMark Brown 
86b83a313bSMark Brown static void regmap_format_7_9_write(struct regmap *map,
87b83a313bSMark Brown 				    unsigned int reg, unsigned int val)
88b83a313bSMark Brown {
89b83a313bSMark Brown 	__be16 *out = map->work_buf;
90b83a313bSMark Brown 	*out = cpu_to_be16((reg << 9) | val);
91b83a313bSMark Brown }
92b83a313bSMark Brown 
937e5ec63eSLars-Peter Clausen static void regmap_format_10_14_write(struct regmap *map,
947e5ec63eSLars-Peter Clausen 				    unsigned int reg, unsigned int val)
957e5ec63eSLars-Peter Clausen {
967e5ec63eSLars-Peter Clausen 	u8 *out = map->work_buf;
977e5ec63eSLars-Peter Clausen 
987e5ec63eSLars-Peter Clausen 	out[2] = val;
997e5ec63eSLars-Peter Clausen 	out[1] = (val >> 8) | (reg << 6);
1007e5ec63eSLars-Peter Clausen 	out[0] = reg >> 2;
1017e5ec63eSLars-Peter Clausen }
1027e5ec63eSLars-Peter Clausen 
103b83a313bSMark Brown static void regmap_format_8(void *buf, unsigned int val)
104b83a313bSMark Brown {
105b83a313bSMark Brown 	u8 *b = buf;
106b83a313bSMark Brown 
107b83a313bSMark Brown 	b[0] = val;
108b83a313bSMark Brown }
109b83a313bSMark Brown 
110b83a313bSMark Brown static void regmap_format_16(void *buf, unsigned int val)
111b83a313bSMark Brown {
112b83a313bSMark Brown 	__be16 *b = buf;
113b83a313bSMark Brown 
114b83a313bSMark Brown 	b[0] = cpu_to_be16(val);
115b83a313bSMark Brown }
116b83a313bSMark Brown 
117b83a313bSMark Brown static unsigned int regmap_parse_8(void *buf)
118b83a313bSMark Brown {
119b83a313bSMark Brown 	u8 *b = buf;
120b83a313bSMark Brown 
121b83a313bSMark Brown 	return b[0];
122b83a313bSMark Brown }
123b83a313bSMark Brown 
124b83a313bSMark Brown static unsigned int regmap_parse_16(void *buf)
125b83a313bSMark Brown {
126b83a313bSMark Brown 	__be16 *b = buf;
127b83a313bSMark Brown 
128b83a313bSMark Brown 	b[0] = be16_to_cpu(b[0]);
129b83a313bSMark Brown 
130b83a313bSMark Brown 	return b[0];
131b83a313bSMark Brown }
132b83a313bSMark Brown 
133b83a313bSMark Brown /**
134b83a313bSMark Brown  * regmap_init(): Initialise register map
135b83a313bSMark Brown  *
136b83a313bSMark Brown  * @dev: Device that will be interacted with
137b83a313bSMark Brown  * @bus: Bus-specific callbacks to use with device
138b83a313bSMark Brown  * @config: Configuration for register map
139b83a313bSMark Brown  *
140b83a313bSMark Brown  * The return value will be an ERR_PTR() on error or a valid pointer to
141b83a313bSMark Brown  * a struct regmap.  This function should generally not be called
142b83a313bSMark Brown  * directly, it should be called by bus-specific init functions.
143b83a313bSMark Brown  */
144b83a313bSMark Brown struct regmap *regmap_init(struct device *dev,
145b83a313bSMark Brown 			   const struct regmap_bus *bus,
146b83a313bSMark Brown 			   const struct regmap_config *config)
147b83a313bSMark Brown {
148b83a313bSMark Brown 	struct regmap *map;
149b83a313bSMark Brown 	int ret = -EINVAL;
150b83a313bSMark Brown 
151b83a313bSMark Brown 	if (!bus || !config)
152abbb18fbSLars-Peter Clausen 		goto err;
153b83a313bSMark Brown 
154b83a313bSMark Brown 	map = kzalloc(sizeof(*map), GFP_KERNEL);
155b83a313bSMark Brown 	if (map == NULL) {
156b83a313bSMark Brown 		ret = -ENOMEM;
157b83a313bSMark Brown 		goto err;
158b83a313bSMark Brown 	}
159b83a313bSMark Brown 
160b83a313bSMark Brown 	mutex_init(&map->lock);
161b83a313bSMark Brown 	map->format.buf_size = (config->reg_bits + config->val_bits) / 8;
162b83a313bSMark Brown 	map->format.reg_bytes = config->reg_bits / 8;
163b83a313bSMark Brown 	map->format.val_bytes = config->val_bits / 8;
164b83a313bSMark Brown 	map->dev = dev;
165b83a313bSMark Brown 	map->bus = bus;
1662e2ae66dSMark Brown 	map->max_register = config->max_register;
1672e2ae66dSMark Brown 	map->writeable_reg = config->writeable_reg;
1682e2ae66dSMark Brown 	map->readable_reg = config->readable_reg;
1692e2ae66dSMark Brown 	map->volatile_reg = config->volatile_reg;
1702efe1642SMark Brown 	map->precious_reg = config->precious_reg;
1715d1729e7SDimitris Papastamos 	map->cache_type = config->cache_type;
172b83a313bSMark Brown 
1736f306441SLars-Peter Clausen 	if (config->read_flag_mask || config->write_flag_mask) {
1746f306441SLars-Peter Clausen 		map->read_flag_mask = config->read_flag_mask;
1756f306441SLars-Peter Clausen 		map->write_flag_mask = config->write_flag_mask;
1766f306441SLars-Peter Clausen 	} else {
1776f306441SLars-Peter Clausen 		map->read_flag_mask = bus->read_flag_mask;
1786f306441SLars-Peter Clausen 	}
1796f306441SLars-Peter Clausen 
180b83a313bSMark Brown 	switch (config->reg_bits) {
181b83a313bSMark Brown 	case 4:
182b83a313bSMark Brown 		switch (config->val_bits) {
183b83a313bSMark Brown 		case 12:
184b83a313bSMark Brown 			map->format.format_write = regmap_format_4_12_write;
185b83a313bSMark Brown 			break;
186b83a313bSMark Brown 		default:
187b83a313bSMark Brown 			goto err_map;
188b83a313bSMark Brown 		}
189b83a313bSMark Brown 		break;
190b83a313bSMark Brown 
191b83a313bSMark Brown 	case 7:
192b83a313bSMark Brown 		switch (config->val_bits) {
193b83a313bSMark Brown 		case 9:
194b83a313bSMark Brown 			map->format.format_write = regmap_format_7_9_write;
195b83a313bSMark Brown 			break;
196b83a313bSMark Brown 		default:
197b83a313bSMark Brown 			goto err_map;
198b83a313bSMark Brown 		}
199b83a313bSMark Brown 		break;
200b83a313bSMark Brown 
2017e5ec63eSLars-Peter Clausen 	case 10:
2027e5ec63eSLars-Peter Clausen 		switch (config->val_bits) {
2037e5ec63eSLars-Peter Clausen 		case 14:
2047e5ec63eSLars-Peter Clausen 			map->format.format_write = regmap_format_10_14_write;
2057e5ec63eSLars-Peter Clausen 			break;
2067e5ec63eSLars-Peter Clausen 		default:
2077e5ec63eSLars-Peter Clausen 			goto err_map;
2087e5ec63eSLars-Peter Clausen 		}
2097e5ec63eSLars-Peter Clausen 		break;
2107e5ec63eSLars-Peter Clausen 
211b83a313bSMark Brown 	case 8:
212b83a313bSMark Brown 		map->format.format_reg = regmap_format_8;
213b83a313bSMark Brown 		break;
214b83a313bSMark Brown 
215b83a313bSMark Brown 	case 16:
216b83a313bSMark Brown 		map->format.format_reg = regmap_format_16;
217b83a313bSMark Brown 		break;
218b83a313bSMark Brown 
219b83a313bSMark Brown 	default:
220b83a313bSMark Brown 		goto err_map;
221b83a313bSMark Brown 	}
222b83a313bSMark Brown 
223b83a313bSMark Brown 	switch (config->val_bits) {
224b83a313bSMark Brown 	case 8:
225b83a313bSMark Brown 		map->format.format_val = regmap_format_8;
226b83a313bSMark Brown 		map->format.parse_val = regmap_parse_8;
227b83a313bSMark Brown 		break;
228b83a313bSMark Brown 	case 16:
229b83a313bSMark Brown 		map->format.format_val = regmap_format_16;
230b83a313bSMark Brown 		map->format.parse_val = regmap_parse_16;
231b83a313bSMark Brown 		break;
232b83a313bSMark Brown 	}
233b83a313bSMark Brown 
234b83a313bSMark Brown 	if (!map->format.format_write &&
235b83a313bSMark Brown 	    !(map->format.format_reg && map->format.format_val))
236b83a313bSMark Brown 		goto err_map;
237b83a313bSMark Brown 
238b83a313bSMark Brown 	map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL);
239b83a313bSMark Brown 	if (map->work_buf == NULL) {
240b83a313bSMark Brown 		ret = -ENOMEM;
2415204f5e3SMark Brown 		goto err_map;
242b83a313bSMark Brown 	}
243b83a313bSMark Brown 
244*052d2cd1SMark Brown 	regmap_debugfs_init(map);
245*052d2cd1SMark Brown 
246e5e3b8abSLars-Peter Clausen 	ret = regcache_init(map, config);
2475d1729e7SDimitris Papastamos 	if (ret < 0)
24858072cbfSLars-Peter Clausen 		goto err_free_workbuf;
2495d1729e7SDimitris Papastamos 
250b83a313bSMark Brown 	return map;
251b83a313bSMark Brown 
25258072cbfSLars-Peter Clausen err_free_workbuf:
25358072cbfSLars-Peter Clausen 	kfree(map->work_buf);
254b83a313bSMark Brown err_map:
255b83a313bSMark Brown 	kfree(map);
256b83a313bSMark Brown err:
257b83a313bSMark Brown 	return ERR_PTR(ret);
258b83a313bSMark Brown }
259b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_init);
260b83a313bSMark Brown 
261b83a313bSMark Brown /**
262b83a313bSMark Brown  * regmap_exit(): Free a previously allocated register map
263b83a313bSMark Brown  */
264b83a313bSMark Brown void regmap_exit(struct regmap *map)
265b83a313bSMark Brown {
2665d1729e7SDimitris Papastamos 	regcache_exit(map);
26731244e39SMark Brown 	regmap_debugfs_exit(map);
268b83a313bSMark Brown 	kfree(map->work_buf);
269b83a313bSMark Brown 	kfree(map);
270b83a313bSMark Brown }
271b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_exit);
272b83a313bSMark Brown 
273b83a313bSMark Brown static int _regmap_raw_write(struct regmap *map, unsigned int reg,
274b83a313bSMark Brown 			     const void *val, size_t val_len)
275b83a313bSMark Brown {
2766f306441SLars-Peter Clausen 	u8 *u8 = map->work_buf;
277b83a313bSMark Brown 	void *buf;
278b83a313bSMark Brown 	int ret = -ENOTSUPP;
279b83a313bSMark Brown 	size_t len;
28073304781SMark Brown 	int i;
28173304781SMark Brown 
28273304781SMark Brown 	/* Check for unwritable registers before we start */
28373304781SMark Brown 	if (map->writeable_reg)
28473304781SMark Brown 		for (i = 0; i < val_len / map->format.val_bytes; i++)
28573304781SMark Brown 			if (!map->writeable_reg(map->dev, reg + i))
28673304781SMark Brown 				return -EINVAL;
287b83a313bSMark Brown 
288b83a313bSMark Brown 	map->format.format_reg(map->work_buf, reg);
289b83a313bSMark Brown 
2906f306441SLars-Peter Clausen 	u8[0] |= map->write_flag_mask;
2916f306441SLars-Peter Clausen 
292fb2736bbSMark Brown 	trace_regmap_hw_write_start(map->dev, reg,
293fb2736bbSMark Brown 				    val_len / map->format.val_bytes);
294fb2736bbSMark Brown 
2952547e201SMark Brown 	/* If we're doing a single register write we can probably just
2962547e201SMark Brown 	 * send the work_buf directly, otherwise try to do a gather
2972547e201SMark Brown 	 * write.
2982547e201SMark Brown 	 */
2992547e201SMark Brown 	if (val == map->work_buf + map->format.reg_bytes)
3002547e201SMark Brown 		ret = map->bus->write(map->dev, map->work_buf,
3012547e201SMark Brown 				      map->format.reg_bytes + val_len);
3022547e201SMark Brown 	else if (map->bus->gather_write)
303b83a313bSMark Brown 		ret = map->bus->gather_write(map->dev, map->work_buf,
304b83a313bSMark Brown 					     map->format.reg_bytes,
305b83a313bSMark Brown 					     val, val_len);
306b83a313bSMark Brown 
3072547e201SMark Brown 	/* If that didn't work fall back on linearising by hand. */
308b83a313bSMark Brown 	if (ret == -ENOTSUPP) {
309b83a313bSMark Brown 		len = map->format.reg_bytes + val_len;
310b83a313bSMark Brown 		buf = kmalloc(len, GFP_KERNEL);
311b83a313bSMark Brown 		if (!buf)
312b83a313bSMark Brown 			return -ENOMEM;
313b83a313bSMark Brown 
314b83a313bSMark Brown 		memcpy(buf, map->work_buf, map->format.reg_bytes);
315b83a313bSMark Brown 		memcpy(buf + map->format.reg_bytes, val, val_len);
316b83a313bSMark Brown 		ret = map->bus->write(map->dev, buf, len);
317b83a313bSMark Brown 
318b83a313bSMark Brown 		kfree(buf);
319b83a313bSMark Brown 	}
320b83a313bSMark Brown 
321fb2736bbSMark Brown 	trace_regmap_hw_write_done(map->dev, reg,
322fb2736bbSMark Brown 				   val_len / map->format.val_bytes);
323fb2736bbSMark Brown 
324b83a313bSMark Brown 	return ret;
325b83a313bSMark Brown }
326b83a313bSMark Brown 
3274d2dc095SDimitris Papastamos int _regmap_write(struct regmap *map, unsigned int reg,
328b83a313bSMark Brown 		  unsigned int val)
329b83a313bSMark Brown {
330fb2736bbSMark Brown 	int ret;
331b83a313bSMark Brown 	BUG_ON(!map->format.format_write && !map->format.format_val);
332b83a313bSMark Brown 
3335d1729e7SDimitris Papastamos 	if (!map->cache_bypass) {
3345d1729e7SDimitris Papastamos 		ret = regcache_write(map, reg, val);
3355d1729e7SDimitris Papastamos 		if (ret != 0)
3365d1729e7SDimitris Papastamos 			return ret;
3378ae0d7e8SMark Brown 		if (map->cache_only) {
3388ae0d7e8SMark Brown 			map->cache_dirty = true;
3395d1729e7SDimitris Papastamos 			return 0;
3405d1729e7SDimitris Papastamos 		}
3418ae0d7e8SMark Brown 	}
3425d1729e7SDimitris Papastamos 
343fb2736bbSMark Brown 	trace_regmap_reg_write(map->dev, reg, val);
344fb2736bbSMark Brown 
345b83a313bSMark Brown 	if (map->format.format_write) {
346b83a313bSMark Brown 		map->format.format_write(map, reg, val);
347b83a313bSMark Brown 
348fb2736bbSMark Brown 		trace_regmap_hw_write_start(map->dev, reg, 1);
349fb2736bbSMark Brown 
350fb2736bbSMark Brown 		ret = map->bus->write(map->dev, map->work_buf,
351b83a313bSMark Brown 				      map->format.buf_size);
352fb2736bbSMark Brown 
353fb2736bbSMark Brown 		trace_regmap_hw_write_done(map->dev, reg, 1);
354fb2736bbSMark Brown 
355fb2736bbSMark Brown 		return ret;
356b83a313bSMark Brown 	} else {
357b83a313bSMark Brown 		map->format.format_val(map->work_buf + map->format.reg_bytes,
358b83a313bSMark Brown 				       val);
359b83a313bSMark Brown 		return _regmap_raw_write(map, reg,
360b83a313bSMark Brown 					 map->work_buf + map->format.reg_bytes,
361b83a313bSMark Brown 					 map->format.val_bytes);
362b83a313bSMark Brown 	}
363b83a313bSMark Brown }
364b83a313bSMark Brown 
365b83a313bSMark Brown /**
366b83a313bSMark Brown  * regmap_write(): Write a value to a single register
367b83a313bSMark Brown  *
368b83a313bSMark Brown  * @map: Register map to write to
369b83a313bSMark Brown  * @reg: Register to write to
370b83a313bSMark Brown  * @val: Value to be written
371b83a313bSMark Brown  *
372b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
373b83a313bSMark Brown  * be returned in error cases.
374b83a313bSMark Brown  */
375b83a313bSMark Brown int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
376b83a313bSMark Brown {
377b83a313bSMark Brown 	int ret;
378b83a313bSMark Brown 
379b83a313bSMark Brown 	mutex_lock(&map->lock);
380b83a313bSMark Brown 
381b83a313bSMark Brown 	ret = _regmap_write(map, reg, val);
382b83a313bSMark Brown 
383b83a313bSMark Brown 	mutex_unlock(&map->lock);
384b83a313bSMark Brown 
385b83a313bSMark Brown 	return ret;
386b83a313bSMark Brown }
387b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_write);
388b83a313bSMark Brown 
389b83a313bSMark Brown /**
390b83a313bSMark Brown  * regmap_raw_write(): Write raw values to one or more registers
391b83a313bSMark Brown  *
392b83a313bSMark Brown  * @map: Register map to write to
393b83a313bSMark Brown  * @reg: Initial register to write to
394b83a313bSMark Brown  * @val: Block of data to be written, laid out for direct transmission to the
395b83a313bSMark Brown  *       device
396b83a313bSMark Brown  * @val_len: Length of data pointed to by val.
397b83a313bSMark Brown  *
398b83a313bSMark Brown  * This function is intended to be used for things like firmware
399b83a313bSMark Brown  * download where a large block of data needs to be transferred to the
400b83a313bSMark Brown  * device.  No formatting will be done on the data provided.
401b83a313bSMark Brown  *
402b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
403b83a313bSMark Brown  * be returned in error cases.
404b83a313bSMark Brown  */
405b83a313bSMark Brown int regmap_raw_write(struct regmap *map, unsigned int reg,
406b83a313bSMark Brown 		     const void *val, size_t val_len)
407b83a313bSMark Brown {
408c48a9d74SLars-Peter Clausen 	size_t val_count = val_len / map->format.val_bytes;
409b83a313bSMark Brown 	int ret;
410b83a313bSMark Brown 
411c48a9d74SLars-Peter Clausen 	WARN_ON(!regmap_volatile_range(map, reg, val_count) &&
412c48a9d74SLars-Peter Clausen 		map->cache_type != REGCACHE_NONE);
41304e016adSMark Brown 
414b83a313bSMark Brown 	mutex_lock(&map->lock);
415b83a313bSMark Brown 
416b83a313bSMark Brown 	ret = _regmap_raw_write(map, reg, val, val_len);
417b83a313bSMark Brown 
418b83a313bSMark Brown 	mutex_unlock(&map->lock);
419b83a313bSMark Brown 
420b83a313bSMark Brown 	return ret;
421b83a313bSMark Brown }
422b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_write);
423b83a313bSMark Brown 
424b83a313bSMark Brown static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
425b83a313bSMark Brown 			    unsigned int val_len)
426b83a313bSMark Brown {
427b83a313bSMark Brown 	u8 *u8 = map->work_buf;
428b83a313bSMark Brown 	int ret;
429b83a313bSMark Brown 
430b83a313bSMark Brown 	map->format.format_reg(map->work_buf, reg);
431b83a313bSMark Brown 
432b83a313bSMark Brown 	/*
4336f306441SLars-Peter Clausen 	 * Some buses or devices flag reads by setting the high bits in the
434b83a313bSMark Brown 	 * register addresss; since it's always the high bits for all
435b83a313bSMark Brown 	 * current formats we can do this here rather than in
436b83a313bSMark Brown 	 * formatting.  This may break if we get interesting formats.
437b83a313bSMark Brown 	 */
4386f306441SLars-Peter Clausen 	u8[0] |= map->read_flag_mask;
439b83a313bSMark Brown 
440fb2736bbSMark Brown 	trace_regmap_hw_read_start(map->dev, reg,
441fb2736bbSMark Brown 				   val_len / map->format.val_bytes);
442fb2736bbSMark Brown 
443b83a313bSMark Brown 	ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
44440c5cc26SMark Brown 			     val, val_len);
445b83a313bSMark Brown 
446fb2736bbSMark Brown 	trace_regmap_hw_read_done(map->dev, reg,
447fb2736bbSMark Brown 				  val_len / map->format.val_bytes);
448fb2736bbSMark Brown 
449fb2736bbSMark Brown 	return ret;
450b83a313bSMark Brown }
451b83a313bSMark Brown 
452b83a313bSMark Brown static int _regmap_read(struct regmap *map, unsigned int reg,
453b83a313bSMark Brown 			unsigned int *val)
454b83a313bSMark Brown {
455b83a313bSMark Brown 	int ret;
456b83a313bSMark Brown 
4575d1729e7SDimitris Papastamos 	if (!map->cache_bypass) {
4585d1729e7SDimitris Papastamos 		ret = regcache_read(map, reg, val);
4595d1729e7SDimitris Papastamos 		if (ret == 0)
4605d1729e7SDimitris Papastamos 			return 0;
4615d1729e7SDimitris Papastamos 	}
4625d1729e7SDimitris Papastamos 
46319254411SLars-Peter Clausen 	if (!map->format.parse_val)
46419254411SLars-Peter Clausen 		return -EINVAL;
46519254411SLars-Peter Clausen 
4665d1729e7SDimitris Papastamos 	if (map->cache_only)
4675d1729e7SDimitris Papastamos 		return -EBUSY;
4685d1729e7SDimitris Papastamos 
469b83a313bSMark Brown 	ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
470fb2736bbSMark Brown 	if (ret == 0) {
471b83a313bSMark Brown 		*val = map->format.parse_val(map->work_buf);
472fb2736bbSMark Brown 		trace_regmap_reg_read(map->dev, reg, *val);
473fb2736bbSMark Brown 	}
474b83a313bSMark Brown 
475b83a313bSMark Brown 	return ret;
476b83a313bSMark Brown }
477b83a313bSMark Brown 
478b83a313bSMark Brown /**
479b83a313bSMark Brown  * regmap_read(): Read a value from a single register
480b83a313bSMark Brown  *
481b83a313bSMark Brown  * @map: Register map to write to
482b83a313bSMark Brown  * @reg: Register to be read from
483b83a313bSMark Brown  * @val: Pointer to store read value
484b83a313bSMark Brown  *
485b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
486b83a313bSMark Brown  * be returned in error cases.
487b83a313bSMark Brown  */
488b83a313bSMark Brown int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
489b83a313bSMark Brown {
490b83a313bSMark Brown 	int ret;
491b83a313bSMark Brown 
492b83a313bSMark Brown 	mutex_lock(&map->lock);
493b83a313bSMark Brown 
494b83a313bSMark Brown 	ret = _regmap_read(map, reg, val);
495b83a313bSMark Brown 
496b83a313bSMark Brown 	mutex_unlock(&map->lock);
497b83a313bSMark Brown 
498b83a313bSMark Brown 	return ret;
499b83a313bSMark Brown }
500b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_read);
501b83a313bSMark Brown 
502b83a313bSMark Brown /**
503b83a313bSMark Brown  * regmap_raw_read(): Read raw data from the device
504b83a313bSMark Brown  *
505b83a313bSMark Brown  * @map: Register map to write to
506b83a313bSMark Brown  * @reg: First register to be read from
507b83a313bSMark Brown  * @val: Pointer to store read value
508b83a313bSMark Brown  * @val_len: Size of data to read
509b83a313bSMark Brown  *
510b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
511b83a313bSMark Brown  * be returned in error cases.
512b83a313bSMark Brown  */
513b83a313bSMark Brown int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
514b83a313bSMark Brown 		    size_t val_len)
515b83a313bSMark Brown {
51682cd9965SLars-Peter Clausen 	size_t val_count = val_len / map->format.val_bytes;
517b83a313bSMark Brown 	int ret;
518b83a313bSMark Brown 
51982cd9965SLars-Peter Clausen 	WARN_ON(!regmap_volatile_range(map, reg, val_count) &&
52082cd9965SLars-Peter Clausen 		map->cache_type != REGCACHE_NONE);
52104e016adSMark Brown 
522b83a313bSMark Brown 	mutex_lock(&map->lock);
523b83a313bSMark Brown 
524b83a313bSMark Brown 	ret = _regmap_raw_read(map, reg, val, val_len);
525b83a313bSMark Brown 
526b83a313bSMark Brown 	mutex_unlock(&map->lock);
527b83a313bSMark Brown 
528b83a313bSMark Brown 	return ret;
529b83a313bSMark Brown }
530b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_read);
531b83a313bSMark Brown 
532b83a313bSMark Brown /**
533b83a313bSMark Brown  * regmap_bulk_read(): Read multiple registers from the device
534b83a313bSMark Brown  *
535b83a313bSMark Brown  * @map: Register map to write to
536b83a313bSMark Brown  * @reg: First register to be read from
537b83a313bSMark Brown  * @val: Pointer to store read value, in native register size for device
538b83a313bSMark Brown  * @val_count: Number of registers to read
539b83a313bSMark Brown  *
540b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
541b83a313bSMark Brown  * be returned in error cases.
542b83a313bSMark Brown  */
543b83a313bSMark Brown int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
544b83a313bSMark Brown 		     size_t val_count)
545b83a313bSMark Brown {
546b83a313bSMark Brown 	int ret, i;
547b83a313bSMark Brown 	size_t val_bytes = map->format.val_bytes;
54882cd9965SLars-Peter Clausen 	bool vol = regmap_volatile_range(map, reg, val_count);
5495d1729e7SDimitris Papastamos 
550b83a313bSMark Brown 	if (!map->format.parse_val)
551b83a313bSMark Brown 		return -EINVAL;
552b83a313bSMark Brown 
553de2d808fSMark Brown 	if (vol || map->cache_type == REGCACHE_NONE) {
554b83a313bSMark Brown 		ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
555b83a313bSMark Brown 		if (ret != 0)
556b83a313bSMark Brown 			return ret;
557b83a313bSMark Brown 
558b83a313bSMark Brown 		for (i = 0; i < val_count * val_bytes; i += val_bytes)
559b83a313bSMark Brown 			map->format.parse_val(val + i);
560de2d808fSMark Brown 	} else {
561de2d808fSMark Brown 		for (i = 0; i < val_count; i++) {
562de2d808fSMark Brown 			ret = regmap_read(map, reg + i, val + (i * val_bytes));
563de2d808fSMark Brown 			if (ret != 0)
564de2d808fSMark Brown 				return ret;
565de2d808fSMark Brown 		}
566de2d808fSMark Brown 	}
567b83a313bSMark Brown 
568b83a313bSMark Brown 	return 0;
569b83a313bSMark Brown }
570b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_bulk_read);
571b83a313bSMark Brown 
572b83a313bSMark Brown /**
573b973aa36SMark Brown  * regmap_update_bits: Perform a read/modify/write cycle on the register map
574b83a313bSMark Brown  *
575b83a313bSMark Brown  * @map: Register map to update
576b83a313bSMark Brown  * @reg: Register to update
577b83a313bSMark Brown  * @mask: Bitmask to change
578b83a313bSMark Brown  * @val: New value for bitmask
579b83a313bSMark Brown  *
580b83a313bSMark Brown  * Returns zero for success, a negative number on error.
581b83a313bSMark Brown  */
582b83a313bSMark Brown int regmap_update_bits(struct regmap *map, unsigned int reg,
583b83a313bSMark Brown 		       unsigned int mask, unsigned int val)
584b83a313bSMark Brown {
585b83a313bSMark Brown 	int ret;
586d91e8db2SMark Brown 	unsigned int tmp, orig;
587b83a313bSMark Brown 
588b83a313bSMark Brown 	mutex_lock(&map->lock);
589b83a313bSMark Brown 
590d91e8db2SMark Brown 	ret = _regmap_read(map, reg, &orig);
591b83a313bSMark Brown 	if (ret != 0)
592b83a313bSMark Brown 		goto out;
593b83a313bSMark Brown 
594d91e8db2SMark Brown 	tmp = orig & ~mask;
595b83a313bSMark Brown 	tmp |= val & mask;
596b83a313bSMark Brown 
597d91e8db2SMark Brown 	if (tmp != orig)
598b83a313bSMark Brown 		ret = _regmap_write(map, reg, tmp);
599b83a313bSMark Brown 
600b83a313bSMark Brown out:
601b83a313bSMark Brown 	mutex_unlock(&map->lock);
602b83a313bSMark Brown 
603b83a313bSMark Brown 	return ret;
604b83a313bSMark Brown }
605b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_update_bits);
60631244e39SMark Brown 
60731244e39SMark Brown static int __init regmap_initcall(void)
60831244e39SMark Brown {
60931244e39SMark Brown 	regmap_debugfs_initcall();
61031244e39SMark Brown 
61131244e39SMark Brown 	return 0;
61231244e39SMark Brown }
61331244e39SMark Brown postcore_initcall(regmap_initcall);
614