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