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, ®, 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, ®, 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, ®, 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, ®, 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, ®, 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, ®_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 ®_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