aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/regmap/regcache-rbtree.c8
-rw-r--r--drivers/base/regmap/regmap-i2c.c104
-rw-r--r--drivers/base/regmap/regmap-irq.c9
-rw-r--r--drivers/base/regmap/regmap-mmio.c35
-rw-r--r--drivers/base/regmap/regmap.c83
-rw-r--r--include/linux/regmap.h6
6 files changed, 227 insertions, 18 deletions
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 930cad4e5df8..6a7e4fa12854 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -23,16 +23,16 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
23static int regcache_rbtree_exit(struct regmap *map); 23static int regcache_rbtree_exit(struct regmap *map);
24 24
25struct regcache_rbtree_node { 25struct regcache_rbtree_node {
26 /* the actual rbtree node holding this block */
27 struct rb_node node;
28 /* base register handled by this block */
29 unsigned int base_reg;
30 /* block of adjacent registers */ 26 /* block of adjacent registers */
31 void *block; 27 void *block;
32 /* Which registers are present */ 28 /* Which registers are present */
33 long *cache_present; 29 long *cache_present;
30 /* base register handled by this block */
31 unsigned int base_reg;
34 /* number of registers available in the block */ 32 /* number of registers available in the block */
35 unsigned int blklen; 33 unsigned int blklen;
34 /* the actual rbtree node holding this block */
35 struct rb_node node;
36} __attribute__ ((packed)); 36} __attribute__ ((packed));
37 37
38struct regcache_rbtree_ctx { 38struct regcache_rbtree_ctx {
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index ebd189529760..ca193d1ef47c 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -14,6 +14,79 @@
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/module.h> 15#include <linux/module.h>
16 16
17
18static int regmap_smbus_byte_reg_read(void *context, unsigned int reg,
19 unsigned int *val)
20{
21 struct device *dev = context;
22 struct i2c_client *i2c = to_i2c_client(dev);
23 int ret;
24
25 if (reg > 0xff)
26 return -EINVAL;
27
28 ret = i2c_smbus_read_byte_data(i2c, reg);
29 if (ret < 0)
30 return ret;
31
32 *val = ret;
33
34 return 0;
35}
36
37static int regmap_smbus_byte_reg_write(void *context, unsigned int reg,
38 unsigned int val)
39{
40 struct device *dev = context;
41 struct i2c_client *i2c = to_i2c_client(dev);
42
43 if (val > 0xff || reg > 0xff)
44 return -EINVAL;
45
46 return i2c_smbus_write_byte_data(i2c, reg, val);
47}
48
49static struct regmap_bus regmap_smbus_byte = {
50 .reg_write = regmap_smbus_byte_reg_write,
51 .reg_read = regmap_smbus_byte_reg_read,
52};
53
54static int regmap_smbus_word_reg_read(void *context, unsigned int reg,
55 unsigned int *val)
56{
57 struct device *dev = context;
58 struct i2c_client *i2c = to_i2c_client(dev);
59 int ret;
60
61 if (reg > 0xff)
62 return -EINVAL;
63
64 ret = i2c_smbus_read_word_data(i2c, reg);
65 if (ret < 0)
66 return ret;
67
68 *val = ret;
69
70 return 0;
71}
72
73static int regmap_smbus_word_reg_write(void *context, unsigned int reg,
74 unsigned int val)
75{
76 struct device *dev = context;
77 struct i2c_client *i2c = to_i2c_client(dev);
78
79 if (val > 0xffff || reg > 0xff)
80 return -EINVAL;
81
82 return i2c_smbus_write_word_data(i2c, reg, val);
83}
84
85static struct regmap_bus regmap_smbus_word = {
86 .reg_write = regmap_smbus_word_reg_write,
87 .reg_read = regmap_smbus_word_reg_read,
88};
89
17static int regmap_i2c_write(void *context, const void *data, size_t count) 90static int regmap_i2c_write(void *context, const void *data, size_t count)
18{ 91{
19 struct device *dev = context; 92 struct device *dev = context;
@@ -97,6 +170,23 @@ static struct regmap_bus regmap_i2c = {
97 .read = regmap_i2c_read, 170 .read = regmap_i2c_read,
98}; 171};
99 172
173static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
174 const struct regmap_config *config)
175{
176 if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C))
177 return &regmap_i2c;
178 else if (config->val_bits == 16 && config->reg_bits == 8 &&
179 i2c_check_functionality(i2c->adapter,
180 I2C_FUNC_SMBUS_WORD_DATA))
181 return &regmap_smbus_word;
182 else if (config->val_bits == 8 && config->reg_bits == 8 &&
183 i2c_check_functionality(i2c->adapter,
184 I2C_FUNC_SMBUS_BYTE_DATA))
185 return &regmap_smbus_byte;
186
187 return ERR_PTR(-ENOTSUPP);
188}
189
100/** 190/**
101 * regmap_init_i2c(): Initialise register map 191 * regmap_init_i2c(): Initialise register map
102 * 192 *
@@ -109,7 +199,12 @@ static struct regmap_bus regmap_i2c = {
109struct regmap *regmap_init_i2c(struct i2c_client *i2c, 199struct regmap *regmap_init_i2c(struct i2c_client *i2c,
110 const struct regmap_config *config) 200 const struct regmap_config *config)
111{ 201{
112 return regmap_init(&i2c->dev, &regmap_i2c, &i2c->dev, config); 202 const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
203
204 if (IS_ERR(bus))
205 return ERR_CAST(bus);
206
207 return regmap_init(&i2c->dev, bus, &i2c->dev, config);
113} 208}
114EXPORT_SYMBOL_GPL(regmap_init_i2c); 209EXPORT_SYMBOL_GPL(regmap_init_i2c);
115 210
@@ -126,7 +221,12 @@ EXPORT_SYMBOL_GPL(regmap_init_i2c);
126struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, 221struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
127 const struct regmap_config *config) 222 const struct regmap_config *config)
128{ 223{
129 return devm_regmap_init(&i2c->dev, &regmap_i2c, &i2c->dev, config); 224 const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
225
226 if (IS_ERR(bus))
227 return ERR_CAST(bus);
228
229 return devm_regmap_init(&i2c->dev, bus, &i2c->dev, config);
130} 230}
131EXPORT_SYMBOL_GPL(devm_regmap_init_i2c); 231EXPORT_SYMBOL_GPL(devm_regmap_init_i2c);
132 232
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index edf88f20cbce..6299a50a5960 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -10,13 +10,13 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/export.h>
14#include <linux/device.h> 13#include <linux/device.h>
15#include <linux/regmap.h> 14#include <linux/export.h>
16#include <linux/irq.h>
17#include <linux/interrupt.h> 15#include <linux/interrupt.h>
16#include <linux/irq.h>
18#include <linux/irqdomain.h> 17#include <linux/irqdomain.h>
19#include <linux/pm_runtime.h> 18#include <linux/pm_runtime.h>
19#include <linux/regmap.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21 21
22#include "internal.h" 22#include "internal.h"
@@ -347,6 +347,9 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
347 int ret = -ENOMEM; 347 int ret = -ENOMEM;
348 u32 reg; 348 u32 reg;
349 349
350 if (chip->num_regs <= 0)
351 return -EINVAL;
352
350 for (i = 0; i < chip->num_irqs; i++) { 353 for (i = 0; i < chip->num_irqs; i++) {
351 if (chip->irqs[i].reg_offset % map->reg_stride) 354 if (chip->irqs[i].reg_offset % map->reg_stride)
352 return -EINVAL; 355 return -EINVAL;
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 1e03e7f8bacb..04a329a377e9 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -61,9 +61,28 @@ static int regmap_mmio_regbits_check(size_t reg_bits)
61 } 61 }
62} 62}
63 63
64static inline void regmap_mmio_count_check(size_t count) 64static inline void regmap_mmio_count_check(size_t count, u32 offset)
65{ 65{
66 BUG_ON(count % 2 != 0); 66 BUG_ON(count <= offset);
67}
68
69static inline unsigned int
70regmap_mmio_get_offset(const void *reg, size_t reg_size)
71{
72 switch (reg_size) {
73 case 1:
74 return *(u8 *)reg;
75 case 2:
76 return *(u16 *)reg;
77 case 4:
78 return *(u32 *)reg;
79#ifdef CONFIG_64BIT
80 case 8:
81 return *(u64 *)reg;
82#endif
83 default:
84 BUG();
85 }
67} 86}
68 87
69static int regmap_mmio_gather_write(void *context, 88static int regmap_mmio_gather_write(void *context,
@@ -71,7 +90,7 @@ static int regmap_mmio_gather_write(void *context,
71 const void *val, size_t val_size) 90 const void *val, size_t val_size)
72{ 91{
73 struct regmap_mmio_context *ctx = context; 92 struct regmap_mmio_context *ctx = context;
74 u32 offset; 93 unsigned int offset;
75 int ret; 94 int ret;
76 95
77 regmap_mmio_regsize_check(reg_size); 96 regmap_mmio_regsize_check(reg_size);
@@ -82,7 +101,7 @@ static int regmap_mmio_gather_write(void *context,
82 return ret; 101 return ret;
83 } 102 }
84 103
85 offset = *(u32 *)reg; 104 offset = regmap_mmio_get_offset(reg, reg_size);
86 105
87 while (val_size) { 106 while (val_size) {
88 switch (ctx->val_bytes) { 107 switch (ctx->val_bytes) {
@@ -118,9 +137,9 @@ static int regmap_mmio_gather_write(void *context,
118static int regmap_mmio_write(void *context, const void *data, size_t count) 137static int regmap_mmio_write(void *context, const void *data, size_t count)
119{ 138{
120 struct regmap_mmio_context *ctx = context; 139 struct regmap_mmio_context *ctx = context;
121 u32 offset = ctx->reg_bytes + ctx->pad_bytes; 140 unsigned int offset = ctx->reg_bytes + ctx->pad_bytes;
122 141
123 regmap_mmio_count_check(count); 142 regmap_mmio_count_check(count, offset);
124 143
125 return regmap_mmio_gather_write(context, data, ctx->reg_bytes, 144 return regmap_mmio_gather_write(context, data, ctx->reg_bytes,
126 data + offset, count - offset); 145 data + offset, count - offset);
@@ -131,7 +150,7 @@ static int regmap_mmio_read(void *context,
131 void *val, size_t val_size) 150 void *val, size_t val_size)
132{ 151{
133 struct regmap_mmio_context *ctx = context; 152 struct regmap_mmio_context *ctx = context;
134 u32 offset; 153 unsigned int offset;
135 int ret; 154 int ret;
136 155
137 regmap_mmio_regsize_check(reg_size); 156 regmap_mmio_regsize_check(reg_size);
@@ -142,7 +161,7 @@ static int regmap_mmio_read(void *context,
142 return ret; 161 return ret;
143 } 162 }
144 163
145 offset = *(u32 *)reg; 164 offset = regmap_mmio_get_offset(reg, reg_size);
146 165
147 while (val_size) { 166 while (val_size) {
148 switch (ctx->val_bytes) { 167 switch (ctx->val_bytes) {
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 63e30ef096e2..74d8c0672cf6 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -35,10 +35,14 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
35 unsigned int mask, unsigned int val, 35 unsigned int mask, unsigned int val,
36 bool *change); 36 bool *change);
37 37
38static int _regmap_bus_reg_read(void *context, unsigned int reg,
39 unsigned int *val);
38static int _regmap_bus_read(void *context, unsigned int reg, 40static int _regmap_bus_read(void *context, unsigned int reg,
39 unsigned int *val); 41 unsigned int *val);
40static int _regmap_bus_formatted_write(void *context, unsigned int reg, 42static int _regmap_bus_formatted_write(void *context, unsigned int reg,
41 unsigned int val); 43 unsigned int val);
44static int _regmap_bus_reg_write(void *context, unsigned int reg,
45 unsigned int val);
42static int _regmap_bus_raw_write(void *context, unsigned int reg, 46static int _regmap_bus_raw_write(void *context, unsigned int reg,
43 unsigned int val); 47 unsigned int val);
44 48
@@ -192,6 +196,13 @@ static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift)
192 b[0] = cpu_to_be16(val << shift); 196 b[0] = cpu_to_be16(val << shift);
193} 197}
194 198
199static void regmap_format_16_le(void *buf, unsigned int val, unsigned int shift)
200{
201 __le16 *b = buf;
202
203 b[0] = cpu_to_le16(val << shift);
204}
205
195static void regmap_format_16_native(void *buf, unsigned int val, 206static void regmap_format_16_native(void *buf, unsigned int val,
196 unsigned int shift) 207 unsigned int shift)
197{ 208{
@@ -216,6 +227,13 @@ static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift)
216 b[0] = cpu_to_be32(val << shift); 227 b[0] = cpu_to_be32(val << shift);
217} 228}
218 229
230static void regmap_format_32_le(void *buf, unsigned int val, unsigned int shift)
231{
232 __le32 *b = buf;
233
234 b[0] = cpu_to_le32(val << shift);
235}
236
219static void regmap_format_32_native(void *buf, unsigned int val, 237static void regmap_format_32_native(void *buf, unsigned int val,
220 unsigned int shift) 238 unsigned int shift)
221{ 239{
@@ -240,6 +258,13 @@ static unsigned int regmap_parse_16_be(const void *buf)
240 return be16_to_cpu(b[0]); 258 return be16_to_cpu(b[0]);
241} 259}
242 260
261static unsigned int regmap_parse_16_le(const void *buf)
262{
263 const __le16 *b = buf;
264
265 return le16_to_cpu(b[0]);
266}
267
243static void regmap_parse_16_be_inplace(void *buf) 268static void regmap_parse_16_be_inplace(void *buf)
244{ 269{
245 __be16 *b = buf; 270 __be16 *b = buf;
@@ -247,6 +272,13 @@ static void regmap_parse_16_be_inplace(void *buf)
247 b[0] = be16_to_cpu(b[0]); 272 b[0] = be16_to_cpu(b[0]);
248} 273}
249 274
275static void regmap_parse_16_le_inplace(void *buf)
276{
277 __le16 *b = buf;
278
279 b[0] = le16_to_cpu(b[0]);
280}
281
250static unsigned int regmap_parse_16_native(const void *buf) 282static unsigned int regmap_parse_16_native(const void *buf)
251{ 283{
252 return *(u16 *)buf; 284 return *(u16 *)buf;
@@ -269,6 +301,13 @@ static unsigned int regmap_parse_32_be(const void *buf)
269 return be32_to_cpu(b[0]); 301 return be32_to_cpu(b[0]);
270} 302}
271 303
304static unsigned int regmap_parse_32_le(const void *buf)
305{
306 const __le32 *b = buf;
307
308 return le32_to_cpu(b[0]);
309}
310
272static void regmap_parse_32_be_inplace(void *buf) 311static void regmap_parse_32_be_inplace(void *buf)
273{ 312{
274 __be32 *b = buf; 313 __be32 *b = buf;
@@ -276,6 +315,13 @@ static void regmap_parse_32_be_inplace(void *buf)
276 b[0] = be32_to_cpu(b[0]); 315 b[0] = be32_to_cpu(b[0]);
277} 316}
278 317
318static void regmap_parse_32_le_inplace(void *buf)
319{
320 __le32 *b = buf;
321
322 b[0] = le32_to_cpu(b[0]);
323}
324
279static unsigned int regmap_parse_32_native(const void *buf) 325static unsigned int regmap_parse_32_native(const void *buf)
280{ 326{
281 return *(u32 *)buf; 327 return *(u32 *)buf;
@@ -495,6 +541,12 @@ struct regmap *regmap_init(struct device *dev,
495 541
496 map->defer_caching = false; 542 map->defer_caching = false;
497 goto skip_format_initialization; 543 goto skip_format_initialization;
544 } else if (!bus->read || !bus->write) {
545 map->reg_read = _regmap_bus_reg_read;
546 map->reg_write = _regmap_bus_reg_write;
547
548 map->defer_caching = false;
549 goto skip_format_initialization;
498 } else { 550 } else {
499 map->reg_read = _regmap_bus_read; 551 map->reg_read = _regmap_bus_read;
500 } 552 }
@@ -608,6 +660,11 @@ struct regmap *regmap_init(struct device *dev,
608 map->format.parse_val = regmap_parse_16_be; 660 map->format.parse_val = regmap_parse_16_be;
609 map->format.parse_inplace = regmap_parse_16_be_inplace; 661 map->format.parse_inplace = regmap_parse_16_be_inplace;
610 break; 662 break;
663 case REGMAP_ENDIAN_LITTLE:
664 map->format.format_val = regmap_format_16_le;
665 map->format.parse_val = regmap_parse_16_le;
666 map->format.parse_inplace = regmap_parse_16_le_inplace;
667 break;
611 case REGMAP_ENDIAN_NATIVE: 668 case REGMAP_ENDIAN_NATIVE:
612 map->format.format_val = regmap_format_16_native; 669 map->format.format_val = regmap_format_16_native;
613 map->format.parse_val = regmap_parse_16_native; 670 map->format.parse_val = regmap_parse_16_native;
@@ -629,6 +686,11 @@ struct regmap *regmap_init(struct device *dev,
629 map->format.parse_val = regmap_parse_32_be; 686 map->format.parse_val = regmap_parse_32_be;
630 map->format.parse_inplace = regmap_parse_32_be_inplace; 687 map->format.parse_inplace = regmap_parse_32_be_inplace;
631 break; 688 break;
689 case REGMAP_ENDIAN_LITTLE:
690 map->format.format_val = regmap_format_32_le;
691 map->format.parse_val = regmap_parse_32_le;
692 map->format.parse_inplace = regmap_parse_32_le_inplace;
693 break;
632 case REGMAP_ENDIAN_NATIVE: 694 case REGMAP_ENDIAN_NATIVE:
633 map->format.format_val = regmap_format_32_native; 695 map->format.format_val = regmap_format_32_native;
634 map->format.parse_val = regmap_parse_32_native; 696 map->format.parse_val = regmap_parse_32_native;
@@ -1284,6 +1346,14 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
1284 return ret; 1346 return ret;
1285} 1347}
1286 1348
1349static int _regmap_bus_reg_write(void *context, unsigned int reg,
1350 unsigned int val)
1351{
1352 struct regmap *map = context;
1353
1354 return map->bus->reg_write(map->bus_context, reg, val);
1355}
1356
1287static int _regmap_bus_raw_write(void *context, unsigned int reg, 1357static int _regmap_bus_raw_write(void *context, unsigned int reg,
1288 unsigned int val) 1358 unsigned int val)
1289{ 1359{
@@ -1615,6 +1685,9 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
1615 size_t pair_size = reg_bytes + pad_bytes + val_bytes; 1685 size_t pair_size = reg_bytes + pad_bytes + val_bytes;
1616 size_t len = pair_size * num_regs; 1686 size_t len = pair_size * num_regs;
1617 1687
1688 if (!len)
1689 return -EINVAL;
1690
1618 buf = kzalloc(len, GFP_KERNEL); 1691 buf = kzalloc(len, GFP_KERNEL);
1619 if (!buf) 1692 if (!buf)
1620 return -ENOMEM; 1693 return -ENOMEM;
@@ -1662,7 +1735,7 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map,
1662 int ret; 1735 int ret;
1663 int i, n; 1736 int i, n;
1664 struct reg_default *base; 1737 struct reg_default *base;
1665 unsigned int this_page; 1738 unsigned int this_page = 0;
1666 /* 1739 /*
1667 * the set of registers are not neccessarily in order, but 1740 * the set of registers are not neccessarily in order, but
1668 * since the order of write must be preserved this algorithm 1741 * since the order of write must be preserved this algorithm
@@ -1925,6 +1998,14 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
1925 return ret; 1998 return ret;
1926} 1999}
1927 2000
2001static int _regmap_bus_reg_read(void *context, unsigned int reg,
2002 unsigned int *val)
2003{
2004 struct regmap *map = context;
2005
2006 return map->bus->reg_read(map->bus_context, reg, val);
2007}
2008
1928static int _regmap_bus_read(void *context, unsigned int reg, 2009static int _regmap_bus_read(void *context, unsigned int reg,
1929 unsigned int *val) 2010 unsigned int *val)
1930{ 2011{
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 85691b9b4fa7..7b0e4b425cdf 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -276,6 +276,10 @@ typedef int (*regmap_hw_async_write)(void *context,
276typedef int (*regmap_hw_read)(void *context, 276typedef int (*regmap_hw_read)(void *context,
277 const void *reg_buf, size_t reg_size, 277 const void *reg_buf, size_t reg_size,
278 void *val_buf, size_t val_size); 278 void *val_buf, size_t val_size);
279typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg,
280 unsigned int *val);
281typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg,
282 unsigned int val);
279typedef struct regmap_async *(*regmap_hw_async_alloc)(void); 283typedef struct regmap_async *(*regmap_hw_async_alloc)(void);
280typedef void (*regmap_hw_free_context)(void *context); 284typedef void (*regmap_hw_free_context)(void *context);
281 285
@@ -309,7 +313,9 @@ struct regmap_bus {
309 regmap_hw_write write; 313 regmap_hw_write write;
310 regmap_hw_gather_write gather_write; 314 regmap_hw_gather_write gather_write;
311 regmap_hw_async_write async_write; 315 regmap_hw_async_write async_write;
316 regmap_hw_reg_write reg_write;
312 regmap_hw_read read; 317 regmap_hw_read read;
318 regmap_hw_reg_read reg_read;
313 regmap_hw_free_context free_context; 319 regmap_hw_free_context free_context;
314 regmap_hw_async_alloc async_alloc; 320 regmap_hw_async_alloc async_alloc;
315 u8 read_flag_mask; 321 u8 read_flag_mask;