xref: /linux-6.15/drivers/base/regmap/regmap.c (revision eb708cd6)
137613fa5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
237613fa5SGreg Kroah-Hartman //
337613fa5SGreg Kroah-Hartman // Register map access API
437613fa5SGreg Kroah-Hartman //
537613fa5SGreg Kroah-Hartman // Copyright 2011 Wolfson Microelectronics plc
637613fa5SGreg Kroah-Hartman //
737613fa5SGreg Kroah-Hartman // Author: Mark Brown <[email protected]>
8b83a313bSMark Brown 
9f5d6eba7SStephen Warren #include <linux/device.h>
10b83a313bSMark Brown #include <linux/slab.h>
1119694b5eSPaul Gortmaker #include <linux/export.h>
12b83a313bSMark Brown #include <linux/mutex.h>
13b83a313bSMark Brown #include <linux/err.h>
14c916d6efSAndy Shevchenko #include <linux/property.h>
156863ca62SKrystian Garbaciak #include <linux/rbtree.h>
1630b2a553SStephen Warren #include <linux/sched.h>
172de9d600SNariman Poushin #include <linux/delay.h>
18ca747be2SXiubo Li #include <linux/log2.h>
198698b936SBaolin Wang #include <linux/hwspinlock.h>
205f60d5f6SAl Viro #include <linux/unaligned.h>
21b83a313bSMark Brown 
22fb2736bbSMark Brown #define CREATE_TRACE_POINTS
23f58078daSSteven Rostedt #include "trace.h"
24fb2736bbSMark Brown 
2593de9124SMark Brown #include "internal.h"
26b83a313bSMark Brown 
271044c180SMark Brown /*
281044c180SMark Brown  * Sometimes for failures during very early init the trace
291044c180SMark Brown  * infrastructure isn't available early enough to be used.  For this
301044c180SMark Brown  * sort of problem defining LOG_DEVICE will add printks for basic
311044c180SMark Brown  * register I/O on a specific device.
321044c180SMark Brown  */
331044c180SMark Brown #undef LOG_DEVICE
341044c180SMark Brown 
3595093762SBen Dooks #ifdef LOG_DEVICE
regmap_should_log(struct regmap * map)3695093762SBen Dooks static inline bool regmap_should_log(struct regmap *map)
3795093762SBen Dooks {
3895093762SBen Dooks 	return (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0);
3995093762SBen Dooks }
4095093762SBen Dooks #else
regmap_should_log(struct regmap * map)4195093762SBen Dooks static inline bool regmap_should_log(struct regmap *map) { return false; }
4295093762SBen Dooks #endif
4395093762SBen Dooks 
4495093762SBen Dooks 
451044c180SMark Brown static int _regmap_update_bits(struct regmap *map, unsigned int reg,
461044c180SMark Brown 			       unsigned int mask, unsigned int val,
477ff0589cSKuninori Morimoto 			       bool *change, bool force_write);
481044c180SMark Brown 
493ac17037SBoris BREZILLON static int _regmap_bus_reg_read(void *context, unsigned int reg,
503ac17037SBoris BREZILLON 				unsigned int *val);
51ad278406SAndrey Smirnov static int _regmap_bus_read(void *context, unsigned int reg,
52ad278406SAndrey Smirnov 			    unsigned int *val);
5307c320dcSAndrey Smirnov static int _regmap_bus_formatted_write(void *context, unsigned int reg,
5407c320dcSAndrey Smirnov 				       unsigned int val);
553ac17037SBoris BREZILLON static int _regmap_bus_reg_write(void *context, unsigned int reg,
563ac17037SBoris BREZILLON 				 unsigned int val);
5707c320dcSAndrey Smirnov static int _regmap_bus_raw_write(void *context, unsigned int reg,
5807c320dcSAndrey Smirnov 				 unsigned int val);
59ad278406SAndrey Smirnov 
regmap_reg_in_ranges(unsigned int reg,const struct regmap_range * ranges,unsigned int nranges)6076aad392SDavide Ciminaghi bool regmap_reg_in_ranges(unsigned int reg,
6176aad392SDavide Ciminaghi 			  const struct regmap_range *ranges,
6276aad392SDavide Ciminaghi 			  unsigned int nranges)
6376aad392SDavide Ciminaghi {
6476aad392SDavide Ciminaghi 	const struct regmap_range *r;
6576aad392SDavide Ciminaghi 	int i;
6676aad392SDavide Ciminaghi 
6776aad392SDavide Ciminaghi 	for (i = 0, r = ranges; i < nranges; i++, r++)
6876aad392SDavide Ciminaghi 		if (regmap_reg_in_range(reg, r))
6976aad392SDavide Ciminaghi 			return true;
7076aad392SDavide Ciminaghi 	return false;
7176aad392SDavide Ciminaghi }
7276aad392SDavide Ciminaghi EXPORT_SYMBOL_GPL(regmap_reg_in_ranges);
7376aad392SDavide Ciminaghi 
regmap_check_range_table(struct regmap * map,unsigned int reg,const struct regmap_access_table * table)74154881e5SMark Brown bool regmap_check_range_table(struct regmap *map, unsigned int reg,
7576aad392SDavide Ciminaghi 			      const struct regmap_access_table *table)
7676aad392SDavide Ciminaghi {
7776aad392SDavide Ciminaghi 	/* Check "no ranges" first */
7876aad392SDavide Ciminaghi 	if (regmap_reg_in_ranges(reg, table->no_ranges, table->n_no_ranges))
7976aad392SDavide Ciminaghi 		return false;
8076aad392SDavide Ciminaghi 
8176aad392SDavide Ciminaghi 	/* In case zero "yes ranges" are supplied, any reg is OK */
8276aad392SDavide Ciminaghi 	if (!table->n_yes_ranges)
8376aad392SDavide Ciminaghi 		return true;
8476aad392SDavide Ciminaghi 
8576aad392SDavide Ciminaghi 	return regmap_reg_in_ranges(reg, table->yes_ranges,
8676aad392SDavide Ciminaghi 				    table->n_yes_ranges);
8776aad392SDavide Ciminaghi }
88154881e5SMark Brown EXPORT_SYMBOL_GPL(regmap_check_range_table);
8976aad392SDavide Ciminaghi 
regmap_writeable(struct regmap * map,unsigned int reg)908de2f081SMark Brown bool regmap_writeable(struct regmap *map, unsigned int reg)
918de2f081SMark Brown {
920ec74ad3SJan Dakinevich 	if (map->max_register_is_set && reg > map->max_register)
938de2f081SMark Brown 		return false;
948de2f081SMark Brown 
958de2f081SMark Brown 	if (map->writeable_reg)
968de2f081SMark Brown 		return map->writeable_reg(map->dev, reg);
978de2f081SMark Brown 
9876aad392SDavide Ciminaghi 	if (map->wr_table)
99154881e5SMark Brown 		return regmap_check_range_table(map, reg, map->wr_table);
10076aad392SDavide Ciminaghi 
1018de2f081SMark Brown 	return true;
1028de2f081SMark Brown }
1038de2f081SMark Brown 
regmap_cached(struct regmap * map,unsigned int reg)1041ea975cfSCristian Birsan bool regmap_cached(struct regmap *map, unsigned int reg)
1051ea975cfSCristian Birsan {
1061ea975cfSCristian Birsan 	int ret;
1071ea975cfSCristian Birsan 	unsigned int val;
1081ea975cfSCristian Birsan 
10971df1793SCharles Keepax 	if (map->cache_type == REGCACHE_NONE)
1101ea975cfSCristian Birsan 		return false;
1111ea975cfSCristian Birsan 
1121ea975cfSCristian Birsan 	if (!map->cache_ops)
1131ea975cfSCristian Birsan 		return false;
1141ea975cfSCristian Birsan 
1150ec74ad3SJan Dakinevich 	if (map->max_register_is_set && reg > map->max_register)
1161ea975cfSCristian Birsan 		return false;
1171ea975cfSCristian Birsan 
1181ea975cfSCristian Birsan 	map->lock(map->lock_arg);
1191ea975cfSCristian Birsan 	ret = regcache_read(map, reg, &val);
1201ea975cfSCristian Birsan 	map->unlock(map->lock_arg);
1211ea975cfSCristian Birsan 	if (ret)
1221ea975cfSCristian Birsan 		return false;
1231ea975cfSCristian Birsan 
1241ea975cfSCristian Birsan 	return true;
1251ea975cfSCristian Birsan }
1261ea975cfSCristian Birsan 
regmap_readable(struct regmap * map,unsigned int reg)1278de2f081SMark Brown bool regmap_readable(struct regmap *map, unsigned int reg)
1288de2f081SMark Brown {
12904dc91ceSLars-Peter Clausen 	if (!map->reg_read)
13004dc91ceSLars-Peter Clausen 		return false;
13104dc91ceSLars-Peter Clausen 
1320ec74ad3SJan Dakinevich 	if (map->max_register_is_set && reg > map->max_register)
1338de2f081SMark Brown 		return false;
1348de2f081SMark Brown 
1354191f197SWolfram Sang 	if (map->format.format_write)
1364191f197SWolfram Sang 		return false;
1374191f197SWolfram Sang 
1388de2f081SMark Brown 	if (map->readable_reg)
1398de2f081SMark Brown 		return map->readable_reg(map->dev, reg);
1408de2f081SMark Brown 
14176aad392SDavide Ciminaghi 	if (map->rd_table)
142154881e5SMark Brown 		return regmap_check_range_table(map, reg, map->rd_table);
14376aad392SDavide Ciminaghi 
1448de2f081SMark Brown 	return true;
1458de2f081SMark Brown }
1468de2f081SMark Brown 
regmap_volatile(struct regmap * map,unsigned int reg)1478de2f081SMark Brown bool regmap_volatile(struct regmap *map, unsigned int reg)
1488de2f081SMark Brown {
1495844a8b9SMark Brown 	if (!map->format.format_write && !regmap_readable(map, reg))
1508de2f081SMark Brown 		return false;
1518de2f081SMark Brown 
1528de2f081SMark Brown 	if (map->volatile_reg)
1538de2f081SMark Brown 		return map->volatile_reg(map->dev, reg);
1548de2f081SMark Brown 
15576aad392SDavide Ciminaghi 	if (map->volatile_table)
156154881e5SMark Brown 		return regmap_check_range_table(map, reg, map->volatile_table);
15776aad392SDavide Ciminaghi 
158b92be6feSMark Brown 	if (map->cache_ops)
159b92be6feSMark Brown 		return false;
160b92be6feSMark Brown 	else
1618de2f081SMark Brown 		return true;
1628de2f081SMark Brown }
1638de2f081SMark Brown 
regmap_precious(struct regmap * map,unsigned int reg)1648de2f081SMark Brown bool regmap_precious(struct regmap *map, unsigned int reg)
1658de2f081SMark Brown {
1664191f197SWolfram Sang 	if (!regmap_readable(map, reg))
1678de2f081SMark Brown 		return false;
1688de2f081SMark Brown 
1698de2f081SMark Brown 	if (map->precious_reg)
1708de2f081SMark Brown 		return map->precious_reg(map->dev, reg);
1718de2f081SMark Brown 
17276aad392SDavide Ciminaghi 	if (map->precious_table)
173154881e5SMark Brown 		return regmap_check_range_table(map, reg, map->precious_table);
17476aad392SDavide Ciminaghi 
1758de2f081SMark Brown 	return false;
1768de2f081SMark Brown }
1778de2f081SMark Brown 
regmap_writeable_noinc(struct regmap * map,unsigned int reg)178cdf6b11dSBen Whitten bool regmap_writeable_noinc(struct regmap *map, unsigned int reg)
179cdf6b11dSBen Whitten {
180cdf6b11dSBen Whitten 	if (map->writeable_noinc_reg)
181cdf6b11dSBen Whitten 		return map->writeable_noinc_reg(map->dev, reg);
182cdf6b11dSBen Whitten 
183cdf6b11dSBen Whitten 	if (map->wr_noinc_table)
184cdf6b11dSBen Whitten 		return regmap_check_range_table(map, reg, map->wr_noinc_table);
185cdf6b11dSBen Whitten 
186cdf6b11dSBen Whitten 	return true;
187cdf6b11dSBen Whitten }
188cdf6b11dSBen Whitten 
regmap_readable_noinc(struct regmap * map,unsigned int reg)18974fe7b55SCrestez Dan Leonard bool regmap_readable_noinc(struct regmap *map, unsigned int reg)
19074fe7b55SCrestez Dan Leonard {
19174fe7b55SCrestez Dan Leonard 	if (map->readable_noinc_reg)
19274fe7b55SCrestez Dan Leonard 		return map->readable_noinc_reg(map->dev, reg);
19374fe7b55SCrestez Dan Leonard 
19474fe7b55SCrestez Dan Leonard 	if (map->rd_noinc_table)
19574fe7b55SCrestez Dan Leonard 		return regmap_check_range_table(map, reg, map->rd_noinc_table);
19674fe7b55SCrestez Dan Leonard 
19774fe7b55SCrestez Dan Leonard 	return true;
19874fe7b55SCrestez Dan Leonard }
19974fe7b55SCrestez Dan Leonard 
regmap_volatile_range(struct regmap * map,unsigned int reg,size_t num)20082cd9965SLars-Peter Clausen static bool regmap_volatile_range(struct regmap *map, unsigned int reg,
201a8f28cfaSPaul Bolle 	size_t num)
20282cd9965SLars-Peter Clausen {
20382cd9965SLars-Peter Clausen 	unsigned int i;
20482cd9965SLars-Peter Clausen 
20582cd9965SLars-Peter Clausen 	for (i = 0; i < num; i++)
206b8f9a03bSCharles Keepax 		if (!regmap_volatile(map, reg + regmap_get_offset(map, i)))
20782cd9965SLars-Peter Clausen 			return false;
20882cd9965SLars-Peter Clausen 
20982cd9965SLars-Peter Clausen 	return true;
21082cd9965SLars-Peter Clausen }
21182cd9965SLars-Peter Clausen 
regmap_format_12_20_write(struct regmap * map,unsigned int reg,unsigned int val)2120c2191c3SRicardo Ribalda static void regmap_format_12_20_write(struct regmap *map,
2130c2191c3SRicardo Ribalda 				     unsigned int reg, unsigned int val)
2140c2191c3SRicardo Ribalda {
2150c2191c3SRicardo Ribalda 	u8 *out = map->work_buf;
2160c2191c3SRicardo Ribalda 
2170c2191c3SRicardo Ribalda 	out[0] = reg >> 4;
2180c2191c3SRicardo Ribalda 	out[1] = (reg << 4) | (val >> 16);
2190c2191c3SRicardo Ribalda 	out[2] = val >> 8;
2200c2191c3SRicardo Ribalda 	out[3] = val;
2210c2191c3SRicardo Ribalda }
2220c2191c3SRicardo Ribalda 
2230c2191c3SRicardo Ribalda 
regmap_format_2_6_write(struct regmap * map,unsigned int reg,unsigned int val)2249aa50750SWolfram Sang static void regmap_format_2_6_write(struct regmap *map,
2259aa50750SWolfram Sang 				     unsigned int reg, unsigned int val)
2269aa50750SWolfram Sang {
2279aa50750SWolfram Sang 	u8 *out = map->work_buf;
2289aa50750SWolfram Sang 
2299aa50750SWolfram Sang 	*out = (reg << 6) | val;
2309aa50750SWolfram Sang }
2319aa50750SWolfram Sang 
regmap_format_4_12_write(struct regmap * map,unsigned int reg,unsigned int val)232b83a313bSMark Brown static void regmap_format_4_12_write(struct regmap *map,
233b83a313bSMark Brown 				     unsigned int reg, unsigned int val)
234b83a313bSMark Brown {
235b83a313bSMark Brown 	__be16 *out = map->work_buf;
236b83a313bSMark Brown 	*out = cpu_to_be16((reg << 12) | val);
237b83a313bSMark Brown }
238b83a313bSMark Brown 
regmap_format_7_9_write(struct regmap * map,unsigned int reg,unsigned int val)239b83a313bSMark Brown static void regmap_format_7_9_write(struct regmap *map,
240b83a313bSMark Brown 				    unsigned int reg, unsigned int val)
241b83a313bSMark Brown {
242b83a313bSMark Brown 	__be16 *out = map->work_buf;
243b83a313bSMark Brown 	*out = cpu_to_be16((reg << 9) | val);
244b83a313bSMark Brown }
245b83a313bSMark Brown 
regmap_format_7_17_write(struct regmap * map,unsigned int reg,unsigned int val)246b24412afSAntoniu Miclaus static void regmap_format_7_17_write(struct regmap *map,
247b24412afSAntoniu Miclaus 				    unsigned int reg, unsigned int val)
248b24412afSAntoniu Miclaus {
249b24412afSAntoniu Miclaus 	u8 *out = map->work_buf;
250b24412afSAntoniu Miclaus 
251b24412afSAntoniu Miclaus 	out[2] = val;
252b24412afSAntoniu Miclaus 	out[1] = val >> 8;
253b24412afSAntoniu Miclaus 	out[0] = (val >> 16) | (reg << 1);
254b24412afSAntoniu Miclaus }
255b24412afSAntoniu Miclaus 
regmap_format_10_14_write(struct regmap * map,unsigned int reg,unsigned int val)2567e5ec63eSLars-Peter Clausen static void regmap_format_10_14_write(struct regmap *map,
2577e5ec63eSLars-Peter Clausen 				    unsigned int reg, unsigned int val)
2587e5ec63eSLars-Peter Clausen {
2597e5ec63eSLars-Peter Clausen 	u8 *out = map->work_buf;
2607e5ec63eSLars-Peter Clausen 
2617e5ec63eSLars-Peter Clausen 	out[2] = val;
2627e5ec63eSLars-Peter Clausen 	out[1] = (val >> 8) | (reg << 6);
2637e5ec63eSLars-Peter Clausen 	out[0] = reg >> 2;
2647e5ec63eSLars-Peter Clausen }
2657e5ec63eSLars-Peter Clausen 
regmap_format_8(void * buf,unsigned int val,unsigned int shift)266d939fb9aSMarc Reilly static void regmap_format_8(void *buf, unsigned int val, unsigned int shift)
267b83a313bSMark Brown {
268b83a313bSMark Brown 	u8 *b = buf;
269b83a313bSMark Brown 
270d939fb9aSMarc Reilly 	b[0] = val << shift;
271b83a313bSMark Brown }
272b83a313bSMark Brown 
regmap_format_16_be(void * buf,unsigned int val,unsigned int shift)273141eba2eSStephen Warren static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift)
274b83a313bSMark Brown {
27553d86095SJens Thoms Toerring 	put_unaligned_be16(val << shift, buf);
276b83a313bSMark Brown }
277b83a313bSMark Brown 
regmap_format_16_le(void * buf,unsigned int val,unsigned int shift)2784aa8c069SXiubo Li static void regmap_format_16_le(void *buf, unsigned int val, unsigned int shift)
2794aa8c069SXiubo Li {
28053d86095SJens Thoms Toerring 	put_unaligned_le16(val << shift, buf);
2814aa8c069SXiubo Li }
2824aa8c069SXiubo Li 
regmap_format_16_native(void * buf,unsigned int val,unsigned int shift)283141eba2eSStephen Warren static void regmap_format_16_native(void *buf, unsigned int val,
284141eba2eSStephen Warren 				    unsigned int shift)
285141eba2eSStephen Warren {
28653d86095SJens Thoms Toerring 	u16 v = val << shift;
28753d86095SJens Thoms Toerring 
28853d86095SJens Thoms Toerring 	memcpy(buf, &v, sizeof(v));
289141eba2eSStephen Warren }
290141eba2eSStephen Warren 
regmap_format_24_be(void * buf,unsigned int val,unsigned int shift)29106000443SAndy Shevchenko static void regmap_format_24_be(void *buf, unsigned int val, unsigned int shift)
292ea279fc5SMarc Reilly {
29306000443SAndy Shevchenko 	put_unaligned_be24(val << shift, buf);
294ea279fc5SMarc Reilly }
295ea279fc5SMarc Reilly 
regmap_format_32_be(void * buf,unsigned int val,unsigned int shift)296141eba2eSStephen Warren static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift)
2977d5e525bSMark Brown {
29853d86095SJens Thoms Toerring 	put_unaligned_be32(val << shift, buf);
2997d5e525bSMark Brown }
3007d5e525bSMark Brown 
regmap_format_32_le(void * buf,unsigned int val,unsigned int shift)3014aa8c069SXiubo Li static void regmap_format_32_le(void *buf, unsigned int val, unsigned int shift)
3024aa8c069SXiubo Li {
30353d86095SJens Thoms Toerring 	put_unaligned_le32(val << shift, buf);
3044aa8c069SXiubo Li }
3054aa8c069SXiubo Li 
regmap_format_32_native(void * buf,unsigned int val,unsigned int shift)306141eba2eSStephen Warren static void regmap_format_32_native(void *buf, unsigned int val,
307141eba2eSStephen Warren 				    unsigned int shift)
308141eba2eSStephen Warren {
30953d86095SJens Thoms Toerring 	u32 v = val << shift;
31053d86095SJens Thoms Toerring 
31153d86095SJens Thoms Toerring 	memcpy(buf, &v, sizeof(v));
312141eba2eSStephen Warren }
313141eba2eSStephen Warren 
regmap_parse_inplace_noop(void * buf)3148a819ff8SMark Brown static void regmap_parse_inplace_noop(void *buf)
315b83a313bSMark Brown {
3168a819ff8SMark Brown }
3178a819ff8SMark Brown 
regmap_parse_8(const void * buf)3188a819ff8SMark Brown static unsigned int regmap_parse_8(const void *buf)
3198a819ff8SMark Brown {
3208a819ff8SMark Brown 	const u8 *b = buf;
321b83a313bSMark Brown 
322b83a313bSMark Brown 	return b[0];
323b83a313bSMark Brown }
324b83a313bSMark Brown 
regmap_parse_16_be(const void * buf)3258a819ff8SMark Brown static unsigned int regmap_parse_16_be(const void *buf)
3268a819ff8SMark Brown {
32753d86095SJens Thoms Toerring 	return get_unaligned_be16(buf);
3288a819ff8SMark Brown }
3298a819ff8SMark Brown 
regmap_parse_16_le(const void * buf)3304aa8c069SXiubo Li static unsigned int regmap_parse_16_le(const void *buf)
3314aa8c069SXiubo Li {
33253d86095SJens Thoms Toerring 	return get_unaligned_le16(buf);
3334aa8c069SXiubo Li }
3344aa8c069SXiubo Li 
regmap_parse_16_be_inplace(void * buf)3358a819ff8SMark Brown static void regmap_parse_16_be_inplace(void *buf)
336b83a313bSMark Brown {
33753d86095SJens Thoms Toerring 	u16 v = get_unaligned_be16(buf);
338b83a313bSMark Brown 
33953d86095SJens Thoms Toerring 	memcpy(buf, &v, sizeof(v));
340b83a313bSMark Brown }
341b83a313bSMark Brown 
regmap_parse_16_le_inplace(void * buf)3424aa8c069SXiubo Li static void regmap_parse_16_le_inplace(void *buf)
3434aa8c069SXiubo Li {
34453d86095SJens Thoms Toerring 	u16 v = get_unaligned_le16(buf);
3454aa8c069SXiubo Li 
34653d86095SJens Thoms Toerring 	memcpy(buf, &v, sizeof(v));
3474aa8c069SXiubo Li }
3484aa8c069SXiubo Li 
regmap_parse_16_native(const void * buf)3498a819ff8SMark Brown static unsigned int regmap_parse_16_native(const void *buf)
350141eba2eSStephen Warren {
35153d86095SJens Thoms Toerring 	u16 v;
35253d86095SJens Thoms Toerring 
35353d86095SJens Thoms Toerring 	memcpy(&v, buf, sizeof(v));
35453d86095SJens Thoms Toerring 	return v;
355141eba2eSStephen Warren }
356141eba2eSStephen Warren 
regmap_parse_24_be(const void * buf)35706000443SAndy Shevchenko static unsigned int regmap_parse_24_be(const void *buf)
358ea279fc5SMarc Reilly {
35906000443SAndy Shevchenko 	return get_unaligned_be24(buf);
360ea279fc5SMarc Reilly }
361ea279fc5SMarc Reilly 
regmap_parse_32_be(const void * buf)3628a819ff8SMark Brown static unsigned int regmap_parse_32_be(const void *buf)
3638a819ff8SMark Brown {
36453d86095SJens Thoms Toerring 	return get_unaligned_be32(buf);
3658a819ff8SMark Brown }
3668a819ff8SMark Brown 
regmap_parse_32_le(const void * buf)3674aa8c069SXiubo Li static unsigned int regmap_parse_32_le(const void *buf)
3684aa8c069SXiubo Li {
36953d86095SJens Thoms Toerring 	return get_unaligned_le32(buf);
3704aa8c069SXiubo Li }
3714aa8c069SXiubo Li 
regmap_parse_32_be_inplace(void * buf)3728a819ff8SMark Brown static void regmap_parse_32_be_inplace(void *buf)
3737d5e525bSMark Brown {
37453d86095SJens Thoms Toerring 	u32 v = get_unaligned_be32(buf);
3757d5e525bSMark Brown 
37653d86095SJens Thoms Toerring 	memcpy(buf, &v, sizeof(v));
3777d5e525bSMark Brown }
3787d5e525bSMark Brown 
regmap_parse_32_le_inplace(void * buf)3794aa8c069SXiubo Li static void regmap_parse_32_le_inplace(void *buf)
3804aa8c069SXiubo Li {
38153d86095SJens Thoms Toerring 	u32 v = get_unaligned_le32(buf);
3824aa8c069SXiubo Li 
38353d86095SJens Thoms Toerring 	memcpy(buf, &v, sizeof(v));
3844aa8c069SXiubo Li }
3854aa8c069SXiubo Li 
regmap_parse_32_native(const void * buf)3868a819ff8SMark Brown static unsigned int regmap_parse_32_native(const void *buf)
387141eba2eSStephen Warren {
38853d86095SJens Thoms Toerring 	u32 v;
38953d86095SJens Thoms Toerring 
39053d86095SJens Thoms Toerring 	memcpy(&v, buf, sizeof(v));
39153d86095SJens Thoms Toerring 	return v;
392141eba2eSStephen Warren }
393141eba2eSStephen Warren 
regmap_lock_hwlock(void * __map)3948698b936SBaolin Wang static void regmap_lock_hwlock(void *__map)
3958698b936SBaolin Wang {
3968698b936SBaolin Wang 	struct regmap *map = __map;
3978698b936SBaolin Wang 
3988698b936SBaolin Wang 	hwspin_lock_timeout(map->hwlock, UINT_MAX);
3998698b936SBaolin Wang }
4008698b936SBaolin Wang 
regmap_lock_hwlock_irq(void * __map)4018698b936SBaolin Wang static void regmap_lock_hwlock_irq(void *__map)
4028698b936SBaolin Wang {
4038698b936SBaolin Wang 	struct regmap *map = __map;
4048698b936SBaolin Wang 
4058698b936SBaolin Wang 	hwspin_lock_timeout_irq(map->hwlock, UINT_MAX);
4068698b936SBaolin Wang }
4078698b936SBaolin Wang 
regmap_lock_hwlock_irqsave(void * __map)4088698b936SBaolin Wang static void regmap_lock_hwlock_irqsave(void *__map)
4098698b936SBaolin Wang {
4108698b936SBaolin Wang 	struct regmap *map = __map;
4118698b936SBaolin Wang 
4128698b936SBaolin Wang 	hwspin_lock_timeout_irqsave(map->hwlock, UINT_MAX,
4138698b936SBaolin Wang 				    &map->spinlock_flags);
4148698b936SBaolin Wang }
4158698b936SBaolin Wang 
regmap_unlock_hwlock(void * __map)4168698b936SBaolin Wang static void regmap_unlock_hwlock(void *__map)
4178698b936SBaolin Wang {
4188698b936SBaolin Wang 	struct regmap *map = __map;
4198698b936SBaolin Wang 
4208698b936SBaolin Wang 	hwspin_unlock(map->hwlock);
4218698b936SBaolin Wang }
4228698b936SBaolin Wang 
regmap_unlock_hwlock_irq(void * __map)4238698b936SBaolin Wang static void regmap_unlock_hwlock_irq(void *__map)
4248698b936SBaolin Wang {
4258698b936SBaolin Wang 	struct regmap *map = __map;
4268698b936SBaolin Wang 
4278698b936SBaolin Wang 	hwspin_unlock_irq(map->hwlock);
4288698b936SBaolin Wang }
4298698b936SBaolin Wang 
regmap_unlock_hwlock_irqrestore(void * __map)4308698b936SBaolin Wang static void regmap_unlock_hwlock_irqrestore(void *__map)
4318698b936SBaolin Wang {
4328698b936SBaolin Wang 	struct regmap *map = __map;
4338698b936SBaolin Wang 
4348698b936SBaolin Wang 	hwspin_unlock_irqrestore(map->hwlock, &map->spinlock_flags);
4358698b936SBaolin Wang }
4368698b936SBaolin Wang 
regmap_lock_unlock_none(void * __map)43781e30b18SBartosz Golaszewski static void regmap_lock_unlock_none(void *__map)
438c9b41fcfSBartosz Golaszewski {
439c9b41fcfSBartosz Golaszewski 
440c9b41fcfSBartosz Golaszewski }
441afcc00b9SXiubo Li 
regmap_lock_mutex(void * __map)4420d4529c5SDavide Ciminaghi static void regmap_lock_mutex(void *__map)
443bacdbe07SStephen Warren {
4440d4529c5SDavide Ciminaghi 	struct regmap *map = __map;
445bacdbe07SStephen Warren 	mutex_lock(&map->mutex);
446bacdbe07SStephen Warren }
447bacdbe07SStephen Warren 
regmap_unlock_mutex(void * __map)4480d4529c5SDavide Ciminaghi static void regmap_unlock_mutex(void *__map)
449bacdbe07SStephen Warren {
4500d4529c5SDavide Ciminaghi 	struct regmap *map = __map;
451bacdbe07SStephen Warren 	mutex_unlock(&map->mutex);
452bacdbe07SStephen Warren }
453bacdbe07SStephen Warren 
regmap_lock_spinlock(void * __map)4540d4529c5SDavide Ciminaghi static void regmap_lock_spinlock(void *__map)
455b4519c71SFabio Estevam __acquires(&map->spinlock)
456bacdbe07SStephen Warren {
4570d4529c5SDavide Ciminaghi 	struct regmap *map = __map;
45892ab1aabSLars-Peter Clausen 	unsigned long flags;
45992ab1aabSLars-Peter Clausen 
46092ab1aabSLars-Peter Clausen 	spin_lock_irqsave(&map->spinlock, flags);
46192ab1aabSLars-Peter Clausen 	map->spinlock_flags = flags;
462bacdbe07SStephen Warren }
463bacdbe07SStephen Warren 
regmap_unlock_spinlock(void * __map)4640d4529c5SDavide Ciminaghi static void regmap_unlock_spinlock(void *__map)
465b4519c71SFabio Estevam __releases(&map->spinlock)
466bacdbe07SStephen Warren {
4670d4529c5SDavide Ciminaghi 	struct regmap *map = __map;
46892ab1aabSLars-Peter Clausen 	spin_unlock_irqrestore(&map->spinlock, map->spinlock_flags);
469bacdbe07SStephen Warren }
470bacdbe07SStephen Warren 
regmap_lock_raw_spinlock(void * __map)47167021f25SVladimir Oltean static void regmap_lock_raw_spinlock(void *__map)
47267021f25SVladimir Oltean __acquires(&map->raw_spinlock)
47367021f25SVladimir Oltean {
47467021f25SVladimir Oltean 	struct regmap *map = __map;
47567021f25SVladimir Oltean 	unsigned long flags;
47667021f25SVladimir Oltean 
47767021f25SVladimir Oltean 	raw_spin_lock_irqsave(&map->raw_spinlock, flags);
47867021f25SVladimir Oltean 	map->raw_spinlock_flags = flags;
47967021f25SVladimir Oltean }
48067021f25SVladimir Oltean 
regmap_unlock_raw_spinlock(void * __map)48167021f25SVladimir Oltean static void regmap_unlock_raw_spinlock(void *__map)
48267021f25SVladimir Oltean __releases(&map->raw_spinlock)
48367021f25SVladimir Oltean {
48467021f25SVladimir Oltean 	struct regmap *map = __map;
48567021f25SVladimir Oltean 	raw_spin_unlock_irqrestore(&map->raw_spinlock, map->raw_spinlock_flags);
48667021f25SVladimir Oltean }
48767021f25SVladimir Oltean 
dev_get_regmap_release(struct device * dev,void * res)48872b39f6fSMark Brown static void dev_get_regmap_release(struct device *dev, void *res)
48972b39f6fSMark Brown {
49072b39f6fSMark Brown 	/*
49172b39f6fSMark Brown 	 * We don't actually have anything to do here; the goal here
49272b39f6fSMark Brown 	 * is not to manage the regmap but to provide a simple way to
49372b39f6fSMark Brown 	 * get the regmap back given a struct device.
49472b39f6fSMark Brown 	 */
49572b39f6fSMark Brown }
49672b39f6fSMark Brown 
_regmap_range_add(struct regmap * map,struct regmap_range_node * data)4976863ca62SKrystian Garbaciak static bool _regmap_range_add(struct regmap *map,
4986863ca62SKrystian Garbaciak 			      struct regmap_range_node *data)
4996863ca62SKrystian Garbaciak {
5006863ca62SKrystian Garbaciak 	struct rb_root *root = &map->range_tree;
5016863ca62SKrystian Garbaciak 	struct rb_node **new = &(root->rb_node), *parent = NULL;
5026863ca62SKrystian Garbaciak 
5036863ca62SKrystian Garbaciak 	while (*new) {
5046863ca62SKrystian Garbaciak 		struct regmap_range_node *this =
505671a911bSGeliang Tang 			rb_entry(*new, struct regmap_range_node, node);
5066863ca62SKrystian Garbaciak 
5076863ca62SKrystian Garbaciak 		parent = *new;
5086863ca62SKrystian Garbaciak 		if (data->range_max < this->range_min)
5096863ca62SKrystian Garbaciak 			new = &((*new)->rb_left);
5106863ca62SKrystian Garbaciak 		else if (data->range_min > this->range_max)
5116863ca62SKrystian Garbaciak 			new = &((*new)->rb_right);
5126863ca62SKrystian Garbaciak 		else
5136863ca62SKrystian Garbaciak 			return false;
5146863ca62SKrystian Garbaciak 	}
5156863ca62SKrystian Garbaciak 
5166863ca62SKrystian Garbaciak 	rb_link_node(&data->node, parent, new);
5176863ca62SKrystian Garbaciak 	rb_insert_color(&data->node, root);
5186863ca62SKrystian Garbaciak 
5196863ca62SKrystian Garbaciak 	return true;
5206863ca62SKrystian Garbaciak }
5216863ca62SKrystian Garbaciak 
_regmap_range_lookup(struct regmap * map,unsigned int reg)5226863ca62SKrystian Garbaciak static struct regmap_range_node *_regmap_range_lookup(struct regmap *map,
5236863ca62SKrystian Garbaciak 						      unsigned int reg)
5246863ca62SKrystian Garbaciak {
5256863ca62SKrystian Garbaciak 	struct rb_node *node = map->range_tree.rb_node;
5266863ca62SKrystian Garbaciak 
5276863ca62SKrystian Garbaciak 	while (node) {
5286863ca62SKrystian Garbaciak 		struct regmap_range_node *this =
529671a911bSGeliang Tang 			rb_entry(node, struct regmap_range_node, node);
5306863ca62SKrystian Garbaciak 
5316863ca62SKrystian Garbaciak 		if (reg < this->range_min)
5326863ca62SKrystian Garbaciak 			node = node->rb_left;
5336863ca62SKrystian Garbaciak 		else if (reg > this->range_max)
5346863ca62SKrystian Garbaciak 			node = node->rb_right;
5356863ca62SKrystian Garbaciak 		else
5366863ca62SKrystian Garbaciak 			return this;
5376863ca62SKrystian Garbaciak 	}
5386863ca62SKrystian Garbaciak 
5396863ca62SKrystian Garbaciak 	return NULL;
5406863ca62SKrystian Garbaciak }
5416863ca62SKrystian Garbaciak 
regmap_range_exit(struct regmap * map)5426863ca62SKrystian Garbaciak static void regmap_range_exit(struct regmap *map)
5436863ca62SKrystian Garbaciak {
5446863ca62SKrystian Garbaciak 	struct rb_node *next;
5456863ca62SKrystian Garbaciak 	struct regmap_range_node *range_node;
5466863ca62SKrystian Garbaciak 
5476863ca62SKrystian Garbaciak 	next = rb_first(&map->range_tree);
5486863ca62SKrystian Garbaciak 	while (next) {
5496863ca62SKrystian Garbaciak 		range_node = rb_entry(next, struct regmap_range_node, node);
5506863ca62SKrystian Garbaciak 		next = rb_next(&range_node->node);
5516863ca62SKrystian Garbaciak 		rb_erase(&range_node->node, &map->range_tree);
5526863ca62SKrystian Garbaciak 		kfree(range_node);
5536863ca62SKrystian Garbaciak 	}
5546863ca62SKrystian Garbaciak 
5556863ca62SKrystian Garbaciak 	kfree(map->selector_work_buf);
5566863ca62SKrystian Garbaciak }
5576863ca62SKrystian Garbaciak 
regmap_set_name(struct regmap * map,const struct regmap_config * config)55894cc89ebSCharles Keepax static int regmap_set_name(struct regmap *map, const struct regmap_config *config)
55994cc89ebSCharles Keepax {
56094cc89ebSCharles Keepax 	if (config->name) {
56194cc89ebSCharles Keepax 		const char *name = kstrdup_const(config->name, GFP_KERNEL);
56294cc89ebSCharles Keepax 
56394cc89ebSCharles Keepax 		if (!name)
56494cc89ebSCharles Keepax 			return -ENOMEM;
56594cc89ebSCharles Keepax 
56694cc89ebSCharles Keepax 		kfree_const(map->name);
56794cc89ebSCharles Keepax 		map->name = name;
56894cc89ebSCharles Keepax 	}
56994cc89ebSCharles Keepax 
57094cc89ebSCharles Keepax 	return 0;
57194cc89ebSCharles Keepax }
57294cc89ebSCharles Keepax 
regmap_attach_dev(struct device * dev,struct regmap * map,const struct regmap_config * config)5736cfec04bSMichal Simek int regmap_attach_dev(struct device *dev, struct regmap *map,
5746cfec04bSMichal Simek 		      const struct regmap_config *config)
5756cfec04bSMichal Simek {
5766cfec04bSMichal Simek 	struct regmap **m;
57794cc89ebSCharles Keepax 	int ret;
5786cfec04bSMichal Simek 
5796cfec04bSMichal Simek 	map->dev = dev;
5806cfec04bSMichal Simek 
58194cc89ebSCharles Keepax 	ret = regmap_set_name(map, config);
58294cc89ebSCharles Keepax 	if (ret)
58394cc89ebSCharles Keepax 		return ret;
58494cc89ebSCharles Keepax 
585530792efSFabio Estevam 	regmap_debugfs_exit(map);
58694cc89ebSCharles Keepax 	regmap_debugfs_init(map);
5876cfec04bSMichal Simek 
5886cfec04bSMichal Simek 	/* Add a devres resource for dev_get_regmap() */
5896cfec04bSMichal Simek 	m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
5906cfec04bSMichal Simek 	if (!m) {
5916cfec04bSMichal Simek 		regmap_debugfs_exit(map);
5926cfec04bSMichal Simek 		return -ENOMEM;
5936cfec04bSMichal Simek 	}
5946cfec04bSMichal Simek 	*m = map;
5956cfec04bSMichal Simek 	devres_add(dev, m);
5966cfec04bSMichal Simek 
5976cfec04bSMichal Simek 	return 0;
5986cfec04bSMichal Simek }
5996cfec04bSMichal Simek EXPORT_SYMBOL_GPL(regmap_attach_dev);
6006cfec04bSMichal Simek 
6013061e170SCosmin Tanislav static int dev_get_regmap_match(struct device *dev, void *res, void *data);
6023061e170SCosmin Tanislav 
regmap_detach_dev(struct device * dev,struct regmap * map)6033061e170SCosmin Tanislav static int regmap_detach_dev(struct device *dev, struct regmap *map)
6043061e170SCosmin Tanislav {
6053061e170SCosmin Tanislav 	if (!dev)
6063061e170SCosmin Tanislav 		return 0;
6073061e170SCosmin Tanislav 
6083061e170SCosmin Tanislav 	return devres_release(dev, dev_get_regmap_release,
6093061e170SCosmin Tanislav 			      dev_get_regmap_match, (void *)map->name);
6103061e170SCosmin Tanislav }
6113061e170SCosmin Tanislav 
regmap_get_reg_endian(const struct regmap_bus * bus,const struct regmap_config * config)612cf673fbcSGeert Uytterhoeven static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
613cf673fbcSGeert Uytterhoeven 					const struct regmap_config *config)
614d647c199SXiubo Li {
615cf673fbcSGeert Uytterhoeven 	enum regmap_endian endian;
616d647c199SXiubo Li 
61745e1a279SStephen Warren 	/* Retrieve the endianness specification from the regmap config */
618cf673fbcSGeert Uytterhoeven 	endian = config->reg_format_endian;
619d647c199SXiubo Li 
62045e1a279SStephen Warren 	/* If the regmap config specified a non-default value, use that */
621cf673fbcSGeert Uytterhoeven 	if (endian != REGMAP_ENDIAN_DEFAULT)
622cf673fbcSGeert Uytterhoeven 		return endian;
62345e1a279SStephen Warren 
62445e1a279SStephen Warren 	/* Retrieve the endianness specification from the bus config */
625d647c199SXiubo Li 	if (bus && bus->reg_format_endian_default)
626cf673fbcSGeert Uytterhoeven 		endian = bus->reg_format_endian_default;
627d647c199SXiubo Li 
62845e1a279SStephen Warren 	/* If the bus specified a non-default value, use that */
629cf673fbcSGeert Uytterhoeven 	if (endian != REGMAP_ENDIAN_DEFAULT)
630cf673fbcSGeert Uytterhoeven 		return endian;
63145e1a279SStephen Warren 
63245e1a279SStephen Warren 	/* Use this if no other value was found */
633cf673fbcSGeert Uytterhoeven 	return REGMAP_ENDIAN_BIG;
634cf673fbcSGeert Uytterhoeven }
63545e1a279SStephen Warren 
regmap_get_val_endian(struct device * dev,const struct regmap_bus * bus,const struct regmap_config * config)6363c174d29SGuenter Roeck enum regmap_endian regmap_get_val_endian(struct device *dev,
637cf673fbcSGeert Uytterhoeven 					 const struct regmap_bus *bus,
638cf673fbcSGeert Uytterhoeven 					 const struct regmap_config *config)
639cf673fbcSGeert Uytterhoeven {
640c916d6efSAndy Shevchenko 	struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL;
641cf673fbcSGeert Uytterhoeven 	enum regmap_endian endian;
642cf673fbcSGeert Uytterhoeven 
643cf673fbcSGeert Uytterhoeven 	/* Retrieve the endianness specification from the regmap config */
644cf673fbcSGeert Uytterhoeven 	endian = config->val_format_endian;
645cf673fbcSGeert Uytterhoeven 
646cf673fbcSGeert Uytterhoeven 	/* If the regmap config specified a non-default value, use that */
647cf673fbcSGeert Uytterhoeven 	if (endian != REGMAP_ENDIAN_DEFAULT)
648cf673fbcSGeert Uytterhoeven 		return endian;
649cf673fbcSGeert Uytterhoeven 
650c916d6efSAndy Shevchenko 	/* If the firmware node exist try to get endianness from it */
651c916d6efSAndy Shevchenko 	if (fwnode_property_read_bool(fwnode, "big-endian"))
652cf673fbcSGeert Uytterhoeven 		endian = REGMAP_ENDIAN_BIG;
653c916d6efSAndy Shevchenko 	else if (fwnode_property_read_bool(fwnode, "little-endian"))
654cf673fbcSGeert Uytterhoeven 		endian = REGMAP_ENDIAN_LITTLE;
655c916d6efSAndy Shevchenko 	else if (fwnode_property_read_bool(fwnode, "native-endian"))
656a06c488dSMark Brown 		endian = REGMAP_ENDIAN_NATIVE;
657cf673fbcSGeert Uytterhoeven 
658c916d6efSAndy Shevchenko 	/* If the endianness was specified in fwnode, use that */
659cf673fbcSGeert Uytterhoeven 	if (endian != REGMAP_ENDIAN_DEFAULT)
660cf673fbcSGeert Uytterhoeven 		return endian;
661cf673fbcSGeert Uytterhoeven 
662cf673fbcSGeert Uytterhoeven 	/* Retrieve the endianness specification from the bus config */
663cf673fbcSGeert Uytterhoeven 	if (bus && bus->val_format_endian_default)
664cf673fbcSGeert Uytterhoeven 		endian = bus->val_format_endian_default;
665cf673fbcSGeert Uytterhoeven 
666cf673fbcSGeert Uytterhoeven 	/* If the bus specified a non-default value, use that */
667cf673fbcSGeert Uytterhoeven 	if (endian != REGMAP_ENDIAN_DEFAULT)
668cf673fbcSGeert Uytterhoeven 		return endian;
669cf673fbcSGeert Uytterhoeven 
670cf673fbcSGeert Uytterhoeven 	/* Use this if no other value was found */
671cf673fbcSGeert Uytterhoeven 	return REGMAP_ENDIAN_BIG;
672d647c199SXiubo Li }
6733c174d29SGuenter Roeck EXPORT_SYMBOL_GPL(regmap_get_val_endian);
674d647c199SXiubo Li 
__regmap_init(struct device * dev,const struct regmap_bus * bus,void * bus_context,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)6753cfe7a74SNicolas Boichat struct regmap *__regmap_init(struct device *dev,
676b83a313bSMark Brown 			     const struct regmap_bus *bus,
6770135bbccSStephen Warren 			     void *bus_context,
6783cfe7a74SNicolas Boichat 			     const struct regmap_config *config,
6793cfe7a74SNicolas Boichat 			     struct lock_class_key *lock_key,
6803cfe7a74SNicolas Boichat 			     const char *lock_name)
681b83a313bSMark Brown {
6826cfec04bSMichal Simek 	struct regmap *map;
683d36cb020SCharles Keepax 	int ret = -EINVAL;
684141eba2eSStephen Warren 	enum regmap_endian reg_endian, val_endian;
6856863ca62SKrystian Garbaciak 	int i, j;
686b83a313bSMark Brown 
687d2a5884aSAndrey Smirnov 	if (!config)
688abbb18fbSLars-Peter Clausen 		goto err;
689b83a313bSMark Brown 
690b83a313bSMark Brown 	map = kzalloc(sizeof(*map), GFP_KERNEL);
691b83a313bSMark Brown 	if (map == NULL) {
692b83a313bSMark Brown 		ret = -ENOMEM;
693b83a313bSMark Brown 		goto err;
694b83a313bSMark Brown 	}
695b83a313bSMark Brown 
69694cc89ebSCharles Keepax 	ret = regmap_set_name(map, config);
69794cc89ebSCharles Keepax 	if (ret)
6988253bb3fSBartosz Golaszewski 		goto err_map;
6998253bb3fSBartosz Golaszewski 
7001d512ee8SCharles Keepax 	ret = -EINVAL; /* Later error paths rely on this */
7011d512ee8SCharles Keepax 
702c9b41fcfSBartosz Golaszewski 	if (config->disable_locking) {
70381e30b18SBartosz Golaszewski 		map->lock = map->unlock = regmap_lock_unlock_none;
70421f8e482SDmitry Osipenko 		map->can_sleep = config->can_sleep;
70572465736SMark Brown 		regmap_debugfs_disable(map);
706c9b41fcfSBartosz Golaszewski 	} else if (config->lock && config->unlock) {
7070d4529c5SDavide Ciminaghi 		map->lock = config->lock;
7080d4529c5SDavide Ciminaghi 		map->unlock = config->unlock;
7090d4529c5SDavide Ciminaghi 		map->lock_arg = config->lock_arg;
71021f8e482SDmitry Osipenko 		map->can_sleep = config->can_sleep;
711a4887813SBaolin Wang 	} else if (config->use_hwlock) {
7128698b936SBaolin Wang 		map->hwlock = hwspin_lock_request_specific(config->hwlock_id);
7138698b936SBaolin Wang 		if (!map->hwlock) {
7148698b936SBaolin Wang 			ret = -ENXIO;
7158253bb3fSBartosz Golaszewski 			goto err_name;
7168698b936SBaolin Wang 		}
7178698b936SBaolin Wang 
7188698b936SBaolin Wang 		switch (config->hwlock_mode) {
7198698b936SBaolin Wang 		case HWLOCK_IRQSTATE:
7208698b936SBaolin Wang 			map->lock = regmap_lock_hwlock_irqsave;
7218698b936SBaolin Wang 			map->unlock = regmap_unlock_hwlock_irqrestore;
7228698b936SBaolin Wang 			break;
7238698b936SBaolin Wang 		case HWLOCK_IRQ:
7248698b936SBaolin Wang 			map->lock = regmap_lock_hwlock_irq;
7258698b936SBaolin Wang 			map->unlock = regmap_unlock_hwlock_irq;
7268698b936SBaolin Wang 			break;
7278698b936SBaolin Wang 		default:
7288698b936SBaolin Wang 			map->lock = regmap_lock_hwlock;
7298698b936SBaolin Wang 			map->unlock = regmap_unlock_hwlock;
7308698b936SBaolin Wang 			break;
7318698b936SBaolin Wang 		}
7328698b936SBaolin Wang 
7338698b936SBaolin Wang 		map->lock_arg = map;
7340d4529c5SDavide Ciminaghi 	} else {
735d2a5884aSAndrey Smirnov 		if ((bus && bus->fast_io) ||
736d2a5884aSAndrey Smirnov 		    config->fast_io) {
73767021f25SVladimir Oltean 			if (config->use_raw_spinlock) {
73867021f25SVladimir Oltean 				raw_spin_lock_init(&map->raw_spinlock);
73967021f25SVladimir Oltean 				map->lock = regmap_lock_raw_spinlock;
74067021f25SVladimir Oltean 				map->unlock = regmap_unlock_raw_spinlock;
74167021f25SVladimir Oltean 				lockdep_set_class_and_name(&map->raw_spinlock,
74267021f25SVladimir Oltean 							   lock_key, lock_name);
74367021f25SVladimir Oltean 			} else {
744bacdbe07SStephen Warren 				spin_lock_init(&map->spinlock);
745bacdbe07SStephen Warren 				map->lock = regmap_lock_spinlock;
746bacdbe07SStephen Warren 				map->unlock = regmap_unlock_spinlock;
7473cfe7a74SNicolas Boichat 				lockdep_set_class_and_name(&map->spinlock,
7483cfe7a74SNicolas Boichat 							   lock_key, lock_name);
74967021f25SVladimir Oltean 			}
750bacdbe07SStephen Warren 		} else {
751bacdbe07SStephen Warren 			mutex_init(&map->mutex);
752bacdbe07SStephen Warren 			map->lock = regmap_lock_mutex;
753bacdbe07SStephen Warren 			map->unlock = regmap_unlock_mutex;
75421f8e482SDmitry Osipenko 			map->can_sleep = true;
7553cfe7a74SNicolas Boichat 			lockdep_set_class_and_name(&map->mutex,
7563cfe7a74SNicolas Boichat 						   lock_key, lock_name);
757bacdbe07SStephen Warren 		}
7580d4529c5SDavide Ciminaghi 		map->lock_arg = map;
7591ed9b927SCristian Ciocaltea 		map->lock_key = lock_key;
7600d4529c5SDavide Ciminaghi 	}
761b4a21fc2SStephen Boyd 
762b4a21fc2SStephen Boyd 	/*
763b4a21fc2SStephen Boyd 	 * When we write in fast-paths with regmap_bulk_write() don't allocate
764b4a21fc2SStephen Boyd 	 * scratch buffers with sleeping allocations.
765b4a21fc2SStephen Boyd 	 */
766b4a21fc2SStephen Boyd 	if ((bus && bus->fast_io) || config->fast_io)
767b4a21fc2SStephen Boyd 		map->alloc_flags = GFP_ATOMIC;
768b4a21fc2SStephen Boyd 	else
769b4a21fc2SStephen Boyd 		map->alloc_flags = GFP_KERNEL;
770b4a21fc2SStephen Boyd 
7710074f3f2SColin Foster 	map->reg_base = config->reg_base;
7729b3cd5c7SAndy Shevchenko 	map->reg_shift = config->pad_bits % 8;
7730074f3f2SColin Foster 
77482159ba8SMark Brown 	map->format.pad_bytes = config->pad_bits / 8;
7754a670ac3SMaxime Chevallier 	map->format.reg_shift = config->reg_shift;
7769b3cd5c7SAndy Shevchenko 	map->format.reg_bytes = BITS_TO_BYTES(config->reg_bits);
777a4a7d86bSAndy Shevchenko 	map->format.val_bytes = BITS_TO_BYTES(config->val_bits);
778a4a7d86bSAndy Shevchenko 	map->format.buf_size = BITS_TO_BYTES(config->reg_bits + config->val_bits + config->pad_bits);
779f01ee60fSStephen Warren 	if (config->reg_stride)
780f01ee60fSStephen Warren 		map->reg_stride = config->reg_stride;
781f01ee60fSStephen Warren 	else
782f01ee60fSStephen Warren 		map->reg_stride = 1;
783ca747be2SXiubo Li 	if (is_power_of_2(map->reg_stride))
784ca747be2SXiubo Li 		map->reg_stride_order = ilog2(map->reg_stride);
785ca747be2SXiubo Li 	else
786ca747be2SXiubo Li 		map->reg_stride_order = -1;
787d77e7456SMarek Vasut 	map->use_single_read = config->use_single_read || !(config->read || (bus && bus->read));
788d77e7456SMarek Vasut 	map->use_single_write = config->use_single_write || !(config->write || (bus && bus->write));
789d77e7456SMarek Vasut 	map->can_multi_write = config->can_multi_write && (config->write || (bus && bus->write));
79017649c90SSergey SENOZHATSKY 	if (bus) {
791adaac459SMarkus Pargmann 		map->max_raw_read = bus->max_raw_read;
792adaac459SMarkus Pargmann 		map->max_raw_write = bus->max_raw_write;
793d77e7456SMarek Vasut 	} else if (config->max_raw_read && config->max_raw_write) {
794d77e7456SMarek Vasut 		map->max_raw_read = config->max_raw_read;
795d77e7456SMarek Vasut 		map->max_raw_write = config->max_raw_write;
79617649c90SSergey SENOZHATSKY 	}
797b83a313bSMark Brown 	map->dev = dev;
798b83a313bSMark Brown 	map->bus = bus;
7990135bbccSStephen Warren 	map->bus_context = bus_context;
8002e2ae66dSMark Brown 	map->max_register = config->max_register;
8010ec74ad3SJan Dakinevich 	map->max_register_is_set = map->max_register ?: config->max_register_is_0;
80276aad392SDavide Ciminaghi 	map->wr_table = config->wr_table;
80376aad392SDavide Ciminaghi 	map->rd_table = config->rd_table;
80476aad392SDavide Ciminaghi 	map->volatile_table = config->volatile_table;
80576aad392SDavide Ciminaghi 	map->precious_table = config->precious_table;
806cdf6b11dSBen Whitten 	map->wr_noinc_table = config->wr_noinc_table;
80774fe7b55SCrestez Dan Leonard 	map->rd_noinc_table = config->rd_noinc_table;
8082e2ae66dSMark Brown 	map->writeable_reg = config->writeable_reg;
8092e2ae66dSMark Brown 	map->readable_reg = config->readable_reg;
8102e2ae66dSMark Brown 	map->volatile_reg = config->volatile_reg;
8112efe1642SMark Brown 	map->precious_reg = config->precious_reg;
812cdf6b11dSBen Whitten 	map->writeable_noinc_reg = config->writeable_noinc_reg;
81374fe7b55SCrestez Dan Leonard 	map->readable_noinc_reg = config->readable_noinc_reg;
8145d1729e7SDimitris Papastamos 	map->cache_type = config->cache_type;
815b83a313bSMark Brown 
8160d509f2bSMark Brown 	spin_lock_init(&map->async_lock);
8170d509f2bSMark Brown 	INIT_LIST_HEAD(&map->async_list);
8187e09a979SMark Brown 	INIT_LIST_HEAD(&map->async_free);
8190d509f2bSMark Brown 	init_waitqueue_head(&map->async_waitq);
8200d509f2bSMark Brown 
8219bf485c9SAndrew F. Davis 	if (config->read_flag_mask ||
8229bf485c9SAndrew F. Davis 	    config->write_flag_mask ||
8239bf485c9SAndrew F. Davis 	    config->zero_flag_mask) {
8246f306441SLars-Peter Clausen 		map->read_flag_mask = config->read_flag_mask;
8256f306441SLars-Peter Clausen 		map->write_flag_mask = config->write_flag_mask;
826d2a5884aSAndrey Smirnov 	} else if (bus) {
8276f306441SLars-Peter Clausen 		map->read_flag_mask = bus->read_flag_mask;
8286f306441SLars-Peter Clausen 	}
8296f306441SLars-Peter Clausen 
830d77e7456SMarek Vasut 	if (config && config->read && config->write) {
831d77e7456SMarek Vasut 		map->reg_read  = _regmap_bus_read;
832739f872eSChristian Marangi 		if (config->reg_update_bits)
833739f872eSChristian Marangi 			map->reg_update_bits = config->reg_update_bits;
834d77e7456SMarek Vasut 
835d77e7456SMarek Vasut 		/* Bulk read/write */
836d77e7456SMarek Vasut 		map->read = config->read;
837d77e7456SMarek Vasut 		map->write = config->write;
838d77e7456SMarek Vasut 
839d77e7456SMarek Vasut 		reg_endian = REGMAP_ENDIAN_NATIVE;
840d77e7456SMarek Vasut 		val_endian = REGMAP_ENDIAN_NATIVE;
841d77e7456SMarek Vasut 	} else if (!bus) {
842d2a5884aSAndrey Smirnov 		map->reg_read  = config->reg_read;
843d2a5884aSAndrey Smirnov 		map->reg_write = config->reg_write;
84402d6fdecSAnsuel Smith 		map->reg_update_bits = config->reg_update_bits;
845d2a5884aSAndrey Smirnov 
846d2a5884aSAndrey Smirnov 		map->defer_caching = false;
847d2a5884aSAndrey Smirnov 		goto skip_format_initialization;
8483ac17037SBoris BREZILLON 	} else if (!bus->read || !bus->write) {
8493ac17037SBoris BREZILLON 		map->reg_read = _regmap_bus_reg_read;
8503ac17037SBoris BREZILLON 		map->reg_write = _regmap_bus_reg_write;
85180215f13SBaolin Wang 		map->reg_update_bits = bus->reg_update_bits;
8523ac17037SBoris BREZILLON 
8533ac17037SBoris BREZILLON 		map->defer_caching = false;
8543ac17037SBoris BREZILLON 		goto skip_format_initialization;
855d2a5884aSAndrey Smirnov 	} else {
856ad278406SAndrey Smirnov 		map->reg_read  = _regmap_bus_read;
85777792b11SJon Ringle 		map->reg_update_bits = bus->reg_update_bits;
858d77e7456SMarek Vasut 		/* Bulk read/write */
859d77e7456SMarek Vasut 		map->read = bus->read;
860d77e7456SMarek Vasut 		map->write = bus->write;
861ad278406SAndrey Smirnov 
862cf673fbcSGeert Uytterhoeven 		reg_endian = regmap_get_reg_endian(bus, config);
863cf673fbcSGeert Uytterhoeven 		val_endian = regmap_get_val_endian(dev, bus, config);
864d77e7456SMarek Vasut 	}
865141eba2eSStephen Warren 
866d939fb9aSMarc Reilly 	switch (config->reg_bits + map->reg_shift) {
8679aa50750SWolfram Sang 	case 2:
8689aa50750SWolfram Sang 		switch (config->val_bits) {
8699aa50750SWolfram Sang 		case 6:
8709aa50750SWolfram Sang 			map->format.format_write = regmap_format_2_6_write;
8719aa50750SWolfram Sang 			break;
8729aa50750SWolfram Sang 		default:
8738698b936SBaolin Wang 			goto err_hwlock;
8749aa50750SWolfram Sang 		}
8759aa50750SWolfram Sang 		break;
8769aa50750SWolfram Sang 
877b83a313bSMark Brown 	case 4:
878b83a313bSMark Brown 		switch (config->val_bits) {
879b83a313bSMark Brown 		case 12:
880b83a313bSMark Brown 			map->format.format_write = regmap_format_4_12_write;
881b83a313bSMark Brown 			break;
882b83a313bSMark Brown 		default:
8838698b936SBaolin Wang 			goto err_hwlock;
884b83a313bSMark Brown 		}
885b83a313bSMark Brown 		break;
886b83a313bSMark Brown 
887b83a313bSMark Brown 	case 7:
888b83a313bSMark Brown 		switch (config->val_bits) {
889b83a313bSMark Brown 		case 9:
890b83a313bSMark Brown 			map->format.format_write = regmap_format_7_9_write;
891b83a313bSMark Brown 			break;
892b24412afSAntoniu Miclaus 		case 17:
893b24412afSAntoniu Miclaus 			map->format.format_write = regmap_format_7_17_write;
894b24412afSAntoniu Miclaus 			break;
895b83a313bSMark Brown 		default:
8968698b936SBaolin Wang 			goto err_hwlock;
897b83a313bSMark Brown 		}
898b83a313bSMark Brown 		break;
899b83a313bSMark Brown 
9007e5ec63eSLars-Peter Clausen 	case 10:
9017e5ec63eSLars-Peter Clausen 		switch (config->val_bits) {
9027e5ec63eSLars-Peter Clausen 		case 14:
9037e5ec63eSLars-Peter Clausen 			map->format.format_write = regmap_format_10_14_write;
9047e5ec63eSLars-Peter Clausen 			break;
9057e5ec63eSLars-Peter Clausen 		default:
9068698b936SBaolin Wang 			goto err_hwlock;
9077e5ec63eSLars-Peter Clausen 		}
9087e5ec63eSLars-Peter Clausen 		break;
9097e5ec63eSLars-Peter Clausen 
9100c2191c3SRicardo Ribalda 	case 12:
9110c2191c3SRicardo Ribalda 		switch (config->val_bits) {
9120c2191c3SRicardo Ribalda 		case 20:
9130c2191c3SRicardo Ribalda 			map->format.format_write = regmap_format_12_20_write;
9140c2191c3SRicardo Ribalda 			break;
9150c2191c3SRicardo Ribalda 		default:
9160c2191c3SRicardo Ribalda 			goto err_hwlock;
9170c2191c3SRicardo Ribalda 		}
9180c2191c3SRicardo Ribalda 		break;
9190c2191c3SRicardo Ribalda 
920b83a313bSMark Brown 	case 8:
921b83a313bSMark Brown 		map->format.format_reg = regmap_format_8;
922b83a313bSMark Brown 		break;
923b83a313bSMark Brown 
924b83a313bSMark Brown 	case 16:
925141eba2eSStephen Warren 		switch (reg_endian) {
926141eba2eSStephen Warren 		case REGMAP_ENDIAN_BIG:
927141eba2eSStephen Warren 			map->format.format_reg = regmap_format_16_be;
928141eba2eSStephen Warren 			break;
92955562449STony Lindgren 		case REGMAP_ENDIAN_LITTLE:
93055562449STony Lindgren 			map->format.format_reg = regmap_format_16_le;
93155562449STony Lindgren 			break;
932141eba2eSStephen Warren 		case REGMAP_ENDIAN_NATIVE:
933141eba2eSStephen Warren 			map->format.format_reg = regmap_format_16_native;
934141eba2eSStephen Warren 			break;
935141eba2eSStephen Warren 		default:
9368698b936SBaolin Wang 			goto err_hwlock;
937141eba2eSStephen Warren 		}
938b83a313bSMark Brown 		break;
939b83a313bSMark Brown 
940237019e7SLars-Peter Clausen 	case 24:
94106000443SAndy Shevchenko 		switch (reg_endian) {
94206000443SAndy Shevchenko 		case REGMAP_ENDIAN_BIG:
94306000443SAndy Shevchenko 			map->format.format_reg = regmap_format_24_be;
94406000443SAndy Shevchenko 			break;
94506000443SAndy Shevchenko 		default:
9468698b936SBaolin Wang 			goto err_hwlock;
94706000443SAndy Shevchenko 		}
948237019e7SLars-Peter Clausen 		break;
949237019e7SLars-Peter Clausen 
9507d5e525bSMark Brown 	case 32:
951141eba2eSStephen Warren 		switch (reg_endian) {
952141eba2eSStephen Warren 		case REGMAP_ENDIAN_BIG:
953141eba2eSStephen Warren 			map->format.format_reg = regmap_format_32_be;
954141eba2eSStephen Warren 			break;
95555562449STony Lindgren 		case REGMAP_ENDIAN_LITTLE:
95655562449STony Lindgren 			map->format.format_reg = regmap_format_32_le;
95755562449STony Lindgren 			break;
958141eba2eSStephen Warren 		case REGMAP_ENDIAN_NATIVE:
959141eba2eSStephen Warren 			map->format.format_reg = regmap_format_32_native;
960141eba2eSStephen Warren 			break;
961141eba2eSStephen Warren 		default:
9628698b936SBaolin Wang 			goto err_hwlock;
963141eba2eSStephen Warren 		}
9647d5e525bSMark Brown 		break;
9657d5e525bSMark Brown 
966b83a313bSMark Brown 	default:
9678698b936SBaolin Wang 		goto err_hwlock;
968b83a313bSMark Brown 	}
969b83a313bSMark Brown 
9708a819ff8SMark Brown 	if (val_endian == REGMAP_ENDIAN_NATIVE)
9718a819ff8SMark Brown 		map->format.parse_inplace = regmap_parse_inplace_noop;
9728a819ff8SMark Brown 
973b83a313bSMark Brown 	switch (config->val_bits) {
974b83a313bSMark Brown 	case 8:
975b83a313bSMark Brown 		map->format.format_val = regmap_format_8;
976b83a313bSMark Brown 		map->format.parse_val = regmap_parse_8;
9778a819ff8SMark Brown 		map->format.parse_inplace = regmap_parse_inplace_noop;
978b83a313bSMark Brown 		break;
979b83a313bSMark Brown 	case 16:
980141eba2eSStephen Warren 		switch (val_endian) {
981141eba2eSStephen Warren 		case REGMAP_ENDIAN_BIG:
982141eba2eSStephen Warren 			map->format.format_val = regmap_format_16_be;
983141eba2eSStephen Warren 			map->format.parse_val = regmap_parse_16_be;
9848a819ff8SMark Brown 			map->format.parse_inplace = regmap_parse_16_be_inplace;
985141eba2eSStephen Warren 			break;
9864aa8c069SXiubo Li 		case REGMAP_ENDIAN_LITTLE:
9874aa8c069SXiubo Li 			map->format.format_val = regmap_format_16_le;
9884aa8c069SXiubo Li 			map->format.parse_val = regmap_parse_16_le;
9894aa8c069SXiubo Li 			map->format.parse_inplace = regmap_parse_16_le_inplace;
9904aa8c069SXiubo Li 			break;
991141eba2eSStephen Warren 		case REGMAP_ENDIAN_NATIVE:
992141eba2eSStephen Warren 			map->format.format_val = regmap_format_16_native;
993141eba2eSStephen Warren 			map->format.parse_val = regmap_parse_16_native;
994141eba2eSStephen Warren 			break;
995141eba2eSStephen Warren 		default:
9968698b936SBaolin Wang 			goto err_hwlock;
997141eba2eSStephen Warren 		}
998b83a313bSMark Brown 		break;
999ea279fc5SMarc Reilly 	case 24:
100006000443SAndy Shevchenko 		switch (val_endian) {
100106000443SAndy Shevchenko 		case REGMAP_ENDIAN_BIG:
100206000443SAndy Shevchenko 			map->format.format_val = regmap_format_24_be;
100306000443SAndy Shevchenko 			map->format.parse_val = regmap_parse_24_be;
100406000443SAndy Shevchenko 			break;
100506000443SAndy Shevchenko 		default:
10068698b936SBaolin Wang 			goto err_hwlock;
100706000443SAndy Shevchenko 		}
1008ea279fc5SMarc Reilly 		break;
10097d5e525bSMark Brown 	case 32:
1010141eba2eSStephen Warren 		switch (val_endian) {
1011141eba2eSStephen Warren 		case REGMAP_ENDIAN_BIG:
1012141eba2eSStephen Warren 			map->format.format_val = regmap_format_32_be;
1013141eba2eSStephen Warren 			map->format.parse_val = regmap_parse_32_be;
10148a819ff8SMark Brown 			map->format.parse_inplace = regmap_parse_32_be_inplace;
1015141eba2eSStephen Warren 			break;
10164aa8c069SXiubo Li 		case REGMAP_ENDIAN_LITTLE:
10174aa8c069SXiubo Li 			map->format.format_val = regmap_format_32_le;
10184aa8c069SXiubo Li 			map->format.parse_val = regmap_parse_32_le;
10194aa8c069SXiubo Li 			map->format.parse_inplace = regmap_parse_32_le_inplace;
10204aa8c069SXiubo Li 			break;
1021141eba2eSStephen Warren 		case REGMAP_ENDIAN_NATIVE:
1022141eba2eSStephen Warren 			map->format.format_val = regmap_format_32_native;
1023141eba2eSStephen Warren 			map->format.parse_val = regmap_parse_32_native;
1024141eba2eSStephen Warren 			break;
1025141eba2eSStephen Warren 		default:
10268698b936SBaolin Wang 			goto err_hwlock;
1027141eba2eSStephen Warren 		}
10287d5e525bSMark Brown 		break;
1029b83a313bSMark Brown 	}
1030b83a313bSMark Brown 
1031141eba2eSStephen Warren 	if (map->format.format_write) {
1032141eba2eSStephen Warren 		if ((reg_endian != REGMAP_ENDIAN_BIG) ||
1033141eba2eSStephen Warren 		    (val_endian != REGMAP_ENDIAN_BIG))
10348698b936SBaolin Wang 			goto err_hwlock;
103567921a1aSMarkus Pargmann 		map->use_single_write = true;
1036141eba2eSStephen Warren 	}
10377a647614SMark Brown 
1038b83a313bSMark Brown 	if (!map->format.format_write &&
1039b83a313bSMark Brown 	    !(map->format.format_reg && map->format.format_val))
10408698b936SBaolin Wang 		goto err_hwlock;
1041b83a313bSMark Brown 
104282159ba8SMark Brown 	map->work_buf = kzalloc(map->format.buf_size, GFP_KERNEL);
1043b83a313bSMark Brown 	if (map->work_buf == NULL) {
1044b83a313bSMark Brown 		ret = -ENOMEM;
10458698b936SBaolin Wang 		goto err_hwlock;
1046b83a313bSMark Brown 	}
1047b83a313bSMark Brown 
1048d2a5884aSAndrey Smirnov 	if (map->format.format_write) {
1049d2a5884aSAndrey Smirnov 		map->defer_caching = false;
105007c320dcSAndrey Smirnov 		map->reg_write = _regmap_bus_formatted_write;
1051d2a5884aSAndrey Smirnov 	} else if (map->format.format_val) {
1052d2a5884aSAndrey Smirnov 		map->defer_caching = true;
105307c320dcSAndrey Smirnov 		map->reg_write = _regmap_bus_raw_write;
1054d2a5884aSAndrey Smirnov 	}
1055d2a5884aSAndrey Smirnov 
1056d2a5884aSAndrey Smirnov skip_format_initialization:
105707c320dcSAndrey Smirnov 
10586863ca62SKrystian Garbaciak 	map->range_tree = RB_ROOT;
1059e3549cd0SMark Brown 	for (i = 0; i < config->num_ranges; i++) {
10606863ca62SKrystian Garbaciak 		const struct regmap_range_cfg *range_cfg = &config->ranges[i];
10616863ca62SKrystian Garbaciak 		struct regmap_range_node *new;
10626863ca62SKrystian Garbaciak 
10636863ca62SKrystian Garbaciak 		/* Sanity check */
1064061adc06SMark Brown 		if (range_cfg->range_max < range_cfg->range_min) {
10653f1aa0c5SMark Brown 			dev_err(map->dev, "Invalid range %d: %u < %u\n", i,
1066061adc06SMark Brown 				range_cfg->range_max, range_cfg->range_min);
10676863ca62SKrystian Garbaciak 			goto err_range;
1068061adc06SMark Brown 		}
1069061adc06SMark Brown 
1070061adc06SMark Brown 		if (range_cfg->range_max > map->max_register) {
10713f1aa0c5SMark Brown 			dev_err(map->dev, "Invalid range %d: %u > %u\n", i,
1072061adc06SMark Brown 				range_cfg->range_max, map->max_register);
1073061adc06SMark Brown 			goto err_range;
1074061adc06SMark Brown 		}
1075061adc06SMark Brown 
1076061adc06SMark Brown 		if (range_cfg->selector_reg > map->max_register) {
1077061adc06SMark Brown 			dev_err(map->dev,
1078061adc06SMark Brown 				"Invalid range %d: selector out of map\n", i);
1079061adc06SMark Brown 			goto err_range;
1080061adc06SMark Brown 		}
1081061adc06SMark Brown 
1082061adc06SMark Brown 		if (range_cfg->window_len == 0) {
1083061adc06SMark Brown 			dev_err(map->dev, "Invalid range %d: window_len 0\n",
1084061adc06SMark Brown 				i);
1085061adc06SMark Brown 			goto err_range;
1086061adc06SMark Brown 		}
10876863ca62SKrystian Garbaciak 
10886863ca62SKrystian Garbaciak 		/* Make sure, that this register range has no selector
10896863ca62SKrystian Garbaciak 		   or data window within its boundary */
1090e3549cd0SMark Brown 		for (j = 0; j < config->num_ranges; j++) {
1091d63aa09fSJinchao Wang 			unsigned int sel_reg = config->ranges[j].selector_reg;
1092d63aa09fSJinchao Wang 			unsigned int win_min = config->ranges[j].window_start;
1093d63aa09fSJinchao Wang 			unsigned int win_max = win_min +
10946863ca62SKrystian Garbaciak 					       config->ranges[j].window_len - 1;
10956863ca62SKrystian Garbaciak 
1096f161d220SPhilipp Zabel 			/* Allow data window inside its own virtual range */
1097f161d220SPhilipp Zabel 			if (j == i)
1098f161d220SPhilipp Zabel 				continue;
1099f161d220SPhilipp Zabel 
11006863ca62SKrystian Garbaciak 			if (range_cfg->range_min <= sel_reg &&
11016863ca62SKrystian Garbaciak 			    sel_reg <= range_cfg->range_max) {
1102061adc06SMark Brown 				dev_err(map->dev,
1103061adc06SMark Brown 					"Range %d: selector for %d in window\n",
1104061adc06SMark Brown 					i, j);
11056863ca62SKrystian Garbaciak 				goto err_range;
11066863ca62SKrystian Garbaciak 			}
11076863ca62SKrystian Garbaciak 
11086863ca62SKrystian Garbaciak 			if (!(win_max < range_cfg->range_min ||
11096863ca62SKrystian Garbaciak 			      win_min > range_cfg->range_max)) {
1110061adc06SMark Brown 				dev_err(map->dev,
1111061adc06SMark Brown 					"Range %d: window for %d in window\n",
1112061adc06SMark Brown 					i, j);
11136863ca62SKrystian Garbaciak 				goto err_range;
11146863ca62SKrystian Garbaciak 			}
11156863ca62SKrystian Garbaciak 		}
11166863ca62SKrystian Garbaciak 
11176863ca62SKrystian Garbaciak 		new = kzalloc(sizeof(*new), GFP_KERNEL);
11186863ca62SKrystian Garbaciak 		if (new == NULL) {
11196863ca62SKrystian Garbaciak 			ret = -ENOMEM;
11206863ca62SKrystian Garbaciak 			goto err_range;
11216863ca62SKrystian Garbaciak 		}
11226863ca62SKrystian Garbaciak 
11234b020b3fSMark Brown 		new->map = map;
1124d058bb49SMark Brown 		new->name = range_cfg->name;
11256863ca62SKrystian Garbaciak 		new->range_min = range_cfg->range_min;
11266863ca62SKrystian Garbaciak 		new->range_max = range_cfg->range_max;
11276863ca62SKrystian Garbaciak 		new->selector_reg = range_cfg->selector_reg;
11286863ca62SKrystian Garbaciak 		new->selector_mask = range_cfg->selector_mask;
11296863ca62SKrystian Garbaciak 		new->selector_shift = range_cfg->selector_shift;
11306863ca62SKrystian Garbaciak 		new->window_start = range_cfg->window_start;
11316863ca62SKrystian Garbaciak 		new->window_len = range_cfg->window_len;
11326863ca62SKrystian Garbaciak 
113353e87f88SNenghua Cao 		if (!_regmap_range_add(map, new)) {
1134061adc06SMark Brown 			dev_err(map->dev, "Failed to add range %d\n", i);
11356863ca62SKrystian Garbaciak 			kfree(new);
11366863ca62SKrystian Garbaciak 			goto err_range;
11376863ca62SKrystian Garbaciak 		}
11386863ca62SKrystian Garbaciak 
11396863ca62SKrystian Garbaciak 		if (map->selector_work_buf == NULL) {
11406863ca62SKrystian Garbaciak 			map->selector_work_buf =
11416863ca62SKrystian Garbaciak 				kzalloc(map->format.buf_size, GFP_KERNEL);
11426863ca62SKrystian Garbaciak 			if (map->selector_work_buf == NULL) {
11436863ca62SKrystian Garbaciak 				ret = -ENOMEM;
11446863ca62SKrystian Garbaciak 				goto err_range;
11456863ca62SKrystian Garbaciak 			}
11466863ca62SKrystian Garbaciak 		}
11476863ca62SKrystian Garbaciak 	}
1148052d2cd1SMark Brown 
1149e5e3b8abSLars-Peter Clausen 	ret = regcache_init(map, config);
11500ff3e62fSMark Brown 	if (ret != 0)
11516863ca62SKrystian Garbaciak 		goto err_range;
11526863ca62SKrystian Garbaciak 
1153a7a037c8SDaeseok Youn 	if (dev) {
11546cfec04bSMichal Simek 		ret = regmap_attach_dev(dev, map, config);
11556cfec04bSMichal Simek 		if (ret != 0)
11566cfec04bSMichal Simek 			goto err_regcache;
11579b947a13SDavid Lechner 	} else {
115894cc89ebSCharles Keepax 		regmap_debugfs_init(map);
1159a7a037c8SDaeseok Youn 	}
116072b39f6fSMark Brown 
1161b83a313bSMark Brown 	return map;
1162b83a313bSMark Brown 
11636cfec04bSMichal Simek err_regcache:
116472b39f6fSMark Brown 	regcache_exit(map);
11656863ca62SKrystian Garbaciak err_range:
11666863ca62SKrystian Garbaciak 	regmap_range_exit(map);
116758072cbfSLars-Peter Clausen 	kfree(map->work_buf);
11688698b936SBaolin Wang err_hwlock:
1169a1a68fcaSBaolin Wang 	if (map->hwlock)
11708698b936SBaolin Wang 		hwspin_lock_free(map->hwlock);
11718253bb3fSBartosz Golaszewski err_name:
11728253bb3fSBartosz Golaszewski 	kfree_const(map->name);
1173b83a313bSMark Brown err_map:
1174b83a313bSMark Brown 	kfree(map);
1175b83a313bSMark Brown err:
1176b83a313bSMark Brown 	return ERR_PTR(ret);
1177b83a313bSMark Brown }
11783cfe7a74SNicolas Boichat EXPORT_SYMBOL_GPL(__regmap_init);
1179b83a313bSMark Brown 
devm_regmap_release(struct device * dev,void * res)1180c0eb4676SMark Brown static void devm_regmap_release(struct device *dev, void *res)
1181c0eb4676SMark Brown {
1182c0eb4676SMark Brown 	regmap_exit(*(struct regmap **)res);
1183c0eb4676SMark Brown }
1184c0eb4676SMark Brown 
__devm_regmap_init(struct device * dev,const struct regmap_bus * bus,void * bus_context,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)11853cfe7a74SNicolas Boichat struct regmap *__devm_regmap_init(struct device *dev,
1186c0eb4676SMark Brown 				  const struct regmap_bus *bus,
11870135bbccSStephen Warren 				  void *bus_context,
11883cfe7a74SNicolas Boichat 				  const struct regmap_config *config,
11893cfe7a74SNicolas Boichat 				  struct lock_class_key *lock_key,
11903cfe7a74SNicolas Boichat 				  const char *lock_name)
1191c0eb4676SMark Brown {
1192c0eb4676SMark Brown 	struct regmap **ptr, *regmap;
1193c0eb4676SMark Brown 
1194c0eb4676SMark Brown 	ptr = devres_alloc(devm_regmap_release, sizeof(*ptr), GFP_KERNEL);
1195c0eb4676SMark Brown 	if (!ptr)
1196c0eb4676SMark Brown 		return ERR_PTR(-ENOMEM);
1197c0eb4676SMark Brown 
11983cfe7a74SNicolas Boichat 	regmap = __regmap_init(dev, bus, bus_context, config,
11993cfe7a74SNicolas Boichat 			       lock_key, lock_name);
1200c0eb4676SMark Brown 	if (!IS_ERR(regmap)) {
1201c0eb4676SMark Brown 		*ptr = regmap;
1202c0eb4676SMark Brown 		devres_add(dev, ptr);
1203c0eb4676SMark Brown 	} else {
1204c0eb4676SMark Brown 		devres_free(ptr);
1205c0eb4676SMark Brown 	}
1206c0eb4676SMark Brown 
1207c0eb4676SMark Brown 	return regmap;
1208c0eb4676SMark Brown }
12093cfe7a74SNicolas Boichat EXPORT_SYMBOL_GPL(__devm_regmap_init);
1210c0eb4676SMark Brown 
regmap_field_init(struct regmap_field * rm_field,struct regmap * regmap,struct reg_field reg_field)121167252287SSrinivas Kandagatla static void regmap_field_init(struct regmap_field *rm_field,
121267252287SSrinivas Kandagatla 	struct regmap *regmap, struct reg_field reg_field)
121367252287SSrinivas Kandagatla {
121467252287SSrinivas Kandagatla 	rm_field->regmap = regmap;
121567252287SSrinivas Kandagatla 	rm_field->reg = reg_field.reg;
121667252287SSrinivas Kandagatla 	rm_field->shift = reg_field.lsb;
1217921cc294SMaxime Coquelin 	rm_field->mask = GENMASK(reg_field.msb, reg_field.lsb);
1218cf39ed2eSMatt Ranostay 
1219cf39ed2eSMatt Ranostay 	WARN_ONCE(rm_field->mask == 0, "invalid empty mask defined\n");
1220cf39ed2eSMatt Ranostay 
1221a0102375SKuninori Morimoto 	rm_field->id_size = reg_field.id_size;
1222a0102375SKuninori Morimoto 	rm_field->id_offset = reg_field.id_offset;
122367252287SSrinivas Kandagatla }
122467252287SSrinivas Kandagatla 
122567252287SSrinivas Kandagatla /**
12262cf8e2dfSCharles Keepax  * devm_regmap_field_alloc() - Allocate and initialise a register field.
122767252287SSrinivas Kandagatla  *
122867252287SSrinivas Kandagatla  * @dev: Device that will be interacted with
122967252287SSrinivas Kandagatla  * @regmap: regmap bank in which this register field is located.
123067252287SSrinivas Kandagatla  * @reg_field: Register field with in the bank.
123167252287SSrinivas Kandagatla  *
123267252287SSrinivas Kandagatla  * The return value will be an ERR_PTR() on error or a valid pointer
123367252287SSrinivas Kandagatla  * to a struct regmap_field. The regmap_field will be automatically freed
123467252287SSrinivas Kandagatla  * by the device management code.
123567252287SSrinivas Kandagatla  */
devm_regmap_field_alloc(struct device * dev,struct regmap * regmap,struct reg_field reg_field)123667252287SSrinivas Kandagatla struct regmap_field *devm_regmap_field_alloc(struct device *dev,
123767252287SSrinivas Kandagatla 		struct regmap *regmap, struct reg_field reg_field)
123867252287SSrinivas Kandagatla {
123967252287SSrinivas Kandagatla 	struct regmap_field *rm_field = devm_kzalloc(dev,
124067252287SSrinivas Kandagatla 					sizeof(*rm_field), GFP_KERNEL);
124167252287SSrinivas Kandagatla 	if (!rm_field)
124267252287SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
124367252287SSrinivas Kandagatla 
124467252287SSrinivas Kandagatla 	regmap_field_init(rm_field, regmap, reg_field);
124567252287SSrinivas Kandagatla 
124667252287SSrinivas Kandagatla 	return rm_field;
124767252287SSrinivas Kandagatla 
124867252287SSrinivas Kandagatla }
124967252287SSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
125067252287SSrinivas Kandagatla 
1251ea470b82SSrinivas Kandagatla 
1252ea470b82SSrinivas Kandagatla /**
1253ea470b82SSrinivas Kandagatla  * regmap_field_bulk_alloc() - Allocate and initialise a bulk register field.
1254ea470b82SSrinivas Kandagatla  *
1255ea470b82SSrinivas Kandagatla  * @regmap: regmap bank in which this register field is located.
1256ea470b82SSrinivas Kandagatla  * @rm_field: regmap register fields within the bank.
1257ea470b82SSrinivas Kandagatla  * @reg_field: Register fields within the bank.
1258ea470b82SSrinivas Kandagatla  * @num_fields: Number of register fields.
1259ea470b82SSrinivas Kandagatla  *
1260ea470b82SSrinivas Kandagatla  * The return value will be an -ENOMEM on error or zero for success.
1261ea470b82SSrinivas Kandagatla  * Newly allocated regmap_fields should be freed by calling
1262ea470b82SSrinivas Kandagatla  * regmap_field_bulk_free()
1263ea470b82SSrinivas Kandagatla  */
regmap_field_bulk_alloc(struct regmap * regmap,struct regmap_field ** rm_field,const struct reg_field * reg_field,int num_fields)1264ea470b82SSrinivas Kandagatla int regmap_field_bulk_alloc(struct regmap *regmap,
1265ea470b82SSrinivas Kandagatla 			    struct regmap_field **rm_field,
126629c34975SIcenowy Zheng 			    const struct reg_field *reg_field,
1267ea470b82SSrinivas Kandagatla 			    int num_fields)
1268ea470b82SSrinivas Kandagatla {
1269ea470b82SSrinivas Kandagatla 	struct regmap_field *rf;
1270ea470b82SSrinivas Kandagatla 	int i;
1271ea470b82SSrinivas Kandagatla 
1272ea470b82SSrinivas Kandagatla 	rf = kcalloc(num_fields, sizeof(*rf), GFP_KERNEL);
1273ea470b82SSrinivas Kandagatla 	if (!rf)
1274ea470b82SSrinivas Kandagatla 		return -ENOMEM;
1275ea470b82SSrinivas Kandagatla 
1276ea470b82SSrinivas Kandagatla 	for (i = 0; i < num_fields; i++) {
1277ea470b82SSrinivas Kandagatla 		regmap_field_init(&rf[i], regmap, reg_field[i]);
1278ea470b82SSrinivas Kandagatla 		rm_field[i] = &rf[i];
1279ea470b82SSrinivas Kandagatla 	}
1280ea470b82SSrinivas Kandagatla 
1281ea470b82SSrinivas Kandagatla 	return 0;
1282ea470b82SSrinivas Kandagatla }
1283ea470b82SSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_field_bulk_alloc);
1284ea470b82SSrinivas Kandagatla 
1285ea470b82SSrinivas Kandagatla /**
1286ea470b82SSrinivas Kandagatla  * devm_regmap_field_bulk_alloc() - Allocate and initialise a bulk register
1287ea470b82SSrinivas Kandagatla  * fields.
1288ea470b82SSrinivas Kandagatla  *
1289ea470b82SSrinivas Kandagatla  * @dev: Device that will be interacted with
1290ea470b82SSrinivas Kandagatla  * @regmap: regmap bank in which this register field is located.
1291ea470b82SSrinivas Kandagatla  * @rm_field: regmap register fields within the bank.
1292ea470b82SSrinivas Kandagatla  * @reg_field: Register fields within the bank.
1293ea470b82SSrinivas Kandagatla  * @num_fields: Number of register fields.
1294ea470b82SSrinivas Kandagatla  *
1295ea470b82SSrinivas Kandagatla  * The return value will be an -ENOMEM on error or zero for success.
1296ea470b82SSrinivas Kandagatla  * Newly allocated regmap_fields will be automatically freed by the
1297ea470b82SSrinivas Kandagatla  * device management code.
1298ea470b82SSrinivas Kandagatla  */
devm_regmap_field_bulk_alloc(struct device * dev,struct regmap * regmap,struct regmap_field ** rm_field,const struct reg_field * reg_field,int num_fields)1299ea470b82SSrinivas Kandagatla int devm_regmap_field_bulk_alloc(struct device *dev,
1300ea470b82SSrinivas Kandagatla 				 struct regmap *regmap,
1301ea470b82SSrinivas Kandagatla 				 struct regmap_field **rm_field,
130229c34975SIcenowy Zheng 				 const struct reg_field *reg_field,
1303ea470b82SSrinivas Kandagatla 				 int num_fields)
1304ea470b82SSrinivas Kandagatla {
1305ea470b82SSrinivas Kandagatla 	struct regmap_field *rf;
1306ea470b82SSrinivas Kandagatla 	int i;
1307ea470b82SSrinivas Kandagatla 
1308ea470b82SSrinivas Kandagatla 	rf = devm_kcalloc(dev, num_fields, sizeof(*rf), GFP_KERNEL);
1309ea470b82SSrinivas Kandagatla 	if (!rf)
1310ea470b82SSrinivas Kandagatla 		return -ENOMEM;
1311ea470b82SSrinivas Kandagatla 
1312ea470b82SSrinivas Kandagatla 	for (i = 0; i < num_fields; i++) {
1313ea470b82SSrinivas Kandagatla 		regmap_field_init(&rf[i], regmap, reg_field[i]);
1314ea470b82SSrinivas Kandagatla 		rm_field[i] = &rf[i];
1315ea470b82SSrinivas Kandagatla 	}
1316ea470b82SSrinivas Kandagatla 
1317ea470b82SSrinivas Kandagatla 	return 0;
1318ea470b82SSrinivas Kandagatla }
1319ea470b82SSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_regmap_field_bulk_alloc);
1320ea470b82SSrinivas Kandagatla 
1321ea470b82SSrinivas Kandagatla /**
1322ea470b82SSrinivas Kandagatla  * regmap_field_bulk_free() - Free register field allocated using
1323ea470b82SSrinivas Kandagatla  *                       regmap_field_bulk_alloc.
1324ea470b82SSrinivas Kandagatla  *
1325ea470b82SSrinivas Kandagatla  * @field: regmap fields which should be freed.
1326ea470b82SSrinivas Kandagatla  */
regmap_field_bulk_free(struct regmap_field * field)1327ea470b82SSrinivas Kandagatla void regmap_field_bulk_free(struct regmap_field *field)
1328ea470b82SSrinivas Kandagatla {
1329ea470b82SSrinivas Kandagatla 	kfree(field);
1330ea470b82SSrinivas Kandagatla }
1331ea470b82SSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_field_bulk_free);
1332ea470b82SSrinivas Kandagatla 
1333ea470b82SSrinivas Kandagatla /**
1334ea470b82SSrinivas Kandagatla  * devm_regmap_field_bulk_free() - Free a bulk register field allocated using
1335ea470b82SSrinivas Kandagatla  *                            devm_regmap_field_bulk_alloc.
1336ea470b82SSrinivas Kandagatla  *
1337ea470b82SSrinivas Kandagatla  * @dev: Device that will be interacted with
1338ea470b82SSrinivas Kandagatla  * @field: regmap field which should be freed.
1339ea470b82SSrinivas Kandagatla  *
1340ea470b82SSrinivas Kandagatla  * Free register field allocated using devm_regmap_field_bulk_alloc(). Usually
1341ea470b82SSrinivas Kandagatla  * drivers need not call this function, as the memory allocated via devm
1342ea470b82SSrinivas Kandagatla  * will be freed as per device-driver life-cycle.
1343ea470b82SSrinivas Kandagatla  */
devm_regmap_field_bulk_free(struct device * dev,struct regmap_field * field)1344ea470b82SSrinivas Kandagatla void devm_regmap_field_bulk_free(struct device *dev,
1345ea470b82SSrinivas Kandagatla 				 struct regmap_field *field)
1346ea470b82SSrinivas Kandagatla {
1347ea470b82SSrinivas Kandagatla 	devm_kfree(dev, field);
1348ea470b82SSrinivas Kandagatla }
1349ea470b82SSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_regmap_field_bulk_free);
1350ea470b82SSrinivas Kandagatla 
135167252287SSrinivas Kandagatla /**
13522cf8e2dfSCharles Keepax  * devm_regmap_field_free() - Free a register field allocated using
13532cf8e2dfSCharles Keepax  *                            devm_regmap_field_alloc.
135467252287SSrinivas Kandagatla  *
135567252287SSrinivas Kandagatla  * @dev: Device that will be interacted with
135667252287SSrinivas Kandagatla  * @field: regmap field which should be freed.
13572cf8e2dfSCharles Keepax  *
13582cf8e2dfSCharles Keepax  * Free register field allocated using devm_regmap_field_alloc(). Usually
13592cf8e2dfSCharles Keepax  * drivers need not call this function, as the memory allocated via devm
13602cf8e2dfSCharles Keepax  * will be freed as per device-driver life-cyle.
136167252287SSrinivas Kandagatla  */
devm_regmap_field_free(struct device * dev,struct regmap_field * field)136267252287SSrinivas Kandagatla void devm_regmap_field_free(struct device *dev,
136367252287SSrinivas Kandagatla 	struct regmap_field *field)
136467252287SSrinivas Kandagatla {
136567252287SSrinivas Kandagatla 	devm_kfree(dev, field);
136667252287SSrinivas Kandagatla }
136767252287SSrinivas Kandagatla EXPORT_SYMBOL_GPL(devm_regmap_field_free);
136867252287SSrinivas Kandagatla 
136967252287SSrinivas Kandagatla /**
13702cf8e2dfSCharles Keepax  * regmap_field_alloc() - Allocate and initialise a register field.
137167252287SSrinivas Kandagatla  *
137267252287SSrinivas Kandagatla  * @regmap: regmap bank in which this register field is located.
137367252287SSrinivas Kandagatla  * @reg_field: Register field with in the bank.
137467252287SSrinivas Kandagatla  *
137567252287SSrinivas Kandagatla  * The return value will be an ERR_PTR() on error or a valid pointer
137667252287SSrinivas Kandagatla  * to a struct regmap_field. The regmap_field should be freed by the
137767252287SSrinivas Kandagatla  * user once its finished working with it using regmap_field_free().
137867252287SSrinivas Kandagatla  */
regmap_field_alloc(struct regmap * regmap,struct reg_field reg_field)137967252287SSrinivas Kandagatla struct regmap_field *regmap_field_alloc(struct regmap *regmap,
138067252287SSrinivas Kandagatla 		struct reg_field reg_field)
138167252287SSrinivas Kandagatla {
138267252287SSrinivas Kandagatla 	struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
138367252287SSrinivas Kandagatla 
138467252287SSrinivas Kandagatla 	if (!rm_field)
138567252287SSrinivas Kandagatla 		return ERR_PTR(-ENOMEM);
138667252287SSrinivas Kandagatla 
138767252287SSrinivas Kandagatla 	regmap_field_init(rm_field, regmap, reg_field);
138867252287SSrinivas Kandagatla 
138967252287SSrinivas Kandagatla 	return rm_field;
139067252287SSrinivas Kandagatla }
139167252287SSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_field_alloc);
139267252287SSrinivas Kandagatla 
139367252287SSrinivas Kandagatla /**
13942cf8e2dfSCharles Keepax  * regmap_field_free() - Free register field allocated using
13952cf8e2dfSCharles Keepax  *                       regmap_field_alloc.
139667252287SSrinivas Kandagatla  *
139767252287SSrinivas Kandagatla  * @field: regmap field which should be freed.
139867252287SSrinivas Kandagatla  */
regmap_field_free(struct regmap_field * field)139967252287SSrinivas Kandagatla void regmap_field_free(struct regmap_field *field)
140067252287SSrinivas Kandagatla {
140167252287SSrinivas Kandagatla 	kfree(field);
140267252287SSrinivas Kandagatla }
140367252287SSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_field_free);
140467252287SSrinivas Kandagatla 
1405b83a313bSMark Brown /**
14062cf8e2dfSCharles Keepax  * regmap_reinit_cache() - Reinitialise the current register cache
1407bf315173SMark Brown  *
1408bf315173SMark Brown  * @map: Register map to operate on.
1409bf315173SMark Brown  * @config: New configuration.  Only the cache data will be used.
1410bf315173SMark Brown  *
1411bf315173SMark Brown  * Discard any existing register cache for the map and initialize a
1412bf315173SMark Brown  * new cache.  This can be used to restore the cache to defaults or to
1413bf315173SMark Brown  * update the cache configuration to reflect runtime discovery of the
1414bf315173SMark Brown  * hardware.
14154d879514SDimitris Papastamos  *
14164d879514SDimitris Papastamos  * No explicit locking is done here, the user needs to ensure that
14174d879514SDimitris Papastamos  * this function will not race with other calls to regmap.
1418bf315173SMark Brown  */
regmap_reinit_cache(struct regmap * map,const struct regmap_config * config)1419bf315173SMark Brown int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
1420bf315173SMark Brown {
142194cc89ebSCharles Keepax 	int ret;
142294cc89ebSCharles Keepax 
1423bf315173SMark Brown 	regcache_exit(map);
1424a24f64a6SMark Brown 	regmap_debugfs_exit(map);
1425bf315173SMark Brown 
1426bf315173SMark Brown 	map->max_register = config->max_register;
14270ec74ad3SJan Dakinevich 	map->max_register_is_set = map->max_register ?: config->max_register_is_0;
1428bf315173SMark Brown 	map->writeable_reg = config->writeable_reg;
1429bf315173SMark Brown 	map->readable_reg = config->readable_reg;
1430bf315173SMark Brown 	map->volatile_reg = config->volatile_reg;
1431bf315173SMark Brown 	map->precious_reg = config->precious_reg;
1432cdf6b11dSBen Whitten 	map->writeable_noinc_reg = config->writeable_noinc_reg;
143374fe7b55SCrestez Dan Leonard 	map->readable_noinc_reg = config->readable_noinc_reg;
1434bf315173SMark Brown 	map->cache_type = config->cache_type;
1435bf315173SMark Brown 
143694cc89ebSCharles Keepax 	ret = regmap_set_name(map, config);
143794cc89ebSCharles Keepax 	if (ret)
143894cc89ebSCharles Keepax 		return ret;
143994cc89ebSCharles Keepax 
144094cc89ebSCharles Keepax 	regmap_debugfs_init(map);
1441a24f64a6SMark Brown 
1442421e8d2dSMark Brown 	map->cache_bypass = false;
1443421e8d2dSMark Brown 	map->cache_only = false;
1444421e8d2dSMark Brown 
14454d879514SDimitris Papastamos 	return regcache_init(map, config);
1446bf315173SMark Brown }
1447752a6a5fSMark Brown EXPORT_SYMBOL_GPL(regmap_reinit_cache);
1448bf315173SMark Brown 
1449bf315173SMark Brown /**
14502cf8e2dfSCharles Keepax  * regmap_exit() - Free a previously allocated register map
14512cf8e2dfSCharles Keepax  *
14522cf8e2dfSCharles Keepax  * @map: Register map to operate on.
1453b83a313bSMark Brown  */
regmap_exit(struct regmap * map)1454b83a313bSMark Brown void regmap_exit(struct regmap *map)
1455b83a313bSMark Brown {
14567e09a979SMark Brown 	struct regmap_async *async;
14577e09a979SMark Brown 
14583061e170SCosmin Tanislav 	regmap_detach_dev(map->dev, map);
14595d1729e7SDimitris Papastamos 	regcache_exit(map);
1460fd4ebc07SMark Brown 
146131244e39SMark Brown 	regmap_debugfs_exit(map);
14626863ca62SKrystian Garbaciak 	regmap_range_exit(map);
1463d2a5884aSAndrey Smirnov 	if (map->bus && map->bus->free_context)
14640135bbccSStephen Warren 		map->bus->free_context(map->bus_context);
1465b83a313bSMark Brown 	kfree(map->work_buf);
14667e09a979SMark Brown 	while (!list_empty(&map->async_free)) {
14677e09a979SMark Brown 		async = list_first_entry_or_null(&map->async_free,
14687e09a979SMark Brown 						 struct regmap_async,
14697e09a979SMark Brown 						 list);
14707e09a979SMark Brown 		list_del(&async->list);
14717e09a979SMark Brown 		kfree(async->work_buf);
14727e09a979SMark Brown 		kfree(async);
14737e09a979SMark Brown 	}
1474a1a68fcaSBaolin Wang 	if (map->hwlock)
1475e8419c40SMark Brown 		hwspin_lock_free(map->hwlock);
1476f74d63b8SBartosz Golaszewski 	if (map->lock == regmap_lock_mutex)
1477f74d63b8SBartosz Golaszewski 		mutex_destroy(&map->mutex);
14788253bb3fSBartosz Golaszewski 	kfree_const(map->name);
147995b2c3ecSCharles Keepax 	kfree(map->patch);
1480ea030ca6SLucas Tanure 	if (map->bus && map->bus->free_on_exit)
1481ea030ca6SLucas Tanure 		kfree(map->bus);
1482b83a313bSMark Brown 	kfree(map);
1483b83a313bSMark Brown }
1484b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_exit);
1485b83a313bSMark Brown 
dev_get_regmap_match(struct device * dev,void * res,void * data)148672b39f6fSMark Brown static int dev_get_regmap_match(struct device *dev, void *res, void *data)
148772b39f6fSMark Brown {
148872b39f6fSMark Brown 	struct regmap **r = res;
148972b39f6fSMark Brown 	if (!r || !*r) {
149072b39f6fSMark Brown 		WARN_ON(!r || !*r);
149172b39f6fSMark Brown 		return 0;
149272b39f6fSMark Brown 	}
149372b39f6fSMark Brown 
149472b39f6fSMark Brown 	/* If the user didn't specify a name match any */
149572b39f6fSMark Brown 	if (data)
1496c6df8433SJohan Hovold 		return (*r)->name && !strcmp((*r)->name, data);
149772b39f6fSMark Brown 	else
149872b39f6fSMark Brown 		return 1;
149972b39f6fSMark Brown }
150072b39f6fSMark Brown 
150172b39f6fSMark Brown /**
15022cf8e2dfSCharles Keepax  * dev_get_regmap() - Obtain the regmap (if any) for a device
150372b39f6fSMark Brown  *
150472b39f6fSMark Brown  * @dev: Device to retrieve the map for
150572b39f6fSMark Brown  * @name: Optional name for the register map, usually NULL.
150672b39f6fSMark Brown  *
150772b39f6fSMark Brown  * Returns the regmap for the device if one is present, or NULL.  If
150872b39f6fSMark Brown  * name is specified then it must match the name specified when
150972b39f6fSMark Brown  * registering the device, if it is NULL then the first regmap found
151072b39f6fSMark Brown  * will be used.  Devices with multiple register maps are very rare,
151172b39f6fSMark Brown  * generic code should normally not need to specify a name.
151272b39f6fSMark Brown  */
dev_get_regmap(struct device * dev,const char * name)151372b39f6fSMark Brown struct regmap *dev_get_regmap(struct device *dev, const char *name)
151472b39f6fSMark Brown {
151572b39f6fSMark Brown 	struct regmap **r = devres_find(dev, dev_get_regmap_release,
151672b39f6fSMark Brown 					dev_get_regmap_match, (void *)name);
151772b39f6fSMark Brown 
151872b39f6fSMark Brown 	if (!r)
151972b39f6fSMark Brown 		return NULL;
152072b39f6fSMark Brown 	return *r;
152172b39f6fSMark Brown }
152272b39f6fSMark Brown EXPORT_SYMBOL_GPL(dev_get_regmap);
152372b39f6fSMark Brown 
15248d7d3972STuomas Tynkkynen /**
15252cf8e2dfSCharles Keepax  * regmap_get_device() - Obtain the device from a regmap
15268d7d3972STuomas Tynkkynen  *
15278d7d3972STuomas Tynkkynen  * @map: Register map to operate on.
15288d7d3972STuomas Tynkkynen  *
15298d7d3972STuomas Tynkkynen  * Returns the underlying device that the regmap has been created for.
15308d7d3972STuomas Tynkkynen  */
regmap_get_device(struct regmap * map)15318d7d3972STuomas Tynkkynen struct device *regmap_get_device(struct regmap *map)
15328d7d3972STuomas Tynkkynen {
15338d7d3972STuomas Tynkkynen 	return map->dev;
15348d7d3972STuomas Tynkkynen }
1535fa2fbe4aSMark Brown EXPORT_SYMBOL_GPL(regmap_get_device);
15368d7d3972STuomas Tynkkynen 
_regmap_select_page(struct regmap * map,unsigned int * reg,struct regmap_range_node * range,unsigned int val_num)15376863ca62SKrystian Garbaciak static int _regmap_select_page(struct regmap *map, unsigned int *reg,
153898bc7dfdSMark Brown 			       struct regmap_range_node *range,
15396863ca62SKrystian Garbaciak 			       unsigned int val_num)
15406863ca62SKrystian Garbaciak {
15416863ca62SKrystian Garbaciak 	void *orig_work_buf;
15426863ca62SKrystian Garbaciak 	unsigned int win_offset;
15436863ca62SKrystian Garbaciak 	unsigned int win_page;
15446863ca62SKrystian Garbaciak 	bool page_chg;
15456863ca62SKrystian Garbaciak 	int ret;
15466863ca62SKrystian Garbaciak 
15476863ca62SKrystian Garbaciak 	win_offset = (*reg - range->range_min) % range->window_len;
15486863ca62SKrystian Garbaciak 	win_page = (*reg - range->range_min) / range->window_len;
15496863ca62SKrystian Garbaciak 
15506863ca62SKrystian Garbaciak 	if (val_num > 1) {
15516863ca62SKrystian Garbaciak 		/* Bulk write shouldn't cross range boundary */
15526863ca62SKrystian Garbaciak 		if (*reg + val_num - 1 > range->range_max)
15536863ca62SKrystian Garbaciak 			return -EINVAL;
15546863ca62SKrystian Garbaciak 
15556863ca62SKrystian Garbaciak 		/* ... or single page boundary */
15566863ca62SKrystian Garbaciak 		if (val_num > range->window_len - win_offset)
15576863ca62SKrystian Garbaciak 			return -EINVAL;
15586863ca62SKrystian Garbaciak 	}
15596863ca62SKrystian Garbaciak 
15606863ca62SKrystian Garbaciak 	/* It is possible to have selector register inside data window.
15616863ca62SKrystian Garbaciak 	   In that case, selector register is located on every page and
15626863ca62SKrystian Garbaciak 	   it needs no page switching, when accessed alone. */
15636863ca62SKrystian Garbaciak 	if (val_num > 1 ||
15646863ca62SKrystian Garbaciak 	    range->window_start + win_offset != range->selector_reg) {
15656863ca62SKrystian Garbaciak 		/* Use separate work_buf during page switching */
15666863ca62SKrystian Garbaciak 		orig_work_buf = map->work_buf;
15676863ca62SKrystian Garbaciak 		map->work_buf = map->selector_work_buf;
15686863ca62SKrystian Garbaciak 
15696863ca62SKrystian Garbaciak 		ret = _regmap_update_bits(map, range->selector_reg,
15706863ca62SKrystian Garbaciak 					  range->selector_mask,
15716863ca62SKrystian Garbaciak 					  win_page << range->selector_shift,
15727ff0589cSKuninori Morimoto 					  &page_chg, false);
15736863ca62SKrystian Garbaciak 
15746863ca62SKrystian Garbaciak 		map->work_buf = orig_work_buf;
1575632a5b01SKrystian Garbaciak 
15760ff3e62fSMark Brown 		if (ret != 0)
1577632a5b01SKrystian Garbaciak 			return ret;
15786863ca62SKrystian Garbaciak 	}
15796863ca62SKrystian Garbaciak 
15806863ca62SKrystian Garbaciak 	*reg = range->window_start + win_offset;
15816863ca62SKrystian Garbaciak 
15826863ca62SKrystian Garbaciak 	return 0;
15836863ca62SKrystian Garbaciak }
15846863ca62SKrystian Garbaciak 
regmap_set_work_buf_flag_mask(struct regmap * map,int max_bytes,unsigned long mask)1585f50e38c9STony Lindgren static void regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes,
1586f50e38c9STony Lindgren 					  unsigned long mask)
1587f50e38c9STony Lindgren {
1588f50e38c9STony Lindgren 	u8 *buf;
1589f50e38c9STony Lindgren 	int i;
1590f50e38c9STony Lindgren 
1591f50e38c9STony Lindgren 	if (!mask || !map->work_buf)
1592f50e38c9STony Lindgren 		return;
1593f50e38c9STony Lindgren 
1594f50e38c9STony Lindgren 	buf = map->work_buf;
1595f50e38c9STony Lindgren 
1596f50e38c9STony Lindgren 	for (i = 0; i < max_bytes; i++)
1597f50e38c9STony Lindgren 		buf[i] |= (mask >> (8 * i)) & 0xff;
1598f50e38c9STony Lindgren }
1599f50e38c9STony Lindgren 
regmap_reg_addr(struct regmap * map,unsigned int reg)16003f58f6dcSMaxime Chevallier static unsigned int regmap_reg_addr(struct regmap *map, unsigned int reg)
16013f58f6dcSMaxime Chevallier {
16023f58f6dcSMaxime Chevallier 	reg += map->reg_base;
16034a670ac3SMaxime Chevallier 
16044a670ac3SMaxime Chevallier 	if (map->format.reg_shift > 0)
16054a670ac3SMaxime Chevallier 		reg >>= map->format.reg_shift;
16064a670ac3SMaxime Chevallier 	else if (map->format.reg_shift < 0)
16074a670ac3SMaxime Chevallier 		reg <<= -(map->format.reg_shift);
16084a670ac3SMaxime Chevallier 
16094a670ac3SMaxime Chevallier 	return reg;
16103f58f6dcSMaxime Chevallier }
16113f58f6dcSMaxime Chevallier 
_regmap_raw_write_impl(struct regmap * map,unsigned int reg,const void * val,size_t val_len,bool noinc)16127ef2c6b8SCharles Keepax static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
161305669b63SDmitry Baryshkov 				  const void *val, size_t val_len, bool noinc)
1614b83a313bSMark Brown {
161598bc7dfdSMark Brown 	struct regmap_range_node *range;
16160d509f2bSMark Brown 	unsigned long flags;
16170d509f2bSMark Brown 	void *work_val = map->work_buf + map->format.reg_bytes +
16180d509f2bSMark Brown 		map->format.pad_bytes;
1619b83a313bSMark Brown 	void *buf;
1620b83a313bSMark Brown 	int ret = -ENOTSUPP;
1621b83a313bSMark Brown 	size_t len;
162273304781SMark Brown 	int i;
162373304781SMark Brown 
16242e31aab0SBen Whitten 	/* Check for unwritable or noinc registers in range
16252e31aab0SBen Whitten 	 * before we start
16262e31aab0SBen Whitten 	 */
16272e31aab0SBen Whitten 	if (!regmap_writeable_noinc(map, reg)) {
16282e31aab0SBen Whitten 		for (i = 0; i < val_len / map->format.val_bytes; i++) {
16292e31aab0SBen Whitten 			unsigned int element =
16302e31aab0SBen Whitten 				reg + regmap_get_offset(map, i);
16312e31aab0SBen Whitten 			if (!regmap_writeable(map, element) ||
16322e31aab0SBen Whitten 				regmap_writeable_noinc(map, element))
163373304781SMark Brown 				return -EINVAL;
16342e31aab0SBen Whitten 		}
16352e31aab0SBen Whitten 	}
1636b83a313bSMark Brown 
1637c9157198SLaxman Dewangan 	if (!map->cache_bypass && map->format.parse_val) {
1638984a4afdSBen Wolsieffer 		unsigned int ival, offset;
1639c9157198SLaxman Dewangan 		int val_bytes = map->format.val_bytes;
1640984a4afdSBen Wolsieffer 
1641984a4afdSBen Wolsieffer 		/* Cache the last written value for noinc writes */
1642984a4afdSBen Wolsieffer 		i = noinc ? val_len - val_bytes : 0;
1643984a4afdSBen Wolsieffer 		for (; i < val_len; i += val_bytes) {
1644984a4afdSBen Wolsieffer 			ival = map->format.parse_val(val + i);
1645984a4afdSBen Wolsieffer 			offset = noinc ? 0 : regmap_get_offset(map, i / val_bytes);
1646984a4afdSBen Wolsieffer 			ret = regcache_write(map, reg + offset, ival);
1647c9157198SLaxman Dewangan 			if (ret) {
1648c9157198SLaxman Dewangan 				dev_err(map->dev,
16496d04b8acSMark Brown 					"Error in caching of register: %x ret: %d\n",
1650984a4afdSBen Wolsieffer 					reg + offset, ret);
1651c9157198SLaxman Dewangan 				return ret;
1652c9157198SLaxman Dewangan 			}
1653c9157198SLaxman Dewangan 		}
1654c9157198SLaxman Dewangan 		if (map->cache_only) {
1655c9157198SLaxman Dewangan 			map->cache_dirty = true;
1656c9157198SLaxman Dewangan 			return 0;
1657c9157198SLaxman Dewangan 		}
1658c9157198SLaxman Dewangan 	}
1659c9157198SLaxman Dewangan 
166098bc7dfdSMark Brown 	range = _regmap_range_lookup(map, reg);
166198bc7dfdSMark Brown 	if (range) {
16628a2ceac6SMark Brown 		int val_num = val_len / map->format.val_bytes;
16638a2ceac6SMark Brown 		int win_offset = (reg - range->range_min) % range->window_len;
16648a2ceac6SMark Brown 		int win_residue = range->window_len - win_offset;
16658a2ceac6SMark Brown 
16668a2ceac6SMark Brown 		/* If the write goes beyond the end of the window split it */
16678a2ceac6SMark Brown 		while (val_num > win_residue) {
16681a61cfe3SFabio Estevam 			dev_dbg(map->dev, "Writing window %d/%zu\n",
16698a2ceac6SMark Brown 				win_residue, val_len / map->format.val_bytes);
16707ef2c6b8SCharles Keepax 			ret = _regmap_raw_write_impl(map, reg, val,
16717ef2c6b8SCharles Keepax 						     win_residue *
167205669b63SDmitry Baryshkov 						     map->format.val_bytes, noinc);
16738a2ceac6SMark Brown 			if (ret != 0)
16746863ca62SKrystian Garbaciak 				return ret;
16756863ca62SKrystian Garbaciak 
16768a2ceac6SMark Brown 			reg += win_residue;
16778a2ceac6SMark Brown 			val_num -= win_residue;
16788a2ceac6SMark Brown 			val += win_residue * map->format.val_bytes;
16798a2ceac6SMark Brown 			val_len -= win_residue * map->format.val_bytes;
16808a2ceac6SMark Brown 
16818a2ceac6SMark Brown 			win_offset = (reg - range->range_min) %
16828a2ceac6SMark Brown 				range->window_len;
16838a2ceac6SMark Brown 			win_residue = range->window_len - win_offset;
16848a2ceac6SMark Brown 		}
16858a2ceac6SMark Brown 
168605669b63SDmitry Baryshkov 		ret = _regmap_select_page(map, &reg, range, noinc ? 1 : val_num);
16870ff3e62fSMark Brown 		if (ret != 0)
16882547e201SMark Brown 			return ret;
168998bc7dfdSMark Brown 	}
1690b83a313bSMark Brown 
16913f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
1692d939fb9aSMarc Reilly 	map->format.format_reg(map->work_buf, reg, map->reg_shift);
1693f50e38c9STony Lindgren 	regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
1694f50e38c9STony Lindgren 				      map->write_flag_mask);
16956f306441SLars-Peter Clausen 
1696651e013eSMark Brown 	/*
1697651e013eSMark Brown 	 * Essentially all I/O mechanisms will be faster with a single
1698651e013eSMark Brown 	 * buffer to write.  Since register syncs often generate raw
1699651e013eSMark Brown 	 * writes of single registers optimise that case.
1700651e013eSMark Brown 	 */
1701651e013eSMark Brown 	if (val != work_val && val_len == map->format.val_bytes) {
1702651e013eSMark Brown 		memcpy(work_val, val, map->format.val_bytes);
1703651e013eSMark Brown 		val = work_val;
1704651e013eSMark Brown 	}
1705651e013eSMark Brown 
1706d77e7456SMarek Vasut 	if (map->async && map->bus && map->bus->async_write) {
17077e09a979SMark Brown 		struct regmap_async *async;
17080d509f2bSMark Brown 
1709c6b570d9SPhilipp Zabel 		trace_regmap_async_write_start(map, reg, val_len);
1710fe7d4ccdSMark Brown 
17117e09a979SMark Brown 		spin_lock_irqsave(&map->async_lock, flags);
17127e09a979SMark Brown 		async = list_first_entry_or_null(&map->async_free,
17137e09a979SMark Brown 						 struct regmap_async,
17147e09a979SMark Brown 						 list);
17157e09a979SMark Brown 		if (async)
17167e09a979SMark Brown 			list_del(&async->list);
17177e09a979SMark Brown 		spin_unlock_irqrestore(&map->async_lock, flags);
17187e09a979SMark Brown 
17197e09a979SMark Brown 		if (!async) {
17207e09a979SMark Brown 			async = map->bus->async_alloc();
17217e09a979SMark Brown 			if (!async)
17227e09a979SMark Brown 				return -ENOMEM;
17237e09a979SMark Brown 
17240d509f2bSMark Brown 			async->work_buf = kzalloc(map->format.buf_size,
17250d509f2bSMark Brown 						  GFP_KERNEL | GFP_DMA);
17260d509f2bSMark Brown 			if (!async->work_buf) {
17270d509f2bSMark Brown 				kfree(async);
17280d509f2bSMark Brown 				return -ENOMEM;
17290d509f2bSMark Brown 			}
17307e09a979SMark Brown 		}
17310d509f2bSMark Brown 
17320d509f2bSMark Brown 		async->map = map;
17330d509f2bSMark Brown 
17340d509f2bSMark Brown 		/* If the caller supplied the value we can use it safely. */
17350d509f2bSMark Brown 		memcpy(async->work_buf, map->work_buf, map->format.pad_bytes +
17360d509f2bSMark Brown 		       map->format.reg_bytes + map->format.val_bytes);
17370d509f2bSMark Brown 
17380d509f2bSMark Brown 		spin_lock_irqsave(&map->async_lock, flags);
17390d509f2bSMark Brown 		list_add_tail(&async->list, &map->async_list);
17400d509f2bSMark Brown 		spin_unlock_irqrestore(&map->async_lock, flags);
17410d509f2bSMark Brown 
174204c50ccfSMark Brown 		if (val != work_val)
174304c50ccfSMark Brown 			ret = map->bus->async_write(map->bus_context,
174404c50ccfSMark Brown 						    async->work_buf,
17450d509f2bSMark Brown 						    map->format.reg_bytes +
17460d509f2bSMark Brown 						    map->format.pad_bytes,
17470d509f2bSMark Brown 						    val, val_len, async);
174804c50ccfSMark Brown 		else
174904c50ccfSMark Brown 			ret = map->bus->async_write(map->bus_context,
175004c50ccfSMark Brown 						    async->work_buf,
175104c50ccfSMark Brown 						    map->format.reg_bytes +
175204c50ccfSMark Brown 						    map->format.pad_bytes +
175304c50ccfSMark Brown 						    val_len, NULL, 0, async);
17540d509f2bSMark Brown 
17550d509f2bSMark Brown 		if (ret != 0) {
17560d509f2bSMark Brown 			dev_err(map->dev, "Failed to schedule write: %d\n",
17570d509f2bSMark Brown 				ret);
17580d509f2bSMark Brown 
17590d509f2bSMark Brown 			spin_lock_irqsave(&map->async_lock, flags);
17607e09a979SMark Brown 			list_move(&async->list, &map->async_free);
17610d509f2bSMark Brown 			spin_unlock_irqrestore(&map->async_lock, flags);
17620d509f2bSMark Brown 		}
1763f951b658SMark Brown 
1764f951b658SMark Brown 		return ret;
17650d509f2bSMark Brown 	}
17660d509f2bSMark Brown 
1767c6b570d9SPhilipp Zabel 	trace_regmap_hw_write_start(map, reg, val_len / map->format.val_bytes);
1768b83a313bSMark Brown 
17692547e201SMark Brown 	/* If we're doing a single register write we can probably just
17702547e201SMark Brown 	 * send the work_buf directly, otherwise try to do a gather
17712547e201SMark Brown 	 * write.
17722547e201SMark Brown 	 */
17730d509f2bSMark Brown 	if (val == work_val)
1774d77e7456SMarek Vasut 		ret = map->write(map->bus_context, map->work_buf,
177582159ba8SMark Brown 				 map->format.reg_bytes +
177682159ba8SMark Brown 				 map->format.pad_bytes +
177782159ba8SMark Brown 				 val_len);
17785c422f0bSMarek Vasut 	else if (map->bus && map->bus->gather_write)
17790135bbccSStephen Warren 		ret = map->bus->gather_write(map->bus_context, map->work_buf,
178082159ba8SMark Brown 					     map->format.reg_bytes +
178182159ba8SMark Brown 					     map->format.pad_bytes,
1782b83a313bSMark Brown 					     val, val_len);
1783db057679SSrinivas Kandagatla 	else
1784db057679SSrinivas Kandagatla 		ret = -ENOTSUPP;
1785b83a313bSMark Brown 
17862547e201SMark Brown 	/* If that didn't work fall back on linearising by hand. */
1787b83a313bSMark Brown 	if (ret == -ENOTSUPP) {
178882159ba8SMark Brown 		len = map->format.reg_bytes + map->format.pad_bytes + val_len;
178982159ba8SMark Brown 		buf = kzalloc(len, GFP_KERNEL);
1790b83a313bSMark Brown 		if (!buf)
1791b83a313bSMark Brown 			return -ENOMEM;
1792b83a313bSMark Brown 
1793b83a313bSMark Brown 		memcpy(buf, map->work_buf, map->format.reg_bytes);
179482159ba8SMark Brown 		memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
179582159ba8SMark Brown 		       val, val_len);
1796d77e7456SMarek Vasut 		ret = map->write(map->bus_context, buf, len);
1797b83a313bSMark Brown 
1798b83a313bSMark Brown 		kfree(buf);
1799815806e3SElaine Zhang 	} else if (ret != 0 && !map->cache_bypass && map->format.parse_val) {
1800f0aa1ce6SNikita Yushchenko 		/* regcache_drop_region() takes lock that we already have,
1801f0aa1ce6SNikita Yushchenko 		 * thus call map->cache_ops->drop() directly
1802f0aa1ce6SNikita Yushchenko 		 */
1803f0aa1ce6SNikita Yushchenko 		if (map->cache_ops && map->cache_ops->drop)
1804f0aa1ce6SNikita Yushchenko 			map->cache_ops->drop(map, reg, reg + 1);
1805b83a313bSMark Brown 	}
1806b83a313bSMark Brown 
1807c6b570d9SPhilipp Zabel 	trace_regmap_hw_write_done(map, reg, val_len / map->format.val_bytes);
1808fb2736bbSMark Brown 
1809b83a313bSMark Brown 	return ret;
1810b83a313bSMark Brown }
1811b83a313bSMark Brown 
1812221ad7f2SMark Brown /**
1813221ad7f2SMark Brown  * regmap_can_raw_write - Test if regmap_raw_write() is supported
1814221ad7f2SMark Brown  *
1815221ad7f2SMark Brown  * @map: Map to check.
1816221ad7f2SMark Brown  */
regmap_can_raw_write(struct regmap * map)1817221ad7f2SMark Brown bool regmap_can_raw_write(struct regmap *map)
1818221ad7f2SMark Brown {
18192a166929SJavier Martinez Canillas 	return map->write && map->format.format_val && map->format.format_reg;
1820221ad7f2SMark Brown }
1821221ad7f2SMark Brown EXPORT_SYMBOL_GPL(regmap_can_raw_write);
1822221ad7f2SMark Brown 
1823f50c9eb4SMarkus Pargmann /**
1824f50c9eb4SMarkus Pargmann  * regmap_get_raw_read_max - Get the maximum size we can read
1825f50c9eb4SMarkus Pargmann  *
1826f50c9eb4SMarkus Pargmann  * @map: Map to check.
1827f50c9eb4SMarkus Pargmann  */
regmap_get_raw_read_max(struct regmap * map)1828f50c9eb4SMarkus Pargmann size_t regmap_get_raw_read_max(struct regmap *map)
1829f50c9eb4SMarkus Pargmann {
1830f50c9eb4SMarkus Pargmann 	return map->max_raw_read;
1831f50c9eb4SMarkus Pargmann }
1832f50c9eb4SMarkus Pargmann EXPORT_SYMBOL_GPL(regmap_get_raw_read_max);
1833f50c9eb4SMarkus Pargmann 
1834f50c9eb4SMarkus Pargmann /**
1835f50c9eb4SMarkus Pargmann  * regmap_get_raw_write_max - Get the maximum size we can read
1836f50c9eb4SMarkus Pargmann  *
1837f50c9eb4SMarkus Pargmann  * @map: Map to check.
1838f50c9eb4SMarkus Pargmann  */
regmap_get_raw_write_max(struct regmap * map)1839f50c9eb4SMarkus Pargmann size_t regmap_get_raw_write_max(struct regmap *map)
1840f50c9eb4SMarkus Pargmann {
1841f50c9eb4SMarkus Pargmann 	return map->max_raw_write;
1842f50c9eb4SMarkus Pargmann }
1843f50c9eb4SMarkus Pargmann EXPORT_SYMBOL_GPL(regmap_get_raw_write_max);
1844f50c9eb4SMarkus Pargmann 
_regmap_bus_formatted_write(void * context,unsigned int reg,unsigned int val)184507c320dcSAndrey Smirnov static int _regmap_bus_formatted_write(void *context, unsigned int reg,
184607c320dcSAndrey Smirnov 				       unsigned int val)
184707c320dcSAndrey Smirnov {
184807c320dcSAndrey Smirnov 	int ret;
184907c320dcSAndrey Smirnov 	struct regmap_range_node *range;
185007c320dcSAndrey Smirnov 	struct regmap *map = context;
185107c320dcSAndrey Smirnov 
1852d77e7456SMarek Vasut 	WARN_ON(!map->format.format_write);
185307c320dcSAndrey Smirnov 
185407c320dcSAndrey Smirnov 	range = _regmap_range_lookup(map, reg);
185507c320dcSAndrey Smirnov 	if (range) {
185607c320dcSAndrey Smirnov 		ret = _regmap_select_page(map, &reg, range, 1);
185707c320dcSAndrey Smirnov 		if (ret != 0)
185807c320dcSAndrey Smirnov 			return ret;
185907c320dcSAndrey Smirnov 	}
186007c320dcSAndrey Smirnov 
18613f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
186207c320dcSAndrey Smirnov 	map->format.format_write(map, reg, val);
186307c320dcSAndrey Smirnov 
1864c6b570d9SPhilipp Zabel 	trace_regmap_hw_write_start(map, reg, 1);
186507c320dcSAndrey Smirnov 
1866d77e7456SMarek Vasut 	ret = map->write(map->bus_context, map->work_buf, map->format.buf_size);
186707c320dcSAndrey Smirnov 
1868c6b570d9SPhilipp Zabel 	trace_regmap_hw_write_done(map, reg, 1);
186907c320dcSAndrey Smirnov 
187007c320dcSAndrey Smirnov 	return ret;
187107c320dcSAndrey Smirnov }
187207c320dcSAndrey Smirnov 
_regmap_bus_reg_write(void * context,unsigned int reg,unsigned int val)18733ac17037SBoris BREZILLON static int _regmap_bus_reg_write(void *context, unsigned int reg,
18743ac17037SBoris BREZILLON 				 unsigned int val)
18753ac17037SBoris BREZILLON {
18763ac17037SBoris BREZILLON 	struct regmap *map = context;
1877f18ee501SMark Brown 	struct regmap_range_node *range;
1878f18ee501SMark Brown 	int ret;
1879f18ee501SMark Brown 
1880f18ee501SMark Brown 	range = _regmap_range_lookup(map, reg);
1881f18ee501SMark Brown 	if (range) {
1882f18ee501SMark Brown 		ret = _regmap_select_page(map, &reg, range, 1);
1883f18ee501SMark Brown 		if (ret != 0)
1884f18ee501SMark Brown 			return ret;
1885f18ee501SMark Brown 	}
18863ac17037SBoris BREZILLON 
18873f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
18883ac17037SBoris BREZILLON 	return map->bus->reg_write(map->bus_context, reg, val);
18893ac17037SBoris BREZILLON }
18903ac17037SBoris BREZILLON 
_regmap_bus_raw_write(void * context,unsigned int reg,unsigned int val)189107c320dcSAndrey Smirnov static int _regmap_bus_raw_write(void *context, unsigned int reg,
189207c320dcSAndrey Smirnov 				 unsigned int val)
189307c320dcSAndrey Smirnov {
189407c320dcSAndrey Smirnov 	struct regmap *map = context;
189507c320dcSAndrey Smirnov 
1896d77e7456SMarek Vasut 	WARN_ON(!map->format.format_val);
189707c320dcSAndrey Smirnov 
189807c320dcSAndrey Smirnov 	map->format.format_val(map->work_buf + map->format.reg_bytes
189907c320dcSAndrey Smirnov 			       + map->format.pad_bytes, val, 0);
19007ef2c6b8SCharles Keepax 	return _regmap_raw_write_impl(map, reg,
190107c320dcSAndrey Smirnov 				      map->work_buf +
190207c320dcSAndrey Smirnov 				      map->format.reg_bytes +
190307c320dcSAndrey Smirnov 				      map->format.pad_bytes,
190405669b63SDmitry Baryshkov 				      map->format.val_bytes,
190505669b63SDmitry Baryshkov 				      false);
190607c320dcSAndrey Smirnov }
190707c320dcSAndrey Smirnov 
_regmap_map_get_context(struct regmap * map)1908d2a5884aSAndrey Smirnov static inline void *_regmap_map_get_context(struct regmap *map)
1909d2a5884aSAndrey Smirnov {
1910d77e7456SMarek Vasut 	return (map->bus || (!map->bus && map->read)) ? map : map->bus_context;
1911d2a5884aSAndrey Smirnov }
1912d2a5884aSAndrey Smirnov 
_regmap_write(struct regmap * map,unsigned int reg,unsigned int val)19134d2dc095SDimitris Papastamos int _regmap_write(struct regmap *map, unsigned int reg,
1914b83a313bSMark Brown 		  unsigned int val)
1915b83a313bSMark Brown {
1916fb2736bbSMark Brown 	int ret;
1917d2a5884aSAndrey Smirnov 	void *context = _regmap_map_get_context(map);
1918b83a313bSMark Brown 
1919515f2261SIonut Nicu 	if (!regmap_writeable(map, reg))
1920515f2261SIonut Nicu 		return -EIO;
1921515f2261SIonut Nicu 
1922d2a5884aSAndrey Smirnov 	if (!map->cache_bypass && !map->defer_caching) {
19235d1729e7SDimitris Papastamos 		ret = regcache_write(map, reg, val);
19245d1729e7SDimitris Papastamos 		if (ret != 0)
19255d1729e7SDimitris Papastamos 			return ret;
19268ae0d7e8SMark Brown 		if (map->cache_only) {
19278ae0d7e8SMark Brown 			map->cache_dirty = true;
19285d1729e7SDimitris Papastamos 			return 0;
19295d1729e7SDimitris Papastamos 		}
19308ae0d7e8SMark Brown 	}
19315d1729e7SDimitris Papastamos 
1932f7d01359SLucas Tanure 	ret = map->reg_write(context, reg, val);
1933f7d01359SLucas Tanure 	if (ret == 0) {
193495093762SBen Dooks 		if (regmap_should_log(map))
19351044c180SMark Brown 			dev_info(map->dev, "%x <= %x\n", reg, val);
19361044c180SMark Brown 
1937c6b570d9SPhilipp Zabel 		trace_regmap_reg_write(map, reg, val);
1938f7d01359SLucas Tanure 	}
1939fb2736bbSMark Brown 
1940f7d01359SLucas Tanure 	return ret;
1941b83a313bSMark Brown }
1942b83a313bSMark Brown 
1943b83a313bSMark Brown /**
19442cf8e2dfSCharles Keepax  * regmap_write() - Write a value to a single register
1945b83a313bSMark Brown  *
1946b83a313bSMark Brown  * @map: Register map to write to
1947b83a313bSMark Brown  * @reg: Register to write to
1948b83a313bSMark Brown  * @val: Value to be written
1949b83a313bSMark Brown  *
1950b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
1951b83a313bSMark Brown  * be returned in error cases.
1952b83a313bSMark Brown  */
regmap_write(struct regmap * map,unsigned int reg,unsigned int val)1953b83a313bSMark Brown int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
1954b83a313bSMark Brown {
1955b83a313bSMark Brown 	int ret;
1956b83a313bSMark Brown 
1957fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
1958f01ee60fSStephen Warren 		return -EINVAL;
1959f01ee60fSStephen Warren 
19600d4529c5SDavide Ciminaghi 	map->lock(map->lock_arg);
1961b83a313bSMark Brown 
1962b83a313bSMark Brown 	ret = _regmap_write(map, reg, val);
1963b83a313bSMark Brown 
19640d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
1965b83a313bSMark Brown 
1966b83a313bSMark Brown 	return ret;
1967b83a313bSMark Brown }
1968b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_write);
1969b83a313bSMark Brown 
1970b83a313bSMark Brown /**
19712cf8e2dfSCharles Keepax  * regmap_write_async() - Write a value to a single register asynchronously
1972915f441bSMark Brown  *
1973915f441bSMark Brown  * @map: Register map to write to
1974915f441bSMark Brown  * @reg: Register to write to
1975915f441bSMark Brown  * @val: Value to be written
1976915f441bSMark Brown  *
1977915f441bSMark Brown  * A value of zero will be returned on success, a negative errno will
1978915f441bSMark Brown  * be returned in error cases.
1979915f441bSMark Brown  */
regmap_write_async(struct regmap * map,unsigned int reg,unsigned int val)1980915f441bSMark Brown int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val)
1981915f441bSMark Brown {
1982915f441bSMark Brown 	int ret;
1983915f441bSMark Brown 
1984fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
1985915f441bSMark Brown 		return -EINVAL;
1986915f441bSMark Brown 
1987915f441bSMark Brown 	map->lock(map->lock_arg);
1988915f441bSMark Brown 
1989915f441bSMark Brown 	map->async = true;
1990915f441bSMark Brown 
1991915f441bSMark Brown 	ret = _regmap_write(map, reg, val);
1992915f441bSMark Brown 
1993915f441bSMark Brown 	map->async = false;
1994915f441bSMark Brown 
1995915f441bSMark Brown 	map->unlock(map->lock_arg);
1996915f441bSMark Brown 
1997915f441bSMark Brown 	return ret;
1998915f441bSMark Brown }
1999915f441bSMark Brown EXPORT_SYMBOL_GPL(regmap_write_async);
2000915f441bSMark Brown 
_regmap_raw_write(struct regmap * map,unsigned int reg,const void * val,size_t val_len,bool noinc)20017ef2c6b8SCharles Keepax int _regmap_raw_write(struct regmap *map, unsigned int reg,
200205669b63SDmitry Baryshkov 		      const void *val, size_t val_len, bool noinc)
20037ef2c6b8SCharles Keepax {
20047ef2c6b8SCharles Keepax 	size_t val_bytes = map->format.val_bytes;
20057ef2c6b8SCharles Keepax 	size_t val_count = val_len / val_bytes;
2006364e378bSCharles Keepax 	size_t chunk_count, chunk_bytes;
2007364e378bSCharles Keepax 	size_t chunk_regs = val_count;
20087ef2c6b8SCharles Keepax 	int ret, i;
20097ef2c6b8SCharles Keepax 
20107ef2c6b8SCharles Keepax 	if (!val_count)
20117ef2c6b8SCharles Keepax 		return -EINVAL;
20127ef2c6b8SCharles Keepax 
2013364e378bSCharles Keepax 	if (map->use_single_write)
2014364e378bSCharles Keepax 		chunk_regs = 1;
2015bc647348SMark Brown 	else if (map->max_raw_write && val_len > map->max_raw_write)
2016bc647348SMark Brown 		chunk_regs = map->max_raw_write / val_bytes;
2017364e378bSCharles Keepax 
2018364e378bSCharles Keepax 	chunk_count = val_count / chunk_regs;
2019364e378bSCharles Keepax 	chunk_bytes = chunk_regs * val_bytes;
20207ef2c6b8SCharles Keepax 
20217ef2c6b8SCharles Keepax 	/* Write as many bytes as possible with chunk_size */
20227ef2c6b8SCharles Keepax 	for (i = 0; i < chunk_count; i++) {
202305669b63SDmitry Baryshkov 		ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes, noinc);
20247ef2c6b8SCharles Keepax 		if (ret)
20257ef2c6b8SCharles Keepax 			return ret;
2026364e378bSCharles Keepax 
2027364e378bSCharles Keepax 		reg += regmap_get_offset(map, chunk_regs);
2028364e378bSCharles Keepax 		val += chunk_bytes;
2029364e378bSCharles Keepax 		val_len -= chunk_bytes;
20307ef2c6b8SCharles Keepax 	}
20317ef2c6b8SCharles Keepax 
20327ef2c6b8SCharles Keepax 	/* Write remaining bytes */
2033364e378bSCharles Keepax 	if (val_len)
203405669b63SDmitry Baryshkov 		ret = _regmap_raw_write_impl(map, reg, val, val_len, noinc);
20357ef2c6b8SCharles Keepax 
20367ef2c6b8SCharles Keepax 	return ret;
20377ef2c6b8SCharles Keepax }
20387ef2c6b8SCharles Keepax 
2039915f441bSMark Brown /**
20402cf8e2dfSCharles Keepax  * regmap_raw_write() - Write raw values to one or more registers
2041b83a313bSMark Brown  *
2042b83a313bSMark Brown  * @map: Register map to write to
2043b83a313bSMark Brown  * @reg: Initial register to write to
2044b83a313bSMark Brown  * @val: Block of data to be written, laid out for direct transmission to the
2045b83a313bSMark Brown  *       device
2046b83a313bSMark Brown  * @val_len: Length of data pointed to by val.
2047b83a313bSMark Brown  *
2048b83a313bSMark Brown  * This function is intended to be used for things like firmware
2049b83a313bSMark Brown  * download where a large block of data needs to be transferred to the
2050b83a313bSMark Brown  * device.  No formatting will be done on the data provided.
2051b83a313bSMark Brown  *
2052b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
2053b83a313bSMark Brown  * be returned in error cases.
2054b83a313bSMark Brown  */
regmap_raw_write(struct regmap * map,unsigned int reg,const void * val,size_t val_len)2055b83a313bSMark Brown int regmap_raw_write(struct regmap *map, unsigned int reg,
2056b83a313bSMark Brown 		     const void *val, size_t val_len)
2057b83a313bSMark Brown {
2058b83a313bSMark Brown 	int ret;
2059b83a313bSMark Brown 
2060221ad7f2SMark Brown 	if (!regmap_can_raw_write(map))
2061d2a5884aSAndrey Smirnov 		return -EINVAL;
2062851960baSStephen Warren 	if (val_len % map->format.val_bytes)
2063851960baSStephen Warren 		return -EINVAL;
2064851960baSStephen Warren 
20650d4529c5SDavide Ciminaghi 	map->lock(map->lock_arg);
2066b83a313bSMark Brown 
206705669b63SDmitry Baryshkov 	ret = _regmap_raw_write(map, reg, val, val_len, false);
2068b83a313bSMark Brown 
20690d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
2070b83a313bSMark Brown 
2071b83a313bSMark Brown 	return ret;
2072b83a313bSMark Brown }
2073b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_write);
2074b83a313bSMark Brown 
regmap_noinc_readwrite(struct regmap * map,unsigned int reg,void * val,unsigned int val_len,bool write)2075c20cc099SLinus Walleij static int regmap_noinc_readwrite(struct regmap *map, unsigned int reg,
2076c20cc099SLinus Walleij 				  void *val, unsigned int val_len, bool write)
2077c20cc099SLinus Walleij {
2078c20cc099SLinus Walleij 	size_t val_bytes = map->format.val_bytes;
2079c20cc099SLinus Walleij 	size_t val_count = val_len / val_bytes;
2080c20cc099SLinus Walleij 	unsigned int lastval;
2081c20cc099SLinus Walleij 	u8 *u8p;
2082c20cc099SLinus Walleij 	u16 *u16p;
2083c20cc099SLinus Walleij 	u32 *u32p;
2084c20cc099SLinus Walleij 	int ret;
2085c20cc099SLinus Walleij 	int i;
2086c20cc099SLinus Walleij 
2087c20cc099SLinus Walleij 	switch (val_bytes) {
2088c20cc099SLinus Walleij 	case 1:
2089c20cc099SLinus Walleij 		u8p = val;
2090c20cc099SLinus Walleij 		if (write)
2091c20cc099SLinus Walleij 			lastval = (unsigned int)u8p[val_count - 1];
2092c20cc099SLinus Walleij 		break;
2093c20cc099SLinus Walleij 	case 2:
2094c20cc099SLinus Walleij 		u16p = val;
2095c20cc099SLinus Walleij 		if (write)
2096c20cc099SLinus Walleij 			lastval = (unsigned int)u16p[val_count - 1];
2097c20cc099SLinus Walleij 		break;
2098c20cc099SLinus Walleij 	case 4:
2099c20cc099SLinus Walleij 		u32p = val;
2100c20cc099SLinus Walleij 		if (write)
2101c20cc099SLinus Walleij 			lastval = (unsigned int)u32p[val_count - 1];
2102c20cc099SLinus Walleij 		break;
2103c20cc099SLinus Walleij 	default:
2104c20cc099SLinus Walleij 		return -EINVAL;
2105c20cc099SLinus Walleij 	}
2106c20cc099SLinus Walleij 
2107c20cc099SLinus Walleij 	/*
2108c20cc099SLinus Walleij 	 * Update the cache with the last value we write, the rest is just
2109c20cc099SLinus Walleij 	 * gone down in the hardware FIFO. We can't cache FIFOs. This makes
2110c20cc099SLinus Walleij 	 * sure a single read from the cache will work.
2111c20cc099SLinus Walleij 	 */
2112c20cc099SLinus Walleij 	if (write) {
2113c20cc099SLinus Walleij 		if (!map->cache_bypass && !map->defer_caching) {
2114c20cc099SLinus Walleij 			ret = regcache_write(map, reg, lastval);
2115c20cc099SLinus Walleij 			if (ret != 0)
2116c20cc099SLinus Walleij 				return ret;
2117c20cc099SLinus Walleij 			if (map->cache_only) {
2118c20cc099SLinus Walleij 				map->cache_dirty = true;
2119c20cc099SLinus Walleij 				return 0;
2120c20cc099SLinus Walleij 			}
2121c20cc099SLinus Walleij 		}
2122c20cc099SLinus Walleij 		ret = map->bus->reg_noinc_write(map->bus_context, reg, val, val_count);
2123c20cc099SLinus Walleij 	} else {
2124c20cc099SLinus Walleij 		ret = map->bus->reg_noinc_read(map->bus_context, reg, val, val_count);
2125c20cc099SLinus Walleij 	}
2126c20cc099SLinus Walleij 
2127c20cc099SLinus Walleij 	if (!ret && regmap_should_log(map)) {
2128c20cc099SLinus Walleij 		dev_info(map->dev, "%x %s [", reg, write ? "<=" : "=>");
2129b7059927SLinus Walleij 		for (i = 0; i < val_count; i++) {
2130c20cc099SLinus Walleij 			switch (val_bytes) {
2131c20cc099SLinus Walleij 			case 1:
2132c20cc099SLinus Walleij 				pr_cont("%x", u8p[i]);
2133c20cc099SLinus Walleij 				break;
2134c20cc099SLinus Walleij 			case 2:
2135c20cc099SLinus Walleij 				pr_cont("%x", u16p[i]);
2136c20cc099SLinus Walleij 				break;
2137c20cc099SLinus Walleij 			case 4:
2138c20cc099SLinus Walleij 				pr_cont("%x", u32p[i]);
2139c20cc099SLinus Walleij 				break;
2140c20cc099SLinus Walleij 			default:
2141c20cc099SLinus Walleij 				break;
2142c20cc099SLinus Walleij 			}
2143b7059927SLinus Walleij 			if (i == (val_count - 1))
2144c20cc099SLinus Walleij 				pr_cont("]\n");
2145c20cc099SLinus Walleij 			else
2146c20cc099SLinus Walleij 				pr_cont(",");
2147c20cc099SLinus Walleij 		}
2148c20cc099SLinus Walleij 	}
2149c20cc099SLinus Walleij 
2150c20cc099SLinus Walleij 	return 0;
2151c20cc099SLinus Walleij }
2152c20cc099SLinus Walleij 
215367252287SSrinivas Kandagatla /**
21541957b92aSHugo Villeneuve  * regmap_noinc_write(): Write data to a register without incrementing the
2155cdf6b11dSBen Whitten  *			register number
2156cdf6b11dSBen Whitten  *
2157cdf6b11dSBen Whitten  * @map: Register map to write to
2158cdf6b11dSBen Whitten  * @reg: Register to write to
2159cdf6b11dSBen Whitten  * @val: Pointer to data buffer
2160cdf6b11dSBen Whitten  * @val_len: Length of output buffer in bytes.
2161cdf6b11dSBen Whitten  *
2162cdf6b11dSBen Whitten  * The regmap API usually assumes that bulk bus write operations will write a
2163cdf6b11dSBen Whitten  * range of registers. Some devices have certain registers for which a write
2164cdf6b11dSBen Whitten  * operation can write to an internal FIFO.
2165cdf6b11dSBen Whitten  *
2166cdf6b11dSBen Whitten  * The target register must be volatile but registers after it can be
2167cdf6b11dSBen Whitten  * completely unrelated cacheable registers.
2168cdf6b11dSBen Whitten  *
2169cdf6b11dSBen Whitten  * This will attempt multiple writes as required to write val_len bytes.
2170cdf6b11dSBen Whitten  *
2171cdf6b11dSBen Whitten  * A value of zero will be returned on success, a negative errno will be
2172cdf6b11dSBen Whitten  * returned in error cases.
2173cdf6b11dSBen Whitten  */
regmap_noinc_write(struct regmap * map,unsigned int reg,const void * val,size_t val_len)2174cdf6b11dSBen Whitten int regmap_noinc_write(struct regmap *map, unsigned int reg,
2175cdf6b11dSBen Whitten 		      const void *val, size_t val_len)
2176cdf6b11dSBen Whitten {
2177cdf6b11dSBen Whitten 	size_t write_len;
2178cdf6b11dSBen Whitten 	int ret;
2179cdf6b11dSBen Whitten 
2180c20cc099SLinus Walleij 	if (!map->write && !(map->bus && map->bus->reg_noinc_write))
2181c20cc099SLinus Walleij 		return -EINVAL;
2182cdf6b11dSBen Whitten 	if (val_len % map->format.val_bytes)
2183cdf6b11dSBen Whitten 		return -EINVAL;
2184cdf6b11dSBen Whitten 	if (!IS_ALIGNED(reg, map->reg_stride))
2185cdf6b11dSBen Whitten 		return -EINVAL;
2186cdf6b11dSBen Whitten 	if (val_len == 0)
2187cdf6b11dSBen Whitten 		return -EINVAL;
2188cdf6b11dSBen Whitten 
2189cdf6b11dSBen Whitten 	map->lock(map->lock_arg);
2190cdf6b11dSBen Whitten 
2191cdf6b11dSBen Whitten 	if (!regmap_volatile(map, reg) || !regmap_writeable_noinc(map, reg)) {
2192cdf6b11dSBen Whitten 		ret = -EINVAL;
2193cdf6b11dSBen Whitten 		goto out_unlock;
2194cdf6b11dSBen Whitten 	}
2195cdf6b11dSBen Whitten 
2196c20cc099SLinus Walleij 	/*
2197c20cc099SLinus Walleij 	 * Use the accelerated operation if we can. The val drops the const
2198c20cc099SLinus Walleij 	 * typing in order to facilitate code reuse in regmap_noinc_readwrite().
2199c20cc099SLinus Walleij 	 */
2200c20cc099SLinus Walleij 	if (map->bus->reg_noinc_write) {
2201c20cc099SLinus Walleij 		ret = regmap_noinc_readwrite(map, reg, (void *)val, val_len, true);
2202c20cc099SLinus Walleij 		goto out_unlock;
2203c20cc099SLinus Walleij 	}
2204c20cc099SLinus Walleij 
2205cdf6b11dSBen Whitten 	while (val_len) {
2206cdf6b11dSBen Whitten 		if (map->max_raw_write && map->max_raw_write < val_len)
2207cdf6b11dSBen Whitten 			write_len = map->max_raw_write;
2208cdf6b11dSBen Whitten 		else
2209cdf6b11dSBen Whitten 			write_len = val_len;
221005669b63SDmitry Baryshkov 		ret = _regmap_raw_write(map, reg, val, write_len, true);
2211cdf6b11dSBen Whitten 		if (ret)
2212cdf6b11dSBen Whitten 			goto out_unlock;
2213cdf6b11dSBen Whitten 		val = ((u8 *)val) + write_len;
2214cdf6b11dSBen Whitten 		val_len -= write_len;
2215cdf6b11dSBen Whitten 	}
2216cdf6b11dSBen Whitten 
2217cdf6b11dSBen Whitten out_unlock:
2218cdf6b11dSBen Whitten 	map->unlock(map->lock_arg);
2219cdf6b11dSBen Whitten 	return ret;
2220cdf6b11dSBen Whitten }
2221cdf6b11dSBen Whitten EXPORT_SYMBOL_GPL(regmap_noinc_write);
2222cdf6b11dSBen Whitten 
2223cdf6b11dSBen Whitten /**
22242cf8e2dfSCharles Keepax  * regmap_field_update_bits_base() - Perform a read/modify/write cycle a
22252cf8e2dfSCharles Keepax  *                                   register field.
2226fdf20029SKuninori Morimoto  *
2227fdf20029SKuninori Morimoto  * @field: Register field to write to
2228fdf20029SKuninori Morimoto  * @mask: Bitmask to change
2229fdf20029SKuninori Morimoto  * @val: Value to be written
223028972eaaSKuninori Morimoto  * @change: Boolean indicating if a write was done
223128972eaaSKuninori Morimoto  * @async: Boolean indicating asynchronously
223228972eaaSKuninori Morimoto  * @force: Boolean indicating use force update
2233fdf20029SKuninori Morimoto  *
22342cf8e2dfSCharles Keepax  * Perform a read/modify/write cycle on the register field with change,
22352cf8e2dfSCharles Keepax  * async, force option.
22362cf8e2dfSCharles Keepax  *
2237fdf20029SKuninori Morimoto  * A value of zero will be returned on success, a negative errno will
2238fdf20029SKuninori Morimoto  * be returned in error cases.
2239fdf20029SKuninori Morimoto  */
regmap_field_update_bits_base(struct regmap_field * field,unsigned int mask,unsigned int val,bool * change,bool async,bool force)224028972eaaSKuninori Morimoto int regmap_field_update_bits_base(struct regmap_field *field,
224128972eaaSKuninori Morimoto 				  unsigned int mask, unsigned int val,
224228972eaaSKuninori Morimoto 				  bool *change, bool async, bool force)
2243fdf20029SKuninori Morimoto {
2244fdf20029SKuninori Morimoto 	mask = (mask << field->shift) & field->mask;
2245fdf20029SKuninori Morimoto 
224628972eaaSKuninori Morimoto 	return regmap_update_bits_base(field->regmap, field->reg,
224728972eaaSKuninori Morimoto 				       mask, val << field->shift,
224828972eaaSKuninori Morimoto 				       change, async, force);
2249fdf20029SKuninori Morimoto }
225028972eaaSKuninori Morimoto EXPORT_SYMBOL_GPL(regmap_field_update_bits_base);
2251fdf20029SKuninori Morimoto 
2252a0102375SKuninori Morimoto /**
2253f67be8b7SLi Chen  * regmap_field_test_bits() - Check if all specified bits are set in a
2254f67be8b7SLi Chen  *                            register field.
2255f67be8b7SLi Chen  *
2256f67be8b7SLi Chen  * @field: Register field to operate on
2257f67be8b7SLi Chen  * @bits: Bits to test
2258f67be8b7SLi Chen  *
2259f67be8b7SLi Chen  * Returns -1 if the underlying regmap_field_read() fails, 0 if at least one of the
2260f67be8b7SLi Chen  * tested bits is not set and 1 if all tested bits are set.
2261f67be8b7SLi Chen  */
regmap_field_test_bits(struct regmap_field * field,unsigned int bits)2262f67be8b7SLi Chen int regmap_field_test_bits(struct regmap_field *field, unsigned int bits)
2263f67be8b7SLi Chen {
2264f67be8b7SLi Chen 	unsigned int val, ret;
2265f67be8b7SLi Chen 
2266f67be8b7SLi Chen 	ret = regmap_field_read(field, &val);
2267f67be8b7SLi Chen 	if (ret)
2268f67be8b7SLi Chen 		return ret;
2269f67be8b7SLi Chen 
2270f67be8b7SLi Chen 	return (val & bits) == bits;
2271f67be8b7SLi Chen }
2272f67be8b7SLi Chen EXPORT_SYMBOL_GPL(regmap_field_test_bits);
2273f67be8b7SLi Chen 
2274f67be8b7SLi Chen /**
22752cf8e2dfSCharles Keepax  * regmap_fields_update_bits_base() - Perform a read/modify/write cycle a
22762cf8e2dfSCharles Keepax  *                                    register field with port ID
2277a0102375SKuninori Morimoto  *
2278a0102375SKuninori Morimoto  * @field: Register field to write to
2279a0102375SKuninori Morimoto  * @id: port ID
2280a0102375SKuninori Morimoto  * @mask: Bitmask to change
2281a0102375SKuninori Morimoto  * @val: Value to be written
2282e126edecSKuninori Morimoto  * @change: Boolean indicating if a write was done
2283e126edecSKuninori Morimoto  * @async: Boolean indicating asynchronously
2284e126edecSKuninori Morimoto  * @force: Boolean indicating use force update
2285a0102375SKuninori Morimoto  *
2286a0102375SKuninori Morimoto  * A value of zero will be returned on success, a negative errno will
2287a0102375SKuninori Morimoto  * be returned in error cases.
2288a0102375SKuninori Morimoto  */
regmap_fields_update_bits_base(struct regmap_field * field,unsigned int id,unsigned int mask,unsigned int val,bool * change,bool async,bool force)2289e126edecSKuninori Morimoto int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id,
2290e126edecSKuninori Morimoto 				   unsigned int mask, unsigned int val,
2291e126edecSKuninori Morimoto 				   bool *change, bool async, bool force)
2292a0102375SKuninori Morimoto {
2293a0102375SKuninori Morimoto 	if (id >= field->id_size)
2294a0102375SKuninori Morimoto 		return -EINVAL;
2295a0102375SKuninori Morimoto 
2296a0102375SKuninori Morimoto 	mask = (mask << field->shift) & field->mask;
2297a0102375SKuninori Morimoto 
2298e126edecSKuninori Morimoto 	return regmap_update_bits_base(field->regmap,
2299a0102375SKuninori Morimoto 				       field->reg + (field->id_offset * id),
2300e126edecSKuninori Morimoto 				       mask, val << field->shift,
2301e126edecSKuninori Morimoto 				       change, async, force);
2302a0102375SKuninori Morimoto }
2303e126edecSKuninori Morimoto EXPORT_SYMBOL_GPL(regmap_fields_update_bits_base);
2304a0102375SKuninori Morimoto 
23052cf8e2dfSCharles Keepax /**
23062cf8e2dfSCharles Keepax  * regmap_bulk_write() - Write multiple registers to the device
23078eaeb219SLaxman Dewangan  *
23088eaeb219SLaxman Dewangan  * @map: Register map to write to
23098eaeb219SLaxman Dewangan  * @reg: First register to be write from
23108eaeb219SLaxman Dewangan  * @val: Block of data to be written, in native register size for device
23118eaeb219SLaxman Dewangan  * @val_count: Number of registers to write
23128eaeb219SLaxman Dewangan  *
23138eaeb219SLaxman Dewangan  * This function is intended to be used for writing a large block of
231431b35e9eSNestor Ovroy  * data to the device either in single transfer or multiple transfer.
23158eaeb219SLaxman Dewangan  *
23168eaeb219SLaxman Dewangan  * A value of zero will be returned on success, a negative errno will
23178eaeb219SLaxman Dewangan  * be returned in error cases.
23188eaeb219SLaxman Dewangan  */
regmap_bulk_write(struct regmap * map,unsigned int reg,const void * val,size_t val_count)23198eaeb219SLaxman Dewangan int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
23208eaeb219SLaxman Dewangan 		     size_t val_count)
23218eaeb219SLaxman Dewangan {
23228eaeb219SLaxman Dewangan 	int ret = 0, i;
23238eaeb219SLaxman Dewangan 	size_t val_bytes = map->format.val_bytes;
23248eaeb219SLaxman Dewangan 
2325fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
2326f01ee60fSStephen Warren 		return -EINVAL;
23278eaeb219SLaxman Dewangan 
2328f4298360SStephen Boyd 	/*
2329fb44f3ceSCharles Keepax 	 * Some devices don't support bulk write, for them we have a series of
2330fb44f3ceSCharles Keepax 	 * single write operations.
2331f4298360SStephen Boyd 	 */
23322a166929SJavier Martinez Canillas 	if (!map->write || !map->format.parse_inplace) {
23334999e962STakashi Iwai 		map->lock(map->lock_arg);
2334f4298360SStephen Boyd 		for (i = 0; i < val_count; i++) {
2335f4298360SStephen Boyd 			unsigned int ival;
23368eaeb219SLaxman Dewangan 
2337f4298360SStephen Boyd 			switch (val_bytes) {
2338f4298360SStephen Boyd 			case 1:
2339f4298360SStephen Boyd 				ival = *(u8 *)(val + (i * val_bytes));
2340f4298360SStephen Boyd 				break;
2341f4298360SStephen Boyd 			case 2:
2342f4298360SStephen Boyd 				ival = *(u16 *)(val + (i * val_bytes));
2343f4298360SStephen Boyd 				break;
2344f4298360SStephen Boyd 			case 4:
2345f4298360SStephen Boyd 				ival = *(u32 *)(val + (i * val_bytes));
2346f4298360SStephen Boyd 				break;
2347f4298360SStephen Boyd 			default:
2348f4298360SStephen Boyd 				ret = -EINVAL;
2349f4298360SStephen Boyd 				goto out;
2350f4298360SStephen Boyd 			}
2351f4298360SStephen Boyd 
2352ca747be2SXiubo Li 			ret = _regmap_write(map,
2353ca747be2SXiubo Li 					    reg + regmap_get_offset(map, i),
2354f4298360SStephen Boyd 					    ival);
2355f4298360SStephen Boyd 			if (ret != 0)
2356f4298360SStephen Boyd 				goto out;
2357f4298360SStephen Boyd 		}
23584999e962STakashi Iwai out:
23594999e962STakashi Iwai 		map->unlock(map->lock_arg);
23608eaeb219SLaxman Dewangan 	} else {
2361f4298360SStephen Boyd 		void *wval;
2362f4298360SStephen Boyd 
2363f6841d41SAndy Shevchenko 		wval = kmemdup_array(val, val_count, val_bytes, map->alloc_flags);
2364b4ecfec5SCharles Keepax 		if (!wval)
23654999e962STakashi Iwai 			return -ENOMEM;
2366b4ecfec5SCharles Keepax 
23678eaeb219SLaxman Dewangan 		for (i = 0; i < val_count * val_bytes; i += val_bytes)
23688a819ff8SMark Brown 			map->format.parse_inplace(wval + i);
2369f4298360SStephen Boyd 
23707ef2c6b8SCharles Keepax 		ret = regmap_raw_write(map, reg, wval, val_bytes * val_count);
23718eaeb219SLaxman Dewangan 
23728eaeb219SLaxman Dewangan 		kfree(wval);
2373f4298360SStephen Boyd 	}
2374026c99b5SDmitry Rokosov 
2375026c99b5SDmitry Rokosov 	if (!ret)
2376026c99b5SDmitry Rokosov 		trace_regmap_bulk_write(map, reg, val, val_bytes * val_count);
2377026c99b5SDmitry Rokosov 
23788eaeb219SLaxman Dewangan 	return ret;
23798eaeb219SLaxman Dewangan }
23808eaeb219SLaxman Dewangan EXPORT_SYMBOL_GPL(regmap_bulk_write);
23818eaeb219SLaxman Dewangan 
2382e33fabd3SAnthony Olech /*
2383e894c3f4SOpensource [Anthony Olech]  * _regmap_raw_multi_reg_write()
2384e894c3f4SOpensource [Anthony Olech]  *
2385e894c3f4SOpensource [Anthony Olech]  * the (register,newvalue) pairs in regs have not been formatted, but
2386e894c3f4SOpensource [Anthony Olech]  * they are all in the same page and have been changed to being page
2387b486afbdSXiubo Li  * relative. The page register has been written if that was necessary.
2388e894c3f4SOpensource [Anthony Olech]  */
_regmap_raw_multi_reg_write(struct regmap * map,const struct reg_sequence * regs,size_t num_regs)2389e894c3f4SOpensource [Anthony Olech] static int _regmap_raw_multi_reg_write(struct regmap *map,
23908019ff6cSNariman Poushin 				       const struct reg_sequence *regs,
2391e894c3f4SOpensource [Anthony Olech] 				       size_t num_regs)
23921d5b40bcSCharles Keepax {
2393e894c3f4SOpensource [Anthony Olech] 	int ret;
2394e894c3f4SOpensource [Anthony Olech] 	void *buf;
2395e894c3f4SOpensource [Anthony Olech] 	int i;
2396e894c3f4SOpensource [Anthony Olech] 	u8 *u8;
2397e894c3f4SOpensource [Anthony Olech] 	size_t val_bytes = map->format.val_bytes;
2398e894c3f4SOpensource [Anthony Olech] 	size_t reg_bytes = map->format.reg_bytes;
2399e894c3f4SOpensource [Anthony Olech] 	size_t pad_bytes = map->format.pad_bytes;
2400e894c3f4SOpensource [Anthony Olech] 	size_t pair_size = reg_bytes + pad_bytes + val_bytes;
2401e894c3f4SOpensource [Anthony Olech] 	size_t len = pair_size * num_regs;
2402e894c3f4SOpensource [Anthony Olech] 
2403f5727cd3SXiubo Li 	if (!len)
2404f5727cd3SXiubo Li 		return -EINVAL;
2405f5727cd3SXiubo Li 
2406e894c3f4SOpensource [Anthony Olech] 	buf = kzalloc(len, GFP_KERNEL);
2407e894c3f4SOpensource [Anthony Olech] 	if (!buf)
2408e894c3f4SOpensource [Anthony Olech] 		return -ENOMEM;
2409e894c3f4SOpensource [Anthony Olech] 
2410e894c3f4SOpensource [Anthony Olech] 	/* We have to linearise by hand. */
2411e894c3f4SOpensource [Anthony Olech] 
2412e894c3f4SOpensource [Anthony Olech] 	u8 = buf;
24131d5b40bcSCharles Keepax 
24141d5b40bcSCharles Keepax 	for (i = 0; i < num_regs; i++) {
24152f9b660bSMarkus Pargmann 		unsigned int reg = regs[i].reg;
24162f9b660bSMarkus Pargmann 		unsigned int val = regs[i].def;
2417c6b570d9SPhilipp Zabel 		trace_regmap_hw_write_start(map, reg, 1);
24183f58f6dcSMaxime Chevallier 		reg = regmap_reg_addr(map, reg);
2419e894c3f4SOpensource [Anthony Olech] 		map->format.format_reg(u8, reg, map->reg_shift);
2420e894c3f4SOpensource [Anthony Olech] 		u8 += reg_bytes + pad_bytes;
2421e894c3f4SOpensource [Anthony Olech] 		map->format.format_val(u8, val, 0);
2422e894c3f4SOpensource [Anthony Olech] 		u8 += val_bytes;
2423e894c3f4SOpensource [Anthony Olech] 	}
2424e894c3f4SOpensource [Anthony Olech] 	u8 = buf;
2425e894c3f4SOpensource [Anthony Olech] 	*u8 |= map->write_flag_mask;
2426e894c3f4SOpensource [Anthony Olech] 
2427d77e7456SMarek Vasut 	ret = map->write(map->bus_context, buf, len);
2428e894c3f4SOpensource [Anthony Olech] 
2429e894c3f4SOpensource [Anthony Olech] 	kfree(buf);
2430e894c3f4SOpensource [Anthony Olech] 
2431e894c3f4SOpensource [Anthony Olech] 	for (i = 0; i < num_regs; i++) {
2432e894c3f4SOpensource [Anthony Olech] 		int reg = regs[i].reg;
2433c6b570d9SPhilipp Zabel 		trace_regmap_hw_write_done(map, reg, 1);
2434e894c3f4SOpensource [Anthony Olech] 	}
2435e894c3f4SOpensource [Anthony Olech] 	return ret;
2436e894c3f4SOpensource [Anthony Olech] }
2437e894c3f4SOpensource [Anthony Olech] 
_regmap_register_page(struct regmap * map,unsigned int reg,struct regmap_range_node * range)2438e894c3f4SOpensource [Anthony Olech] static unsigned int _regmap_register_page(struct regmap *map,
2439e894c3f4SOpensource [Anthony Olech] 					  unsigned int reg,
2440e894c3f4SOpensource [Anthony Olech] 					  struct regmap_range_node *range)
2441e894c3f4SOpensource [Anthony Olech] {
2442e894c3f4SOpensource [Anthony Olech] 	unsigned int win_page = (reg - range->range_min) / range->window_len;
2443e894c3f4SOpensource [Anthony Olech] 
2444e894c3f4SOpensource [Anthony Olech] 	return win_page;
2445e894c3f4SOpensource [Anthony Olech] }
2446e894c3f4SOpensource [Anthony Olech] 
_regmap_range_multi_paged_reg_write(struct regmap * map,struct reg_sequence * regs,size_t num_regs)2447e894c3f4SOpensource [Anthony Olech] static int _regmap_range_multi_paged_reg_write(struct regmap *map,
24488019ff6cSNariman Poushin 					       struct reg_sequence *regs,
2449e894c3f4SOpensource [Anthony Olech] 					       size_t num_regs)
2450e894c3f4SOpensource [Anthony Olech] {
2451e894c3f4SOpensource [Anthony Olech] 	int ret;
2452e894c3f4SOpensource [Anthony Olech] 	int i, n;
24538019ff6cSNariman Poushin 	struct reg_sequence *base;
2454b48d1398SGeert Uytterhoeven 	unsigned int this_page = 0;
24552de9d600SNariman Poushin 	unsigned int page_change = 0;
2456e894c3f4SOpensource [Anthony Olech] 	/*
2457e894c3f4SOpensource [Anthony Olech] 	 * the set of registers are not neccessarily in order, but
2458e894c3f4SOpensource [Anthony Olech] 	 * since the order of write must be preserved this algorithm
24592de9d600SNariman Poushin 	 * chops the set each time the page changes. This also applies
24602de9d600SNariman Poushin 	 * if there is a delay required at any point in the sequence.
2461e894c3f4SOpensource [Anthony Olech] 	 */
2462e894c3f4SOpensource [Anthony Olech] 	base = regs;
2463e894c3f4SOpensource [Anthony Olech] 	for (i = 0, n = 0; i < num_regs; i++, n++) {
2464e894c3f4SOpensource [Anthony Olech] 		unsigned int reg = regs[i].reg;
2465e894c3f4SOpensource [Anthony Olech] 		struct regmap_range_node *range;
2466e894c3f4SOpensource [Anthony Olech] 
2467e894c3f4SOpensource [Anthony Olech] 		range = _regmap_range_lookup(map, reg);
2468e894c3f4SOpensource [Anthony Olech] 		if (range) {
2469e894c3f4SOpensource [Anthony Olech] 			unsigned int win_page = _regmap_register_page(map, reg,
2470e894c3f4SOpensource [Anthony Olech] 								      range);
2471e894c3f4SOpensource [Anthony Olech] 
2472e894c3f4SOpensource [Anthony Olech] 			if (i == 0)
2473e894c3f4SOpensource [Anthony Olech] 				this_page = win_page;
2474e894c3f4SOpensource [Anthony Olech] 			if (win_page != this_page) {
2475e894c3f4SOpensource [Anthony Olech] 				this_page = win_page;
24762de9d600SNariman Poushin 				page_change = 1;
24772de9d600SNariman Poushin 			}
24782de9d600SNariman Poushin 		}
24792de9d600SNariman Poushin 
24802de9d600SNariman Poushin 		/* If we have both a page change and a delay make sure to
24812de9d600SNariman Poushin 		 * write the regs and apply the delay before we change the
24822de9d600SNariman Poushin 		 * page.
24832de9d600SNariman Poushin 		 */
24842de9d600SNariman Poushin 
24852de9d600SNariman Poushin 		if (page_change || regs[i].delay_us) {
24862de9d600SNariman Poushin 
24872de9d600SNariman Poushin 				/* For situations where the first write requires
24882de9d600SNariman Poushin 				 * a delay we need to make sure we don't call
24892de9d600SNariman Poushin 				 * raw_multi_reg_write with n=0
24902de9d600SNariman Poushin 				 * This can't occur with page breaks as we
24912de9d600SNariman Poushin 				 * never write on the first iteration
24922de9d600SNariman Poushin 				 */
24932de9d600SNariman Poushin 				if (regs[i].delay_us && i == 0)
24942de9d600SNariman Poushin 					n = 1;
24952de9d600SNariman Poushin 
2496e894c3f4SOpensource [Anthony Olech] 				ret = _regmap_raw_multi_reg_write(map, base, n);
2497e894c3f4SOpensource [Anthony Olech] 				if (ret != 0)
2498e894c3f4SOpensource [Anthony Olech] 					return ret;
24992de9d600SNariman Poushin 
250021f8e482SDmitry Osipenko 				if (regs[i].delay_us) {
250121f8e482SDmitry Osipenko 					if (map->can_sleep)
25022b32d2f7SDmitry Osipenko 						fsleep(regs[i].delay_us);
250321f8e482SDmitry Osipenko 					else
25042de9d600SNariman Poushin 						udelay(regs[i].delay_us);
250521f8e482SDmitry Osipenko 				}
25062de9d600SNariman Poushin 
2507e894c3f4SOpensource [Anthony Olech] 				base += n;
2508e894c3f4SOpensource [Anthony Olech] 				n = 0;
25092de9d600SNariman Poushin 
25102de9d600SNariman Poushin 				if (page_change) {
25112de9d600SNariman Poushin 					ret = _regmap_select_page(map,
25122de9d600SNariman Poushin 								  &base[n].reg,
25132de9d600SNariman Poushin 								  range, 1);
2514e894c3f4SOpensource [Anthony Olech] 					if (ret != 0)
25151d5b40bcSCharles Keepax 						return ret;
25162de9d600SNariman Poushin 
25172de9d600SNariman Poushin 					page_change = 0;
25181d5b40bcSCharles Keepax 				}
25192de9d600SNariman Poushin 
25202de9d600SNariman Poushin 		}
25212de9d600SNariman Poushin 
25221d5b40bcSCharles Keepax 	}
2523e894c3f4SOpensource [Anthony Olech] 	if (n > 0)
2524e894c3f4SOpensource [Anthony Olech] 		return _regmap_raw_multi_reg_write(map, base, n);
25251d5b40bcSCharles Keepax 	return 0;
25261d5b40bcSCharles Keepax }
25271d5b40bcSCharles Keepax 
_regmap_multi_reg_write(struct regmap * map,const struct reg_sequence * regs,size_t num_regs)2528e894c3f4SOpensource [Anthony Olech] static int _regmap_multi_reg_write(struct regmap *map,
25298019ff6cSNariman Poushin 				   const struct reg_sequence *regs,
2530e894c3f4SOpensource [Anthony Olech] 				   size_t num_regs)
2531e894c3f4SOpensource [Anthony Olech] {
2532e894c3f4SOpensource [Anthony Olech] 	int i;
2533e894c3f4SOpensource [Anthony Olech] 	int ret;
2534e894c3f4SOpensource [Anthony Olech] 
2535e894c3f4SOpensource [Anthony Olech] 	if (!map->can_multi_write) {
2536e894c3f4SOpensource [Anthony Olech] 		for (i = 0; i < num_regs; i++) {
2537e894c3f4SOpensource [Anthony Olech] 			ret = _regmap_write(map, regs[i].reg, regs[i].def);
2538e894c3f4SOpensource [Anthony Olech] 			if (ret != 0)
2539e894c3f4SOpensource [Anthony Olech] 				return ret;
25402de9d600SNariman Poushin 
254121f8e482SDmitry Osipenko 			if (regs[i].delay_us) {
254221f8e482SDmitry Osipenko 				if (map->can_sleep)
25432b32d2f7SDmitry Osipenko 					fsleep(regs[i].delay_us);
254421f8e482SDmitry Osipenko 				else
25452de9d600SNariman Poushin 					udelay(regs[i].delay_us);
2546e894c3f4SOpensource [Anthony Olech] 			}
2547e894c3f4SOpensource [Anthony Olech] 		}
2548e894c3f4SOpensource [Anthony Olech] 		return 0;
2549e894c3f4SOpensource [Anthony Olech] 	}
2550e894c3f4SOpensource [Anthony Olech] 
2551e894c3f4SOpensource [Anthony Olech] 	if (!map->format.parse_inplace)
2552e894c3f4SOpensource [Anthony Olech] 		return -EINVAL;
2553e894c3f4SOpensource [Anthony Olech] 
2554e894c3f4SOpensource [Anthony Olech] 	if (map->writeable_reg)
2555e894c3f4SOpensource [Anthony Olech] 		for (i = 0; i < num_regs; i++) {
2556e894c3f4SOpensource [Anthony Olech] 			int reg = regs[i].reg;
2557e894c3f4SOpensource [Anthony Olech] 			if (!map->writeable_reg(map->dev, reg))
2558e894c3f4SOpensource [Anthony Olech] 				return -EINVAL;
2559fcac0233SXiubo Li 			if (!IS_ALIGNED(reg, map->reg_stride))
2560e894c3f4SOpensource [Anthony Olech] 				return -EINVAL;
2561e894c3f4SOpensource [Anthony Olech] 		}
2562e894c3f4SOpensource [Anthony Olech] 
2563e894c3f4SOpensource [Anthony Olech] 	if (!map->cache_bypass) {
2564e894c3f4SOpensource [Anthony Olech] 		for (i = 0; i < num_regs; i++) {
2565e894c3f4SOpensource [Anthony Olech] 			unsigned int val = regs[i].def;
2566e894c3f4SOpensource [Anthony Olech] 			unsigned int reg = regs[i].reg;
2567e894c3f4SOpensource [Anthony Olech] 			ret = regcache_write(map, reg, val);
2568e894c3f4SOpensource [Anthony Olech] 			if (ret) {
2569e894c3f4SOpensource [Anthony Olech] 				dev_err(map->dev,
2570e894c3f4SOpensource [Anthony Olech] 				"Error in caching of register: %x ret: %d\n",
2571e894c3f4SOpensource [Anthony Olech] 								reg, ret);
2572e894c3f4SOpensource [Anthony Olech] 				return ret;
2573e894c3f4SOpensource [Anthony Olech] 			}
2574e894c3f4SOpensource [Anthony Olech] 		}
2575e894c3f4SOpensource [Anthony Olech] 		if (map->cache_only) {
2576e894c3f4SOpensource [Anthony Olech] 			map->cache_dirty = true;
2577e894c3f4SOpensource [Anthony Olech] 			return 0;
2578e894c3f4SOpensource [Anthony Olech] 		}
2579e894c3f4SOpensource [Anthony Olech] 	}
2580e894c3f4SOpensource [Anthony Olech] 
2581e894c3f4SOpensource [Anthony Olech] 	WARN_ON(!map->bus);
2582e894c3f4SOpensource [Anthony Olech] 
2583e894c3f4SOpensource [Anthony Olech] 	for (i = 0; i < num_regs; i++) {
2584e894c3f4SOpensource [Anthony Olech] 		unsigned int reg = regs[i].reg;
2585e894c3f4SOpensource [Anthony Olech] 		struct regmap_range_node *range;
25862de9d600SNariman Poushin 
25872de9d600SNariman Poushin 		/* Coalesce all the writes between a page break or a delay
25882de9d600SNariman Poushin 		 * in a sequence
25892de9d600SNariman Poushin 		 */
2590e894c3f4SOpensource [Anthony Olech] 		range = _regmap_range_lookup(map, reg);
25912de9d600SNariman Poushin 		if (range || regs[i].delay_us) {
25928019ff6cSNariman Poushin 			size_t len = sizeof(struct reg_sequence)*num_regs;
25938019ff6cSNariman Poushin 			struct reg_sequence *base = kmemdup(regs, len,
2594e894c3f4SOpensource [Anthony Olech] 							   GFP_KERNEL);
2595e894c3f4SOpensource [Anthony Olech] 			if (!base)
2596e894c3f4SOpensource [Anthony Olech] 				return -ENOMEM;
2597e894c3f4SOpensource [Anthony Olech] 			ret = _regmap_range_multi_paged_reg_write(map, base,
2598e894c3f4SOpensource [Anthony Olech] 								  num_regs);
2599e894c3f4SOpensource [Anthony Olech] 			kfree(base);
2600e894c3f4SOpensource [Anthony Olech] 
2601e894c3f4SOpensource [Anthony Olech] 			return ret;
2602e894c3f4SOpensource [Anthony Olech] 		}
2603e894c3f4SOpensource [Anthony Olech] 	}
2604e894c3f4SOpensource [Anthony Olech] 	return _regmap_raw_multi_reg_write(map, regs, num_regs);
2605e894c3f4SOpensource [Anthony Olech] }
2606e894c3f4SOpensource [Anthony Olech] 
26072cf8e2dfSCharles Keepax /**
26082cf8e2dfSCharles Keepax  * regmap_multi_reg_write() - Write multiple registers to the device
2609e33fabd3SAnthony Olech  *
2610e33fabd3SAnthony Olech  * @map: Register map to write to
2611e33fabd3SAnthony Olech  * @regs: Array of structures containing register,value to be written
2612e33fabd3SAnthony Olech  * @num_regs: Number of registers to write
2613e33fabd3SAnthony Olech  *
26142cf8e2dfSCharles Keepax  * Write multiple registers to the device where the set of register, value
26152cf8e2dfSCharles Keepax  * pairs are supplied in any order, possibly not all in a single range.
26162cf8e2dfSCharles Keepax  *
2617e894c3f4SOpensource [Anthony Olech]  * The 'normal' block write mode will send ultimately send data on the
26182cf8e2dfSCharles Keepax  * target bus as R,V1,V2,V3,..,Vn where successively higher registers are
2619e894c3f4SOpensource [Anthony Olech]  * addressed. However, this alternative block multi write mode will send
2620e894c3f4SOpensource [Anthony Olech]  * the data as R1,V1,R2,V2,..,Rn,Vn on the target bus. The target device
2621e894c3f4SOpensource [Anthony Olech]  * must of course support the mode.
2622e33fabd3SAnthony Olech  *
2623e894c3f4SOpensource [Anthony Olech]  * A value of zero will be returned on success, a negative errno will be
2624e894c3f4SOpensource [Anthony Olech]  * returned in error cases.
2625e33fabd3SAnthony Olech  */
regmap_multi_reg_write(struct regmap * map,const struct reg_sequence * regs,int num_regs)26268019ff6cSNariman Poushin int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs,
2627e33fabd3SAnthony Olech 			   int num_regs)
2628e33fabd3SAnthony Olech {
26291d5b40bcSCharles Keepax 	int ret;
2630e33fabd3SAnthony Olech 
2631e33fabd3SAnthony Olech 	map->lock(map->lock_arg);
2632e33fabd3SAnthony Olech 
26331d5b40bcSCharles Keepax 	ret = _regmap_multi_reg_write(map, regs, num_regs);
26341d5b40bcSCharles Keepax 
2635e33fabd3SAnthony Olech 	map->unlock(map->lock_arg);
2636e33fabd3SAnthony Olech 
2637e33fabd3SAnthony Olech 	return ret;
2638e33fabd3SAnthony Olech }
2639e33fabd3SAnthony Olech EXPORT_SYMBOL_GPL(regmap_multi_reg_write);
2640e33fabd3SAnthony Olech 
26412cf8e2dfSCharles Keepax /**
26422cf8e2dfSCharles Keepax  * regmap_multi_reg_write_bypassed() - Write multiple registers to the
26431d5b40bcSCharles Keepax  *                                     device but not the cache
26441d5b40bcSCharles Keepax  *
26450d509f2bSMark Brown  * @map: Register map to write to
26460d509f2bSMark Brown  * @regs: Array of structures containing register,value to be written
26470d509f2bSMark Brown  * @num_regs: Number of registers to write
26480d509f2bSMark Brown  *
26492cf8e2dfSCharles Keepax  * Write multiple registers to the device but not the cache where the set
26502cf8e2dfSCharles Keepax  * of register are supplied in any order.
26512cf8e2dfSCharles Keepax  *
26520d509f2bSMark Brown  * This function is intended to be used for writing a large block of data
26530d509f2bSMark Brown  * atomically to the device in single transfer for those I2C client devices
26540d509f2bSMark Brown  * that implement this alternative block write mode.
26550d509f2bSMark Brown  *
26560d509f2bSMark Brown  * A value of zero will be returned on success, a negative errno will
26570d509f2bSMark Brown  * be returned in error cases.
26580d509f2bSMark Brown  */
regmap_multi_reg_write_bypassed(struct regmap * map,const struct reg_sequence * regs,int num_regs)26591d5b40bcSCharles Keepax int regmap_multi_reg_write_bypassed(struct regmap *map,
26608019ff6cSNariman Poushin 				    const struct reg_sequence *regs,
26610d509f2bSMark Brown 				    int num_regs)
26620d509f2bSMark Brown {
26631d5b40bcSCharles Keepax 	int ret;
26641d5b40bcSCharles Keepax 	bool bypass;
26650d509f2bSMark Brown 
26660d509f2bSMark Brown 	map->lock(map->lock_arg);
26670d509f2bSMark Brown 
26681d5b40bcSCharles Keepax 	bypass = map->cache_bypass;
26691d5b40bcSCharles Keepax 	map->cache_bypass = true;
26701d5b40bcSCharles Keepax 
26711d5b40bcSCharles Keepax 	ret = _regmap_multi_reg_write(map, regs, num_regs);
26721d5b40bcSCharles Keepax 
26731d5b40bcSCharles Keepax 	map->cache_bypass = bypass;
26741d5b40bcSCharles Keepax 
26750a819809SMark Brown 	map->unlock(map->lock_arg);
26760a819809SMark Brown 
26770a819809SMark Brown 	return ret;
26780a819809SMark Brown }
26791d5b40bcSCharles Keepax EXPORT_SYMBOL_GPL(regmap_multi_reg_write_bypassed);
26800d509f2bSMark Brown 
26810d509f2bSMark Brown /**
26822cf8e2dfSCharles Keepax  * regmap_raw_write_async() - Write raw values to one or more registers
26830d509f2bSMark Brown  *                            asynchronously
26840d509f2bSMark Brown  *
26850d509f2bSMark Brown  * @map: Register map to write to
26860d509f2bSMark Brown  * @reg: Initial register to write to
26870d509f2bSMark Brown  * @val: Block of data to be written, laid out for direct transmission to the
26880d509f2bSMark Brown  *       device.  Must be valid until regmap_async_complete() is called.
26890d509f2bSMark Brown  * @val_len: Length of data pointed to by val.
26900d509f2bSMark Brown  *
26910d509f2bSMark Brown  * This function is intended to be used for things like firmware
26920d509f2bSMark Brown  * download where a large block of data needs to be transferred to the
26930d509f2bSMark Brown  * device.  No formatting will be done on the data provided.
26940d509f2bSMark Brown  *
26950d509f2bSMark Brown  * If supported by the underlying bus the write will be scheduled
26960d509f2bSMark Brown  * asynchronously, helping maximise I/O speed on higher speed buses
26970d509f2bSMark Brown  * like SPI.  regmap_async_complete() can be called to ensure that all
26980d509f2bSMark Brown  * asynchrnous writes have been completed.
26990d509f2bSMark Brown  *
27000d509f2bSMark Brown  * A value of zero will be returned on success, a negative errno will
27010d509f2bSMark Brown  * be returned in error cases.
27020d509f2bSMark Brown  */
regmap_raw_write_async(struct regmap * map,unsigned int reg,const void * val,size_t val_len)27030d509f2bSMark Brown int regmap_raw_write_async(struct regmap *map, unsigned int reg,
27040d509f2bSMark Brown 			   const void *val, size_t val_len)
27050d509f2bSMark Brown {
27060d509f2bSMark Brown 	int ret;
27070d509f2bSMark Brown 
27080d509f2bSMark Brown 	if (val_len % map->format.val_bytes)
27090d509f2bSMark Brown 		return -EINVAL;
2710fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
27110d509f2bSMark Brown 		return -EINVAL;
27120d509f2bSMark Brown 
27130d509f2bSMark Brown 	map->lock(map->lock_arg);
27140d509f2bSMark Brown 
27150d509f2bSMark Brown 	map->async = true;
27160d509f2bSMark Brown 
271705669b63SDmitry Baryshkov 	ret = _regmap_raw_write(map, reg, val, val_len, false);
27180d509f2bSMark Brown 
27190d509f2bSMark Brown 	map->async = false;
27200d509f2bSMark Brown 
27210d509f2bSMark Brown 	map->unlock(map->lock_arg);
27220d509f2bSMark Brown 
27230d509f2bSMark Brown 	return ret;
2724b83a313bSMark Brown }
2725b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_write_async);
2726b83a313bSMark Brown 
_regmap_raw_read(struct regmap * map,unsigned int reg,void * val,unsigned int val_len,bool noinc)272798bc7dfdSMark Brown static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
272840033248SDmitry Baryshkov 			    unsigned int val_len, bool noinc)
2729b83a313bSMark Brown {
2730b83a313bSMark Brown 	struct regmap_range_node *range;
2731b83a313bSMark Brown 	int ret;
2732b83a313bSMark Brown 
2733d77e7456SMarek Vasut 	if (!map->read)
2734bb2bb45dSMark Brown 		return -EINVAL;
2735bb2bb45dSMark Brown 
273698bc7dfdSMark Brown 	range = _regmap_range_lookup(map, reg);
273798bc7dfdSMark Brown 	if (range) {
273898bc7dfdSMark Brown 		ret = _regmap_select_page(map, &reg, range,
273940033248SDmitry Baryshkov 					  noinc ? 1 : val_len / map->format.val_bytes);
27400ff3e62fSMark Brown 		if (ret != 0)
27416863ca62SKrystian Garbaciak 			return ret;
274298bc7dfdSMark Brown 	}
27436863ca62SKrystian Garbaciak 
27443f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
2745d939fb9aSMarc Reilly 	map->format.format_reg(map->work_buf, reg, map->reg_shift);
2746f50e38c9STony Lindgren 	regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
2747f50e38c9STony Lindgren 				      map->read_flag_mask);
2748c6b570d9SPhilipp Zabel 	trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
2749fb2736bbSMark Brown 
2750d77e7456SMarek Vasut 	ret = map->read(map->bus_context, map->work_buf,
275182159ba8SMark Brown 			map->format.reg_bytes + map->format.pad_bytes,
275240c5cc26SMark Brown 			val, val_len);
2753b83a313bSMark Brown 
2754c6b570d9SPhilipp Zabel 	trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes);
2755fb2736bbSMark Brown 
2756fb2736bbSMark Brown 	return ret;
2757b83a313bSMark Brown }
2758b83a313bSMark Brown 
_regmap_bus_reg_read(void * context,unsigned int reg,unsigned int * val)27593ac17037SBoris BREZILLON static int _regmap_bus_reg_read(void *context, unsigned int reg,
27603ac17037SBoris BREZILLON 				unsigned int *val)
27613ac17037SBoris BREZILLON {
27623ac17037SBoris BREZILLON 	struct regmap *map = context;
2763f18ee501SMark Brown 	struct regmap_range_node *range;
2764f18ee501SMark Brown 	int ret;
2765f18ee501SMark Brown 
2766f18ee501SMark Brown 	range = _regmap_range_lookup(map, reg);
2767f18ee501SMark Brown 	if (range) {
2768f18ee501SMark Brown 		ret = _regmap_select_page(map, &reg, range, 1);
2769f18ee501SMark Brown 		if (ret != 0)
2770f18ee501SMark Brown 			return ret;
2771f18ee501SMark Brown 	}
27723ac17037SBoris BREZILLON 
27733f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
27743ac17037SBoris BREZILLON 	return map->bus->reg_read(map->bus_context, reg, val);
27753ac17037SBoris BREZILLON }
27763ac17037SBoris BREZILLON 
_regmap_bus_read(void * context,unsigned int reg,unsigned int * val)2777ad278406SAndrey Smirnov static int _regmap_bus_read(void *context, unsigned int reg,
2778ad278406SAndrey Smirnov 			    unsigned int *val)
2779ad278406SAndrey Smirnov {
2780ad278406SAndrey Smirnov 	int ret;
2781ad278406SAndrey Smirnov 	struct regmap *map = context;
27824c90f297SKrzysztof Adamski 	void *work_val = map->work_buf + map->format.reg_bytes +
27834c90f297SKrzysztof Adamski 		map->format.pad_bytes;
2784ad278406SAndrey Smirnov 
2785ad278406SAndrey Smirnov 	if (!map->format.parse_val)
2786ad278406SAndrey Smirnov 		return -EINVAL;
2787ad278406SAndrey Smirnov 
278840033248SDmitry Baryshkov 	ret = _regmap_raw_read(map, reg, work_val, map->format.val_bytes, false);
2789ad278406SAndrey Smirnov 	if (ret == 0)
27904c90f297SKrzysztof Adamski 		*val = map->format.parse_val(work_val);
2791ad278406SAndrey Smirnov 
2792ad278406SAndrey Smirnov 	return ret;
2793ad278406SAndrey Smirnov }
2794ad278406SAndrey Smirnov 
_regmap_read(struct regmap * map,unsigned int reg,unsigned int * val)2795b83a313bSMark Brown static int _regmap_read(struct regmap *map, unsigned int reg,
2796b83a313bSMark Brown 			unsigned int *val)
2797b83a313bSMark Brown {
2798b83a313bSMark Brown 	int ret;
2799d2a5884aSAndrey Smirnov 	void *context = _regmap_map_get_context(map);
2800d2a5884aSAndrey Smirnov 
28015d1729e7SDimitris Papastamos 	if (!map->cache_bypass) {
28025d1729e7SDimitris Papastamos 		ret = regcache_read(map, reg, val);
28035d1729e7SDimitris Papastamos 		if (ret == 0)
28045d1729e7SDimitris Papastamos 			return 0;
28055d1729e7SDimitris Papastamos 	}
28065d1729e7SDimitris Papastamos 
28075d1729e7SDimitris Papastamos 	if (map->cache_only)
28085d1729e7SDimitris Papastamos 		return -EBUSY;
28095d1729e7SDimitris Papastamos 
28103e47b887SMark Brown 	if (!regmap_readable(map, reg))
28113e47b887SMark Brown 		return -EIO;
28123e47b887SMark Brown 
2813d2a5884aSAndrey Smirnov 	ret = map->reg_read(context, reg, val);
2814fb2736bbSMark Brown 	if (ret == 0) {
281595093762SBen Dooks 		if (regmap_should_log(map))
28161044c180SMark Brown 			dev_info(map->dev, "%x => %x\n", reg, *val);
28171044c180SMark Brown 
2818c6b570d9SPhilipp Zabel 		trace_regmap_reg_read(map, reg, *val);
2819b83a313bSMark Brown 
2820ad278406SAndrey Smirnov 		if (!map->cache_bypass)
2821f2985367SMark Brown 			regcache_write(map, reg, *val);
2822ad278406SAndrey Smirnov 	}
2823f2985367SMark Brown 
2824b83a313bSMark Brown 	return ret;
2825b83a313bSMark Brown }
2826b83a313bSMark Brown 
2827b83a313bSMark Brown /**
28282cf8e2dfSCharles Keepax  * regmap_read() - Read a value from a single register
2829b83a313bSMark Brown  *
28300093380cSGerhard Sittig  * @map: Register map to read from
2831b83a313bSMark Brown  * @reg: Register to be read from
2832b83a313bSMark Brown  * @val: Pointer to store read value
2833b83a313bSMark Brown  *
2834b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
2835b83a313bSMark Brown  * be returned in error cases.
2836b83a313bSMark Brown  */
regmap_read(struct regmap * map,unsigned int reg,unsigned int * val)2837b83a313bSMark Brown int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
2838b83a313bSMark Brown {
2839b83a313bSMark Brown 	int ret;
2840b83a313bSMark Brown 
2841fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
2842f01ee60fSStephen Warren 		return -EINVAL;
2843f01ee60fSStephen Warren 
28440d4529c5SDavide Ciminaghi 	map->lock(map->lock_arg);
2845b83a313bSMark Brown 
2846b83a313bSMark Brown 	ret = _regmap_read(map, reg, val);
2847b83a313bSMark Brown 
28480d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
2849b83a313bSMark Brown 
2850b83a313bSMark Brown 	return ret;
2851b83a313bSMark Brown }
2852b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_read);
2853b83a313bSMark Brown 
2854b83a313bSMark Brown /**
285570ee853eSRichard Fitzgerald  * regmap_read_bypassed() - Read a value from a single register direct
285670ee853eSRichard Fitzgerald  *			    from the device, bypassing the cache
285770ee853eSRichard Fitzgerald  *
285870ee853eSRichard Fitzgerald  * @map: Register map to read from
285970ee853eSRichard Fitzgerald  * @reg: Register to be read from
286070ee853eSRichard Fitzgerald  * @val: Pointer to store read value
286170ee853eSRichard Fitzgerald  *
286270ee853eSRichard Fitzgerald  * A value of zero will be returned on success, a negative errno will
286370ee853eSRichard Fitzgerald  * be returned in error cases.
286470ee853eSRichard Fitzgerald  */
regmap_read_bypassed(struct regmap * map,unsigned int reg,unsigned int * val)286570ee853eSRichard Fitzgerald int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val)
286670ee853eSRichard Fitzgerald {
286770ee853eSRichard Fitzgerald 	int ret;
286870ee853eSRichard Fitzgerald 	bool bypass, cache_only;
286970ee853eSRichard Fitzgerald 
287070ee853eSRichard Fitzgerald 	if (!IS_ALIGNED(reg, map->reg_stride))
287170ee853eSRichard Fitzgerald 		return -EINVAL;
287270ee853eSRichard Fitzgerald 
287370ee853eSRichard Fitzgerald 	map->lock(map->lock_arg);
287470ee853eSRichard Fitzgerald 
287570ee853eSRichard Fitzgerald 	bypass = map->cache_bypass;
287670ee853eSRichard Fitzgerald 	cache_only = map->cache_only;
287770ee853eSRichard Fitzgerald 	map->cache_bypass = true;
287870ee853eSRichard Fitzgerald 	map->cache_only = false;
287970ee853eSRichard Fitzgerald 
288070ee853eSRichard Fitzgerald 	ret = _regmap_read(map, reg, val);
288170ee853eSRichard Fitzgerald 
288270ee853eSRichard Fitzgerald 	map->cache_bypass = bypass;
288370ee853eSRichard Fitzgerald 	map->cache_only = cache_only;
288470ee853eSRichard Fitzgerald 
288570ee853eSRichard Fitzgerald 	map->unlock(map->lock_arg);
288670ee853eSRichard Fitzgerald 
288770ee853eSRichard Fitzgerald 	return ret;
288870ee853eSRichard Fitzgerald }
288970ee853eSRichard Fitzgerald EXPORT_SYMBOL_GPL(regmap_read_bypassed);
289070ee853eSRichard Fitzgerald 
289170ee853eSRichard Fitzgerald /**
28922cf8e2dfSCharles Keepax  * regmap_raw_read() - Read raw data from the device
2893b83a313bSMark Brown  *
28940093380cSGerhard Sittig  * @map: Register map to read from
2895b83a313bSMark Brown  * @reg: First register to be read from
2896b83a313bSMark Brown  * @val: Pointer to store read value
2897b83a313bSMark Brown  * @val_len: Size of data to read
2898b83a313bSMark Brown  *
2899b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
2900b83a313bSMark Brown  * be returned in error cases.
2901b83a313bSMark Brown  */
regmap_raw_read(struct regmap * map,unsigned int reg,void * val,size_t val_len)2902b83a313bSMark Brown int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
2903b83a313bSMark Brown 		    size_t val_len)
2904b83a313bSMark Brown {
2905b8fb5ab1SMark Brown 	size_t val_bytes = map->format.val_bytes;
2906b8fb5ab1SMark Brown 	size_t val_count = val_len / val_bytes;
2907b8fb5ab1SMark Brown 	unsigned int v;
2908b8fb5ab1SMark Brown 	int ret, i;
290904e016adSMark Brown 
2910851960baSStephen Warren 	if (val_len % map->format.val_bytes)
2911851960baSStephen Warren 		return -EINVAL;
2912fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
2913f01ee60fSStephen Warren 		return -EINVAL;
2914fa3eec77SMark Brown 	if (val_count == 0)
2915fa3eec77SMark Brown 		return -EINVAL;
2916851960baSStephen Warren 
29170d4529c5SDavide Ciminaghi 	map->lock(map->lock_arg);
2918b83a313bSMark Brown 
2919b8fb5ab1SMark Brown 	if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
2920b8fb5ab1SMark Brown 	    map->cache_type == REGCACHE_NONE) {
29211b079ca2SCharles Keepax 		size_t chunk_count, chunk_bytes;
29221b079ca2SCharles Keepax 		size_t chunk_regs = val_count;
29230645ba43SCharles Keepax 
292499e8dd39SCharles Keepax 		if (!map->cache_bypass && map->cache_only) {
292599e8dd39SCharles Keepax 			ret = -EBUSY;
292699e8dd39SCharles Keepax 			goto out;
292799e8dd39SCharles Keepax 		}
292899e8dd39SCharles Keepax 
2929d77e7456SMarek Vasut 		if (!map->read) {
29309a16ea90SMarkus Pargmann 			ret = -ENOTSUPP;
29319a16ea90SMarkus Pargmann 			goto out;
29329a16ea90SMarkus Pargmann 		}
29330645ba43SCharles Keepax 
29341b079ca2SCharles Keepax 		if (map->use_single_read)
29351b079ca2SCharles Keepax 			chunk_regs = 1;
29361b079ca2SCharles Keepax 		else if (map->max_raw_read && val_len > map->max_raw_read)
29371b079ca2SCharles Keepax 			chunk_regs = map->max_raw_read / val_bytes;
29389a16ea90SMarkus Pargmann 
29391b079ca2SCharles Keepax 		chunk_count = val_count / chunk_regs;
29401b079ca2SCharles Keepax 		chunk_bytes = chunk_regs * val_bytes;
29411b079ca2SCharles Keepax 
29421b079ca2SCharles Keepax 		/* Read bytes that fit into whole chunks */
29430645ba43SCharles Keepax 		for (i = 0; i < chunk_count; i++) {
294440033248SDmitry Baryshkov 			ret = _regmap_raw_read(map, reg, val, chunk_bytes, false);
29450645ba43SCharles Keepax 			if (ret != 0)
2946b83a313bSMark Brown 				goto out;
29471b079ca2SCharles Keepax 
29481b079ca2SCharles Keepax 			reg += regmap_get_offset(map, chunk_regs);
29491b079ca2SCharles Keepax 			val += chunk_bytes;
29501b079ca2SCharles Keepax 			val_len -= chunk_bytes;
2951b8fb5ab1SMark Brown 		}
2952b8fb5ab1SMark Brown 
29530645ba43SCharles Keepax 		/* Read remaining bytes */
29541b079ca2SCharles Keepax 		if (val_len) {
295540033248SDmitry Baryshkov 			ret = _regmap_raw_read(map, reg, val, val_len, false);
29560645ba43SCharles Keepax 			if (ret != 0)
29571b079ca2SCharles Keepax 				goto out;
29580645ba43SCharles Keepax 		}
2959b8fb5ab1SMark Brown 	} else {
2960b8fb5ab1SMark Brown 		/* Otherwise go word by word for the cache; should be low
2961b8fb5ab1SMark Brown 		 * cost as we expect to hit the cache.
2962b8fb5ab1SMark Brown 		 */
2963b8fb5ab1SMark Brown 		for (i = 0; i < val_count; i++) {
2964ca747be2SXiubo Li 			ret = _regmap_read(map, reg + regmap_get_offset(map, i),
2965f01ee60fSStephen Warren 					   &v);
2966b8fb5ab1SMark Brown 			if (ret != 0)
2967b8fb5ab1SMark Brown 				goto out;
2968b8fb5ab1SMark Brown 
2969d939fb9aSMarc Reilly 			map->format.format_val(val + (i * val_bytes), v, 0);
2970b8fb5ab1SMark Brown 		}
2971b8fb5ab1SMark Brown 	}
2972b8fb5ab1SMark Brown 
2973b8fb5ab1SMark Brown  out:
29740d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
2975b83a313bSMark Brown 
2976b83a313bSMark Brown 	return ret;
2977b83a313bSMark Brown }
2978b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_read);
2979b83a313bSMark Brown 
2980b83a313bSMark Brown /**
298174fe7b55SCrestez Dan Leonard  * regmap_noinc_read(): Read data from a register without incrementing the
298274fe7b55SCrestez Dan Leonard  *			register number
298374fe7b55SCrestez Dan Leonard  *
298474fe7b55SCrestez Dan Leonard  * @map: Register map to read from
298574fe7b55SCrestez Dan Leonard  * @reg: Register to read from
298674fe7b55SCrestez Dan Leonard  * @val: Pointer to data buffer
298774fe7b55SCrestez Dan Leonard  * @val_len: Length of output buffer in bytes.
298874fe7b55SCrestez Dan Leonard  *
2989d77e7456SMarek Vasut  * The regmap API usually assumes that bulk read operations will read a
299074fe7b55SCrestez Dan Leonard  * range of registers. Some devices have certain registers for which a read
299174fe7b55SCrestez Dan Leonard  * operation read will read from an internal FIFO.
299274fe7b55SCrestez Dan Leonard  *
299374fe7b55SCrestez Dan Leonard  * The target register must be volatile but registers after it can be
299474fe7b55SCrestez Dan Leonard  * completely unrelated cacheable registers.
299574fe7b55SCrestez Dan Leonard  *
299674fe7b55SCrestez Dan Leonard  * This will attempt multiple reads as required to read val_len bytes.
299774fe7b55SCrestez Dan Leonard  *
299874fe7b55SCrestez Dan Leonard  * A value of zero will be returned on success, a negative errno will be
299974fe7b55SCrestez Dan Leonard  * returned in error cases.
300074fe7b55SCrestez Dan Leonard  */
regmap_noinc_read(struct regmap * map,unsigned int reg,void * val,size_t val_len)300174fe7b55SCrestez Dan Leonard int regmap_noinc_read(struct regmap *map, unsigned int reg,
300274fe7b55SCrestez Dan Leonard 		      void *val, size_t val_len)
300374fe7b55SCrestez Dan Leonard {
300474fe7b55SCrestez Dan Leonard 	size_t read_len;
300574fe7b55SCrestez Dan Leonard 	int ret;
300674fe7b55SCrestez Dan Leonard 
3007c42e99a3SJavier Martinez Canillas 	if (!map->read)
3008c42e99a3SJavier Martinez Canillas 		return -ENOTSUPP;
3009c42e99a3SJavier Martinez Canillas 
301074fe7b55SCrestez Dan Leonard 	if (val_len % map->format.val_bytes)
301174fe7b55SCrestez Dan Leonard 		return -EINVAL;
301274fe7b55SCrestez Dan Leonard 	if (!IS_ALIGNED(reg, map->reg_stride))
301374fe7b55SCrestez Dan Leonard 		return -EINVAL;
301474fe7b55SCrestez Dan Leonard 	if (val_len == 0)
301574fe7b55SCrestez Dan Leonard 		return -EINVAL;
301674fe7b55SCrestez Dan Leonard 
301774fe7b55SCrestez Dan Leonard 	map->lock(map->lock_arg);
301874fe7b55SCrestez Dan Leonard 
301974fe7b55SCrestez Dan Leonard 	if (!regmap_volatile(map, reg) || !regmap_readable_noinc(map, reg)) {
302074fe7b55SCrestez Dan Leonard 		ret = -EINVAL;
302174fe7b55SCrestez Dan Leonard 		goto out_unlock;
302274fe7b55SCrestez Dan Leonard 	}
302374fe7b55SCrestez Dan Leonard 
3024c20cc099SLinus Walleij 	/*
3025c20cc099SLinus Walleij 	 * We have not defined the FIFO semantics for cache, as the
3026c20cc099SLinus Walleij 	 * cache is just one value deep. Should we return the last
3027c20cc099SLinus Walleij 	 * written value? Just avoid this by always reading the FIFO
3028c20cc099SLinus Walleij 	 * even when using cache. Cache only will not work.
3029c20cc099SLinus Walleij 	 */
303099e8dd39SCharles Keepax 	if (!map->cache_bypass && map->cache_only) {
3031c20cc099SLinus Walleij 		ret = -EBUSY;
3032c20cc099SLinus Walleij 		goto out_unlock;
3033c20cc099SLinus Walleij 	}
303499e8dd39SCharles Keepax 
303599e8dd39SCharles Keepax 	/* Use the accelerated operation if we can */
303699e8dd39SCharles Keepax 	if (map->bus->reg_noinc_read) {
3037c20cc099SLinus Walleij 		ret = regmap_noinc_readwrite(map, reg, val, val_len, false);
3038c20cc099SLinus Walleij 		goto out_unlock;
3039c20cc099SLinus Walleij 	}
3040c20cc099SLinus Walleij 
304174fe7b55SCrestez Dan Leonard 	while (val_len) {
304274fe7b55SCrestez Dan Leonard 		if (map->max_raw_read && map->max_raw_read < val_len)
304374fe7b55SCrestez Dan Leonard 			read_len = map->max_raw_read;
304474fe7b55SCrestez Dan Leonard 		else
304574fe7b55SCrestez Dan Leonard 			read_len = val_len;
304640033248SDmitry Baryshkov 		ret = _regmap_raw_read(map, reg, val, read_len, true);
304774fe7b55SCrestez Dan Leonard 		if (ret)
304874fe7b55SCrestez Dan Leonard 			goto out_unlock;
304974fe7b55SCrestez Dan Leonard 		val = ((u8 *)val) + read_len;
305074fe7b55SCrestez Dan Leonard 		val_len -= read_len;
305174fe7b55SCrestez Dan Leonard 	}
305274fe7b55SCrestez Dan Leonard 
305374fe7b55SCrestez Dan Leonard out_unlock:
305474fe7b55SCrestez Dan Leonard 	map->unlock(map->lock_arg);
305574fe7b55SCrestez Dan Leonard 	return ret;
305674fe7b55SCrestez Dan Leonard }
305774fe7b55SCrestez Dan Leonard EXPORT_SYMBOL_GPL(regmap_noinc_read);
305874fe7b55SCrestez Dan Leonard 
305974fe7b55SCrestez Dan Leonard /**
306074fe7b55SCrestez Dan Leonard  * regmap_field_read(): Read a value to a single register field
306167252287SSrinivas Kandagatla  *
306267252287SSrinivas Kandagatla  * @field: Register field to read from
306367252287SSrinivas Kandagatla  * @val: Pointer to store read value
306467252287SSrinivas Kandagatla  *
306567252287SSrinivas Kandagatla  * A value of zero will be returned on success, a negative errno will
306667252287SSrinivas Kandagatla  * be returned in error cases.
306767252287SSrinivas Kandagatla  */
regmap_field_read(struct regmap_field * field,unsigned int * val)306867252287SSrinivas Kandagatla int regmap_field_read(struct regmap_field *field, unsigned int *val)
306967252287SSrinivas Kandagatla {
307067252287SSrinivas Kandagatla 	int ret;
307167252287SSrinivas Kandagatla 	unsigned int reg_val;
307267252287SSrinivas Kandagatla 	ret = regmap_read(field->regmap, field->reg, &reg_val);
307367252287SSrinivas Kandagatla 	if (ret != 0)
307467252287SSrinivas Kandagatla 		return ret;
307567252287SSrinivas Kandagatla 
307667252287SSrinivas Kandagatla 	reg_val &= field->mask;
307767252287SSrinivas Kandagatla 	reg_val >>= field->shift;
307867252287SSrinivas Kandagatla 	*val = reg_val;
307967252287SSrinivas Kandagatla 
308067252287SSrinivas Kandagatla 	return ret;
308167252287SSrinivas Kandagatla }
308267252287SSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_field_read);
308367252287SSrinivas Kandagatla 
308467252287SSrinivas Kandagatla /**
30852cf8e2dfSCharles Keepax  * regmap_fields_read() - Read a value to a single register field with port ID
3086a0102375SKuninori Morimoto  *
3087a0102375SKuninori Morimoto  * @field: Register field to read from
3088a0102375SKuninori Morimoto  * @id: port ID
3089a0102375SKuninori Morimoto  * @val: Pointer to store read value
3090a0102375SKuninori Morimoto  *
3091a0102375SKuninori Morimoto  * A value of zero will be returned on success, a negative errno will
3092a0102375SKuninori Morimoto  * be returned in error cases.
3093a0102375SKuninori Morimoto  */
regmap_fields_read(struct regmap_field * field,unsigned int id,unsigned int * val)3094a0102375SKuninori Morimoto int regmap_fields_read(struct regmap_field *field, unsigned int id,
3095a0102375SKuninori Morimoto 		       unsigned int *val)
3096a0102375SKuninori Morimoto {
3097a0102375SKuninori Morimoto 	int ret;
3098a0102375SKuninori Morimoto 	unsigned int reg_val;
3099a0102375SKuninori Morimoto 
3100a0102375SKuninori Morimoto 	if (id >= field->id_size)
3101a0102375SKuninori Morimoto 		return -EINVAL;
3102a0102375SKuninori Morimoto 
3103a0102375SKuninori Morimoto 	ret = regmap_read(field->regmap,
3104a0102375SKuninori Morimoto 			  field->reg + (field->id_offset * id),
3105a0102375SKuninori Morimoto 			  &reg_val);
3106a0102375SKuninori Morimoto 	if (ret != 0)
3107a0102375SKuninori Morimoto 		return ret;
3108a0102375SKuninori Morimoto 
3109a0102375SKuninori Morimoto 	reg_val &= field->mask;
3110a0102375SKuninori Morimoto 	reg_val >>= field->shift;
3111a0102375SKuninori Morimoto 	*val = reg_val;
3112a0102375SKuninori Morimoto 
3113a0102375SKuninori Morimoto 	return ret;
3114a0102375SKuninori Morimoto }
3115a0102375SKuninori Morimoto EXPORT_SYMBOL_GPL(regmap_fields_read);
3116a0102375SKuninori Morimoto 
_regmap_bulk_read(struct regmap * map,unsigned int reg,const unsigned int * regs,void * val,size_t val_count)31173c1ff93bSGuenter Roeck static int _regmap_bulk_read(struct regmap *map, unsigned int reg,
3118*eb708cd6SRichard Fitzgerald 			     const unsigned int *regs, void *val, size_t val_count)
31193c1ff93bSGuenter Roeck {
31203c1ff93bSGuenter Roeck 	u32 *u32 = val;
31213c1ff93bSGuenter Roeck 	u16 *u16 = val;
31223c1ff93bSGuenter Roeck 	u8 *u8 = val;
31233c1ff93bSGuenter Roeck 	int ret, i;
31243c1ff93bSGuenter Roeck 
31253c1ff93bSGuenter Roeck 	map->lock(map->lock_arg);
31263c1ff93bSGuenter Roeck 
31273c1ff93bSGuenter Roeck 	for (i = 0; i < val_count; i++) {
31283c1ff93bSGuenter Roeck 		unsigned int ival;
31293c1ff93bSGuenter Roeck 
31303c1ff93bSGuenter Roeck 		if (regs) {
31313c1ff93bSGuenter Roeck 			if (!IS_ALIGNED(regs[i], map->reg_stride)) {
31323c1ff93bSGuenter Roeck 				ret = -EINVAL;
31333c1ff93bSGuenter Roeck 				goto out;
31343c1ff93bSGuenter Roeck 			}
31353c1ff93bSGuenter Roeck 			ret = _regmap_read(map, regs[i], &ival);
31363c1ff93bSGuenter Roeck 		} else {
31373c1ff93bSGuenter Roeck 			ret = _regmap_read(map, reg + regmap_get_offset(map, i), &ival);
31383c1ff93bSGuenter Roeck 		}
31393c1ff93bSGuenter Roeck 		if (ret != 0)
31403c1ff93bSGuenter Roeck 			goto out;
31413c1ff93bSGuenter Roeck 
31423c1ff93bSGuenter Roeck 		switch (map->format.val_bytes) {
31433c1ff93bSGuenter Roeck 		case 4:
31443c1ff93bSGuenter Roeck 			u32[i] = ival;
31453c1ff93bSGuenter Roeck 			break;
31463c1ff93bSGuenter Roeck 		case 2:
31473c1ff93bSGuenter Roeck 			u16[i] = ival;
31483c1ff93bSGuenter Roeck 			break;
31493c1ff93bSGuenter Roeck 		case 1:
31503c1ff93bSGuenter Roeck 			u8[i] = ival;
31513c1ff93bSGuenter Roeck 			break;
31523c1ff93bSGuenter Roeck 		default:
31533c1ff93bSGuenter Roeck 			ret = -EINVAL;
31543c1ff93bSGuenter Roeck 			goto out;
31553c1ff93bSGuenter Roeck 		}
31563c1ff93bSGuenter Roeck 	}
31573c1ff93bSGuenter Roeck out:
31583c1ff93bSGuenter Roeck 	map->unlock(map->lock_arg);
31593c1ff93bSGuenter Roeck 	return ret;
31603c1ff93bSGuenter Roeck }
31613c1ff93bSGuenter Roeck 
3162a0102375SKuninori Morimoto /**
31633c1ff93bSGuenter Roeck  * regmap_bulk_read() - Read multiple sequential registers from the device
3164b83a313bSMark Brown  *
31650093380cSGerhard Sittig  * @map: Register map to read from
3166b83a313bSMark Brown  * @reg: First register to be read from
3167b83a313bSMark Brown  * @val: Pointer to store read value, in native register size for device
3168b83a313bSMark Brown  * @val_count: Number of registers to read
3169b83a313bSMark Brown  *
3170b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
3171b83a313bSMark Brown  * be returned in error cases.
3172b83a313bSMark Brown  */
regmap_bulk_read(struct regmap * map,unsigned int reg,void * val,size_t val_count)3173b83a313bSMark Brown int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
3174b83a313bSMark Brown 		     size_t val_count)
3175b83a313bSMark Brown {
3176b83a313bSMark Brown 	int ret, i;
3177b83a313bSMark Brown 	size_t val_bytes = map->format.val_bytes;
317882cd9965SLars-Peter Clausen 	bool vol = regmap_volatile_range(map, reg, val_count);
31795d1729e7SDimitris Papastamos 
3180fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
3181f01ee60fSStephen Warren 		return -EINVAL;
3182186ba2eeSCharles Keepax 	if (val_count == 0)
3183186ba2eeSCharles Keepax 		return -EINVAL;
3184b83a313bSMark Brown 
3185ea50e2a1SJavier Martinez Canillas 	if (map->read && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
31860645ba43SCharles Keepax 		ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
31872e33caf1SAshish Jangam 		if (ret != 0)
31882e33caf1SAshish Jangam 			return ret;
3189b83a313bSMark Brown 
3190b83a313bSMark Brown 		for (i = 0; i < val_count * val_bytes; i += val_bytes)
31918a819ff8SMark Brown 			map->format.parse_inplace(val + i);
3192de2d808fSMark Brown 	} else {
31933c1ff93bSGuenter Roeck 		ret = _regmap_bulk_read(map, reg, NULL, val, val_count);
3194de2d808fSMark Brown 	}
3195026c99b5SDmitry Rokosov 	if (!ret)
3196026c99b5SDmitry Rokosov 		trace_regmap_bulk_read(map, reg, val, val_bytes * val_count);
3197186ba2eeSCharles Keepax 	return ret;
3198b83a313bSMark Brown }
3199b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_bulk_read);
3200b83a313bSMark Brown 
32013c1ff93bSGuenter Roeck /**
32023c1ff93bSGuenter Roeck  * regmap_multi_reg_read() - Read multiple non-sequential registers from the device
32033c1ff93bSGuenter Roeck  *
32043c1ff93bSGuenter Roeck  * @map: Register map to read from
32053c1ff93bSGuenter Roeck  * @regs: Array of registers to read from
32063c1ff93bSGuenter Roeck  * @val: Pointer to store read value, in native register size for device
32073c1ff93bSGuenter Roeck  * @val_count: Number of registers to read
32083c1ff93bSGuenter Roeck  *
32093c1ff93bSGuenter Roeck  * A value of zero will be returned on success, a negative errno will
32103c1ff93bSGuenter Roeck  * be returned in error cases.
32113c1ff93bSGuenter Roeck  */
regmap_multi_reg_read(struct regmap * map,const unsigned int * regs,void * val,size_t val_count)3212*eb708cd6SRichard Fitzgerald int regmap_multi_reg_read(struct regmap *map, const unsigned int *regs, void *val,
32133c1ff93bSGuenter Roeck 			  size_t val_count)
32143c1ff93bSGuenter Roeck {
32153c1ff93bSGuenter Roeck 	if (val_count == 0)
32163c1ff93bSGuenter Roeck 		return -EINVAL;
32173c1ff93bSGuenter Roeck 
32183c1ff93bSGuenter Roeck 	return _regmap_bulk_read(map, 0, regs, val, val_count);
32193c1ff93bSGuenter Roeck }
32203c1ff93bSGuenter Roeck EXPORT_SYMBOL_GPL(regmap_multi_reg_read);
32213c1ff93bSGuenter Roeck 
_regmap_update_bits(struct regmap * map,unsigned int reg,unsigned int mask,unsigned int val,bool * change,bool force_write)3222018690d3SMark Brown static int _regmap_update_bits(struct regmap *map, unsigned int reg,
3223018690d3SMark Brown 			       unsigned int mask, unsigned int val,
32247ff0589cSKuninori Morimoto 			       bool *change, bool force_write)
3225b83a313bSMark Brown {
3226b83a313bSMark Brown 	int ret;
3227d91e8db2SMark Brown 	unsigned int tmp, orig;
3228b83a313bSMark Brown 
322977792b11SJon Ringle 	if (change)
323077792b11SJon Ringle 		*change = false;
323177792b11SJon Ringle 
323277792b11SJon Ringle 	if (regmap_volatile(map, reg) && map->reg_update_bits) {
32333f58f6dcSMaxime Chevallier 		reg = regmap_reg_addr(map, reg);
323477792b11SJon Ringle 		ret = map->reg_update_bits(map->bus_context, reg, mask, val);
323577792b11SJon Ringle 		if (ret == 0 && change)
323677792b11SJon Ringle 			*change = true;
323777792b11SJon Ringle 	} else {
3238d91e8db2SMark Brown 		ret = _regmap_read(map, reg, &orig);
3239b83a313bSMark Brown 		if (ret != 0)
3240fc3ebd78SKrystian Garbaciak 			return ret;
3241b83a313bSMark Brown 
3242d91e8db2SMark Brown 		tmp = orig & ~mask;
3243b83a313bSMark Brown 		tmp |= val & mask;
3244b83a313bSMark Brown 
3245b629c698SWaqar Hameed 		if (force_write || (tmp != orig) || map->force_write_field) {
3246b83a313bSMark Brown 			ret = _regmap_write(map, reg, tmp);
324777792b11SJon Ringle 			if (ret == 0 && change)
3248018690d3SMark Brown 				*change = true;
324977792b11SJon Ringle 		}
3250018690d3SMark Brown 	}
3251b83a313bSMark Brown 
3252b83a313bSMark Brown 	return ret;
3253b83a313bSMark Brown }
3254018690d3SMark Brown 
3255018690d3SMark Brown /**
32562cf8e2dfSCharles Keepax  * regmap_update_bits_base() - Perform a read/modify/write cycle on a register
3257018690d3SMark Brown  *
3258018690d3SMark Brown  * @map: Register map to update
3259018690d3SMark Brown  * @reg: Register to update
3260018690d3SMark Brown  * @mask: Bitmask to change
3261018690d3SMark Brown  * @val: New value for bitmask
326291d31b9fSKuninori Morimoto  * @change: Boolean indicating if a write was done
326391d31b9fSKuninori Morimoto  * @async: Boolean indicating asynchronously
326491d31b9fSKuninori Morimoto  * @force: Boolean indicating use force update
3265018690d3SMark Brown  *
32662cf8e2dfSCharles Keepax  * Perform a read/modify/write cycle on a register map with change, async, force
32672cf8e2dfSCharles Keepax  * options.
32682cf8e2dfSCharles Keepax  *
32692cf8e2dfSCharles Keepax  * If async is true:
32702cf8e2dfSCharles Keepax  *
32712cf8e2dfSCharles Keepax  * With most buses the read must be done synchronously so this is most useful
32722cf8e2dfSCharles Keepax  * for devices with a cache which do not need to interact with the hardware to
32732cf8e2dfSCharles Keepax  * determine the current register value.
3274915f441bSMark Brown  *
3275915f441bSMark Brown  * Returns zero for success, a negative number on error.
3276915f441bSMark Brown  */
regmap_update_bits_base(struct regmap * map,unsigned int reg,unsigned int mask,unsigned int val,bool * change,bool async,bool force)327791d31b9fSKuninori Morimoto int regmap_update_bits_base(struct regmap *map, unsigned int reg,
327891d31b9fSKuninori Morimoto 			    unsigned int mask, unsigned int val,
327991d31b9fSKuninori Morimoto 			    bool *change, bool async, bool force)
3280915f441bSMark Brown {
3281915f441bSMark Brown 	int ret;
3282915f441bSMark Brown 
3283915f441bSMark Brown 	map->lock(map->lock_arg);
3284915f441bSMark Brown 
328591d31b9fSKuninori Morimoto 	map->async = async;
3286915f441bSMark Brown 
328791d31b9fSKuninori Morimoto 	ret = _regmap_update_bits(map, reg, mask, val, change, force);
3288915f441bSMark Brown 
3289915f441bSMark Brown 	map->async = false;
3290915f441bSMark Brown 
3291915f441bSMark Brown 	map->unlock(map->lock_arg);
3292915f441bSMark Brown 
3293915f441bSMark Brown 	return ret;
3294915f441bSMark Brown }
329591d31b9fSKuninori Morimoto EXPORT_SYMBOL_GPL(regmap_update_bits_base);
3296915f441bSMark Brown 
3297aa2ff9dbSBartosz Golaszewski /**
3298aa2ff9dbSBartosz Golaszewski  * regmap_test_bits() - Check if all specified bits are set in a register.
3299aa2ff9dbSBartosz Golaszewski  *
3300aa2ff9dbSBartosz Golaszewski  * @map: Register map to operate on
3301aa2ff9dbSBartosz Golaszewski  * @reg: Register to read from
3302aa2ff9dbSBartosz Golaszewski  * @bits: Bits to test
3303aa2ff9dbSBartosz Golaszewski  *
3304e680a409SBartosz Golaszewski  * Returns 0 if at least one of the tested bits is not set, 1 if all tested
3305e680a409SBartosz Golaszewski  * bits are set and a negative error number if the underlying regmap_read()
3306e680a409SBartosz Golaszewski  * fails.
3307aa2ff9dbSBartosz Golaszewski  */
regmap_test_bits(struct regmap * map,unsigned int reg,unsigned int bits)3308aa2ff9dbSBartosz Golaszewski int regmap_test_bits(struct regmap *map, unsigned int reg, unsigned int bits)
3309aa2ff9dbSBartosz Golaszewski {
3310aa2ff9dbSBartosz Golaszewski 	unsigned int val, ret;
3311aa2ff9dbSBartosz Golaszewski 
3312aa2ff9dbSBartosz Golaszewski 	ret = regmap_read(map, reg, &val);
3313aa2ff9dbSBartosz Golaszewski 	if (ret)
3314aa2ff9dbSBartosz Golaszewski 		return ret;
3315aa2ff9dbSBartosz Golaszewski 
3316aa2ff9dbSBartosz Golaszewski 	return (val & bits) == bits;
3317aa2ff9dbSBartosz Golaszewski }
3318aa2ff9dbSBartosz Golaszewski EXPORT_SYMBOL_GPL(regmap_test_bits);
3319aa2ff9dbSBartosz Golaszewski 
regmap_async_complete_cb(struct regmap_async * async,int ret)33200d509f2bSMark Brown void regmap_async_complete_cb(struct regmap_async *async, int ret)
33210d509f2bSMark Brown {
33220d509f2bSMark Brown 	struct regmap *map = async->map;
33230d509f2bSMark Brown 	bool wake;
33240d509f2bSMark Brown 
3325c6b570d9SPhilipp Zabel 	trace_regmap_async_io_complete(map);
3326fe7d4ccdSMark Brown 
33270d509f2bSMark Brown 	spin_lock(&map->async_lock);
33287e09a979SMark Brown 	list_move(&async->list, &map->async_free);
33290d509f2bSMark Brown 	wake = list_empty(&map->async_list);
33300d509f2bSMark Brown 
33310d509f2bSMark Brown 	if (ret != 0)
33320d509f2bSMark Brown 		map->async_ret = ret;
33330d509f2bSMark Brown 
33340d509f2bSMark Brown 	spin_unlock(&map->async_lock);
33350d509f2bSMark Brown 
33360d509f2bSMark Brown 	if (wake)
33370d509f2bSMark Brown 		wake_up(&map->async_waitq);
33380d509f2bSMark Brown }
3339f804fb56SAxel Lin EXPORT_SYMBOL_GPL(regmap_async_complete_cb);
33400d509f2bSMark Brown 
regmap_async_is_done(struct regmap * map)33410d509f2bSMark Brown static int regmap_async_is_done(struct regmap *map)
33420d509f2bSMark Brown {
33430d509f2bSMark Brown 	unsigned long flags;
33440d509f2bSMark Brown 	int ret;
33450d509f2bSMark Brown 
33460d509f2bSMark Brown 	spin_lock_irqsave(&map->async_lock, flags);
33470d509f2bSMark Brown 	ret = list_empty(&map->async_list);
33480d509f2bSMark Brown 	spin_unlock_irqrestore(&map->async_lock, flags);
33490d509f2bSMark Brown 
33500d509f2bSMark Brown 	return ret;
33510d509f2bSMark Brown }
33520d509f2bSMark Brown 
33530d509f2bSMark Brown /**
33542cf8e2dfSCharles Keepax  * regmap_async_complete - Ensure all asynchronous I/O has completed.
33550d509f2bSMark Brown  *
33560d509f2bSMark Brown  * @map: Map to operate on.
33570d509f2bSMark Brown  *
33580d509f2bSMark Brown  * Blocks until any pending asynchronous I/O has completed.  Returns
33590d509f2bSMark Brown  * an error code for any failed I/O operations.
33600d509f2bSMark Brown  */
regmap_async_complete(struct regmap * map)33610d509f2bSMark Brown int regmap_async_complete(struct regmap *map)
33620d509f2bSMark Brown {
33630d509f2bSMark Brown 	unsigned long flags;
33640d509f2bSMark Brown 	int ret;
33650d509f2bSMark Brown 
33660d509f2bSMark Brown 	/* Nothing to do with no async support */
3367f2e055e7SDaniel Mack 	if (!map->bus || !map->bus->async_write)
33680d509f2bSMark Brown 		return 0;
33690d509f2bSMark Brown 
3370c6b570d9SPhilipp Zabel 	trace_regmap_async_complete_start(map);
3371fe7d4ccdSMark Brown 
33720d509f2bSMark Brown 	wait_event(map->async_waitq, regmap_async_is_done(map));
33730d509f2bSMark Brown 
33740d509f2bSMark Brown 	spin_lock_irqsave(&map->async_lock, flags);
33750d509f2bSMark Brown 	ret = map->async_ret;
33760d509f2bSMark Brown 	map->async_ret = 0;
33770d509f2bSMark Brown 	spin_unlock_irqrestore(&map->async_lock, flags);
33780d509f2bSMark Brown 
3379c6b570d9SPhilipp Zabel 	trace_regmap_async_complete_done(map);
3380fe7d4ccdSMark Brown 
33810d509f2bSMark Brown 	return ret;
33820d509f2bSMark Brown }
3383f88948efSMark Brown EXPORT_SYMBOL_GPL(regmap_async_complete);
33840d509f2bSMark Brown 
338522f0d90aSMark Brown /**
33862cf8e2dfSCharles Keepax  * regmap_register_patch - Register and apply register updates to be applied
338722f0d90aSMark Brown  *                         on device initialistion
338822f0d90aSMark Brown  *
338922f0d90aSMark Brown  * @map: Register map to apply updates to.
339022f0d90aSMark Brown  * @regs: Values to update.
339122f0d90aSMark Brown  * @num_regs: Number of entries in regs.
339222f0d90aSMark Brown  *
339322f0d90aSMark Brown  * Register a set of register updates to be applied to the device
339422f0d90aSMark Brown  * whenever the device registers are synchronised with the cache and
339522f0d90aSMark Brown  * apply them immediately.  Typically this is used to apply
339622f0d90aSMark Brown  * corrections to be applied to the device defaults on startup, such
339722f0d90aSMark Brown  * as the updates some vendors provide to undocumented registers.
339856fb1c74SMark Brown  *
339956fb1c74SMark Brown  * The caller must ensure that this function cannot be called
340056fb1c74SMark Brown  * concurrently with either itself or regcache_sync().
340122f0d90aSMark Brown  */
regmap_register_patch(struct regmap * map,const struct reg_sequence * regs,int num_regs)34028019ff6cSNariman Poushin int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs,
340322f0d90aSMark Brown 			  int num_regs)
340422f0d90aSMark Brown {
34058019ff6cSNariman Poushin 	struct reg_sequence *p;
34066bf13103SCharles Keepax 	int ret;
340722f0d90aSMark Brown 	bool bypass;
340822f0d90aSMark Brown 
3409bd60e381SCai Zhiyong 	if (WARN_ONCE(num_regs <= 0, "invalid registers number (%d)\n",
3410bd60e381SCai Zhiyong 	    num_regs))
3411bd60e381SCai Zhiyong 		return 0;
3412bd60e381SCai Zhiyong 
3413aab13ebcSMark Brown 	p = krealloc(map->patch,
34148019ff6cSNariman Poushin 		     sizeof(struct reg_sequence) * (map->patch_regs + num_regs),
3415aab13ebcSMark Brown 		     GFP_KERNEL);
3416aab13ebcSMark Brown 	if (p) {
3417aab13ebcSMark Brown 		memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs));
3418aab13ebcSMark Brown 		map->patch = p;
3419aab13ebcSMark Brown 		map->patch_regs += num_regs;
342022f0d90aSMark Brown 	} else {
342156fb1c74SMark Brown 		return -ENOMEM;
342222f0d90aSMark Brown 	}
342322f0d90aSMark Brown 
342422f0d90aSMark Brown 	map->lock(map->lock_arg);
342522f0d90aSMark Brown 
342622f0d90aSMark Brown 	bypass = map->cache_bypass;
342722f0d90aSMark Brown 
342822f0d90aSMark Brown 	map->cache_bypass = true;
342922f0d90aSMark Brown 	map->async = true;
343022f0d90aSMark Brown 
34316bf13103SCharles Keepax 	ret = _regmap_multi_reg_write(map, regs, num_regs);
343222f0d90aSMark Brown 
34331a25f261SMark Brown 	map->async = false;
343422f0d90aSMark Brown 	map->cache_bypass = bypass;
343522f0d90aSMark Brown 
34360d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
343722f0d90aSMark Brown 
34381a25f261SMark Brown 	regmap_async_complete(map);
34391a25f261SMark Brown 
344022f0d90aSMark Brown 	return ret;
344122f0d90aSMark Brown }
344222f0d90aSMark Brown EXPORT_SYMBOL_GPL(regmap_register_patch);
344322f0d90aSMark Brown 
34442cf8e2dfSCharles Keepax /**
34452cf8e2dfSCharles Keepax  * regmap_get_val_bytes() - Report the size of a register value
34462cf8e2dfSCharles Keepax  *
34472cf8e2dfSCharles Keepax  * @map: Register map to operate on.
3448a6539c32SMark Brown  *
3449a6539c32SMark Brown  * Report the size of a register value, mainly intended to for use by
3450a6539c32SMark Brown  * generic infrastructure built on top of regmap.
3451a6539c32SMark Brown  */
regmap_get_val_bytes(struct regmap * map)3452a6539c32SMark Brown int regmap_get_val_bytes(struct regmap *map)
3453a6539c32SMark Brown {
3454a6539c32SMark Brown 	if (map->format.format_write)
3455a6539c32SMark Brown 		return -EINVAL;
3456a6539c32SMark Brown 
3457a6539c32SMark Brown 	return map->format.val_bytes;
3458a6539c32SMark Brown }
3459a6539c32SMark Brown EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
3460a6539c32SMark Brown 
3461668abc72SSrinivas Kandagatla /**
34622cf8e2dfSCharles Keepax  * regmap_get_max_register() - Report the max register value
34632cf8e2dfSCharles Keepax  *
34642cf8e2dfSCharles Keepax  * @map: Register map to operate on.
3465668abc72SSrinivas Kandagatla  *
3466668abc72SSrinivas Kandagatla  * Report the max register value, mainly intended to for use by
3467668abc72SSrinivas Kandagatla  * generic infrastructure built on top of regmap.
3468668abc72SSrinivas Kandagatla  */
regmap_get_max_register(struct regmap * map)3469668abc72SSrinivas Kandagatla int regmap_get_max_register(struct regmap *map)
3470668abc72SSrinivas Kandagatla {
34710ec74ad3SJan Dakinevich 	return map->max_register_is_set ? map->max_register : -EINVAL;
3472668abc72SSrinivas Kandagatla }
3473668abc72SSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_get_max_register);
3474668abc72SSrinivas Kandagatla 
3475a2f776cbSSrinivas Kandagatla /**
34762cf8e2dfSCharles Keepax  * regmap_get_reg_stride() - Report the register address stride
34772cf8e2dfSCharles Keepax  *
34782cf8e2dfSCharles Keepax  * @map: Register map to operate on.
3479a2f776cbSSrinivas Kandagatla  *
3480a2f776cbSSrinivas Kandagatla  * Report the register address stride, mainly intended to for use by
3481a2f776cbSSrinivas Kandagatla  * generic infrastructure built on top of regmap.
3482a2f776cbSSrinivas Kandagatla  */
regmap_get_reg_stride(struct regmap * map)3483a2f776cbSSrinivas Kandagatla int regmap_get_reg_stride(struct regmap *map)
3484a2f776cbSSrinivas Kandagatla {
3485a2f776cbSSrinivas Kandagatla 	return map->reg_stride;
3486a2f776cbSSrinivas Kandagatla }
3487a2f776cbSSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_get_reg_stride);
3488a2f776cbSSrinivas Kandagatla 
3489a6d99022SMichael Walle /**
3490a6d99022SMichael Walle  * regmap_might_sleep() - Returns whether a regmap access might sleep.
3491a6d99022SMichael Walle  *
3492a6d99022SMichael Walle  * @map: Register map to operate on.
3493a6d99022SMichael Walle  *
3494a6d99022SMichael Walle  * Returns true if an access to the register might sleep, else false.
3495a6d99022SMichael Walle  */
regmap_might_sleep(struct regmap * map)3496a6d99022SMichael Walle bool regmap_might_sleep(struct regmap *map)
3497a6d99022SMichael Walle {
3498a6d99022SMichael Walle 	return map->can_sleep;
3499a6d99022SMichael Walle }
3500a6d99022SMichael Walle EXPORT_SYMBOL_GPL(regmap_might_sleep);
3501a6d99022SMichael Walle 
regmap_parse_val(struct regmap * map,const void * buf,unsigned int * val)350213ff50c8SNenghua Cao int regmap_parse_val(struct regmap *map, const void *buf,
350313ff50c8SNenghua Cao 			unsigned int *val)
350413ff50c8SNenghua Cao {
350513ff50c8SNenghua Cao 	if (!map->format.parse_val)
350613ff50c8SNenghua Cao 		return -EINVAL;
350713ff50c8SNenghua Cao 
350813ff50c8SNenghua Cao 	*val = map->format.parse_val(buf);
350913ff50c8SNenghua Cao 
351013ff50c8SNenghua Cao 	return 0;
351113ff50c8SNenghua Cao }
351213ff50c8SNenghua Cao EXPORT_SYMBOL_GPL(regmap_parse_val);
351313ff50c8SNenghua Cao 
regmap_initcall(void)351431244e39SMark Brown static int __init regmap_initcall(void)
351531244e39SMark Brown {
351631244e39SMark Brown 	regmap_debugfs_initcall();
351731244e39SMark Brown 
351831244e39SMark Brown 	return 0;
351931244e39SMark Brown }
352031244e39SMark Brown postcore_initcall(regmap_initcall);
3521