xref: /openbmc/linux/drivers/base/regmap/regmap.c (revision ed4543328f7108e1047b83b96ca7f7208747d930)
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 <broonie@opensource.wolfsonmicro.com>
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>
2053d86095SJens Thoms Toerring #include <asm/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 {
928de2f081SMark Brown 	if (map->max_register && 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 
1151ea975cfSCristian Birsan 	if (map->max_register && 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 
1328de2f081SMark Brown 	if (map->max_register && 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 
601f1a99d86SCosmin Tanislav static int dev_get_regmap_match(struct device *dev, void *res, void *data);
602f1a99d86SCosmin Tanislav 
regmap_detach_dev(struct device * dev,struct regmap * map)603f1a99d86SCosmin Tanislav static int regmap_detach_dev(struct device *dev, struct regmap *map)
604f1a99d86SCosmin Tanislav {
605f1a99d86SCosmin Tanislav 	if (!dev)
606f1a99d86SCosmin Tanislav 		return 0;
607f1a99d86SCosmin Tanislav 
608f1a99d86SCosmin Tanislav 	return devres_release(dev, dev_get_regmap_release,
609f1a99d86SCosmin Tanislav 			      dev_get_regmap_match, (void *)map->name);
610f1a99d86SCosmin Tanislav }
611f1a99d86SCosmin 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;
75970e2f305SCristian 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;
7720074f3f2SColin Foster 
773c212acccSWolfram Sang 	map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
77482159ba8SMark Brown 	map->format.pad_bytes = config->pad_bits / 8;
7754a670ac3SMaxime Chevallier 	map->format.reg_shift = config->reg_shift;
776c212acccSWolfram Sang 	map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
7775494a98fSFabio Estevam 	map->format.buf_size = DIV_ROUND_UP(config->reg_bits +
7785494a98fSFabio Estevam 			config->val_bits + config->pad_bits, 8);
779d939fb9aSMarc Reilly 	map->reg_shift = config->pad_bits % 8;
780f01ee60fSStephen Warren 	if (config->reg_stride)
781f01ee60fSStephen Warren 		map->reg_stride = config->reg_stride;
782f01ee60fSStephen Warren 	else
783f01ee60fSStephen Warren 		map->reg_stride = 1;
784ca747be2SXiubo Li 	if (is_power_of_2(map->reg_stride))
785ca747be2SXiubo Li 		map->reg_stride_order = ilog2(map->reg_stride);
786ca747be2SXiubo Li 	else
787ca747be2SXiubo Li 		map->reg_stride_order = -1;
788d77e7456SMarek Vasut 	map->use_single_read = config->use_single_read || !(config->read || (bus && bus->read));
789d77e7456SMarek Vasut 	map->use_single_write = config->use_single_write || !(config->write || (bus && bus->write));
790d77e7456SMarek Vasut 	map->can_multi_write = config->can_multi_write && (config->write || (bus && bus->write));
79117649c90SSergey SENOZHATSKY 	if (bus) {
792adaac459SMarkus Pargmann 		map->max_raw_read = bus->max_raw_read;
793adaac459SMarkus Pargmann 		map->max_raw_write = bus->max_raw_write;
794d77e7456SMarek Vasut 	} else if (config->max_raw_read && config->max_raw_write) {
795d77e7456SMarek Vasut 		map->max_raw_read = config->max_raw_read;
796d77e7456SMarek Vasut 		map->max_raw_write = config->max_raw_write;
79717649c90SSergey SENOZHATSKY 	}
798b83a313bSMark Brown 	map->dev = dev;
799b83a313bSMark Brown 	map->bus = bus;
8000135bbccSStephen Warren 	map->bus_context = bus_context;
8012e2ae66dSMark Brown 	map->max_register = config->max_register;
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) {
1065*5e448ea8SMark 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) {
1071*5e448ea8SMark 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;
1427bf315173SMark Brown 	map->writeable_reg = config->writeable_reg;
1428bf315173SMark Brown 	map->readable_reg = config->readable_reg;
1429bf315173SMark Brown 	map->volatile_reg = config->volatile_reg;
1430bf315173SMark Brown 	map->precious_reg = config->precious_reg;
1431cdf6b11dSBen Whitten 	map->writeable_noinc_reg = config->writeable_noinc_reg;
143274fe7b55SCrestez Dan Leonard 	map->readable_noinc_reg = config->readable_noinc_reg;
1433bf315173SMark Brown 	map->cache_type = config->cache_type;
1434bf315173SMark Brown 
143594cc89ebSCharles Keepax 	ret = regmap_set_name(map, config);
143694cc89ebSCharles Keepax 	if (ret)
143794cc89ebSCharles Keepax 		return ret;
143894cc89ebSCharles Keepax 
143994cc89ebSCharles Keepax 	regmap_debugfs_init(map);
1440a24f64a6SMark Brown 
1441421e8d2dSMark Brown 	map->cache_bypass = false;
1442421e8d2dSMark Brown 	map->cache_only = false;
1443421e8d2dSMark Brown 
14444d879514SDimitris Papastamos 	return regcache_init(map, config);
1445bf315173SMark Brown }
1446752a6a5fSMark Brown EXPORT_SYMBOL_GPL(regmap_reinit_cache);
1447bf315173SMark Brown 
1448bf315173SMark Brown /**
14492cf8e2dfSCharles Keepax  * regmap_exit() - Free a previously allocated register map
14502cf8e2dfSCharles Keepax  *
14512cf8e2dfSCharles Keepax  * @map: Register map to operate on.
1452b83a313bSMark Brown  */
regmap_exit(struct regmap * map)1453b83a313bSMark Brown void regmap_exit(struct regmap *map)
1454b83a313bSMark Brown {
14557e09a979SMark Brown 	struct regmap_async *async;
14567e09a979SMark Brown 
1457f1a99d86SCosmin Tanislav 	regmap_detach_dev(map->dev, map);
14585d1729e7SDimitris Papastamos 	regcache_exit(map);
145931244e39SMark Brown 	regmap_debugfs_exit(map);
14606863ca62SKrystian Garbaciak 	regmap_range_exit(map);
1461d2a5884aSAndrey Smirnov 	if (map->bus && map->bus->free_context)
14620135bbccSStephen Warren 		map->bus->free_context(map->bus_context);
1463b83a313bSMark Brown 	kfree(map->work_buf);
14647e09a979SMark Brown 	while (!list_empty(&map->async_free)) {
14657e09a979SMark Brown 		async = list_first_entry_or_null(&map->async_free,
14667e09a979SMark Brown 						 struct regmap_async,
14677e09a979SMark Brown 						 list);
14687e09a979SMark Brown 		list_del(&async->list);
14697e09a979SMark Brown 		kfree(async->work_buf);
14707e09a979SMark Brown 		kfree(async);
14717e09a979SMark Brown 	}
1472a1a68fcaSBaolin Wang 	if (map->hwlock)
1473e8419c40SMark Brown 		hwspin_lock_free(map->hwlock);
1474f74d63b8SBartosz Golaszewski 	if (map->lock == regmap_lock_mutex)
1475f74d63b8SBartosz Golaszewski 		mutex_destroy(&map->mutex);
14768253bb3fSBartosz Golaszewski 	kfree_const(map->name);
147795b2c3ecSCharles Keepax 	kfree(map->patch);
1478ea030ca6SLucas Tanure 	if (map->bus && map->bus->free_on_exit)
1479ea030ca6SLucas Tanure 		kfree(map->bus);
1480b83a313bSMark Brown 	kfree(map);
1481b83a313bSMark Brown }
1482b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_exit);
1483b83a313bSMark Brown 
dev_get_regmap_match(struct device * dev,void * res,void * data)148472b39f6fSMark Brown static int dev_get_regmap_match(struct device *dev, void *res, void *data)
148572b39f6fSMark Brown {
148672b39f6fSMark Brown 	struct regmap **r = res;
148772b39f6fSMark Brown 	if (!r || !*r) {
148872b39f6fSMark Brown 		WARN_ON(!r || !*r);
148972b39f6fSMark Brown 		return 0;
149072b39f6fSMark Brown 	}
149172b39f6fSMark Brown 
149272b39f6fSMark Brown 	/* If the user didn't specify a name match any */
149372b39f6fSMark Brown 	if (data)
1494c6df8433SJohan Hovold 		return (*r)->name && !strcmp((*r)->name, data);
149572b39f6fSMark Brown 	else
149672b39f6fSMark Brown 		return 1;
149772b39f6fSMark Brown }
149872b39f6fSMark Brown 
149972b39f6fSMark Brown /**
15002cf8e2dfSCharles Keepax  * dev_get_regmap() - Obtain the regmap (if any) for a device
150172b39f6fSMark Brown  *
150272b39f6fSMark Brown  * @dev: Device to retrieve the map for
150372b39f6fSMark Brown  * @name: Optional name for the register map, usually NULL.
150472b39f6fSMark Brown  *
150572b39f6fSMark Brown  * Returns the regmap for the device if one is present, or NULL.  If
150672b39f6fSMark Brown  * name is specified then it must match the name specified when
150772b39f6fSMark Brown  * registering the device, if it is NULL then the first regmap found
150872b39f6fSMark Brown  * will be used.  Devices with multiple register maps are very rare,
150972b39f6fSMark Brown  * generic code should normally not need to specify a name.
151072b39f6fSMark Brown  */
dev_get_regmap(struct device * dev,const char * name)151172b39f6fSMark Brown struct regmap *dev_get_regmap(struct device *dev, const char *name)
151272b39f6fSMark Brown {
151372b39f6fSMark Brown 	struct regmap **r = devres_find(dev, dev_get_regmap_release,
151472b39f6fSMark Brown 					dev_get_regmap_match, (void *)name);
151572b39f6fSMark Brown 
151672b39f6fSMark Brown 	if (!r)
151772b39f6fSMark Brown 		return NULL;
151872b39f6fSMark Brown 	return *r;
151972b39f6fSMark Brown }
152072b39f6fSMark Brown EXPORT_SYMBOL_GPL(dev_get_regmap);
152172b39f6fSMark Brown 
15228d7d3972STuomas Tynkkynen /**
15232cf8e2dfSCharles Keepax  * regmap_get_device() - Obtain the device from a regmap
15248d7d3972STuomas Tynkkynen  *
15258d7d3972STuomas Tynkkynen  * @map: Register map to operate on.
15268d7d3972STuomas Tynkkynen  *
15278d7d3972STuomas Tynkkynen  * Returns the underlying device that the regmap has been created for.
15288d7d3972STuomas Tynkkynen  */
regmap_get_device(struct regmap * map)15298d7d3972STuomas Tynkkynen struct device *regmap_get_device(struct regmap *map)
15308d7d3972STuomas Tynkkynen {
15318d7d3972STuomas Tynkkynen 	return map->dev;
15328d7d3972STuomas Tynkkynen }
1533fa2fbe4aSMark Brown EXPORT_SYMBOL_GPL(regmap_get_device);
15348d7d3972STuomas Tynkkynen 
_regmap_select_page(struct regmap * map,unsigned int * reg,struct regmap_range_node * range,unsigned int val_num)15356863ca62SKrystian Garbaciak static int _regmap_select_page(struct regmap *map, unsigned int *reg,
153698bc7dfdSMark Brown 			       struct regmap_range_node *range,
15376863ca62SKrystian Garbaciak 			       unsigned int val_num)
15386863ca62SKrystian Garbaciak {
15396863ca62SKrystian Garbaciak 	void *orig_work_buf;
15406863ca62SKrystian Garbaciak 	unsigned int win_offset;
15416863ca62SKrystian Garbaciak 	unsigned int win_page;
15426863ca62SKrystian Garbaciak 	bool page_chg;
15436863ca62SKrystian Garbaciak 	int ret;
15446863ca62SKrystian Garbaciak 
15456863ca62SKrystian Garbaciak 	win_offset = (*reg - range->range_min) % range->window_len;
15466863ca62SKrystian Garbaciak 	win_page = (*reg - range->range_min) / range->window_len;
15476863ca62SKrystian Garbaciak 
15486863ca62SKrystian Garbaciak 	if (val_num > 1) {
15496863ca62SKrystian Garbaciak 		/* Bulk write shouldn't cross range boundary */
15506863ca62SKrystian Garbaciak 		if (*reg + val_num - 1 > range->range_max)
15516863ca62SKrystian Garbaciak 			return -EINVAL;
15526863ca62SKrystian Garbaciak 
15536863ca62SKrystian Garbaciak 		/* ... or single page boundary */
15546863ca62SKrystian Garbaciak 		if (val_num > range->window_len - win_offset)
15556863ca62SKrystian Garbaciak 			return -EINVAL;
15566863ca62SKrystian Garbaciak 	}
15576863ca62SKrystian Garbaciak 
15586863ca62SKrystian Garbaciak 	/* It is possible to have selector register inside data window.
15596863ca62SKrystian Garbaciak 	   In that case, selector register is located on every page and
15606863ca62SKrystian Garbaciak 	   it needs no page switching, when accessed alone. */
15616863ca62SKrystian Garbaciak 	if (val_num > 1 ||
15626863ca62SKrystian Garbaciak 	    range->window_start + win_offset != range->selector_reg) {
15636863ca62SKrystian Garbaciak 		/* Use separate work_buf during page switching */
15646863ca62SKrystian Garbaciak 		orig_work_buf = map->work_buf;
15656863ca62SKrystian Garbaciak 		map->work_buf = map->selector_work_buf;
15666863ca62SKrystian Garbaciak 
15676863ca62SKrystian Garbaciak 		ret = _regmap_update_bits(map, range->selector_reg,
15686863ca62SKrystian Garbaciak 					  range->selector_mask,
15696863ca62SKrystian Garbaciak 					  win_page << range->selector_shift,
15707ff0589cSKuninori Morimoto 					  &page_chg, false);
15716863ca62SKrystian Garbaciak 
15726863ca62SKrystian Garbaciak 		map->work_buf = orig_work_buf;
1573632a5b01SKrystian Garbaciak 
15740ff3e62fSMark Brown 		if (ret != 0)
1575632a5b01SKrystian Garbaciak 			return ret;
15766863ca62SKrystian Garbaciak 	}
15776863ca62SKrystian Garbaciak 
15786863ca62SKrystian Garbaciak 	*reg = range->window_start + win_offset;
15796863ca62SKrystian Garbaciak 
15806863ca62SKrystian Garbaciak 	return 0;
15816863ca62SKrystian Garbaciak }
15826863ca62SKrystian Garbaciak 
regmap_set_work_buf_flag_mask(struct regmap * map,int max_bytes,unsigned long mask)1583f50e38c9STony Lindgren static void regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes,
1584f50e38c9STony Lindgren 					  unsigned long mask)
1585f50e38c9STony Lindgren {
1586f50e38c9STony Lindgren 	u8 *buf;
1587f50e38c9STony Lindgren 	int i;
1588f50e38c9STony Lindgren 
1589f50e38c9STony Lindgren 	if (!mask || !map->work_buf)
1590f50e38c9STony Lindgren 		return;
1591f50e38c9STony Lindgren 
1592f50e38c9STony Lindgren 	buf = map->work_buf;
1593f50e38c9STony Lindgren 
1594f50e38c9STony Lindgren 	for (i = 0; i < max_bytes; i++)
1595f50e38c9STony Lindgren 		buf[i] |= (mask >> (8 * i)) & 0xff;
1596f50e38c9STony Lindgren }
1597f50e38c9STony Lindgren 
regmap_reg_addr(struct regmap * map,unsigned int reg)15983f58f6dcSMaxime Chevallier static unsigned int regmap_reg_addr(struct regmap *map, unsigned int reg)
15993f58f6dcSMaxime Chevallier {
16003f58f6dcSMaxime Chevallier 	reg += map->reg_base;
16014a670ac3SMaxime Chevallier 
16024a670ac3SMaxime Chevallier 	if (map->format.reg_shift > 0)
16034a670ac3SMaxime Chevallier 		reg >>= map->format.reg_shift;
16044a670ac3SMaxime Chevallier 	else if (map->format.reg_shift < 0)
16054a670ac3SMaxime Chevallier 		reg <<= -(map->format.reg_shift);
16064a670ac3SMaxime Chevallier 
16074a670ac3SMaxime Chevallier 	return reg;
16083f58f6dcSMaxime Chevallier }
16093f58f6dcSMaxime Chevallier 
_regmap_raw_write_impl(struct regmap * map,unsigned int reg,const void * val,size_t val_len,bool noinc)16107ef2c6b8SCharles Keepax static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
161105669b63SDmitry Baryshkov 				  const void *val, size_t val_len, bool noinc)
1612b83a313bSMark Brown {
161398bc7dfdSMark Brown 	struct regmap_range_node *range;
16140d509f2bSMark Brown 	unsigned long flags;
16150d509f2bSMark Brown 	void *work_val = map->work_buf + map->format.reg_bytes +
16160d509f2bSMark Brown 		map->format.pad_bytes;
1617b83a313bSMark Brown 	void *buf;
1618b83a313bSMark Brown 	int ret = -ENOTSUPP;
1619b83a313bSMark Brown 	size_t len;
162073304781SMark Brown 	int i;
162173304781SMark Brown 
16222e31aab0SBen Whitten 	/* Check for unwritable or noinc registers in range
16232e31aab0SBen Whitten 	 * before we start
16242e31aab0SBen Whitten 	 */
16252e31aab0SBen Whitten 	if (!regmap_writeable_noinc(map, reg)) {
16262e31aab0SBen Whitten 		for (i = 0; i < val_len / map->format.val_bytes; i++) {
16272e31aab0SBen Whitten 			unsigned int element =
16282e31aab0SBen Whitten 				reg + regmap_get_offset(map, i);
16292e31aab0SBen Whitten 			if (!regmap_writeable(map, element) ||
16302e31aab0SBen Whitten 				regmap_writeable_noinc(map, element))
163173304781SMark Brown 				return -EINVAL;
16322e31aab0SBen Whitten 		}
16332e31aab0SBen Whitten 	}
1634b83a313bSMark Brown 
1635c9157198SLaxman Dewangan 	if (!map->cache_bypass && map->format.parse_val) {
1636a4b4648cSBen Wolsieffer 		unsigned int ival, offset;
1637c9157198SLaxman Dewangan 		int val_bytes = map->format.val_bytes;
1638a4b4648cSBen Wolsieffer 
1639a4b4648cSBen Wolsieffer 		/* Cache the last written value for noinc writes */
1640a4b4648cSBen Wolsieffer 		i = noinc ? val_len - val_bytes : 0;
1641a4b4648cSBen Wolsieffer 		for (; i < val_len; i += val_bytes) {
1642a4b4648cSBen Wolsieffer 			ival = map->format.parse_val(val + i);
1643a4b4648cSBen Wolsieffer 			offset = noinc ? 0 : regmap_get_offset(map, i / val_bytes);
1644a4b4648cSBen Wolsieffer 			ret = regcache_write(map, reg + offset, ival);
1645c9157198SLaxman Dewangan 			if (ret) {
1646c9157198SLaxman Dewangan 				dev_err(map->dev,
16476d04b8acSMark Brown 					"Error in caching of register: %x ret: %d\n",
1648a4b4648cSBen Wolsieffer 					reg + offset, ret);
1649c9157198SLaxman Dewangan 				return ret;
1650c9157198SLaxman Dewangan 			}
1651c9157198SLaxman Dewangan 		}
1652c9157198SLaxman Dewangan 		if (map->cache_only) {
1653c9157198SLaxman Dewangan 			map->cache_dirty = true;
1654c9157198SLaxman Dewangan 			return 0;
1655c9157198SLaxman Dewangan 		}
1656c9157198SLaxman Dewangan 	}
1657c9157198SLaxman Dewangan 
165898bc7dfdSMark Brown 	range = _regmap_range_lookup(map, reg);
165998bc7dfdSMark Brown 	if (range) {
16608a2ceac6SMark Brown 		int val_num = val_len / map->format.val_bytes;
16618a2ceac6SMark Brown 		int win_offset = (reg - range->range_min) % range->window_len;
16628a2ceac6SMark Brown 		int win_residue = range->window_len - win_offset;
16638a2ceac6SMark Brown 
16648a2ceac6SMark Brown 		/* If the write goes beyond the end of the window split it */
16658a2ceac6SMark Brown 		while (val_num > win_residue) {
16661a61cfe3SFabio Estevam 			dev_dbg(map->dev, "Writing window %d/%zu\n",
16678a2ceac6SMark Brown 				win_residue, val_len / map->format.val_bytes);
16687ef2c6b8SCharles Keepax 			ret = _regmap_raw_write_impl(map, reg, val,
16697ef2c6b8SCharles Keepax 						     win_residue *
167005669b63SDmitry Baryshkov 						     map->format.val_bytes, noinc);
16718a2ceac6SMark Brown 			if (ret != 0)
16726863ca62SKrystian Garbaciak 				return ret;
16736863ca62SKrystian Garbaciak 
16748a2ceac6SMark Brown 			reg += win_residue;
16758a2ceac6SMark Brown 			val_num -= win_residue;
16768a2ceac6SMark Brown 			val += win_residue * map->format.val_bytes;
16778a2ceac6SMark Brown 			val_len -= win_residue * map->format.val_bytes;
16788a2ceac6SMark Brown 
16798a2ceac6SMark Brown 			win_offset = (reg - range->range_min) %
16808a2ceac6SMark Brown 				range->window_len;
16818a2ceac6SMark Brown 			win_residue = range->window_len - win_offset;
16828a2ceac6SMark Brown 		}
16838a2ceac6SMark Brown 
168405669b63SDmitry Baryshkov 		ret = _regmap_select_page(map, &reg, range, noinc ? 1 : val_num);
16850ff3e62fSMark Brown 		if (ret != 0)
16862547e201SMark Brown 			return ret;
168798bc7dfdSMark Brown 	}
1688b83a313bSMark Brown 
16893f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
1690d939fb9aSMarc Reilly 	map->format.format_reg(map->work_buf, reg, map->reg_shift);
1691f50e38c9STony Lindgren 	regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
1692f50e38c9STony Lindgren 				      map->write_flag_mask);
16936f306441SLars-Peter Clausen 
1694651e013eSMark Brown 	/*
1695651e013eSMark Brown 	 * Essentially all I/O mechanisms will be faster with a single
1696651e013eSMark Brown 	 * buffer to write.  Since register syncs often generate raw
1697651e013eSMark Brown 	 * writes of single registers optimise that case.
1698651e013eSMark Brown 	 */
1699651e013eSMark Brown 	if (val != work_val && val_len == map->format.val_bytes) {
1700651e013eSMark Brown 		memcpy(work_val, val, map->format.val_bytes);
1701651e013eSMark Brown 		val = work_val;
1702651e013eSMark Brown 	}
1703651e013eSMark Brown 
1704d77e7456SMarek Vasut 	if (map->async && map->bus && map->bus->async_write) {
17057e09a979SMark Brown 		struct regmap_async *async;
17060d509f2bSMark Brown 
1707c6b570d9SPhilipp Zabel 		trace_regmap_async_write_start(map, reg, val_len);
1708fe7d4ccdSMark Brown 
17097e09a979SMark Brown 		spin_lock_irqsave(&map->async_lock, flags);
17107e09a979SMark Brown 		async = list_first_entry_or_null(&map->async_free,
17117e09a979SMark Brown 						 struct regmap_async,
17127e09a979SMark Brown 						 list);
17137e09a979SMark Brown 		if (async)
17147e09a979SMark Brown 			list_del(&async->list);
17157e09a979SMark Brown 		spin_unlock_irqrestore(&map->async_lock, flags);
17167e09a979SMark Brown 
17177e09a979SMark Brown 		if (!async) {
17187e09a979SMark Brown 			async = map->bus->async_alloc();
17197e09a979SMark Brown 			if (!async)
17207e09a979SMark Brown 				return -ENOMEM;
17217e09a979SMark Brown 
17220d509f2bSMark Brown 			async->work_buf = kzalloc(map->format.buf_size,
17230d509f2bSMark Brown 						  GFP_KERNEL | GFP_DMA);
17240d509f2bSMark Brown 			if (!async->work_buf) {
17250d509f2bSMark Brown 				kfree(async);
17260d509f2bSMark Brown 				return -ENOMEM;
17270d509f2bSMark Brown 			}
17287e09a979SMark Brown 		}
17290d509f2bSMark Brown 
17300d509f2bSMark Brown 		async->map = map;
17310d509f2bSMark Brown 
17320d509f2bSMark Brown 		/* If the caller supplied the value we can use it safely. */
17330d509f2bSMark Brown 		memcpy(async->work_buf, map->work_buf, map->format.pad_bytes +
17340d509f2bSMark Brown 		       map->format.reg_bytes + map->format.val_bytes);
17350d509f2bSMark Brown 
17360d509f2bSMark Brown 		spin_lock_irqsave(&map->async_lock, flags);
17370d509f2bSMark Brown 		list_add_tail(&async->list, &map->async_list);
17380d509f2bSMark Brown 		spin_unlock_irqrestore(&map->async_lock, flags);
17390d509f2bSMark Brown 
174004c50ccfSMark Brown 		if (val != work_val)
174104c50ccfSMark Brown 			ret = map->bus->async_write(map->bus_context,
174204c50ccfSMark Brown 						    async->work_buf,
17430d509f2bSMark Brown 						    map->format.reg_bytes +
17440d509f2bSMark Brown 						    map->format.pad_bytes,
17450d509f2bSMark Brown 						    val, val_len, async);
174604c50ccfSMark Brown 		else
174704c50ccfSMark Brown 			ret = map->bus->async_write(map->bus_context,
174804c50ccfSMark Brown 						    async->work_buf,
174904c50ccfSMark Brown 						    map->format.reg_bytes +
175004c50ccfSMark Brown 						    map->format.pad_bytes +
175104c50ccfSMark Brown 						    val_len, NULL, 0, async);
17520d509f2bSMark Brown 
17530d509f2bSMark Brown 		if (ret != 0) {
17540d509f2bSMark Brown 			dev_err(map->dev, "Failed to schedule write: %d\n",
17550d509f2bSMark Brown 				ret);
17560d509f2bSMark Brown 
17570d509f2bSMark Brown 			spin_lock_irqsave(&map->async_lock, flags);
17587e09a979SMark Brown 			list_move(&async->list, &map->async_free);
17590d509f2bSMark Brown 			spin_unlock_irqrestore(&map->async_lock, flags);
17600d509f2bSMark Brown 		}
1761f951b658SMark Brown 
1762f951b658SMark Brown 		return ret;
17630d509f2bSMark Brown 	}
17640d509f2bSMark Brown 
1765c6b570d9SPhilipp Zabel 	trace_regmap_hw_write_start(map, reg, val_len / map->format.val_bytes);
1766b83a313bSMark Brown 
17672547e201SMark Brown 	/* If we're doing a single register write we can probably just
17682547e201SMark Brown 	 * send the work_buf directly, otherwise try to do a gather
17692547e201SMark Brown 	 * write.
17702547e201SMark Brown 	 */
17710d509f2bSMark Brown 	if (val == work_val)
1772d77e7456SMarek Vasut 		ret = map->write(map->bus_context, map->work_buf,
177382159ba8SMark Brown 				 map->format.reg_bytes +
177482159ba8SMark Brown 				 map->format.pad_bytes +
177582159ba8SMark Brown 				 val_len);
17765c422f0bSMarek Vasut 	else if (map->bus && map->bus->gather_write)
17770135bbccSStephen Warren 		ret = map->bus->gather_write(map->bus_context, map->work_buf,
177882159ba8SMark Brown 					     map->format.reg_bytes +
177982159ba8SMark Brown 					     map->format.pad_bytes,
1780b83a313bSMark Brown 					     val, val_len);
1781db057679SSrinivas Kandagatla 	else
1782db057679SSrinivas Kandagatla 		ret = -ENOTSUPP;
1783b83a313bSMark Brown 
17842547e201SMark Brown 	/* If that didn't work fall back on linearising by hand. */
1785b83a313bSMark Brown 	if (ret == -ENOTSUPP) {
178682159ba8SMark Brown 		len = map->format.reg_bytes + map->format.pad_bytes + val_len;
178782159ba8SMark Brown 		buf = kzalloc(len, GFP_KERNEL);
1788b83a313bSMark Brown 		if (!buf)
1789b83a313bSMark Brown 			return -ENOMEM;
1790b83a313bSMark Brown 
1791b83a313bSMark Brown 		memcpy(buf, map->work_buf, map->format.reg_bytes);
179282159ba8SMark Brown 		memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
179382159ba8SMark Brown 		       val, val_len);
1794d77e7456SMarek Vasut 		ret = map->write(map->bus_context, buf, len);
1795b83a313bSMark Brown 
1796b83a313bSMark Brown 		kfree(buf);
1797815806e3SElaine Zhang 	} else if (ret != 0 && !map->cache_bypass && map->format.parse_val) {
1798f0aa1ce6SNikita Yushchenko 		/* regcache_drop_region() takes lock that we already have,
1799f0aa1ce6SNikita Yushchenko 		 * thus call map->cache_ops->drop() directly
1800f0aa1ce6SNikita Yushchenko 		 */
1801f0aa1ce6SNikita Yushchenko 		if (map->cache_ops && map->cache_ops->drop)
1802f0aa1ce6SNikita Yushchenko 			map->cache_ops->drop(map, reg, reg + 1);
1803b83a313bSMark Brown 	}
1804b83a313bSMark Brown 
1805c6b570d9SPhilipp Zabel 	trace_regmap_hw_write_done(map, reg, val_len / map->format.val_bytes);
1806fb2736bbSMark Brown 
1807b83a313bSMark Brown 	return ret;
1808b83a313bSMark Brown }
1809b83a313bSMark Brown 
1810221ad7f2SMark Brown /**
1811221ad7f2SMark Brown  * regmap_can_raw_write - Test if regmap_raw_write() is supported
1812221ad7f2SMark Brown  *
1813221ad7f2SMark Brown  * @map: Map to check.
1814221ad7f2SMark Brown  */
regmap_can_raw_write(struct regmap * map)1815221ad7f2SMark Brown bool regmap_can_raw_write(struct regmap *map)
1816221ad7f2SMark Brown {
18172a166929SJavier Martinez Canillas 	return map->write && map->format.format_val && map->format.format_reg;
1818221ad7f2SMark Brown }
1819221ad7f2SMark Brown EXPORT_SYMBOL_GPL(regmap_can_raw_write);
1820221ad7f2SMark Brown 
1821f50c9eb4SMarkus Pargmann /**
1822f50c9eb4SMarkus Pargmann  * regmap_get_raw_read_max - Get the maximum size we can read
1823f50c9eb4SMarkus Pargmann  *
1824f50c9eb4SMarkus Pargmann  * @map: Map to check.
1825f50c9eb4SMarkus Pargmann  */
regmap_get_raw_read_max(struct regmap * map)1826f50c9eb4SMarkus Pargmann size_t regmap_get_raw_read_max(struct regmap *map)
1827f50c9eb4SMarkus Pargmann {
1828f50c9eb4SMarkus Pargmann 	return map->max_raw_read;
1829f50c9eb4SMarkus Pargmann }
1830f50c9eb4SMarkus Pargmann EXPORT_SYMBOL_GPL(regmap_get_raw_read_max);
1831f50c9eb4SMarkus Pargmann 
1832f50c9eb4SMarkus Pargmann /**
1833f50c9eb4SMarkus Pargmann  * regmap_get_raw_write_max - Get the maximum size we can read
1834f50c9eb4SMarkus Pargmann  *
1835f50c9eb4SMarkus Pargmann  * @map: Map to check.
1836f50c9eb4SMarkus Pargmann  */
regmap_get_raw_write_max(struct regmap * map)1837f50c9eb4SMarkus Pargmann size_t regmap_get_raw_write_max(struct regmap *map)
1838f50c9eb4SMarkus Pargmann {
1839f50c9eb4SMarkus Pargmann 	return map->max_raw_write;
1840f50c9eb4SMarkus Pargmann }
1841f50c9eb4SMarkus Pargmann EXPORT_SYMBOL_GPL(regmap_get_raw_write_max);
1842f50c9eb4SMarkus Pargmann 
_regmap_bus_formatted_write(void * context,unsigned int reg,unsigned int val)184307c320dcSAndrey Smirnov static int _regmap_bus_formatted_write(void *context, unsigned int reg,
184407c320dcSAndrey Smirnov 				       unsigned int val)
184507c320dcSAndrey Smirnov {
184607c320dcSAndrey Smirnov 	int ret;
184707c320dcSAndrey Smirnov 	struct regmap_range_node *range;
184807c320dcSAndrey Smirnov 	struct regmap *map = context;
184907c320dcSAndrey Smirnov 
1850d77e7456SMarek Vasut 	WARN_ON(!map->format.format_write);
185107c320dcSAndrey Smirnov 
185207c320dcSAndrey Smirnov 	range = _regmap_range_lookup(map, reg);
185307c320dcSAndrey Smirnov 	if (range) {
185407c320dcSAndrey Smirnov 		ret = _regmap_select_page(map, &reg, range, 1);
185507c320dcSAndrey Smirnov 		if (ret != 0)
185607c320dcSAndrey Smirnov 			return ret;
185707c320dcSAndrey Smirnov 	}
185807c320dcSAndrey Smirnov 
18593f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
186007c320dcSAndrey Smirnov 	map->format.format_write(map, reg, val);
186107c320dcSAndrey Smirnov 
1862c6b570d9SPhilipp Zabel 	trace_regmap_hw_write_start(map, reg, 1);
186307c320dcSAndrey Smirnov 
1864d77e7456SMarek Vasut 	ret = map->write(map->bus_context, map->work_buf, map->format.buf_size);
186507c320dcSAndrey Smirnov 
1866c6b570d9SPhilipp Zabel 	trace_regmap_hw_write_done(map, reg, 1);
186707c320dcSAndrey Smirnov 
186807c320dcSAndrey Smirnov 	return ret;
186907c320dcSAndrey Smirnov }
187007c320dcSAndrey Smirnov 
_regmap_bus_reg_write(void * context,unsigned int reg,unsigned int val)18713ac17037SBoris BREZILLON static int _regmap_bus_reg_write(void *context, unsigned int reg,
18723ac17037SBoris BREZILLON 				 unsigned int val)
18733ac17037SBoris BREZILLON {
18743ac17037SBoris BREZILLON 	struct regmap *map = context;
1875f18ee501SMark Brown 	struct regmap_range_node *range;
1876f18ee501SMark Brown 	int ret;
1877f18ee501SMark Brown 
1878f18ee501SMark Brown 	range = _regmap_range_lookup(map, reg);
1879f18ee501SMark Brown 	if (range) {
1880f18ee501SMark Brown 		ret = _regmap_select_page(map, &reg, range, 1);
1881f18ee501SMark Brown 		if (ret != 0)
1882f18ee501SMark Brown 			return ret;
1883f18ee501SMark Brown 	}
18843ac17037SBoris BREZILLON 
18853f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
18863ac17037SBoris BREZILLON 	return map->bus->reg_write(map->bus_context, reg, val);
18873ac17037SBoris BREZILLON }
18883ac17037SBoris BREZILLON 
_regmap_bus_raw_write(void * context,unsigned int reg,unsigned int val)188907c320dcSAndrey Smirnov static int _regmap_bus_raw_write(void *context, unsigned int reg,
189007c320dcSAndrey Smirnov 				 unsigned int val)
189107c320dcSAndrey Smirnov {
189207c320dcSAndrey Smirnov 	struct regmap *map = context;
189307c320dcSAndrey Smirnov 
1894d77e7456SMarek Vasut 	WARN_ON(!map->format.format_val);
189507c320dcSAndrey Smirnov 
189607c320dcSAndrey Smirnov 	map->format.format_val(map->work_buf + map->format.reg_bytes
189707c320dcSAndrey Smirnov 			       + map->format.pad_bytes, val, 0);
18987ef2c6b8SCharles Keepax 	return _regmap_raw_write_impl(map, reg,
189907c320dcSAndrey Smirnov 				      map->work_buf +
190007c320dcSAndrey Smirnov 				      map->format.reg_bytes +
190107c320dcSAndrey Smirnov 				      map->format.pad_bytes,
190205669b63SDmitry Baryshkov 				      map->format.val_bytes,
190305669b63SDmitry Baryshkov 				      false);
190407c320dcSAndrey Smirnov }
190507c320dcSAndrey Smirnov 
_regmap_map_get_context(struct regmap * map)1906d2a5884aSAndrey Smirnov static inline void *_regmap_map_get_context(struct regmap *map)
1907d2a5884aSAndrey Smirnov {
1908d77e7456SMarek Vasut 	return (map->bus || (!map->bus && map->read)) ? map : map->bus_context;
1909d2a5884aSAndrey Smirnov }
1910d2a5884aSAndrey Smirnov 
_regmap_write(struct regmap * map,unsigned int reg,unsigned int val)19114d2dc095SDimitris Papastamos int _regmap_write(struct regmap *map, unsigned int reg,
1912b83a313bSMark Brown 		  unsigned int val)
1913b83a313bSMark Brown {
1914fb2736bbSMark Brown 	int ret;
1915d2a5884aSAndrey Smirnov 	void *context = _regmap_map_get_context(map);
1916b83a313bSMark Brown 
1917515f2261SIonut Nicu 	if (!regmap_writeable(map, reg))
1918515f2261SIonut Nicu 		return -EIO;
1919515f2261SIonut Nicu 
1920d2a5884aSAndrey Smirnov 	if (!map->cache_bypass && !map->defer_caching) {
19215d1729e7SDimitris Papastamos 		ret = regcache_write(map, reg, val);
19225d1729e7SDimitris Papastamos 		if (ret != 0)
19235d1729e7SDimitris Papastamos 			return ret;
19248ae0d7e8SMark Brown 		if (map->cache_only) {
19258ae0d7e8SMark Brown 			map->cache_dirty = true;
19265d1729e7SDimitris Papastamos 			return 0;
19275d1729e7SDimitris Papastamos 		}
19288ae0d7e8SMark Brown 	}
19295d1729e7SDimitris Papastamos 
1930f7d01359SLucas Tanure 	ret = map->reg_write(context, reg, val);
1931f7d01359SLucas Tanure 	if (ret == 0) {
193295093762SBen Dooks 		if (regmap_should_log(map))
19331044c180SMark Brown 			dev_info(map->dev, "%x <= %x\n", reg, val);
19341044c180SMark Brown 
1935c6b570d9SPhilipp Zabel 		trace_regmap_reg_write(map, reg, val);
1936f7d01359SLucas Tanure 	}
1937fb2736bbSMark Brown 
1938f7d01359SLucas Tanure 	return ret;
1939b83a313bSMark Brown }
1940b83a313bSMark Brown 
1941b83a313bSMark Brown /**
19422cf8e2dfSCharles Keepax  * regmap_write() - Write a value to a single register
1943b83a313bSMark Brown  *
1944b83a313bSMark Brown  * @map: Register map to write to
1945b83a313bSMark Brown  * @reg: Register to write to
1946b83a313bSMark Brown  * @val: Value to be written
1947b83a313bSMark Brown  *
1948b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
1949b83a313bSMark Brown  * be returned in error cases.
1950b83a313bSMark Brown  */
regmap_write(struct regmap * map,unsigned int reg,unsigned int val)1951b83a313bSMark Brown int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
1952b83a313bSMark Brown {
1953b83a313bSMark Brown 	int ret;
1954b83a313bSMark Brown 
1955fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
1956f01ee60fSStephen Warren 		return -EINVAL;
1957f01ee60fSStephen Warren 
19580d4529c5SDavide Ciminaghi 	map->lock(map->lock_arg);
1959b83a313bSMark Brown 
1960b83a313bSMark Brown 	ret = _regmap_write(map, reg, val);
1961b83a313bSMark Brown 
19620d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
1963b83a313bSMark Brown 
1964b83a313bSMark Brown 	return ret;
1965b83a313bSMark Brown }
1966b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_write);
1967b83a313bSMark Brown 
1968b83a313bSMark Brown /**
19692cf8e2dfSCharles Keepax  * regmap_write_async() - Write a value to a single register asynchronously
1970915f441bSMark Brown  *
1971915f441bSMark Brown  * @map: Register map to write to
1972915f441bSMark Brown  * @reg: Register to write to
1973915f441bSMark Brown  * @val: Value to be written
1974915f441bSMark Brown  *
1975915f441bSMark Brown  * A value of zero will be returned on success, a negative errno will
1976915f441bSMark Brown  * be returned in error cases.
1977915f441bSMark Brown  */
regmap_write_async(struct regmap * map,unsigned int reg,unsigned int val)1978915f441bSMark Brown int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val)
1979915f441bSMark Brown {
1980915f441bSMark Brown 	int ret;
1981915f441bSMark Brown 
1982fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
1983915f441bSMark Brown 		return -EINVAL;
1984915f441bSMark Brown 
1985915f441bSMark Brown 	map->lock(map->lock_arg);
1986915f441bSMark Brown 
1987915f441bSMark Brown 	map->async = true;
1988915f441bSMark Brown 
1989915f441bSMark Brown 	ret = _regmap_write(map, reg, val);
1990915f441bSMark Brown 
1991915f441bSMark Brown 	map->async = false;
1992915f441bSMark Brown 
1993915f441bSMark Brown 	map->unlock(map->lock_arg);
1994915f441bSMark Brown 
1995915f441bSMark Brown 	return ret;
1996915f441bSMark Brown }
1997915f441bSMark Brown EXPORT_SYMBOL_GPL(regmap_write_async);
1998915f441bSMark Brown 
_regmap_raw_write(struct regmap * map,unsigned int reg,const void * val,size_t val_len,bool noinc)19997ef2c6b8SCharles Keepax int _regmap_raw_write(struct regmap *map, unsigned int reg,
200005669b63SDmitry Baryshkov 		      const void *val, size_t val_len, bool noinc)
20017ef2c6b8SCharles Keepax {
20027ef2c6b8SCharles Keepax 	size_t val_bytes = map->format.val_bytes;
20037ef2c6b8SCharles Keepax 	size_t val_count = val_len / val_bytes;
2004364e378bSCharles Keepax 	size_t chunk_count, chunk_bytes;
2005364e378bSCharles Keepax 	size_t chunk_regs = val_count;
20067ef2c6b8SCharles Keepax 	int ret, i;
20077ef2c6b8SCharles Keepax 
20087ef2c6b8SCharles Keepax 	if (!val_count)
20097ef2c6b8SCharles Keepax 		return -EINVAL;
20107ef2c6b8SCharles Keepax 
2011364e378bSCharles Keepax 	if (map->use_single_write)
2012364e378bSCharles Keepax 		chunk_regs = 1;
2013bc647348SMark Brown 	else if (map->max_raw_write && val_len > map->max_raw_write)
2014bc647348SMark Brown 		chunk_regs = map->max_raw_write / val_bytes;
2015364e378bSCharles Keepax 
2016364e378bSCharles Keepax 	chunk_count = val_count / chunk_regs;
2017364e378bSCharles Keepax 	chunk_bytes = chunk_regs * val_bytes;
20187ef2c6b8SCharles Keepax 
20197ef2c6b8SCharles Keepax 	/* Write as many bytes as possible with chunk_size */
20207ef2c6b8SCharles Keepax 	for (i = 0; i < chunk_count; i++) {
202105669b63SDmitry Baryshkov 		ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes, noinc);
20227ef2c6b8SCharles Keepax 		if (ret)
20237ef2c6b8SCharles Keepax 			return ret;
2024364e378bSCharles Keepax 
2025364e378bSCharles Keepax 		reg += regmap_get_offset(map, chunk_regs);
2026364e378bSCharles Keepax 		val += chunk_bytes;
2027364e378bSCharles Keepax 		val_len -= chunk_bytes;
20287ef2c6b8SCharles Keepax 	}
20297ef2c6b8SCharles Keepax 
20307ef2c6b8SCharles Keepax 	/* Write remaining bytes */
2031364e378bSCharles Keepax 	if (val_len)
203205669b63SDmitry Baryshkov 		ret = _regmap_raw_write_impl(map, reg, val, val_len, noinc);
20337ef2c6b8SCharles Keepax 
20347ef2c6b8SCharles Keepax 	return ret;
20357ef2c6b8SCharles Keepax }
20367ef2c6b8SCharles Keepax 
2037915f441bSMark Brown /**
20382cf8e2dfSCharles Keepax  * regmap_raw_write() - Write raw values to one or more registers
2039b83a313bSMark Brown  *
2040b83a313bSMark Brown  * @map: Register map to write to
2041b83a313bSMark Brown  * @reg: Initial register to write to
2042b83a313bSMark Brown  * @val: Block of data to be written, laid out for direct transmission to the
2043b83a313bSMark Brown  *       device
2044b83a313bSMark Brown  * @val_len: Length of data pointed to by val.
2045b83a313bSMark Brown  *
2046b83a313bSMark Brown  * This function is intended to be used for things like firmware
2047b83a313bSMark Brown  * download where a large block of data needs to be transferred to the
2048b83a313bSMark Brown  * device.  No formatting will be done on the data provided.
2049b83a313bSMark Brown  *
2050b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
2051b83a313bSMark Brown  * be returned in error cases.
2052b83a313bSMark Brown  */
regmap_raw_write(struct regmap * map,unsigned int reg,const void * val,size_t val_len)2053b83a313bSMark Brown int regmap_raw_write(struct regmap *map, unsigned int reg,
2054b83a313bSMark Brown 		     const void *val, size_t val_len)
2055b83a313bSMark Brown {
2056b83a313bSMark Brown 	int ret;
2057b83a313bSMark Brown 
2058221ad7f2SMark Brown 	if (!regmap_can_raw_write(map))
2059d2a5884aSAndrey Smirnov 		return -EINVAL;
2060851960baSStephen Warren 	if (val_len % map->format.val_bytes)
2061851960baSStephen Warren 		return -EINVAL;
2062851960baSStephen Warren 
20630d4529c5SDavide Ciminaghi 	map->lock(map->lock_arg);
2064b83a313bSMark Brown 
206505669b63SDmitry Baryshkov 	ret = _regmap_raw_write(map, reg, val, val_len, false);
2066b83a313bSMark Brown 
20670d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
2068b83a313bSMark Brown 
2069b83a313bSMark Brown 	return ret;
2070b83a313bSMark Brown }
2071b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_write);
2072b83a313bSMark Brown 
regmap_noinc_readwrite(struct regmap * map,unsigned int reg,void * val,unsigned int val_len,bool write)2073c20cc099SLinus Walleij static int regmap_noinc_readwrite(struct regmap *map, unsigned int reg,
2074c20cc099SLinus Walleij 				  void *val, unsigned int val_len, bool write)
2075c20cc099SLinus Walleij {
2076c20cc099SLinus Walleij 	size_t val_bytes = map->format.val_bytes;
2077c20cc099SLinus Walleij 	size_t val_count = val_len / val_bytes;
2078c20cc099SLinus Walleij 	unsigned int lastval;
2079c20cc099SLinus Walleij 	u8 *u8p;
2080c20cc099SLinus Walleij 	u16 *u16p;
2081c20cc099SLinus Walleij 	u32 *u32p;
2082c20cc099SLinus Walleij 	int ret;
2083c20cc099SLinus Walleij 	int i;
2084c20cc099SLinus Walleij 
2085c20cc099SLinus Walleij 	switch (val_bytes) {
2086c20cc099SLinus Walleij 	case 1:
2087c20cc099SLinus Walleij 		u8p = val;
2088c20cc099SLinus Walleij 		if (write)
2089c20cc099SLinus Walleij 			lastval = (unsigned int)u8p[val_count - 1];
2090c20cc099SLinus Walleij 		break;
2091c20cc099SLinus Walleij 	case 2:
2092c20cc099SLinus Walleij 		u16p = val;
2093c20cc099SLinus Walleij 		if (write)
2094c20cc099SLinus Walleij 			lastval = (unsigned int)u16p[val_count - 1];
2095c20cc099SLinus Walleij 		break;
2096c20cc099SLinus Walleij 	case 4:
2097c20cc099SLinus Walleij 		u32p = val;
2098c20cc099SLinus Walleij 		if (write)
2099c20cc099SLinus Walleij 			lastval = (unsigned int)u32p[val_count - 1];
2100c20cc099SLinus Walleij 		break;
2101c20cc099SLinus Walleij 	default:
2102c20cc099SLinus Walleij 		return -EINVAL;
2103c20cc099SLinus Walleij 	}
2104c20cc099SLinus Walleij 
2105c20cc099SLinus Walleij 	/*
2106c20cc099SLinus Walleij 	 * Update the cache with the last value we write, the rest is just
2107c20cc099SLinus Walleij 	 * gone down in the hardware FIFO. We can't cache FIFOs. This makes
2108c20cc099SLinus Walleij 	 * sure a single read from the cache will work.
2109c20cc099SLinus Walleij 	 */
2110c20cc099SLinus Walleij 	if (write) {
2111c20cc099SLinus Walleij 		if (!map->cache_bypass && !map->defer_caching) {
2112c20cc099SLinus Walleij 			ret = regcache_write(map, reg, lastval);
2113c20cc099SLinus Walleij 			if (ret != 0)
2114c20cc099SLinus Walleij 				return ret;
2115c20cc099SLinus Walleij 			if (map->cache_only) {
2116c20cc099SLinus Walleij 				map->cache_dirty = true;
2117c20cc099SLinus Walleij 				return 0;
2118c20cc099SLinus Walleij 			}
2119c20cc099SLinus Walleij 		}
2120c20cc099SLinus Walleij 		ret = map->bus->reg_noinc_write(map->bus_context, reg, val, val_count);
2121c20cc099SLinus Walleij 	} else {
2122c20cc099SLinus Walleij 		ret = map->bus->reg_noinc_read(map->bus_context, reg, val, val_count);
2123c20cc099SLinus Walleij 	}
2124c20cc099SLinus Walleij 
2125c20cc099SLinus Walleij 	if (!ret && regmap_should_log(map)) {
2126c20cc099SLinus Walleij 		dev_info(map->dev, "%x %s [", reg, write ? "<=" : "=>");
2127b7059927SLinus Walleij 		for (i = 0; i < val_count; i++) {
2128c20cc099SLinus Walleij 			switch (val_bytes) {
2129c20cc099SLinus Walleij 			case 1:
2130c20cc099SLinus Walleij 				pr_cont("%x", u8p[i]);
2131c20cc099SLinus Walleij 				break;
2132c20cc099SLinus Walleij 			case 2:
2133c20cc099SLinus Walleij 				pr_cont("%x", u16p[i]);
2134c20cc099SLinus Walleij 				break;
2135c20cc099SLinus Walleij 			case 4:
2136c20cc099SLinus Walleij 				pr_cont("%x", u32p[i]);
2137c20cc099SLinus Walleij 				break;
2138c20cc099SLinus Walleij 			default:
2139c20cc099SLinus Walleij 				break;
2140c20cc099SLinus Walleij 			}
2141b7059927SLinus Walleij 			if (i == (val_count - 1))
2142c20cc099SLinus Walleij 				pr_cont("]\n");
2143c20cc099SLinus Walleij 			else
2144c20cc099SLinus Walleij 				pr_cont(",");
2145c20cc099SLinus Walleij 		}
2146c20cc099SLinus Walleij 	}
2147c20cc099SLinus Walleij 
2148c20cc099SLinus Walleij 	return 0;
2149c20cc099SLinus Walleij }
2150c20cc099SLinus Walleij 
215167252287SSrinivas Kandagatla /**
2152cdf6b11dSBen Whitten  * regmap_noinc_write(): Write data from a register without incrementing the
2153cdf6b11dSBen Whitten  *			register number
2154cdf6b11dSBen Whitten  *
2155cdf6b11dSBen Whitten  * @map: Register map to write to
2156cdf6b11dSBen Whitten  * @reg: Register to write to
2157cdf6b11dSBen Whitten  * @val: Pointer to data buffer
2158cdf6b11dSBen Whitten  * @val_len: Length of output buffer in bytes.
2159cdf6b11dSBen Whitten  *
2160cdf6b11dSBen Whitten  * The regmap API usually assumes that bulk bus write operations will write a
2161cdf6b11dSBen Whitten  * range of registers. Some devices have certain registers for which a write
2162cdf6b11dSBen Whitten  * operation can write to an internal FIFO.
2163cdf6b11dSBen Whitten  *
2164cdf6b11dSBen Whitten  * The target register must be volatile but registers after it can be
2165cdf6b11dSBen Whitten  * completely unrelated cacheable registers.
2166cdf6b11dSBen Whitten  *
2167cdf6b11dSBen Whitten  * This will attempt multiple writes as required to write val_len bytes.
2168cdf6b11dSBen Whitten  *
2169cdf6b11dSBen Whitten  * A value of zero will be returned on success, a negative errno will be
2170cdf6b11dSBen Whitten  * returned in error cases.
2171cdf6b11dSBen Whitten  */
regmap_noinc_write(struct regmap * map,unsigned int reg,const void * val,size_t val_len)2172cdf6b11dSBen Whitten int regmap_noinc_write(struct regmap *map, unsigned int reg,
2173cdf6b11dSBen Whitten 		      const void *val, size_t val_len)
2174cdf6b11dSBen Whitten {
2175cdf6b11dSBen Whitten 	size_t write_len;
2176cdf6b11dSBen Whitten 	int ret;
2177cdf6b11dSBen Whitten 
2178c20cc099SLinus Walleij 	if (!map->write && !(map->bus && map->bus->reg_noinc_write))
2179c20cc099SLinus Walleij 		return -EINVAL;
2180cdf6b11dSBen Whitten 	if (val_len % map->format.val_bytes)
2181cdf6b11dSBen Whitten 		return -EINVAL;
2182cdf6b11dSBen Whitten 	if (!IS_ALIGNED(reg, map->reg_stride))
2183cdf6b11dSBen Whitten 		return -EINVAL;
2184cdf6b11dSBen Whitten 	if (val_len == 0)
2185cdf6b11dSBen Whitten 		return -EINVAL;
2186cdf6b11dSBen Whitten 
2187cdf6b11dSBen Whitten 	map->lock(map->lock_arg);
2188cdf6b11dSBen Whitten 
2189cdf6b11dSBen Whitten 	if (!regmap_volatile(map, reg) || !regmap_writeable_noinc(map, reg)) {
2190cdf6b11dSBen Whitten 		ret = -EINVAL;
2191cdf6b11dSBen Whitten 		goto out_unlock;
2192cdf6b11dSBen Whitten 	}
2193cdf6b11dSBen Whitten 
2194c20cc099SLinus Walleij 	/*
2195c20cc099SLinus Walleij 	 * Use the accelerated operation if we can. The val drops the const
2196c20cc099SLinus Walleij 	 * typing in order to facilitate code reuse in regmap_noinc_readwrite().
2197c20cc099SLinus Walleij 	 */
2198c20cc099SLinus Walleij 	if (map->bus->reg_noinc_write) {
2199c20cc099SLinus Walleij 		ret = regmap_noinc_readwrite(map, reg, (void *)val, val_len, true);
2200c20cc099SLinus Walleij 		goto out_unlock;
2201c20cc099SLinus Walleij 	}
2202c20cc099SLinus Walleij 
2203cdf6b11dSBen Whitten 	while (val_len) {
2204cdf6b11dSBen Whitten 		if (map->max_raw_write && map->max_raw_write < val_len)
2205cdf6b11dSBen Whitten 			write_len = map->max_raw_write;
2206cdf6b11dSBen Whitten 		else
2207cdf6b11dSBen Whitten 			write_len = val_len;
220805669b63SDmitry Baryshkov 		ret = _regmap_raw_write(map, reg, val, write_len, true);
2209cdf6b11dSBen Whitten 		if (ret)
2210cdf6b11dSBen Whitten 			goto out_unlock;
2211cdf6b11dSBen Whitten 		val = ((u8 *)val) + write_len;
2212cdf6b11dSBen Whitten 		val_len -= write_len;
2213cdf6b11dSBen Whitten 	}
2214cdf6b11dSBen Whitten 
2215cdf6b11dSBen Whitten out_unlock:
2216cdf6b11dSBen Whitten 	map->unlock(map->lock_arg);
2217cdf6b11dSBen Whitten 	return ret;
2218cdf6b11dSBen Whitten }
2219cdf6b11dSBen Whitten EXPORT_SYMBOL_GPL(regmap_noinc_write);
2220cdf6b11dSBen Whitten 
2221cdf6b11dSBen Whitten /**
22222cf8e2dfSCharles Keepax  * regmap_field_update_bits_base() - Perform a read/modify/write cycle a
22232cf8e2dfSCharles Keepax  *                                   register field.
2224fdf20029SKuninori Morimoto  *
2225fdf20029SKuninori Morimoto  * @field: Register field to write to
2226fdf20029SKuninori Morimoto  * @mask: Bitmask to change
2227fdf20029SKuninori Morimoto  * @val: Value to be written
222828972eaaSKuninori Morimoto  * @change: Boolean indicating if a write was done
222928972eaaSKuninori Morimoto  * @async: Boolean indicating asynchronously
223028972eaaSKuninori Morimoto  * @force: Boolean indicating use force update
2231fdf20029SKuninori Morimoto  *
22322cf8e2dfSCharles Keepax  * Perform a read/modify/write cycle on the register field with change,
22332cf8e2dfSCharles Keepax  * async, force option.
22342cf8e2dfSCharles Keepax  *
2235fdf20029SKuninori Morimoto  * A value of zero will be returned on success, a negative errno will
2236fdf20029SKuninori Morimoto  * be returned in error cases.
2237fdf20029SKuninori Morimoto  */
regmap_field_update_bits_base(struct regmap_field * field,unsigned int mask,unsigned int val,bool * change,bool async,bool force)223828972eaaSKuninori Morimoto int regmap_field_update_bits_base(struct regmap_field *field,
223928972eaaSKuninori Morimoto 				  unsigned int mask, unsigned int val,
224028972eaaSKuninori Morimoto 				  bool *change, bool async, bool force)
2241fdf20029SKuninori Morimoto {
2242fdf20029SKuninori Morimoto 	mask = (mask << field->shift) & field->mask;
2243fdf20029SKuninori Morimoto 
224428972eaaSKuninori Morimoto 	return regmap_update_bits_base(field->regmap, field->reg,
224528972eaaSKuninori Morimoto 				       mask, val << field->shift,
224628972eaaSKuninori Morimoto 				       change, async, force);
2247fdf20029SKuninori Morimoto }
224828972eaaSKuninori Morimoto EXPORT_SYMBOL_GPL(regmap_field_update_bits_base);
2249fdf20029SKuninori Morimoto 
2250a0102375SKuninori Morimoto /**
2251f67be8b7SLi Chen  * regmap_field_test_bits() - Check if all specified bits are set in a
2252f67be8b7SLi Chen  *                            register field.
2253f67be8b7SLi Chen  *
2254f67be8b7SLi Chen  * @field: Register field to operate on
2255f67be8b7SLi Chen  * @bits: Bits to test
2256f67be8b7SLi Chen  *
2257f67be8b7SLi Chen  * Returns -1 if the underlying regmap_field_read() fails, 0 if at least one of the
2258f67be8b7SLi Chen  * tested bits is not set and 1 if all tested bits are set.
2259f67be8b7SLi Chen  */
regmap_field_test_bits(struct regmap_field * field,unsigned int bits)2260f67be8b7SLi Chen int regmap_field_test_bits(struct regmap_field *field, unsigned int bits)
2261f67be8b7SLi Chen {
2262f67be8b7SLi Chen 	unsigned int val, ret;
2263f67be8b7SLi Chen 
2264f67be8b7SLi Chen 	ret = regmap_field_read(field, &val);
2265f67be8b7SLi Chen 	if (ret)
2266f67be8b7SLi Chen 		return ret;
2267f67be8b7SLi Chen 
2268f67be8b7SLi Chen 	return (val & bits) == bits;
2269f67be8b7SLi Chen }
2270f67be8b7SLi Chen EXPORT_SYMBOL_GPL(regmap_field_test_bits);
2271f67be8b7SLi Chen 
2272f67be8b7SLi Chen /**
22732cf8e2dfSCharles Keepax  * regmap_fields_update_bits_base() - Perform a read/modify/write cycle a
22742cf8e2dfSCharles Keepax  *                                    register field with port ID
2275a0102375SKuninori Morimoto  *
2276a0102375SKuninori Morimoto  * @field: Register field to write to
2277a0102375SKuninori Morimoto  * @id: port ID
2278a0102375SKuninori Morimoto  * @mask: Bitmask to change
2279a0102375SKuninori Morimoto  * @val: Value to be written
2280e126edecSKuninori Morimoto  * @change: Boolean indicating if a write was done
2281e126edecSKuninori Morimoto  * @async: Boolean indicating asynchronously
2282e126edecSKuninori Morimoto  * @force: Boolean indicating use force update
2283a0102375SKuninori Morimoto  *
2284a0102375SKuninori Morimoto  * A value of zero will be returned on success, a negative errno will
2285a0102375SKuninori Morimoto  * be returned in error cases.
2286a0102375SKuninori 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)2287e126edecSKuninori Morimoto int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id,
2288e126edecSKuninori Morimoto 				   unsigned int mask, unsigned int val,
2289e126edecSKuninori Morimoto 				   bool *change, bool async, bool force)
2290a0102375SKuninori Morimoto {
2291a0102375SKuninori Morimoto 	if (id >= field->id_size)
2292a0102375SKuninori Morimoto 		return -EINVAL;
2293a0102375SKuninori Morimoto 
2294a0102375SKuninori Morimoto 	mask = (mask << field->shift) & field->mask;
2295a0102375SKuninori Morimoto 
2296e126edecSKuninori Morimoto 	return regmap_update_bits_base(field->regmap,
2297a0102375SKuninori Morimoto 				       field->reg + (field->id_offset * id),
2298e126edecSKuninori Morimoto 				       mask, val << field->shift,
2299e126edecSKuninori Morimoto 				       change, async, force);
2300a0102375SKuninori Morimoto }
2301e126edecSKuninori Morimoto EXPORT_SYMBOL_GPL(regmap_fields_update_bits_base);
2302a0102375SKuninori Morimoto 
23032cf8e2dfSCharles Keepax /**
23042cf8e2dfSCharles Keepax  * regmap_bulk_write() - Write multiple registers to the device
23058eaeb219SLaxman Dewangan  *
23068eaeb219SLaxman Dewangan  * @map: Register map to write to
23078eaeb219SLaxman Dewangan  * @reg: First register to be write from
23088eaeb219SLaxman Dewangan  * @val: Block of data to be written, in native register size for device
23098eaeb219SLaxman Dewangan  * @val_count: Number of registers to write
23108eaeb219SLaxman Dewangan  *
23118eaeb219SLaxman Dewangan  * This function is intended to be used for writing a large block of
231231b35e9eSNestor Ovroy  * data to the device either in single transfer or multiple transfer.
23138eaeb219SLaxman Dewangan  *
23148eaeb219SLaxman Dewangan  * A value of zero will be returned on success, a negative errno will
23158eaeb219SLaxman Dewangan  * be returned in error cases.
23168eaeb219SLaxman Dewangan  */
regmap_bulk_write(struct regmap * map,unsigned int reg,const void * val,size_t val_count)23178eaeb219SLaxman Dewangan int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
23188eaeb219SLaxman Dewangan 		     size_t val_count)
23198eaeb219SLaxman Dewangan {
23208eaeb219SLaxman Dewangan 	int ret = 0, i;
23218eaeb219SLaxman Dewangan 	size_t val_bytes = map->format.val_bytes;
23228eaeb219SLaxman Dewangan 
2323fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
2324f01ee60fSStephen Warren 		return -EINVAL;
23258eaeb219SLaxman Dewangan 
2326f4298360SStephen Boyd 	/*
2327fb44f3ceSCharles Keepax 	 * Some devices don't support bulk write, for them we have a series of
2328fb44f3ceSCharles Keepax 	 * single write operations.
2329f4298360SStephen Boyd 	 */
23302a166929SJavier Martinez Canillas 	if (!map->write || !map->format.parse_inplace) {
23314999e962STakashi Iwai 		map->lock(map->lock_arg);
2332f4298360SStephen Boyd 		for (i = 0; i < val_count; i++) {
2333f4298360SStephen Boyd 			unsigned int ival;
23348eaeb219SLaxman Dewangan 
2335f4298360SStephen Boyd 			switch (val_bytes) {
2336f4298360SStephen Boyd 			case 1:
2337f4298360SStephen Boyd 				ival = *(u8 *)(val + (i * val_bytes));
2338f4298360SStephen Boyd 				break;
2339f4298360SStephen Boyd 			case 2:
2340f4298360SStephen Boyd 				ival = *(u16 *)(val + (i * val_bytes));
2341f4298360SStephen Boyd 				break;
2342f4298360SStephen Boyd 			case 4:
2343f4298360SStephen Boyd 				ival = *(u32 *)(val + (i * val_bytes));
2344f4298360SStephen Boyd 				break;
2345f4298360SStephen Boyd 			default:
2346f4298360SStephen Boyd 				ret = -EINVAL;
2347f4298360SStephen Boyd 				goto out;
2348f4298360SStephen Boyd 			}
2349f4298360SStephen Boyd 
2350ca747be2SXiubo Li 			ret = _regmap_write(map,
2351ca747be2SXiubo Li 					    reg + regmap_get_offset(map, i),
2352f4298360SStephen Boyd 					    ival);
2353f4298360SStephen Boyd 			if (ret != 0)
2354f4298360SStephen Boyd 				goto out;
2355f4298360SStephen Boyd 		}
23564999e962STakashi Iwai out:
23574999e962STakashi Iwai 		map->unlock(map->lock_arg);
23588eaeb219SLaxman Dewangan 	} else {
2359f4298360SStephen Boyd 		void *wval;
2360f4298360SStephen Boyd 
2361b4a21fc2SStephen Boyd 		wval = kmemdup(val, val_count * val_bytes, map->alloc_flags);
2362b4ecfec5SCharles Keepax 		if (!wval)
23634999e962STakashi Iwai 			return -ENOMEM;
2364b4ecfec5SCharles Keepax 
23658eaeb219SLaxman Dewangan 		for (i = 0; i < val_count * val_bytes; i += val_bytes)
23668a819ff8SMark Brown 			map->format.parse_inplace(wval + i);
2367f4298360SStephen Boyd 
23687ef2c6b8SCharles Keepax 		ret = regmap_raw_write(map, reg, wval, val_bytes * val_count);
23698eaeb219SLaxman Dewangan 
23708eaeb219SLaxman Dewangan 		kfree(wval);
2371f4298360SStephen Boyd 	}
2372026c99b5SDmitry Rokosov 
2373026c99b5SDmitry Rokosov 	if (!ret)
2374026c99b5SDmitry Rokosov 		trace_regmap_bulk_write(map, reg, val, val_bytes * val_count);
2375026c99b5SDmitry Rokosov 
23768eaeb219SLaxman Dewangan 	return ret;
23778eaeb219SLaxman Dewangan }
23788eaeb219SLaxman Dewangan EXPORT_SYMBOL_GPL(regmap_bulk_write);
23798eaeb219SLaxman Dewangan 
2380e33fabd3SAnthony Olech /*
2381e894c3f4SOpensource [Anthony Olech]  * _regmap_raw_multi_reg_write()
2382e894c3f4SOpensource [Anthony Olech]  *
2383e894c3f4SOpensource [Anthony Olech]  * the (register,newvalue) pairs in regs have not been formatted, but
2384e894c3f4SOpensource [Anthony Olech]  * they are all in the same page and have been changed to being page
2385b486afbdSXiubo Li  * relative. The page register has been written if that was necessary.
2386e894c3f4SOpensource [Anthony Olech]  */
_regmap_raw_multi_reg_write(struct regmap * map,const struct reg_sequence * regs,size_t num_regs)2387e894c3f4SOpensource [Anthony Olech] static int _regmap_raw_multi_reg_write(struct regmap *map,
23888019ff6cSNariman Poushin 				       const struct reg_sequence *regs,
2389e894c3f4SOpensource [Anthony Olech] 				       size_t num_regs)
23901d5b40bcSCharles Keepax {
2391e894c3f4SOpensource [Anthony Olech] 	int ret;
2392e894c3f4SOpensource [Anthony Olech] 	void *buf;
2393e894c3f4SOpensource [Anthony Olech] 	int i;
2394e894c3f4SOpensource [Anthony Olech] 	u8 *u8;
2395e894c3f4SOpensource [Anthony Olech] 	size_t val_bytes = map->format.val_bytes;
2396e894c3f4SOpensource [Anthony Olech] 	size_t reg_bytes = map->format.reg_bytes;
2397e894c3f4SOpensource [Anthony Olech] 	size_t pad_bytes = map->format.pad_bytes;
2398e894c3f4SOpensource [Anthony Olech] 	size_t pair_size = reg_bytes + pad_bytes + val_bytes;
2399e894c3f4SOpensource [Anthony Olech] 	size_t len = pair_size * num_regs;
2400e894c3f4SOpensource [Anthony Olech] 
2401f5727cd3SXiubo Li 	if (!len)
2402f5727cd3SXiubo Li 		return -EINVAL;
2403f5727cd3SXiubo Li 
2404e894c3f4SOpensource [Anthony Olech] 	buf = kzalloc(len, GFP_KERNEL);
2405e894c3f4SOpensource [Anthony Olech] 	if (!buf)
2406e894c3f4SOpensource [Anthony Olech] 		return -ENOMEM;
2407e894c3f4SOpensource [Anthony Olech] 
2408e894c3f4SOpensource [Anthony Olech] 	/* We have to linearise by hand. */
2409e894c3f4SOpensource [Anthony Olech] 
2410e894c3f4SOpensource [Anthony Olech] 	u8 = buf;
24111d5b40bcSCharles Keepax 
24121d5b40bcSCharles Keepax 	for (i = 0; i < num_regs; i++) {
24132f9b660bSMarkus Pargmann 		unsigned int reg = regs[i].reg;
24142f9b660bSMarkus Pargmann 		unsigned int val = regs[i].def;
2415c6b570d9SPhilipp Zabel 		trace_regmap_hw_write_start(map, reg, 1);
24163f58f6dcSMaxime Chevallier 		reg = regmap_reg_addr(map, reg);
2417e894c3f4SOpensource [Anthony Olech] 		map->format.format_reg(u8, reg, map->reg_shift);
2418e894c3f4SOpensource [Anthony Olech] 		u8 += reg_bytes + pad_bytes;
2419e894c3f4SOpensource [Anthony Olech] 		map->format.format_val(u8, val, 0);
2420e894c3f4SOpensource [Anthony Olech] 		u8 += val_bytes;
2421e894c3f4SOpensource [Anthony Olech] 	}
2422e894c3f4SOpensource [Anthony Olech] 	u8 = buf;
2423e894c3f4SOpensource [Anthony Olech] 	*u8 |= map->write_flag_mask;
2424e894c3f4SOpensource [Anthony Olech] 
2425d77e7456SMarek Vasut 	ret = map->write(map->bus_context, buf, len);
2426e894c3f4SOpensource [Anthony Olech] 
2427e894c3f4SOpensource [Anthony Olech] 	kfree(buf);
2428e894c3f4SOpensource [Anthony Olech] 
2429e894c3f4SOpensource [Anthony Olech] 	for (i = 0; i < num_regs; i++) {
2430e894c3f4SOpensource [Anthony Olech] 		int reg = regs[i].reg;
2431c6b570d9SPhilipp Zabel 		trace_regmap_hw_write_done(map, reg, 1);
2432e894c3f4SOpensource [Anthony Olech] 	}
2433e894c3f4SOpensource [Anthony Olech] 	return ret;
2434e894c3f4SOpensource [Anthony Olech] }
2435e894c3f4SOpensource [Anthony Olech] 
_regmap_register_page(struct regmap * map,unsigned int reg,struct regmap_range_node * range)2436e894c3f4SOpensource [Anthony Olech] static unsigned int _regmap_register_page(struct regmap *map,
2437e894c3f4SOpensource [Anthony Olech] 					  unsigned int reg,
2438e894c3f4SOpensource [Anthony Olech] 					  struct regmap_range_node *range)
2439e894c3f4SOpensource [Anthony Olech] {
2440e894c3f4SOpensource [Anthony Olech] 	unsigned int win_page = (reg - range->range_min) / range->window_len;
2441e894c3f4SOpensource [Anthony Olech] 
2442e894c3f4SOpensource [Anthony Olech] 	return win_page;
2443e894c3f4SOpensource [Anthony Olech] }
2444e894c3f4SOpensource [Anthony Olech] 
_regmap_range_multi_paged_reg_write(struct regmap * map,struct reg_sequence * regs,size_t num_regs)2445e894c3f4SOpensource [Anthony Olech] static int _regmap_range_multi_paged_reg_write(struct regmap *map,
24468019ff6cSNariman Poushin 					       struct reg_sequence *regs,
2447e894c3f4SOpensource [Anthony Olech] 					       size_t num_regs)
2448e894c3f4SOpensource [Anthony Olech] {
2449e894c3f4SOpensource [Anthony Olech] 	int ret;
2450e894c3f4SOpensource [Anthony Olech] 	int i, n;
24518019ff6cSNariman Poushin 	struct reg_sequence *base;
2452b48d1398SGeert Uytterhoeven 	unsigned int this_page = 0;
24532de9d600SNariman Poushin 	unsigned int page_change = 0;
2454e894c3f4SOpensource [Anthony Olech] 	/*
2455e894c3f4SOpensource [Anthony Olech] 	 * the set of registers are not neccessarily in order, but
2456e894c3f4SOpensource [Anthony Olech] 	 * since the order of write must be preserved this algorithm
24572de9d600SNariman Poushin 	 * chops the set each time the page changes. This also applies
24582de9d600SNariman Poushin 	 * if there is a delay required at any point in the sequence.
2459e894c3f4SOpensource [Anthony Olech] 	 */
2460e894c3f4SOpensource [Anthony Olech] 	base = regs;
2461e894c3f4SOpensource [Anthony Olech] 	for (i = 0, n = 0; i < num_regs; i++, n++) {
2462e894c3f4SOpensource [Anthony Olech] 		unsigned int reg = regs[i].reg;
2463e894c3f4SOpensource [Anthony Olech] 		struct regmap_range_node *range;
2464e894c3f4SOpensource [Anthony Olech] 
2465e894c3f4SOpensource [Anthony Olech] 		range = _regmap_range_lookup(map, reg);
2466e894c3f4SOpensource [Anthony Olech] 		if (range) {
2467e894c3f4SOpensource [Anthony Olech] 			unsigned int win_page = _regmap_register_page(map, reg,
2468e894c3f4SOpensource [Anthony Olech] 								      range);
2469e894c3f4SOpensource [Anthony Olech] 
2470e894c3f4SOpensource [Anthony Olech] 			if (i == 0)
2471e894c3f4SOpensource [Anthony Olech] 				this_page = win_page;
2472e894c3f4SOpensource [Anthony Olech] 			if (win_page != this_page) {
2473e894c3f4SOpensource [Anthony Olech] 				this_page = win_page;
24742de9d600SNariman Poushin 				page_change = 1;
24752de9d600SNariman Poushin 			}
24762de9d600SNariman Poushin 		}
24772de9d600SNariman Poushin 
24782de9d600SNariman Poushin 		/* If we have both a page change and a delay make sure to
24792de9d600SNariman Poushin 		 * write the regs and apply the delay before we change the
24802de9d600SNariman Poushin 		 * page.
24812de9d600SNariman Poushin 		 */
24822de9d600SNariman Poushin 
24832de9d600SNariman Poushin 		if (page_change || regs[i].delay_us) {
24842de9d600SNariman Poushin 
24852de9d600SNariman Poushin 				/* For situations where the first write requires
24862de9d600SNariman Poushin 				 * a delay we need to make sure we don't call
24872de9d600SNariman Poushin 				 * raw_multi_reg_write with n=0
24882de9d600SNariman Poushin 				 * This can't occur with page breaks as we
24892de9d600SNariman Poushin 				 * never write on the first iteration
24902de9d600SNariman Poushin 				 */
24912de9d600SNariman Poushin 				if (regs[i].delay_us && i == 0)
24922de9d600SNariman Poushin 					n = 1;
24932de9d600SNariman Poushin 
2494e894c3f4SOpensource [Anthony Olech] 				ret = _regmap_raw_multi_reg_write(map, base, n);
2495e894c3f4SOpensource [Anthony Olech] 				if (ret != 0)
2496e894c3f4SOpensource [Anthony Olech] 					return ret;
24972de9d600SNariman Poushin 
249821f8e482SDmitry Osipenko 				if (regs[i].delay_us) {
249921f8e482SDmitry Osipenko 					if (map->can_sleep)
25002b32d2f7SDmitry Osipenko 						fsleep(regs[i].delay_us);
250121f8e482SDmitry Osipenko 					else
25022de9d600SNariman Poushin 						udelay(regs[i].delay_us);
250321f8e482SDmitry Osipenko 				}
25042de9d600SNariman Poushin 
2505e894c3f4SOpensource [Anthony Olech] 				base += n;
2506e894c3f4SOpensource [Anthony Olech] 				n = 0;
25072de9d600SNariman Poushin 
25082de9d600SNariman Poushin 				if (page_change) {
25092de9d600SNariman Poushin 					ret = _regmap_select_page(map,
25102de9d600SNariman Poushin 								  &base[n].reg,
25112de9d600SNariman Poushin 								  range, 1);
2512e894c3f4SOpensource [Anthony Olech] 					if (ret != 0)
25131d5b40bcSCharles Keepax 						return ret;
25142de9d600SNariman Poushin 
25152de9d600SNariman Poushin 					page_change = 0;
25161d5b40bcSCharles Keepax 				}
25172de9d600SNariman Poushin 
25182de9d600SNariman Poushin 		}
25192de9d600SNariman Poushin 
25201d5b40bcSCharles Keepax 	}
2521e894c3f4SOpensource [Anthony Olech] 	if (n > 0)
2522e894c3f4SOpensource [Anthony Olech] 		return _regmap_raw_multi_reg_write(map, base, n);
25231d5b40bcSCharles Keepax 	return 0;
25241d5b40bcSCharles Keepax }
25251d5b40bcSCharles Keepax 
_regmap_multi_reg_write(struct regmap * map,const struct reg_sequence * regs,size_t num_regs)2526e894c3f4SOpensource [Anthony Olech] static int _regmap_multi_reg_write(struct regmap *map,
25278019ff6cSNariman Poushin 				   const struct reg_sequence *regs,
2528e894c3f4SOpensource [Anthony Olech] 				   size_t num_regs)
2529e894c3f4SOpensource [Anthony Olech] {
2530e894c3f4SOpensource [Anthony Olech] 	int i;
2531e894c3f4SOpensource [Anthony Olech] 	int ret;
2532e894c3f4SOpensource [Anthony Olech] 
2533e894c3f4SOpensource [Anthony Olech] 	if (!map->can_multi_write) {
2534e894c3f4SOpensource [Anthony Olech] 		for (i = 0; i < num_regs; i++) {
2535e894c3f4SOpensource [Anthony Olech] 			ret = _regmap_write(map, regs[i].reg, regs[i].def);
2536e894c3f4SOpensource [Anthony Olech] 			if (ret != 0)
2537e894c3f4SOpensource [Anthony Olech] 				return ret;
25382de9d600SNariman Poushin 
253921f8e482SDmitry Osipenko 			if (regs[i].delay_us) {
254021f8e482SDmitry Osipenko 				if (map->can_sleep)
25412b32d2f7SDmitry Osipenko 					fsleep(regs[i].delay_us);
254221f8e482SDmitry Osipenko 				else
25432de9d600SNariman Poushin 					udelay(regs[i].delay_us);
2544e894c3f4SOpensource [Anthony Olech] 			}
2545e894c3f4SOpensource [Anthony Olech] 		}
2546e894c3f4SOpensource [Anthony Olech] 		return 0;
2547e894c3f4SOpensource [Anthony Olech] 	}
2548e894c3f4SOpensource [Anthony Olech] 
2549e894c3f4SOpensource [Anthony Olech] 	if (!map->format.parse_inplace)
2550e894c3f4SOpensource [Anthony Olech] 		return -EINVAL;
2551e894c3f4SOpensource [Anthony Olech] 
2552e894c3f4SOpensource [Anthony Olech] 	if (map->writeable_reg)
2553e894c3f4SOpensource [Anthony Olech] 		for (i = 0; i < num_regs; i++) {
2554e894c3f4SOpensource [Anthony Olech] 			int reg = regs[i].reg;
2555e894c3f4SOpensource [Anthony Olech] 			if (!map->writeable_reg(map->dev, reg))
2556e894c3f4SOpensource [Anthony Olech] 				return -EINVAL;
2557fcac0233SXiubo Li 			if (!IS_ALIGNED(reg, map->reg_stride))
2558e894c3f4SOpensource [Anthony Olech] 				return -EINVAL;
2559e894c3f4SOpensource [Anthony Olech] 		}
2560e894c3f4SOpensource [Anthony Olech] 
2561e894c3f4SOpensource [Anthony Olech] 	if (!map->cache_bypass) {
2562e894c3f4SOpensource [Anthony Olech] 		for (i = 0; i < num_regs; i++) {
2563e894c3f4SOpensource [Anthony Olech] 			unsigned int val = regs[i].def;
2564e894c3f4SOpensource [Anthony Olech] 			unsigned int reg = regs[i].reg;
2565e894c3f4SOpensource [Anthony Olech] 			ret = regcache_write(map, reg, val);
2566e894c3f4SOpensource [Anthony Olech] 			if (ret) {
2567e894c3f4SOpensource [Anthony Olech] 				dev_err(map->dev,
2568e894c3f4SOpensource [Anthony Olech] 				"Error in caching of register: %x ret: %d\n",
2569e894c3f4SOpensource [Anthony Olech] 								reg, ret);
2570e894c3f4SOpensource [Anthony Olech] 				return ret;
2571e894c3f4SOpensource [Anthony Olech] 			}
2572e894c3f4SOpensource [Anthony Olech] 		}
2573e894c3f4SOpensource [Anthony Olech] 		if (map->cache_only) {
2574e894c3f4SOpensource [Anthony Olech] 			map->cache_dirty = true;
2575e894c3f4SOpensource [Anthony Olech] 			return 0;
2576e894c3f4SOpensource [Anthony Olech] 		}
2577e894c3f4SOpensource [Anthony Olech] 	}
2578e894c3f4SOpensource [Anthony Olech] 
2579e894c3f4SOpensource [Anthony Olech] 	WARN_ON(!map->bus);
2580e894c3f4SOpensource [Anthony Olech] 
2581e894c3f4SOpensource [Anthony Olech] 	for (i = 0; i < num_regs; i++) {
2582e894c3f4SOpensource [Anthony Olech] 		unsigned int reg = regs[i].reg;
2583e894c3f4SOpensource [Anthony Olech] 		struct regmap_range_node *range;
25842de9d600SNariman Poushin 
25852de9d600SNariman Poushin 		/* Coalesce all the writes between a page break or a delay
25862de9d600SNariman Poushin 		 * in a sequence
25872de9d600SNariman Poushin 		 */
2588e894c3f4SOpensource [Anthony Olech] 		range = _regmap_range_lookup(map, reg);
25892de9d600SNariman Poushin 		if (range || regs[i].delay_us) {
25908019ff6cSNariman Poushin 			size_t len = sizeof(struct reg_sequence)*num_regs;
25918019ff6cSNariman Poushin 			struct reg_sequence *base = kmemdup(regs, len,
2592e894c3f4SOpensource [Anthony Olech] 							   GFP_KERNEL);
2593e894c3f4SOpensource [Anthony Olech] 			if (!base)
2594e894c3f4SOpensource [Anthony Olech] 				return -ENOMEM;
2595e894c3f4SOpensource [Anthony Olech] 			ret = _regmap_range_multi_paged_reg_write(map, base,
2596e894c3f4SOpensource [Anthony Olech] 								  num_regs);
2597e894c3f4SOpensource [Anthony Olech] 			kfree(base);
2598e894c3f4SOpensource [Anthony Olech] 
2599e894c3f4SOpensource [Anthony Olech] 			return ret;
2600e894c3f4SOpensource [Anthony Olech] 		}
2601e894c3f4SOpensource [Anthony Olech] 	}
2602e894c3f4SOpensource [Anthony Olech] 	return _regmap_raw_multi_reg_write(map, regs, num_regs);
2603e894c3f4SOpensource [Anthony Olech] }
2604e894c3f4SOpensource [Anthony Olech] 
26052cf8e2dfSCharles Keepax /**
26062cf8e2dfSCharles Keepax  * regmap_multi_reg_write() - Write multiple registers to the device
2607e33fabd3SAnthony Olech  *
2608e33fabd3SAnthony Olech  * @map: Register map to write to
2609e33fabd3SAnthony Olech  * @regs: Array of structures containing register,value to be written
2610e33fabd3SAnthony Olech  * @num_regs: Number of registers to write
2611e33fabd3SAnthony Olech  *
26122cf8e2dfSCharles Keepax  * Write multiple registers to the device where the set of register, value
26132cf8e2dfSCharles Keepax  * pairs are supplied in any order, possibly not all in a single range.
26142cf8e2dfSCharles Keepax  *
2615e894c3f4SOpensource [Anthony Olech]  * The 'normal' block write mode will send ultimately send data on the
26162cf8e2dfSCharles Keepax  * target bus as R,V1,V2,V3,..,Vn where successively higher registers are
2617e894c3f4SOpensource [Anthony Olech]  * addressed. However, this alternative block multi write mode will send
2618e894c3f4SOpensource [Anthony Olech]  * the data as R1,V1,R2,V2,..,Rn,Vn on the target bus. The target device
2619e894c3f4SOpensource [Anthony Olech]  * must of course support the mode.
2620e33fabd3SAnthony Olech  *
2621e894c3f4SOpensource [Anthony Olech]  * A value of zero will be returned on success, a negative errno will be
2622e894c3f4SOpensource [Anthony Olech]  * returned in error cases.
2623e33fabd3SAnthony Olech  */
regmap_multi_reg_write(struct regmap * map,const struct reg_sequence * regs,int num_regs)26248019ff6cSNariman Poushin int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs,
2625e33fabd3SAnthony Olech 			   int num_regs)
2626e33fabd3SAnthony Olech {
26271d5b40bcSCharles Keepax 	int ret;
2628e33fabd3SAnthony Olech 
2629e33fabd3SAnthony Olech 	map->lock(map->lock_arg);
2630e33fabd3SAnthony Olech 
26311d5b40bcSCharles Keepax 	ret = _regmap_multi_reg_write(map, regs, num_regs);
26321d5b40bcSCharles Keepax 
2633e33fabd3SAnthony Olech 	map->unlock(map->lock_arg);
2634e33fabd3SAnthony Olech 
2635e33fabd3SAnthony Olech 	return ret;
2636e33fabd3SAnthony Olech }
2637e33fabd3SAnthony Olech EXPORT_SYMBOL_GPL(regmap_multi_reg_write);
2638e33fabd3SAnthony Olech 
26392cf8e2dfSCharles Keepax /**
26402cf8e2dfSCharles Keepax  * regmap_multi_reg_write_bypassed() - Write multiple registers to the
26411d5b40bcSCharles Keepax  *                                     device but not the cache
26421d5b40bcSCharles Keepax  *
26430d509f2bSMark Brown  * @map: Register map to write to
26440d509f2bSMark Brown  * @regs: Array of structures containing register,value to be written
26450d509f2bSMark Brown  * @num_regs: Number of registers to write
26460d509f2bSMark Brown  *
26472cf8e2dfSCharles Keepax  * Write multiple registers to the device but not the cache where the set
26482cf8e2dfSCharles Keepax  * of register are supplied in any order.
26492cf8e2dfSCharles Keepax  *
26500d509f2bSMark Brown  * This function is intended to be used for writing a large block of data
26510d509f2bSMark Brown  * atomically to the device in single transfer for those I2C client devices
26520d509f2bSMark Brown  * that implement this alternative block write mode.
26530d509f2bSMark Brown  *
26540d509f2bSMark Brown  * A value of zero will be returned on success, a negative errno will
26550d509f2bSMark Brown  * be returned in error cases.
26560d509f2bSMark Brown  */
regmap_multi_reg_write_bypassed(struct regmap * map,const struct reg_sequence * regs,int num_regs)26571d5b40bcSCharles Keepax int regmap_multi_reg_write_bypassed(struct regmap *map,
26588019ff6cSNariman Poushin 				    const struct reg_sequence *regs,
26590d509f2bSMark Brown 				    int num_regs)
26600d509f2bSMark Brown {
26611d5b40bcSCharles Keepax 	int ret;
26621d5b40bcSCharles Keepax 	bool bypass;
26630d509f2bSMark Brown 
26640d509f2bSMark Brown 	map->lock(map->lock_arg);
26650d509f2bSMark Brown 
26661d5b40bcSCharles Keepax 	bypass = map->cache_bypass;
26671d5b40bcSCharles Keepax 	map->cache_bypass = true;
26681d5b40bcSCharles Keepax 
26691d5b40bcSCharles Keepax 	ret = _regmap_multi_reg_write(map, regs, num_regs);
26701d5b40bcSCharles Keepax 
26711d5b40bcSCharles Keepax 	map->cache_bypass = bypass;
26721d5b40bcSCharles Keepax 
26730a819809SMark Brown 	map->unlock(map->lock_arg);
26740a819809SMark Brown 
26750a819809SMark Brown 	return ret;
26760a819809SMark Brown }
26771d5b40bcSCharles Keepax EXPORT_SYMBOL_GPL(regmap_multi_reg_write_bypassed);
26780d509f2bSMark Brown 
26790d509f2bSMark Brown /**
26802cf8e2dfSCharles Keepax  * regmap_raw_write_async() - Write raw values to one or more registers
26810d509f2bSMark Brown  *                            asynchronously
26820d509f2bSMark Brown  *
26830d509f2bSMark Brown  * @map: Register map to write to
26840d509f2bSMark Brown  * @reg: Initial register to write to
26850d509f2bSMark Brown  * @val: Block of data to be written, laid out for direct transmission to the
26860d509f2bSMark Brown  *       device.  Must be valid until regmap_async_complete() is called.
26870d509f2bSMark Brown  * @val_len: Length of data pointed to by val.
26880d509f2bSMark Brown  *
26890d509f2bSMark Brown  * This function is intended to be used for things like firmware
26900d509f2bSMark Brown  * download where a large block of data needs to be transferred to the
26910d509f2bSMark Brown  * device.  No formatting will be done on the data provided.
26920d509f2bSMark Brown  *
26930d509f2bSMark Brown  * If supported by the underlying bus the write will be scheduled
26940d509f2bSMark Brown  * asynchronously, helping maximise I/O speed on higher speed buses
26950d509f2bSMark Brown  * like SPI.  regmap_async_complete() can be called to ensure that all
26960d509f2bSMark Brown  * asynchrnous writes have been completed.
26970d509f2bSMark Brown  *
26980d509f2bSMark Brown  * A value of zero will be returned on success, a negative errno will
26990d509f2bSMark Brown  * be returned in error cases.
27000d509f2bSMark Brown  */
regmap_raw_write_async(struct regmap * map,unsigned int reg,const void * val,size_t val_len)27010d509f2bSMark Brown int regmap_raw_write_async(struct regmap *map, unsigned int reg,
27020d509f2bSMark Brown 			   const void *val, size_t val_len)
27030d509f2bSMark Brown {
27040d509f2bSMark Brown 	int ret;
27050d509f2bSMark Brown 
27060d509f2bSMark Brown 	if (val_len % map->format.val_bytes)
27070d509f2bSMark Brown 		return -EINVAL;
2708fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
27090d509f2bSMark Brown 		return -EINVAL;
27100d509f2bSMark Brown 
27110d509f2bSMark Brown 	map->lock(map->lock_arg);
27120d509f2bSMark Brown 
27130d509f2bSMark Brown 	map->async = true;
27140d509f2bSMark Brown 
271505669b63SDmitry Baryshkov 	ret = _regmap_raw_write(map, reg, val, val_len, false);
27160d509f2bSMark Brown 
27170d509f2bSMark Brown 	map->async = false;
27180d509f2bSMark Brown 
27190d509f2bSMark Brown 	map->unlock(map->lock_arg);
27200d509f2bSMark Brown 
27210d509f2bSMark Brown 	return ret;
2722b83a313bSMark Brown }
2723b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_write_async);
2724b83a313bSMark Brown 
_regmap_raw_read(struct regmap * map,unsigned int reg,void * val,unsigned int val_len,bool noinc)272598bc7dfdSMark Brown static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
272640033248SDmitry Baryshkov 			    unsigned int val_len, bool noinc)
2727b83a313bSMark Brown {
2728b83a313bSMark Brown 	struct regmap_range_node *range;
2729b83a313bSMark Brown 	int ret;
2730b83a313bSMark Brown 
2731d77e7456SMarek Vasut 	if (!map->read)
2732bb2bb45dSMark Brown 		return -EINVAL;
2733bb2bb45dSMark Brown 
273498bc7dfdSMark Brown 	range = _regmap_range_lookup(map, reg);
273598bc7dfdSMark Brown 	if (range) {
273698bc7dfdSMark Brown 		ret = _regmap_select_page(map, &reg, range,
273740033248SDmitry Baryshkov 					  noinc ? 1 : val_len / map->format.val_bytes);
27380ff3e62fSMark Brown 		if (ret != 0)
27396863ca62SKrystian Garbaciak 			return ret;
274098bc7dfdSMark Brown 	}
27416863ca62SKrystian Garbaciak 
27423f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
2743d939fb9aSMarc Reilly 	map->format.format_reg(map->work_buf, reg, map->reg_shift);
2744f50e38c9STony Lindgren 	regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
2745f50e38c9STony Lindgren 				      map->read_flag_mask);
2746c6b570d9SPhilipp Zabel 	trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
2747fb2736bbSMark Brown 
2748d77e7456SMarek Vasut 	ret = map->read(map->bus_context, map->work_buf,
274982159ba8SMark Brown 			map->format.reg_bytes + map->format.pad_bytes,
275040c5cc26SMark Brown 			val, val_len);
2751b83a313bSMark Brown 
2752c6b570d9SPhilipp Zabel 	trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes);
2753fb2736bbSMark Brown 
2754fb2736bbSMark Brown 	return ret;
2755b83a313bSMark Brown }
2756b83a313bSMark Brown 
_regmap_bus_reg_read(void * context,unsigned int reg,unsigned int * val)27573ac17037SBoris BREZILLON static int _regmap_bus_reg_read(void *context, unsigned int reg,
27583ac17037SBoris BREZILLON 				unsigned int *val)
27593ac17037SBoris BREZILLON {
27603ac17037SBoris BREZILLON 	struct regmap *map = context;
2761f18ee501SMark Brown 	struct regmap_range_node *range;
2762f18ee501SMark Brown 	int ret;
2763f18ee501SMark Brown 
2764f18ee501SMark Brown 	range = _regmap_range_lookup(map, reg);
2765f18ee501SMark Brown 	if (range) {
2766f18ee501SMark Brown 		ret = _regmap_select_page(map, &reg, range, 1);
2767f18ee501SMark Brown 		if (ret != 0)
2768f18ee501SMark Brown 			return ret;
2769f18ee501SMark Brown 	}
27703ac17037SBoris BREZILLON 
27713f58f6dcSMaxime Chevallier 	reg = regmap_reg_addr(map, reg);
27723ac17037SBoris BREZILLON 	return map->bus->reg_read(map->bus_context, reg, val);
27733ac17037SBoris BREZILLON }
27743ac17037SBoris BREZILLON 
_regmap_bus_read(void * context,unsigned int reg,unsigned int * val)2775ad278406SAndrey Smirnov static int _regmap_bus_read(void *context, unsigned int reg,
2776ad278406SAndrey Smirnov 			    unsigned int *val)
2777ad278406SAndrey Smirnov {
2778ad278406SAndrey Smirnov 	int ret;
2779ad278406SAndrey Smirnov 	struct regmap *map = context;
27804c90f297SKrzysztof Adamski 	void *work_val = map->work_buf + map->format.reg_bytes +
27814c90f297SKrzysztof Adamski 		map->format.pad_bytes;
2782ad278406SAndrey Smirnov 
2783ad278406SAndrey Smirnov 	if (!map->format.parse_val)
2784ad278406SAndrey Smirnov 		return -EINVAL;
2785ad278406SAndrey Smirnov 
278640033248SDmitry Baryshkov 	ret = _regmap_raw_read(map, reg, work_val, map->format.val_bytes, false);
2787ad278406SAndrey Smirnov 	if (ret == 0)
27884c90f297SKrzysztof Adamski 		*val = map->format.parse_val(work_val);
2789ad278406SAndrey Smirnov 
2790ad278406SAndrey Smirnov 	return ret;
2791ad278406SAndrey Smirnov }
2792ad278406SAndrey Smirnov 
_regmap_read(struct regmap * map,unsigned int reg,unsigned int * val)2793b83a313bSMark Brown static int _regmap_read(struct regmap *map, unsigned int reg,
2794b83a313bSMark Brown 			unsigned int *val)
2795b83a313bSMark Brown {
2796b83a313bSMark Brown 	int ret;
2797d2a5884aSAndrey Smirnov 	void *context = _regmap_map_get_context(map);
2798d2a5884aSAndrey Smirnov 
27995d1729e7SDimitris Papastamos 	if (!map->cache_bypass) {
28005d1729e7SDimitris Papastamos 		ret = regcache_read(map, reg, val);
28015d1729e7SDimitris Papastamos 		if (ret == 0)
28025d1729e7SDimitris Papastamos 			return 0;
28035d1729e7SDimitris Papastamos 	}
28045d1729e7SDimitris Papastamos 
28055d1729e7SDimitris Papastamos 	if (map->cache_only)
28065d1729e7SDimitris Papastamos 		return -EBUSY;
28075d1729e7SDimitris Papastamos 
28083e47b887SMark Brown 	if (!regmap_readable(map, reg))
28093e47b887SMark Brown 		return -EIO;
28103e47b887SMark Brown 
2811d2a5884aSAndrey Smirnov 	ret = map->reg_read(context, reg, val);
2812fb2736bbSMark Brown 	if (ret == 0) {
281395093762SBen Dooks 		if (regmap_should_log(map))
28141044c180SMark Brown 			dev_info(map->dev, "%x => %x\n", reg, *val);
28151044c180SMark Brown 
2816c6b570d9SPhilipp Zabel 		trace_regmap_reg_read(map, reg, *val);
2817b83a313bSMark Brown 
2818ad278406SAndrey Smirnov 		if (!map->cache_bypass)
2819f2985367SMark Brown 			regcache_write(map, reg, *val);
2820ad278406SAndrey Smirnov 	}
2821f2985367SMark Brown 
2822b83a313bSMark Brown 	return ret;
2823b83a313bSMark Brown }
2824b83a313bSMark Brown 
2825b83a313bSMark Brown /**
28262cf8e2dfSCharles Keepax  * regmap_read() - Read a value from a single register
2827b83a313bSMark Brown  *
28280093380cSGerhard Sittig  * @map: Register map to read from
2829b83a313bSMark Brown  * @reg: Register to be read from
2830b83a313bSMark Brown  * @val: Pointer to store read value
2831b83a313bSMark Brown  *
2832b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
2833b83a313bSMark Brown  * be returned in error cases.
2834b83a313bSMark Brown  */
regmap_read(struct regmap * map,unsigned int reg,unsigned int * val)2835b83a313bSMark Brown int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
2836b83a313bSMark Brown {
2837b83a313bSMark Brown 	int ret;
2838b83a313bSMark Brown 
2839fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
2840f01ee60fSStephen Warren 		return -EINVAL;
2841f01ee60fSStephen Warren 
28420d4529c5SDavide Ciminaghi 	map->lock(map->lock_arg);
2843b83a313bSMark Brown 
2844b83a313bSMark Brown 	ret = _regmap_read(map, reg, val);
2845b83a313bSMark Brown 
28460d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
2847b83a313bSMark Brown 
2848b83a313bSMark Brown 	return ret;
2849b83a313bSMark Brown }
2850b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_read);
2851b83a313bSMark Brown 
2852b83a313bSMark Brown /**
2853b5a291e5SRichard Fitzgerald  * regmap_read_bypassed() - Read a value from a single register direct
2854b5a291e5SRichard Fitzgerald  *			    from the device, bypassing the cache
2855b5a291e5SRichard Fitzgerald  *
2856b5a291e5SRichard Fitzgerald  * @map: Register map to read from
2857b5a291e5SRichard Fitzgerald  * @reg: Register to be read from
2858b5a291e5SRichard Fitzgerald  * @val: Pointer to store read value
2859b5a291e5SRichard Fitzgerald  *
2860b5a291e5SRichard Fitzgerald  * A value of zero will be returned on success, a negative errno will
2861b5a291e5SRichard Fitzgerald  * be returned in error cases.
2862b5a291e5SRichard Fitzgerald  */
regmap_read_bypassed(struct regmap * map,unsigned int reg,unsigned int * val)2863b5a291e5SRichard Fitzgerald int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val)
2864b5a291e5SRichard Fitzgerald {
2865b5a291e5SRichard Fitzgerald 	int ret;
2866b5a291e5SRichard Fitzgerald 	bool bypass, cache_only;
2867b5a291e5SRichard Fitzgerald 
2868b5a291e5SRichard Fitzgerald 	if (!IS_ALIGNED(reg, map->reg_stride))
2869b5a291e5SRichard Fitzgerald 		return -EINVAL;
2870b5a291e5SRichard Fitzgerald 
2871b5a291e5SRichard Fitzgerald 	map->lock(map->lock_arg);
2872b5a291e5SRichard Fitzgerald 
2873b5a291e5SRichard Fitzgerald 	bypass = map->cache_bypass;
2874b5a291e5SRichard Fitzgerald 	cache_only = map->cache_only;
2875b5a291e5SRichard Fitzgerald 	map->cache_bypass = true;
2876b5a291e5SRichard Fitzgerald 	map->cache_only = false;
2877b5a291e5SRichard Fitzgerald 
2878b5a291e5SRichard Fitzgerald 	ret = _regmap_read(map, reg, val);
2879b5a291e5SRichard Fitzgerald 
2880b5a291e5SRichard Fitzgerald 	map->cache_bypass = bypass;
2881b5a291e5SRichard Fitzgerald 	map->cache_only = cache_only;
2882b5a291e5SRichard Fitzgerald 
2883b5a291e5SRichard Fitzgerald 	map->unlock(map->lock_arg);
2884b5a291e5SRichard Fitzgerald 
2885b5a291e5SRichard Fitzgerald 	return ret;
2886b5a291e5SRichard Fitzgerald }
2887b5a291e5SRichard Fitzgerald EXPORT_SYMBOL_GPL(regmap_read_bypassed);
2888b5a291e5SRichard Fitzgerald 
2889b5a291e5SRichard Fitzgerald /**
28902cf8e2dfSCharles Keepax  * regmap_raw_read() - Read raw data from the device
2891b83a313bSMark Brown  *
28920093380cSGerhard Sittig  * @map: Register map to read from
2893b83a313bSMark Brown  * @reg: First register to be read from
2894b83a313bSMark Brown  * @val: Pointer to store read value
2895b83a313bSMark Brown  * @val_len: Size of data to read
2896b83a313bSMark Brown  *
2897b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
2898b83a313bSMark Brown  * be returned in error cases.
2899b83a313bSMark Brown  */
regmap_raw_read(struct regmap * map,unsigned int reg,void * val,size_t val_len)2900b83a313bSMark Brown int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
2901b83a313bSMark Brown 		    size_t val_len)
2902b83a313bSMark Brown {
2903b8fb5ab1SMark Brown 	size_t val_bytes = map->format.val_bytes;
2904b8fb5ab1SMark Brown 	size_t val_count = val_len / val_bytes;
2905b8fb5ab1SMark Brown 	unsigned int v;
2906b8fb5ab1SMark Brown 	int ret, i;
290704e016adSMark Brown 
2908851960baSStephen Warren 	if (val_len % map->format.val_bytes)
2909851960baSStephen Warren 		return -EINVAL;
2910fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
2911f01ee60fSStephen Warren 		return -EINVAL;
2912fa3eec77SMark Brown 	if (val_count == 0)
2913fa3eec77SMark Brown 		return -EINVAL;
2914851960baSStephen Warren 
29150d4529c5SDavide Ciminaghi 	map->lock(map->lock_arg);
2916b83a313bSMark Brown 
2917b8fb5ab1SMark Brown 	if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
2918b8fb5ab1SMark Brown 	    map->cache_type == REGCACHE_NONE) {
29191b079ca2SCharles Keepax 		size_t chunk_count, chunk_bytes;
29201b079ca2SCharles Keepax 		size_t chunk_regs = val_count;
29210645ba43SCharles Keepax 
292299e8dd39SCharles Keepax 		if (!map->cache_bypass && map->cache_only) {
292399e8dd39SCharles Keepax 			ret = -EBUSY;
292499e8dd39SCharles Keepax 			goto out;
292599e8dd39SCharles Keepax 		}
292699e8dd39SCharles Keepax 
2927d77e7456SMarek Vasut 		if (!map->read) {
29289a16ea90SMarkus Pargmann 			ret = -ENOTSUPP;
29299a16ea90SMarkus Pargmann 			goto out;
29309a16ea90SMarkus Pargmann 		}
29310645ba43SCharles Keepax 
29321b079ca2SCharles Keepax 		if (map->use_single_read)
29331b079ca2SCharles Keepax 			chunk_regs = 1;
29341b079ca2SCharles Keepax 		else if (map->max_raw_read && val_len > map->max_raw_read)
29351b079ca2SCharles Keepax 			chunk_regs = map->max_raw_read / val_bytes;
29369a16ea90SMarkus Pargmann 
29371b079ca2SCharles Keepax 		chunk_count = val_count / chunk_regs;
29381b079ca2SCharles Keepax 		chunk_bytes = chunk_regs * val_bytes;
29391b079ca2SCharles Keepax 
29401b079ca2SCharles Keepax 		/* Read bytes that fit into whole chunks */
29410645ba43SCharles Keepax 		for (i = 0; i < chunk_count; i++) {
294240033248SDmitry Baryshkov 			ret = _regmap_raw_read(map, reg, val, chunk_bytes, false);
29430645ba43SCharles Keepax 			if (ret != 0)
2944b83a313bSMark Brown 				goto out;
29451b079ca2SCharles Keepax 
29461b079ca2SCharles Keepax 			reg += regmap_get_offset(map, chunk_regs);
29471b079ca2SCharles Keepax 			val += chunk_bytes;
29481b079ca2SCharles Keepax 			val_len -= chunk_bytes;
2949b8fb5ab1SMark Brown 		}
2950b8fb5ab1SMark Brown 
29510645ba43SCharles Keepax 		/* Read remaining bytes */
29521b079ca2SCharles Keepax 		if (val_len) {
295340033248SDmitry Baryshkov 			ret = _regmap_raw_read(map, reg, val, val_len, false);
29540645ba43SCharles Keepax 			if (ret != 0)
29551b079ca2SCharles Keepax 				goto out;
29560645ba43SCharles Keepax 		}
2957b8fb5ab1SMark Brown 	} else {
2958b8fb5ab1SMark Brown 		/* Otherwise go word by word for the cache; should be low
2959b8fb5ab1SMark Brown 		 * cost as we expect to hit the cache.
2960b8fb5ab1SMark Brown 		 */
2961b8fb5ab1SMark Brown 		for (i = 0; i < val_count; i++) {
2962ca747be2SXiubo Li 			ret = _regmap_read(map, reg + regmap_get_offset(map, i),
2963f01ee60fSStephen Warren 					   &v);
2964b8fb5ab1SMark Brown 			if (ret != 0)
2965b8fb5ab1SMark Brown 				goto out;
2966b8fb5ab1SMark Brown 
2967d939fb9aSMarc Reilly 			map->format.format_val(val + (i * val_bytes), v, 0);
2968b8fb5ab1SMark Brown 		}
2969b8fb5ab1SMark Brown 	}
2970b8fb5ab1SMark Brown 
2971b8fb5ab1SMark Brown  out:
29720d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
2973b83a313bSMark Brown 
2974b83a313bSMark Brown 	return ret;
2975b83a313bSMark Brown }
2976b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_read);
2977b83a313bSMark Brown 
2978b83a313bSMark Brown /**
297974fe7b55SCrestez Dan Leonard  * regmap_noinc_read(): Read data from a register without incrementing the
298074fe7b55SCrestez Dan Leonard  *			register number
298174fe7b55SCrestez Dan Leonard  *
298274fe7b55SCrestez Dan Leonard  * @map: Register map to read from
298374fe7b55SCrestez Dan Leonard  * @reg: Register to read from
298474fe7b55SCrestez Dan Leonard  * @val: Pointer to data buffer
298574fe7b55SCrestez Dan Leonard  * @val_len: Length of output buffer in bytes.
298674fe7b55SCrestez Dan Leonard  *
2987d77e7456SMarek Vasut  * The regmap API usually assumes that bulk read operations will read a
298874fe7b55SCrestez Dan Leonard  * range of registers. Some devices have certain registers for which a read
298974fe7b55SCrestez Dan Leonard  * operation read will read from an internal FIFO.
299074fe7b55SCrestez Dan Leonard  *
299174fe7b55SCrestez Dan Leonard  * The target register must be volatile but registers after it can be
299274fe7b55SCrestez Dan Leonard  * completely unrelated cacheable registers.
299374fe7b55SCrestez Dan Leonard  *
299474fe7b55SCrestez Dan Leonard  * This will attempt multiple reads as required to read val_len bytes.
299574fe7b55SCrestez Dan Leonard  *
299674fe7b55SCrestez Dan Leonard  * A value of zero will be returned on success, a negative errno will be
299774fe7b55SCrestez Dan Leonard  * returned in error cases.
299874fe7b55SCrestez Dan Leonard  */
regmap_noinc_read(struct regmap * map,unsigned int reg,void * val,size_t val_len)299974fe7b55SCrestez Dan Leonard int regmap_noinc_read(struct regmap *map, unsigned int reg,
300074fe7b55SCrestez Dan Leonard 		      void *val, size_t val_len)
300174fe7b55SCrestez Dan Leonard {
300274fe7b55SCrestez Dan Leonard 	size_t read_len;
300374fe7b55SCrestez Dan Leonard 	int ret;
300474fe7b55SCrestez Dan Leonard 
3005c42e99a3SJavier Martinez Canillas 	if (!map->read)
3006c42e99a3SJavier Martinez Canillas 		return -ENOTSUPP;
3007c42e99a3SJavier Martinez Canillas 
300874fe7b55SCrestez Dan Leonard 	if (val_len % map->format.val_bytes)
300974fe7b55SCrestez Dan Leonard 		return -EINVAL;
301074fe7b55SCrestez Dan Leonard 	if (!IS_ALIGNED(reg, map->reg_stride))
301174fe7b55SCrestez Dan Leonard 		return -EINVAL;
301274fe7b55SCrestez Dan Leonard 	if (val_len == 0)
301374fe7b55SCrestez Dan Leonard 		return -EINVAL;
301474fe7b55SCrestez Dan Leonard 
301574fe7b55SCrestez Dan Leonard 	map->lock(map->lock_arg);
301674fe7b55SCrestez Dan Leonard 
301774fe7b55SCrestez Dan Leonard 	if (!regmap_volatile(map, reg) || !regmap_readable_noinc(map, reg)) {
301874fe7b55SCrestez Dan Leonard 		ret = -EINVAL;
301974fe7b55SCrestez Dan Leonard 		goto out_unlock;
302074fe7b55SCrestez Dan Leonard 	}
302174fe7b55SCrestez Dan Leonard 
3022c20cc099SLinus Walleij 	/*
3023c20cc099SLinus Walleij 	 * We have not defined the FIFO semantics for cache, as the
3024c20cc099SLinus Walleij 	 * cache is just one value deep. Should we return the last
3025c20cc099SLinus Walleij 	 * written value? Just avoid this by always reading the FIFO
3026c20cc099SLinus Walleij 	 * even when using cache. Cache only will not work.
3027c20cc099SLinus Walleij 	 */
302899e8dd39SCharles Keepax 	if (!map->cache_bypass && map->cache_only) {
3029c20cc099SLinus Walleij 		ret = -EBUSY;
3030c20cc099SLinus Walleij 		goto out_unlock;
3031c20cc099SLinus Walleij 	}
303299e8dd39SCharles Keepax 
303399e8dd39SCharles Keepax 	/* Use the accelerated operation if we can */
303499e8dd39SCharles Keepax 	if (map->bus->reg_noinc_read) {
3035c20cc099SLinus Walleij 		ret = regmap_noinc_readwrite(map, reg, val, val_len, false);
3036c20cc099SLinus Walleij 		goto out_unlock;
3037c20cc099SLinus Walleij 	}
3038c20cc099SLinus Walleij 
303974fe7b55SCrestez Dan Leonard 	while (val_len) {
304074fe7b55SCrestez Dan Leonard 		if (map->max_raw_read && map->max_raw_read < val_len)
304174fe7b55SCrestez Dan Leonard 			read_len = map->max_raw_read;
304274fe7b55SCrestez Dan Leonard 		else
304374fe7b55SCrestez Dan Leonard 			read_len = val_len;
304440033248SDmitry Baryshkov 		ret = _regmap_raw_read(map, reg, val, read_len, true);
304574fe7b55SCrestez Dan Leonard 		if (ret)
304674fe7b55SCrestez Dan Leonard 			goto out_unlock;
304774fe7b55SCrestez Dan Leonard 		val = ((u8 *)val) + read_len;
304874fe7b55SCrestez Dan Leonard 		val_len -= read_len;
304974fe7b55SCrestez Dan Leonard 	}
305074fe7b55SCrestez Dan Leonard 
305174fe7b55SCrestez Dan Leonard out_unlock:
305274fe7b55SCrestez Dan Leonard 	map->unlock(map->lock_arg);
305374fe7b55SCrestez Dan Leonard 	return ret;
305474fe7b55SCrestez Dan Leonard }
305574fe7b55SCrestez Dan Leonard EXPORT_SYMBOL_GPL(regmap_noinc_read);
305674fe7b55SCrestez Dan Leonard 
305774fe7b55SCrestez Dan Leonard /**
305874fe7b55SCrestez Dan Leonard  * regmap_field_read(): Read a value to a single register field
305967252287SSrinivas Kandagatla  *
306067252287SSrinivas Kandagatla  * @field: Register field to read from
306167252287SSrinivas Kandagatla  * @val: Pointer to store read value
306267252287SSrinivas Kandagatla  *
306367252287SSrinivas Kandagatla  * A value of zero will be returned on success, a negative errno will
306467252287SSrinivas Kandagatla  * be returned in error cases.
306567252287SSrinivas Kandagatla  */
regmap_field_read(struct regmap_field * field,unsigned int * val)306667252287SSrinivas Kandagatla int regmap_field_read(struct regmap_field *field, unsigned int *val)
306767252287SSrinivas Kandagatla {
306867252287SSrinivas Kandagatla 	int ret;
306967252287SSrinivas Kandagatla 	unsigned int reg_val;
307067252287SSrinivas Kandagatla 	ret = regmap_read(field->regmap, field->reg, &reg_val);
307167252287SSrinivas Kandagatla 	if (ret != 0)
307267252287SSrinivas Kandagatla 		return ret;
307367252287SSrinivas Kandagatla 
307467252287SSrinivas Kandagatla 	reg_val &= field->mask;
307567252287SSrinivas Kandagatla 	reg_val >>= field->shift;
307667252287SSrinivas Kandagatla 	*val = reg_val;
307767252287SSrinivas Kandagatla 
307867252287SSrinivas Kandagatla 	return ret;
307967252287SSrinivas Kandagatla }
308067252287SSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_field_read);
308167252287SSrinivas Kandagatla 
308267252287SSrinivas Kandagatla /**
30832cf8e2dfSCharles Keepax  * regmap_fields_read() - Read a value to a single register field with port ID
3084a0102375SKuninori Morimoto  *
3085a0102375SKuninori Morimoto  * @field: Register field to read from
3086a0102375SKuninori Morimoto  * @id: port ID
3087a0102375SKuninori Morimoto  * @val: Pointer to store read value
3088a0102375SKuninori Morimoto  *
3089a0102375SKuninori Morimoto  * A value of zero will be returned on success, a negative errno will
3090a0102375SKuninori Morimoto  * be returned in error cases.
3091a0102375SKuninori Morimoto  */
regmap_fields_read(struct regmap_field * field,unsigned int id,unsigned int * val)3092a0102375SKuninori Morimoto int regmap_fields_read(struct regmap_field *field, unsigned int id,
3093a0102375SKuninori Morimoto 		       unsigned int *val)
3094a0102375SKuninori Morimoto {
3095a0102375SKuninori Morimoto 	int ret;
3096a0102375SKuninori Morimoto 	unsigned int reg_val;
3097a0102375SKuninori Morimoto 
3098a0102375SKuninori Morimoto 	if (id >= field->id_size)
3099a0102375SKuninori Morimoto 		return -EINVAL;
3100a0102375SKuninori Morimoto 
3101a0102375SKuninori Morimoto 	ret = regmap_read(field->regmap,
3102a0102375SKuninori Morimoto 			  field->reg + (field->id_offset * id),
3103a0102375SKuninori Morimoto 			  &reg_val);
3104a0102375SKuninori Morimoto 	if (ret != 0)
3105a0102375SKuninori Morimoto 		return ret;
3106a0102375SKuninori Morimoto 
3107a0102375SKuninori Morimoto 	reg_val &= field->mask;
3108a0102375SKuninori Morimoto 	reg_val >>= field->shift;
3109a0102375SKuninori Morimoto 	*val = reg_val;
3110a0102375SKuninori Morimoto 
3111a0102375SKuninori Morimoto 	return ret;
3112a0102375SKuninori Morimoto }
3113a0102375SKuninori Morimoto EXPORT_SYMBOL_GPL(regmap_fields_read);
3114a0102375SKuninori Morimoto 
3115a0102375SKuninori Morimoto /**
31162cf8e2dfSCharles Keepax  * regmap_bulk_read() - Read multiple registers from the device
3117b83a313bSMark Brown  *
31180093380cSGerhard Sittig  * @map: Register map to read from
3119b83a313bSMark Brown  * @reg: First register to be read from
3120b83a313bSMark Brown  * @val: Pointer to store read value, in native register size for device
3121b83a313bSMark Brown  * @val_count: Number of registers to read
3122b83a313bSMark Brown  *
3123b83a313bSMark Brown  * A value of zero will be returned on success, a negative errno will
3124b83a313bSMark Brown  * be returned in error cases.
3125b83a313bSMark Brown  */
regmap_bulk_read(struct regmap * map,unsigned int reg,void * val,size_t val_count)3126b83a313bSMark Brown int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
3127b83a313bSMark Brown 		     size_t val_count)
3128b83a313bSMark Brown {
3129b83a313bSMark Brown 	int ret, i;
3130b83a313bSMark Brown 	size_t val_bytes = map->format.val_bytes;
313182cd9965SLars-Peter Clausen 	bool vol = regmap_volatile_range(map, reg, val_count);
31325d1729e7SDimitris Papastamos 
3133fcac0233SXiubo Li 	if (!IS_ALIGNED(reg, map->reg_stride))
3134f01ee60fSStephen Warren 		return -EINVAL;
3135186ba2eeSCharles Keepax 	if (val_count == 0)
3136186ba2eeSCharles Keepax 		return -EINVAL;
3137b83a313bSMark Brown 
3138ea50e2a1SJavier Martinez Canillas 	if (map->read && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
31390645ba43SCharles Keepax 		ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
31402e33caf1SAshish Jangam 		if (ret != 0)
31412e33caf1SAshish Jangam 			return ret;
3142b83a313bSMark Brown 
3143b83a313bSMark Brown 		for (i = 0; i < val_count * val_bytes; i += val_bytes)
31448a819ff8SMark Brown 			map->format.parse_inplace(val + i);
3145de2d808fSMark Brown 	} else {
3146d5b98eb1SMark Brown 		u32 *u32 = val;
3147d5b98eb1SMark Brown 		u16 *u16 = val;
3148d5b98eb1SMark Brown 		u8 *u8 = val;
3149d5b98eb1SMark Brown 
3150186ba2eeSCharles Keepax 		map->lock(map->lock_arg);
3151186ba2eeSCharles Keepax 
31529ae27a8dSCharles Keepax 		for (i = 0; i < val_count; i++) {
31539ae27a8dSCharles Keepax 			unsigned int ival;
31549ae27a8dSCharles Keepax 
3155186ba2eeSCharles Keepax 			ret = _regmap_read(map, reg + regmap_get_offset(map, i),
31569ae27a8dSCharles Keepax 					   &ival);
31579ae27a8dSCharles Keepax 			if (ret != 0)
3158186ba2eeSCharles Keepax 				goto out;
31599ae27a8dSCharles Keepax 
3160d5b98eb1SMark Brown 			switch (map->format.val_bytes) {
3161d5b98eb1SMark Brown 			case 4:
3162d5b98eb1SMark Brown 				u32[i] = ival;
3163d5b98eb1SMark Brown 				break;
3164d5b98eb1SMark Brown 			case 2:
3165d5b98eb1SMark Brown 				u16[i] = ival;
3166d5b98eb1SMark Brown 				break;
3167d5b98eb1SMark Brown 			case 1:
3168d5b98eb1SMark Brown 				u8[i] = ival;
3169d5b98eb1SMark Brown 				break;
3170d5b98eb1SMark Brown 			default:
3171186ba2eeSCharles Keepax 				ret = -EINVAL;
3172186ba2eeSCharles Keepax 				goto out;
3173de2d808fSMark Brown 			}
3174de2d808fSMark Brown 		}
3175b83a313bSMark Brown 
3176186ba2eeSCharles Keepax out:
3177186ba2eeSCharles Keepax 		map->unlock(map->lock_arg);
3178186ba2eeSCharles Keepax 	}
3179186ba2eeSCharles Keepax 
3180026c99b5SDmitry Rokosov 	if (!ret)
3181026c99b5SDmitry Rokosov 		trace_regmap_bulk_read(map, reg, val, val_bytes * val_count);
3182026c99b5SDmitry Rokosov 
3183186ba2eeSCharles Keepax 	return ret;
3184b83a313bSMark Brown }
3185b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_bulk_read);
3186b83a313bSMark Brown 
_regmap_update_bits(struct regmap * map,unsigned int reg,unsigned int mask,unsigned int val,bool * change,bool force_write)3187018690d3SMark Brown static int _regmap_update_bits(struct regmap *map, unsigned int reg,
3188018690d3SMark Brown 			       unsigned int mask, unsigned int val,
31897ff0589cSKuninori Morimoto 			       bool *change, bool force_write)
3190b83a313bSMark Brown {
3191b83a313bSMark Brown 	int ret;
3192d91e8db2SMark Brown 	unsigned int tmp, orig;
3193b83a313bSMark Brown 
319477792b11SJon Ringle 	if (change)
319577792b11SJon Ringle 		*change = false;
319677792b11SJon Ringle 
319777792b11SJon Ringle 	if (regmap_volatile(map, reg) && map->reg_update_bits) {
31983f58f6dcSMaxime Chevallier 		reg = regmap_reg_addr(map, reg);
319977792b11SJon Ringle 		ret = map->reg_update_bits(map->bus_context, reg, mask, val);
320077792b11SJon Ringle 		if (ret == 0 && change)
320177792b11SJon Ringle 			*change = true;
320277792b11SJon Ringle 	} else {
3203d91e8db2SMark Brown 		ret = _regmap_read(map, reg, &orig);
3204b83a313bSMark Brown 		if (ret != 0)
3205fc3ebd78SKrystian Garbaciak 			return ret;
3206b83a313bSMark Brown 
3207d91e8db2SMark Brown 		tmp = orig & ~mask;
3208b83a313bSMark Brown 		tmp |= val & mask;
3209b83a313bSMark Brown 
3210b629c698SWaqar Hameed 		if (force_write || (tmp != orig) || map->force_write_field) {
3211b83a313bSMark Brown 			ret = _regmap_write(map, reg, tmp);
321277792b11SJon Ringle 			if (ret == 0 && change)
3213018690d3SMark Brown 				*change = true;
321477792b11SJon Ringle 		}
3215018690d3SMark Brown 	}
3216b83a313bSMark Brown 
3217b83a313bSMark Brown 	return ret;
3218b83a313bSMark Brown }
3219018690d3SMark Brown 
3220018690d3SMark Brown /**
32212cf8e2dfSCharles Keepax  * regmap_update_bits_base() - Perform a read/modify/write cycle on a register
3222018690d3SMark Brown  *
3223018690d3SMark Brown  * @map: Register map to update
3224018690d3SMark Brown  * @reg: Register to update
3225018690d3SMark Brown  * @mask: Bitmask to change
3226018690d3SMark Brown  * @val: New value for bitmask
322791d31b9fSKuninori Morimoto  * @change: Boolean indicating if a write was done
322891d31b9fSKuninori Morimoto  * @async: Boolean indicating asynchronously
322991d31b9fSKuninori Morimoto  * @force: Boolean indicating use force update
3230018690d3SMark Brown  *
32312cf8e2dfSCharles Keepax  * Perform a read/modify/write cycle on a register map with change, async, force
32322cf8e2dfSCharles Keepax  * options.
32332cf8e2dfSCharles Keepax  *
32342cf8e2dfSCharles Keepax  * If async is true:
32352cf8e2dfSCharles Keepax  *
32362cf8e2dfSCharles Keepax  * With most buses the read must be done synchronously so this is most useful
32372cf8e2dfSCharles Keepax  * for devices with a cache which do not need to interact with the hardware to
32382cf8e2dfSCharles Keepax  * determine the current register value.
3239915f441bSMark Brown  *
3240915f441bSMark Brown  * Returns zero for success, a negative number on error.
3241915f441bSMark Brown  */
regmap_update_bits_base(struct regmap * map,unsigned int reg,unsigned int mask,unsigned int val,bool * change,bool async,bool force)324291d31b9fSKuninori Morimoto int regmap_update_bits_base(struct regmap *map, unsigned int reg,
324391d31b9fSKuninori Morimoto 			    unsigned int mask, unsigned int val,
324491d31b9fSKuninori Morimoto 			    bool *change, bool async, bool force)
3245915f441bSMark Brown {
3246915f441bSMark Brown 	int ret;
3247915f441bSMark Brown 
3248915f441bSMark Brown 	map->lock(map->lock_arg);
3249915f441bSMark Brown 
325091d31b9fSKuninori Morimoto 	map->async = async;
3251915f441bSMark Brown 
325291d31b9fSKuninori Morimoto 	ret = _regmap_update_bits(map, reg, mask, val, change, force);
3253915f441bSMark Brown 
3254915f441bSMark Brown 	map->async = false;
3255915f441bSMark Brown 
3256915f441bSMark Brown 	map->unlock(map->lock_arg);
3257915f441bSMark Brown 
3258915f441bSMark Brown 	return ret;
3259915f441bSMark Brown }
326091d31b9fSKuninori Morimoto EXPORT_SYMBOL_GPL(regmap_update_bits_base);
3261915f441bSMark Brown 
3262aa2ff9dbSBartosz Golaszewski /**
3263aa2ff9dbSBartosz Golaszewski  * regmap_test_bits() - Check if all specified bits are set in a register.
3264aa2ff9dbSBartosz Golaszewski  *
3265aa2ff9dbSBartosz Golaszewski  * @map: Register map to operate on
3266aa2ff9dbSBartosz Golaszewski  * @reg: Register to read from
3267aa2ff9dbSBartosz Golaszewski  * @bits: Bits to test
3268aa2ff9dbSBartosz Golaszewski  *
3269e680a409SBartosz Golaszewski  * Returns 0 if at least one of the tested bits is not set, 1 if all tested
3270e680a409SBartosz Golaszewski  * bits are set and a negative error number if the underlying regmap_read()
3271e680a409SBartosz Golaszewski  * fails.
3272aa2ff9dbSBartosz Golaszewski  */
regmap_test_bits(struct regmap * map,unsigned int reg,unsigned int bits)3273aa2ff9dbSBartosz Golaszewski int regmap_test_bits(struct regmap *map, unsigned int reg, unsigned int bits)
3274aa2ff9dbSBartosz Golaszewski {
3275aa2ff9dbSBartosz Golaszewski 	unsigned int val, ret;
3276aa2ff9dbSBartosz Golaszewski 
3277aa2ff9dbSBartosz Golaszewski 	ret = regmap_read(map, reg, &val);
3278aa2ff9dbSBartosz Golaszewski 	if (ret)
3279aa2ff9dbSBartosz Golaszewski 		return ret;
3280aa2ff9dbSBartosz Golaszewski 
3281aa2ff9dbSBartosz Golaszewski 	return (val & bits) == bits;
3282aa2ff9dbSBartosz Golaszewski }
3283aa2ff9dbSBartosz Golaszewski EXPORT_SYMBOL_GPL(regmap_test_bits);
3284aa2ff9dbSBartosz Golaszewski 
regmap_async_complete_cb(struct regmap_async * async,int ret)32850d509f2bSMark Brown void regmap_async_complete_cb(struct regmap_async *async, int ret)
32860d509f2bSMark Brown {
32870d509f2bSMark Brown 	struct regmap *map = async->map;
32880d509f2bSMark Brown 	bool wake;
32890d509f2bSMark Brown 
3290c6b570d9SPhilipp Zabel 	trace_regmap_async_io_complete(map);
3291fe7d4ccdSMark Brown 
32920d509f2bSMark Brown 	spin_lock(&map->async_lock);
32937e09a979SMark Brown 	list_move(&async->list, &map->async_free);
32940d509f2bSMark Brown 	wake = list_empty(&map->async_list);
32950d509f2bSMark Brown 
32960d509f2bSMark Brown 	if (ret != 0)
32970d509f2bSMark Brown 		map->async_ret = ret;
32980d509f2bSMark Brown 
32990d509f2bSMark Brown 	spin_unlock(&map->async_lock);
33000d509f2bSMark Brown 
33010d509f2bSMark Brown 	if (wake)
33020d509f2bSMark Brown 		wake_up(&map->async_waitq);
33030d509f2bSMark Brown }
3304f804fb56SAxel Lin EXPORT_SYMBOL_GPL(regmap_async_complete_cb);
33050d509f2bSMark Brown 
regmap_async_is_done(struct regmap * map)33060d509f2bSMark Brown static int regmap_async_is_done(struct regmap *map)
33070d509f2bSMark Brown {
33080d509f2bSMark Brown 	unsigned long flags;
33090d509f2bSMark Brown 	int ret;
33100d509f2bSMark Brown 
33110d509f2bSMark Brown 	spin_lock_irqsave(&map->async_lock, flags);
33120d509f2bSMark Brown 	ret = list_empty(&map->async_list);
33130d509f2bSMark Brown 	spin_unlock_irqrestore(&map->async_lock, flags);
33140d509f2bSMark Brown 
33150d509f2bSMark Brown 	return ret;
33160d509f2bSMark Brown }
33170d509f2bSMark Brown 
33180d509f2bSMark Brown /**
33192cf8e2dfSCharles Keepax  * regmap_async_complete - Ensure all asynchronous I/O has completed.
33200d509f2bSMark Brown  *
33210d509f2bSMark Brown  * @map: Map to operate on.
33220d509f2bSMark Brown  *
33230d509f2bSMark Brown  * Blocks until any pending asynchronous I/O has completed.  Returns
33240d509f2bSMark Brown  * an error code for any failed I/O operations.
33250d509f2bSMark Brown  */
regmap_async_complete(struct regmap * map)33260d509f2bSMark Brown int regmap_async_complete(struct regmap *map)
33270d509f2bSMark Brown {
33280d509f2bSMark Brown 	unsigned long flags;
33290d509f2bSMark Brown 	int ret;
33300d509f2bSMark Brown 
33310d509f2bSMark Brown 	/* Nothing to do with no async support */
3332f2e055e7SDaniel Mack 	if (!map->bus || !map->bus->async_write)
33330d509f2bSMark Brown 		return 0;
33340d509f2bSMark Brown 
3335c6b570d9SPhilipp Zabel 	trace_regmap_async_complete_start(map);
3336fe7d4ccdSMark Brown 
33370d509f2bSMark Brown 	wait_event(map->async_waitq, regmap_async_is_done(map));
33380d509f2bSMark Brown 
33390d509f2bSMark Brown 	spin_lock_irqsave(&map->async_lock, flags);
33400d509f2bSMark Brown 	ret = map->async_ret;
33410d509f2bSMark Brown 	map->async_ret = 0;
33420d509f2bSMark Brown 	spin_unlock_irqrestore(&map->async_lock, flags);
33430d509f2bSMark Brown 
3344c6b570d9SPhilipp Zabel 	trace_regmap_async_complete_done(map);
3345fe7d4ccdSMark Brown 
33460d509f2bSMark Brown 	return ret;
33470d509f2bSMark Brown }
3348f88948efSMark Brown EXPORT_SYMBOL_GPL(regmap_async_complete);
33490d509f2bSMark Brown 
335022f0d90aSMark Brown /**
33512cf8e2dfSCharles Keepax  * regmap_register_patch - Register and apply register updates to be applied
335222f0d90aSMark Brown  *                         on device initialistion
335322f0d90aSMark Brown  *
335422f0d90aSMark Brown  * @map: Register map to apply updates to.
335522f0d90aSMark Brown  * @regs: Values to update.
335622f0d90aSMark Brown  * @num_regs: Number of entries in regs.
335722f0d90aSMark Brown  *
335822f0d90aSMark Brown  * Register a set of register updates to be applied to the device
335922f0d90aSMark Brown  * whenever the device registers are synchronised with the cache and
336022f0d90aSMark Brown  * apply them immediately.  Typically this is used to apply
336122f0d90aSMark Brown  * corrections to be applied to the device defaults on startup, such
336222f0d90aSMark Brown  * as the updates some vendors provide to undocumented registers.
336356fb1c74SMark Brown  *
336456fb1c74SMark Brown  * The caller must ensure that this function cannot be called
336556fb1c74SMark Brown  * concurrently with either itself or regcache_sync().
336622f0d90aSMark Brown  */
regmap_register_patch(struct regmap * map,const struct reg_sequence * regs,int num_regs)33678019ff6cSNariman Poushin int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs,
336822f0d90aSMark Brown 			  int num_regs)
336922f0d90aSMark Brown {
33708019ff6cSNariman Poushin 	struct reg_sequence *p;
33716bf13103SCharles Keepax 	int ret;
337222f0d90aSMark Brown 	bool bypass;
337322f0d90aSMark Brown 
3374bd60e381SCai Zhiyong 	if (WARN_ONCE(num_regs <= 0, "invalid registers number (%d)\n",
3375bd60e381SCai Zhiyong 	    num_regs))
3376bd60e381SCai Zhiyong 		return 0;
3377bd60e381SCai Zhiyong 
3378aab13ebcSMark Brown 	p = krealloc(map->patch,
33798019ff6cSNariman Poushin 		     sizeof(struct reg_sequence) * (map->patch_regs + num_regs),
3380aab13ebcSMark Brown 		     GFP_KERNEL);
3381aab13ebcSMark Brown 	if (p) {
3382aab13ebcSMark Brown 		memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs));
3383aab13ebcSMark Brown 		map->patch = p;
3384aab13ebcSMark Brown 		map->patch_regs += num_regs;
338522f0d90aSMark Brown 	} else {
338656fb1c74SMark Brown 		return -ENOMEM;
338722f0d90aSMark Brown 	}
338822f0d90aSMark Brown 
338922f0d90aSMark Brown 	map->lock(map->lock_arg);
339022f0d90aSMark Brown 
339122f0d90aSMark Brown 	bypass = map->cache_bypass;
339222f0d90aSMark Brown 
339322f0d90aSMark Brown 	map->cache_bypass = true;
339422f0d90aSMark Brown 	map->async = true;
339522f0d90aSMark Brown 
33966bf13103SCharles Keepax 	ret = _regmap_multi_reg_write(map, regs, num_regs);
339722f0d90aSMark Brown 
33981a25f261SMark Brown 	map->async = false;
339922f0d90aSMark Brown 	map->cache_bypass = bypass;
340022f0d90aSMark Brown 
34010d4529c5SDavide Ciminaghi 	map->unlock(map->lock_arg);
340222f0d90aSMark Brown 
34031a25f261SMark Brown 	regmap_async_complete(map);
34041a25f261SMark Brown 
340522f0d90aSMark Brown 	return ret;
340622f0d90aSMark Brown }
340722f0d90aSMark Brown EXPORT_SYMBOL_GPL(regmap_register_patch);
340822f0d90aSMark Brown 
34092cf8e2dfSCharles Keepax /**
34102cf8e2dfSCharles Keepax  * regmap_get_val_bytes() - Report the size of a register value
34112cf8e2dfSCharles Keepax  *
34122cf8e2dfSCharles Keepax  * @map: Register map to operate on.
3413a6539c32SMark Brown  *
3414a6539c32SMark Brown  * Report the size of a register value, mainly intended to for use by
3415a6539c32SMark Brown  * generic infrastructure built on top of regmap.
3416a6539c32SMark Brown  */
regmap_get_val_bytes(struct regmap * map)3417a6539c32SMark Brown int regmap_get_val_bytes(struct regmap *map)
3418a6539c32SMark Brown {
3419a6539c32SMark Brown 	if (map->format.format_write)
3420a6539c32SMark Brown 		return -EINVAL;
3421a6539c32SMark Brown 
3422a6539c32SMark Brown 	return map->format.val_bytes;
3423a6539c32SMark Brown }
3424a6539c32SMark Brown EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
3425a6539c32SMark Brown 
3426668abc72SSrinivas Kandagatla /**
34272cf8e2dfSCharles Keepax  * regmap_get_max_register() - Report the max register value
34282cf8e2dfSCharles Keepax  *
34292cf8e2dfSCharles Keepax  * @map: Register map to operate on.
3430668abc72SSrinivas Kandagatla  *
3431668abc72SSrinivas Kandagatla  * Report the max register value, mainly intended to for use by
3432668abc72SSrinivas Kandagatla  * generic infrastructure built on top of regmap.
3433668abc72SSrinivas Kandagatla  */
regmap_get_max_register(struct regmap * map)3434668abc72SSrinivas Kandagatla int regmap_get_max_register(struct regmap *map)
3435668abc72SSrinivas Kandagatla {
3436668abc72SSrinivas Kandagatla 	return map->max_register ? map->max_register : -EINVAL;
3437668abc72SSrinivas Kandagatla }
3438668abc72SSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_get_max_register);
3439668abc72SSrinivas Kandagatla 
3440a2f776cbSSrinivas Kandagatla /**
34412cf8e2dfSCharles Keepax  * regmap_get_reg_stride() - Report the register address stride
34422cf8e2dfSCharles Keepax  *
34432cf8e2dfSCharles Keepax  * @map: Register map to operate on.
3444a2f776cbSSrinivas Kandagatla  *
3445a2f776cbSSrinivas Kandagatla  * Report the register address stride, mainly intended to for use by
3446a2f776cbSSrinivas Kandagatla  * generic infrastructure built on top of regmap.
3447a2f776cbSSrinivas Kandagatla  */
regmap_get_reg_stride(struct regmap * map)3448a2f776cbSSrinivas Kandagatla int regmap_get_reg_stride(struct regmap *map)
3449a2f776cbSSrinivas Kandagatla {
3450a2f776cbSSrinivas Kandagatla 	return map->reg_stride;
3451a2f776cbSSrinivas Kandagatla }
3452a2f776cbSSrinivas Kandagatla EXPORT_SYMBOL_GPL(regmap_get_reg_stride);
3453a2f776cbSSrinivas Kandagatla 
3454a6d99022SMichael Walle /**
3455a6d99022SMichael Walle  * regmap_might_sleep() - Returns whether a regmap access might sleep.
3456a6d99022SMichael Walle  *
3457a6d99022SMichael Walle  * @map: Register map to operate on.
3458a6d99022SMichael Walle  *
3459a6d99022SMichael Walle  * Returns true if an access to the register might sleep, else false.
3460a6d99022SMichael Walle  */
regmap_might_sleep(struct regmap * map)3461a6d99022SMichael Walle bool regmap_might_sleep(struct regmap *map)
3462a6d99022SMichael Walle {
3463a6d99022SMichael Walle 	return map->can_sleep;
3464a6d99022SMichael Walle }
3465a6d99022SMichael Walle EXPORT_SYMBOL_GPL(regmap_might_sleep);
3466a6d99022SMichael Walle 
regmap_parse_val(struct regmap * map,const void * buf,unsigned int * val)346713ff50c8SNenghua Cao int regmap_parse_val(struct regmap *map, const void *buf,
346813ff50c8SNenghua Cao 			unsigned int *val)
346913ff50c8SNenghua Cao {
347013ff50c8SNenghua Cao 	if (!map->format.parse_val)
347113ff50c8SNenghua Cao 		return -EINVAL;
347213ff50c8SNenghua Cao 
347313ff50c8SNenghua Cao 	*val = map->format.parse_val(buf);
347413ff50c8SNenghua Cao 
347513ff50c8SNenghua Cao 	return 0;
347613ff50c8SNenghua Cao }
347713ff50c8SNenghua Cao EXPORT_SYMBOL_GPL(regmap_parse_val);
347813ff50c8SNenghua Cao 
regmap_initcall(void)347931244e39SMark Brown static int __init regmap_initcall(void)
348031244e39SMark Brown {
348131244e39SMark Brown 	regmap_debugfs_initcall();
348231244e39SMark Brown 
348331244e39SMark Brown 	return 0;
348431244e39SMark Brown }
348531244e39SMark Brown postcore_initcall(regmap_initcall);
3486