aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-03 14:31:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-03 14:31:04 -0400
commitde6b25de4584febbe1808bc782734ae163b22c26 (patch)
treea9aa0d0009494eed9a496a1093dfdc49617385d0 /drivers/base
parentbd698cf6595b079ce36423e8c7eb4a69a31b1733 (diff)
parentef98ae45e6b3ea17d3ed27cec9afdd7e46f916ae (diff)
Merge tag 'regmap-v3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap into next
Pull regmap updates from Mark Brown: "Another fairly quiet release, a few bug fixes and a couple of new features: - support for I2C devices connected to SMBus rather than full I2C controllers contributed by Boris Brezillon. If the controller is only capable of SMBus operation the framework will transparently fall back to that - suport for little endian values, contributed by Xiubo Li" * tag 'regmap-v3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: mmio: Fix regmap_mmio_write for uneven counts regmap: irq: Fix possible ZERO_SIZE_PTR pointer dereferencing error. regmap: Add missing initialization of this_page regmap: Fix possible ZERO_SIZE_PTR pointer dereferencing error. regmap: i2c: fallback to SMBus if the adapter does not support standard I2C regmap: add reg_read/reg_write callbacks to regmap_bus struct regmap: rbtree: improve 64bits memory alignment regmap: mmio: Fix the bug of 'offset' value parsing. regmap: implement LE formatting/parsing for 16/32-bit values.
Diffstat (limited to 'drivers/base')
-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
5 files changed, 221 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{