summaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2012-04-09 15:40:24 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-10 06:01:18 -0400
commitf01ee60fffa4dc6c77122121233a793f7f696e67 (patch)
tree5072955487b9e4c80f5c6f6454358d80e8f23a48 /drivers/base/regmap
parentc0cc6fe1d09e3f1baecbdf8922473c8e7d3a5317 (diff)
regmap: implement register striding
regmap_config.reg_stride is introduced. All extant register addresses are a multiple of this value. Users of serial-oriented regmap busses will typically set this to 1. Users of the MMIO regmap bus will typically set this based on the value size of their registers, in bytes, so 4 for a 32-bit register. Throughout the regmap code, actual register addresses are used. Wherever the register address is used to index some array of values, the address is divided by the stride to determine the index, or vice-versa. Error- checking is added to all entry-points for register address data to ensure that register addresses actually satisfy the specified stride. The MMIO bus ensures that the specified stride is large enough for the register size. Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/internal.h1
-rw-r--r--drivers/base/regmap/regcache-lzo.c11
-rw-r--r--drivers/base/regmap/regcache-rbtree.c40
-rw-r--r--drivers/base/regmap/regcache.c14
-rw-r--r--drivers/base/regmap/regmap-debugfs.c4
-rw-r--r--drivers/base/regmap/regmap-irq.c34
-rw-r--r--drivers/base/regmap/regmap-mmio.c13
-rw-r--r--drivers/base/regmap/regmap.c30
8 files changed, 105 insertions, 42 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 99b28fffbd0e..d92e9b1cb83c 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -62,6 +62,7 @@ struct regmap {
62 62
63 /* number of bits to (left) shift the reg value when formatting*/ 63 /* number of bits to (left) shift the reg value when formatting*/
64 int reg_shift; 64 int reg_shift;
65 int reg_stride;
65 66
66 /* regcache specific members */ 67 /* regcache specific members */
67 const struct regcache_ops *cache_ops; 68 const struct regcache_ops *cache_ops;
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c
index 483b06d4a380..afd6aa91a0df 100644
--- a/drivers/base/regmap/regcache-lzo.c
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -108,7 +108,7 @@ static int regcache_lzo_decompress_cache_block(struct regmap *map,
108static inline int regcache_lzo_get_blkindex(struct regmap *map, 108static inline int regcache_lzo_get_blkindex(struct regmap *map,
109 unsigned int reg) 109 unsigned int reg)
110{ 110{
111 return (reg * map->cache_word_size) / 111 return ((reg / map->reg_stride) * map->cache_word_size) /
112 DIV_ROUND_UP(map->cache_size_raw, 112 DIV_ROUND_UP(map->cache_size_raw,
113 regcache_lzo_block_count(map)); 113 regcache_lzo_block_count(map));
114} 114}
@@ -116,9 +116,10 @@ static inline int regcache_lzo_get_blkindex(struct regmap *map,
116static inline int regcache_lzo_get_blkpos(struct regmap *map, 116static inline int regcache_lzo_get_blkpos(struct regmap *map,
117 unsigned int reg) 117 unsigned int reg)
118{ 118{
119 return reg % (DIV_ROUND_UP(map->cache_size_raw, 119 return (reg / map->reg_stride) %
120 regcache_lzo_block_count(map)) / 120 (DIV_ROUND_UP(map->cache_size_raw,
121 map->cache_word_size); 121 regcache_lzo_block_count(map)) /
122 map->cache_word_size);
122} 123}
123 124
124static inline int regcache_lzo_get_blksize(struct regmap *map) 125static inline int regcache_lzo_get_blksize(struct regmap *map)
@@ -322,7 +323,7 @@ static int regcache_lzo_write(struct regmap *map,
322 } 323 }
323 324
324 /* set the bit so we know we have to sync this register */ 325 /* set the bit so we know we have to sync this register */
325 set_bit(reg, lzo_block->sync_bmp); 326 set_bit(reg / map->reg_stride, lzo_block->sync_bmp);
326 kfree(tmp_dst); 327 kfree(tmp_dst);
327 kfree(lzo_block->src); 328 kfree(lzo_block->src);
328 return 0; 329 return 0;
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index e49e71fab184..e6732cf7c06e 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -39,11 +39,12 @@ struct regcache_rbtree_ctx {
39}; 39};
40 40
41static inline void regcache_rbtree_get_base_top_reg( 41static inline void regcache_rbtree_get_base_top_reg(
42 struct regmap *map,
42 struct regcache_rbtree_node *rbnode, 43 struct regcache_rbtree_node *rbnode,
43 unsigned int *base, unsigned int *top) 44 unsigned int *base, unsigned int *top)
44{ 45{
45 *base = rbnode->base_reg; 46 *base = rbnode->base_reg;
46 *top = rbnode->base_reg + rbnode->blklen - 1; 47 *top = rbnode->base_reg + ((rbnode->blklen - 1) * map->reg_stride);
47} 48}
48 49
49static unsigned int regcache_rbtree_get_register( 50static unsigned int regcache_rbtree_get_register(
@@ -70,7 +71,8 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
70 71
71 rbnode = rbtree_ctx->cached_rbnode; 72 rbnode = rbtree_ctx->cached_rbnode;
72 if (rbnode) { 73 if (rbnode) {
73 regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg); 74 regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
75 &top_reg);
74 if (reg >= base_reg && reg <= top_reg) 76 if (reg >= base_reg && reg <= top_reg)
75 return rbnode; 77 return rbnode;
76 } 78 }
@@ -78,7 +80,8 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
78 node = rbtree_ctx->root.rb_node; 80 node = rbtree_ctx->root.rb_node;
79 while (node) { 81 while (node) {
80 rbnode = container_of(node, struct regcache_rbtree_node, node); 82 rbnode = container_of(node, struct regcache_rbtree_node, node);
81 regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg); 83 regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
84 &top_reg);
82 if (reg >= base_reg && reg <= top_reg) { 85 if (reg >= base_reg && reg <= top_reg) {
83 rbtree_ctx->cached_rbnode = rbnode; 86 rbtree_ctx->cached_rbnode = rbnode;
84 return rbnode; 87 return rbnode;
@@ -92,7 +95,7 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
92 return NULL; 95 return NULL;
93} 96}
94 97
95static int regcache_rbtree_insert(struct rb_root *root, 98static int regcache_rbtree_insert(struct regmap *map, struct rb_root *root,
96 struct regcache_rbtree_node *rbnode) 99 struct regcache_rbtree_node *rbnode)
97{ 100{
98 struct rb_node **new, *parent; 101 struct rb_node **new, *parent;
@@ -106,7 +109,7 @@ static int regcache_rbtree_insert(struct rb_root *root,
106 rbnode_tmp = container_of(*new, struct regcache_rbtree_node, 109 rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
107 node); 110 node);
108 /* base and top registers of the current rbnode */ 111 /* base and top registers of the current rbnode */
109 regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp, 112 regcache_rbtree_get_base_top_reg(map, rbnode_tmp, &base_reg_tmp,
110 &top_reg_tmp); 113 &top_reg_tmp);
111 /* base register of the rbnode to be added */ 114 /* base register of the rbnode to be added */
112 base_reg = rbnode->base_reg; 115 base_reg = rbnode->base_reg;
@@ -138,7 +141,7 @@ static int rbtree_show(struct seq_file *s, void *ignored)
138 unsigned int base, top; 141 unsigned int base, top;
139 int nodes = 0; 142 int nodes = 0;
140 int registers = 0; 143 int registers = 0;
141 int average; 144 int this_registers, average;
142 145
143 map->lock(map); 146 map->lock(map);
144 147
@@ -146,11 +149,12 @@ static int rbtree_show(struct seq_file *s, void *ignored)
146 node = rb_next(node)) { 149 node = rb_next(node)) {
147 n = container_of(node, struct regcache_rbtree_node, node); 150 n = container_of(node, struct regcache_rbtree_node, node);
148 151
149 regcache_rbtree_get_base_top_reg(n, &base, &top); 152 regcache_rbtree_get_base_top_reg(map, n, &base, &top);
150 seq_printf(s, "%x-%x (%d)\n", base, top, top - base + 1); 153 this_registers = ((top - base) / map->reg_stride) + 1;
154 seq_printf(s, "%x-%x (%d)\n", base, top, this_registers);
151 155
152 nodes++; 156 nodes++;
153 registers += top - base + 1; 157 registers += this_registers;
154 } 158 }
155 159
156 if (nodes) 160 if (nodes)
@@ -255,7 +259,7 @@ static int regcache_rbtree_read(struct regmap *map,
255 259
256 rbnode = regcache_rbtree_lookup(map, reg); 260 rbnode = regcache_rbtree_lookup(map, reg);
257 if (rbnode) { 261 if (rbnode) {
258 reg_tmp = reg - rbnode->base_reg; 262 reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
259 *value = regcache_rbtree_get_register(rbnode, reg_tmp, 263 *value = regcache_rbtree_get_register(rbnode, reg_tmp,
260 map->cache_word_size); 264 map->cache_word_size);
261 } else { 265 } else {
@@ -310,7 +314,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
310 */ 314 */
311 rbnode = regcache_rbtree_lookup(map, reg); 315 rbnode = regcache_rbtree_lookup(map, reg);
312 if (rbnode) { 316 if (rbnode) {
313 reg_tmp = reg - rbnode->base_reg; 317 reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
314 val = regcache_rbtree_get_register(rbnode, reg_tmp, 318 val = regcache_rbtree_get_register(rbnode, reg_tmp,
315 map->cache_word_size); 319 map->cache_word_size);
316 if (val == value) 320 if (val == value)
@@ -321,13 +325,15 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
321 /* look for an adjacent register to the one we are about to add */ 325 /* look for an adjacent register to the one we are about to add */
322 for (node = rb_first(&rbtree_ctx->root); node; 326 for (node = rb_first(&rbtree_ctx->root); node;
323 node = rb_next(node)) { 327 node = rb_next(node)) {
324 rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node); 328 rbnode_tmp = rb_entry(node, struct regcache_rbtree_node,
329 node);
325 for (i = 0; i < rbnode_tmp->blklen; i++) { 330 for (i = 0; i < rbnode_tmp->blklen; i++) {
326 reg_tmp = rbnode_tmp->base_reg + i; 331 reg_tmp = rbnode_tmp->base_reg +
327 if (abs(reg_tmp - reg) != 1) 332 (i * map->reg_stride);
333 if (abs(reg_tmp - reg) != map->reg_stride)
328 continue; 334 continue;
329 /* decide where in the block to place our register */ 335 /* decide where in the block to place our register */
330 if (reg_tmp + 1 == reg) 336 if (reg_tmp + map->reg_stride == reg)
331 pos = i + 1; 337 pos = i + 1;
332 else 338 else
333 pos = i; 339 pos = i;
@@ -357,7 +363,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
357 return -ENOMEM; 363 return -ENOMEM;
358 } 364 }
359 regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size); 365 regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
360 regcache_rbtree_insert(&rbtree_ctx->root, rbnode); 366 regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
361 rbtree_ctx->cached_rbnode = rbnode; 367 rbtree_ctx->cached_rbnode = rbnode;
362 } 368 }
363 369
@@ -397,7 +403,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
397 end = rbnode->blklen; 403 end = rbnode->blklen;
398 404
399 for (i = base; i < end; i++) { 405 for (i = base; i < end; i++) {
400 regtmp = rbnode->base_reg + i; 406 regtmp = rbnode->base_reg + (i * map->reg_stride);
401 val = regcache_rbtree_get_register(rbnode, i, 407 val = regcache_rbtree_get_register(rbnode, i,
402 map->cache_word_size); 408 map->cache_word_size);
403 409
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index d4368e8b6f9d..835883bda977 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -59,7 +59,7 @@ static int regcache_hw_init(struct regmap *map)
59 for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) { 59 for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
60 val = regcache_get_val(map->reg_defaults_raw, 60 val = regcache_get_val(map->reg_defaults_raw,
61 i, map->cache_word_size); 61 i, map->cache_word_size);
62 if (regmap_volatile(map, i)) 62 if (regmap_volatile(map, i * map->reg_stride))
63 continue; 63 continue;
64 count++; 64 count++;
65 } 65 }
@@ -76,9 +76,9 @@ static int regcache_hw_init(struct regmap *map)
76 for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { 76 for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
77 val = regcache_get_val(map->reg_defaults_raw, 77 val = regcache_get_val(map->reg_defaults_raw,
78 i, map->cache_word_size); 78 i, map->cache_word_size);
79 if (regmap_volatile(map, i)) 79 if (regmap_volatile(map, i * map->reg_stride))
80 continue; 80 continue;
81 map->reg_defaults[j].reg = i; 81 map->reg_defaults[j].reg = i * map->reg_stride;
82 map->reg_defaults[j].def = val; 82 map->reg_defaults[j].def = val;
83 j++; 83 j++;
84 } 84 }
@@ -98,6 +98,10 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
98 int i; 98 int i;
99 void *tmp_buf; 99 void *tmp_buf;
100 100
101 for (i = 0; i < config->num_reg_defaults; i++)
102 if (config->reg_defaults[i].reg % map->reg_stride)
103 return -EINVAL;
104
101 if (map->cache_type == REGCACHE_NONE) { 105 if (map->cache_type == REGCACHE_NONE) {
102 map->cache_bypass = true; 106 map->cache_bypass = true;
103 return 0; 107 return 0;
@@ -278,6 +282,10 @@ int regcache_sync(struct regmap *map)
278 /* Apply any patch first */ 282 /* Apply any patch first */
279 map->cache_bypass = 1; 283 map->cache_bypass = 1;
280 for (i = 0; i < map->patch_regs; i++) { 284 for (i = 0; i < map->patch_regs; i++) {
285 if (map->patch[i].reg % map->reg_stride) {
286 ret = -EINVAL;
287 goto out;
288 }
281 ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def); 289 ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
282 if (ret != 0) { 290 if (ret != 0) {
283 dev_err(map->dev, "Failed to write %x = %x: %d\n", 291 dev_err(map->dev, "Failed to write %x = %x: %d\n",
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index df97c93efa8e..bb1ff175b962 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -80,7 +80,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
80 val_len = 2 * map->format.val_bytes; 80 val_len = 2 * map->format.val_bytes;
81 tot_len = reg_len + val_len + 3; /* : \n */ 81 tot_len = reg_len + val_len + 3; /* : \n */
82 82
83 for (i = 0; i < map->max_register + 1; i++) { 83 for (i = 0; i <= map->max_register; i += map->reg_stride) {
84 if (!regmap_readable(map, i)) 84 if (!regmap_readable(map, i))
85 continue; 85 continue;
86 86
@@ -197,7 +197,7 @@ static ssize_t regmap_access_read_file(struct file *file,
197 reg_len = regmap_calc_reg_len(map->max_register, buf, count); 197 reg_len = regmap_calc_reg_len(map->max_register, buf, count);
198 tot_len = reg_len + 10; /* ': R W V P\n' */ 198 tot_len = reg_len + 10; /* ': R W V P\n' */
199 199
200 for (i = 0; i < map->max_register + 1; i++) { 200 for (i = 0; i <= map->max_register; i += map->reg_stride) {
201 /* Ignore registers which are neither readable nor writable */ 201 /* Ignore registers which are neither readable nor writable */
202 if (!regmap_readable(map, i) && !regmap_writeable(map, i)) 202 if (!regmap_readable(map, i) && !regmap_writeable(map, i))
203 continue; 203 continue;
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 1befaa7a31cb..56b8136eb36a 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -58,11 +58,12 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
58 * suppress pointless writes. 58 * suppress pointless writes.
59 */ 59 */
60 for (i = 0; i < d->chip->num_regs; i++) { 60 for (i = 0; i < d->chip->num_regs; i++) {
61 ret = regmap_update_bits(d->map, d->chip->mask_base + i, 61 ret = regmap_update_bits(d->map, d->chip->mask_base +
62 (i * map->map->reg_stride),
62 d->mask_buf_def[i], d->mask_buf[i]); 63 d->mask_buf_def[i], d->mask_buf[i]);
63 if (ret != 0) 64 if (ret != 0)
64 dev_err(d->map->dev, "Failed to sync masks in %x\n", 65 dev_err(d->map->dev, "Failed to sync masks in %x\n",
65 d->chip->mask_base + i); 66 d->chip->mask_base + (i * map->reg_stride));
66 } 67 }
67 68
68 mutex_unlock(&d->lock); 69 mutex_unlock(&d->lock);
@@ -73,7 +74,7 @@ static void regmap_irq_enable(struct irq_data *data)
73 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); 74 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
74 const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq); 75 const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq);
75 76
76 d->mask_buf[irq_data->reg_offset] &= ~irq_data->mask; 77 d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~irq_data->mask;
77} 78}
78 79
79static void regmap_irq_disable(struct irq_data *data) 80static void regmap_irq_disable(struct irq_data *data)
@@ -81,7 +82,7 @@ static void regmap_irq_disable(struct irq_data *data)
81 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); 82 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
82 const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq); 83 const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq);
83 84
84 d->mask_buf[irq_data->reg_offset] |= irq_data->mask; 85 d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
85} 86}
86 87
87static struct irq_chip regmap_irq_chip = { 88static struct irq_chip regmap_irq_chip = {
@@ -136,17 +137,19 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
136 data->status_buf[i] &= ~data->mask_buf[i]; 137 data->status_buf[i] &= ~data->mask_buf[i];
137 138
138 if (data->status_buf[i] && chip->ack_base) { 139 if (data->status_buf[i] && chip->ack_base) {
139 ret = regmap_write(map, chip->ack_base + i, 140 ret = regmap_write(map, chip->ack_base +
141 (i * map->reg_stride),
140 data->status_buf[i]); 142 data->status_buf[i]);
141 if (ret != 0) 143 if (ret != 0)
142 dev_err(map->dev, "Failed to ack 0x%x: %d\n", 144 dev_err(map->dev, "Failed to ack 0x%x: %d\n",
143 chip->ack_base + i, ret); 145 chip->ack_base + (i * map->reg_stride),
146 ret);
144 } 147 }
145 } 148 }
146 149
147 for (i = 0; i < chip->num_irqs; i++) { 150 for (i = 0; i < chip->num_irqs; i++) {
148 if (data->status_buf[chip->irqs[i].reg_offset] & 151 if (data->status_buf[chip->irqs[i].reg_offset /
149 chip->irqs[i].mask) { 152 map->reg_stride] & chip->irqs[i].mask) {
150 handle_nested_irq(data->irq_base + i); 153 handle_nested_irq(data->irq_base + i);
151 handled = true; 154 handled = true;
152 } 155 }
@@ -181,6 +184,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
181 int cur_irq, i; 184 int cur_irq, i;
182 int ret = -ENOMEM; 185 int ret = -ENOMEM;
183 186
187 for (i = 0; i < chip->num_irqs; i++) {
188 if (chip->irqs[i].reg_offset % map->reg_stride)
189 return -EINVAL;
190 if (chip->irqs[i].reg_offset / map->reg_stride >=
191 chip->num_regs)
192 return -EINVAL;
193 }
194
184 irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0); 195 irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0);
185 if (irq_base < 0) { 196 if (irq_base < 0) {
186 dev_warn(map->dev, "Failed to allocate IRQs: %d\n", 197 dev_warn(map->dev, "Failed to allocate IRQs: %d\n",
@@ -218,16 +229,17 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
218 mutex_init(&d->lock); 229 mutex_init(&d->lock);
219 230
220 for (i = 0; i < chip->num_irqs; i++) 231 for (i = 0; i < chip->num_irqs; i++)
221 d->mask_buf_def[chip->irqs[i].reg_offset] 232 d->mask_buf_def[chip->irqs[i].reg_offset / map->reg_stride]
222 |= chip->irqs[i].mask; 233 |= chip->irqs[i].mask;
223 234
224 /* Mask all the interrupts by default */ 235 /* Mask all the interrupts by default */
225 for (i = 0; i < chip->num_regs; i++) { 236 for (i = 0; i < chip->num_regs; i++) {
226 d->mask_buf[i] = d->mask_buf_def[i]; 237 d->mask_buf[i] = d->mask_buf_def[i];
227 ret = regmap_write(map, chip->mask_base + i, d->mask_buf[i]); 238 ret = regmap_write(map, chip->mask_base + (i * map->reg_stride),
239 d->mask_buf[i]);
228 if (ret != 0) { 240 if (ret != 0) {
229 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", 241 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
230 chip->mask_base + i, ret); 242 chip->mask_base + (i * map->reg_stride), ret);
231 goto err_alloc; 243 goto err_alloc;
232 } 244 }
233 } 245 }
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index bdf4dc865293..febd6de6c8ac 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -130,6 +130,7 @@ struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
130 const struct regmap_config *config) 130 const struct regmap_config *config)
131{ 131{
132 struct regmap_mmio_context *ctx; 132 struct regmap_mmio_context *ctx;
133 int min_stride;
133 134
134 if (config->reg_bits != 32) 135 if (config->reg_bits != 32)
135 return ERR_PTR(-EINVAL); 136 return ERR_PTR(-EINVAL);
@@ -139,16 +140,28 @@ struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
139 140
140 switch (config->val_bits) { 141 switch (config->val_bits) {
141 case 8: 142 case 8:
143 /* The core treats 0 as 1 */
144 min_stride = 0;
145 break;
142 case 16: 146 case 16:
147 min_stride = 2;
148 break;
143 case 32: 149 case 32:
150 min_stride = 4;
151 break;
144#ifdef CONFIG_64BIT 152#ifdef CONFIG_64BIT
145 case 64: 153 case 64:
154 min_stride = 8;
155 break;
146#endif 156#endif
147 break; 157 break;
148 default: 158 default:
149 return ERR_PTR(-EINVAL); 159 return ERR_PTR(-EINVAL);
150 } 160 }
151 161
162 if (config->reg_stride < min_stride)
163 return ERR_PTR(-EINVAL);
164
152 ctx = kzalloc(GFP_KERNEL, sizeof(*ctx)); 165 ctx = kzalloc(GFP_KERNEL, sizeof(*ctx));
153 if (!ctx) 166 if (!ctx)
154 return ERR_PTR(-ENOMEM); 167 return ERR_PTR(-ENOMEM);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 40f910162781..8a25006b2a4d 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -243,6 +243,10 @@ struct regmap *regmap_init(struct device *dev,
243 map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); 243 map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
244 map->format.buf_size += map->format.pad_bytes; 244 map->format.buf_size += map->format.pad_bytes;
245 map->reg_shift = config->pad_bits % 8; 245 map->reg_shift = config->pad_bits % 8;
246 if (config->reg_stride)
247 map->reg_stride = config->reg_stride;
248 else
249 map->reg_stride = 1;
246 map->dev = dev; 250 map->dev = dev;
247 map->bus = bus; 251 map->bus = bus;
248 map->bus_context = bus_context; 252 map->bus_context = bus_context;
@@ -469,7 +473,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
469 /* Check for unwritable registers before we start */ 473 /* Check for unwritable registers before we start */
470 if (map->writeable_reg) 474 if (map->writeable_reg)
471 for (i = 0; i < val_len / map->format.val_bytes; i++) 475 for (i = 0; i < val_len / map->format.val_bytes; i++)
472 if (!map->writeable_reg(map->dev, reg + i)) 476 if (!map->writeable_reg(map->dev,
477 reg + (i * map->reg_stride)))
473 return -EINVAL; 478 return -EINVAL;
474 479
475 if (!map->cache_bypass && map->format.parse_val) { 480 if (!map->cache_bypass && map->format.parse_val) {
@@ -478,7 +483,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
478 for (i = 0; i < val_len / val_bytes; i++) { 483 for (i = 0; i < val_len / val_bytes; i++) {
479 memcpy(map->work_buf, val + (i * val_bytes), val_bytes); 484 memcpy(map->work_buf, val + (i * val_bytes), val_bytes);
480 ival = map->format.parse_val(map->work_buf); 485 ival = map->format.parse_val(map->work_buf);
481 ret = regcache_write(map, reg + i, ival); 486 ret = regcache_write(map, reg + (i * map->reg_stride),
487 ival);
482 if (ret) { 488 if (ret) {
483 dev_err(map->dev, 489 dev_err(map->dev,
484 "Error in caching of register: %u ret: %d\n", 490 "Error in caching of register: %u ret: %d\n",
@@ -590,6 +596,9 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
590{ 596{
591 int ret; 597 int ret;
592 598
599 if (reg % map->reg_stride)
600 return -EINVAL;
601
593 map->lock(map); 602 map->lock(map);
594 603
595 ret = _regmap_write(map, reg, val); 604 ret = _regmap_write(map, reg, val);
@@ -623,6 +632,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
623 632
624 if (val_len % map->format.val_bytes) 633 if (val_len % map->format.val_bytes)
625 return -EINVAL; 634 return -EINVAL;
635 if (reg % map->reg_stride)
636 return -EINVAL;
626 637
627 map->lock(map); 638 map->lock(map);
628 639
@@ -657,6 +668,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
657 668
658 if (!map->format.parse_val) 669 if (!map->format.parse_val)
659 return -EINVAL; 670 return -EINVAL;
671 if (reg % map->reg_stride)
672 return -EINVAL;
660 673
661 map->lock(map); 674 map->lock(map);
662 675
@@ -753,6 +766,9 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
753{ 766{
754 int ret; 767 int ret;
755 768
769 if (reg % map->reg_stride)
770 return -EINVAL;
771
756 map->lock(map); 772 map->lock(map);
757 773
758 ret = _regmap_read(map, reg, val); 774 ret = _regmap_read(map, reg, val);
@@ -784,6 +800,8 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
784 800
785 if (val_len % map->format.val_bytes) 801 if (val_len % map->format.val_bytes)
786 return -EINVAL; 802 return -EINVAL;
803 if (reg % map->reg_stride)
804 return -EINVAL;
787 805
788 map->lock(map); 806 map->lock(map);
789 807
@@ -797,7 +815,8 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
797 * cost as we expect to hit the cache. 815 * cost as we expect to hit the cache.
798 */ 816 */
799 for (i = 0; i < val_count; i++) { 817 for (i = 0; i < val_count; i++) {
800 ret = _regmap_read(map, reg + i, &v); 818 ret = _regmap_read(map, reg + (i * map->reg_stride),
819 &v);
801 if (ret != 0) 820 if (ret != 0)
802 goto out; 821 goto out;
803 822
@@ -832,6 +851,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
832 851
833 if (!map->format.parse_val) 852 if (!map->format.parse_val)
834 return -EINVAL; 853 return -EINVAL;
854 if (reg % map->reg_stride)
855 return -EINVAL;
835 856
836 if (vol || map->cache_type == REGCACHE_NONE) { 857 if (vol || map->cache_type == REGCACHE_NONE) {
837 ret = regmap_raw_read(map, reg, val, val_bytes * val_count); 858 ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
@@ -842,7 +863,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
842 map->format.parse_val(val + i); 863 map->format.parse_val(val + i);
843 } else { 864 } else {
844 for (i = 0; i < val_count; i++) { 865 for (i = 0; i < val_count; i++) {
845 ret = regmap_read(map, reg + i, val + (i * val_bytes)); 866 ret = regmap_read(map, reg + (i * map->reg_stride),
867 val + (i * val_bytes));
846 if (ret != 0) 868 if (ret != 0)
847 return ret; 869 return ret;
848 } 870 }