Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 305620
b: refs/heads/master
c: edc9ae4
h: refs/heads/master
v: v3
  • Loading branch information
Stephen Warren authored and Mark Brown committed Apr 13, 2012
1 parent 4a0c028 commit 608155c
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 43 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6a8d2511e13fdcabe4ee8460347115a50c32b0a8
refs/heads/master: edc9ae420f98dd094e47f8b2d33652858bdc830b
1 change: 1 addition & 0 deletions trunk/drivers/base/regmap/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct regmap {

/* number of bits to (left) shift the reg value when formatting*/
int reg_shift;
int reg_stride;

/* regcache specific members */
const struct regcache_ops *cache_ops;
Expand Down
11 changes: 6 additions & 5 deletions trunk/drivers/base/regmap/regcache-lzo.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,18 @@ static int regcache_lzo_decompress_cache_block(struct regmap *map,
static inline int regcache_lzo_get_blkindex(struct regmap *map,
unsigned int reg)
{
return (reg * map->cache_word_size) /
return ((reg / map->reg_stride) * map->cache_word_size) /
DIV_ROUND_UP(map->cache_size_raw,
regcache_lzo_block_count(map));
}

static inline int regcache_lzo_get_blkpos(struct regmap *map,
unsigned int reg)
{
return reg % (DIV_ROUND_UP(map->cache_size_raw,
regcache_lzo_block_count(map)) /
map->cache_word_size);
return (reg / map->reg_stride) %
(DIV_ROUND_UP(map->cache_size_raw,
regcache_lzo_block_count(map)) /
map->cache_word_size);
}

static inline int regcache_lzo_get_blksize(struct regmap *map)
Expand Down Expand Up @@ -322,7 +323,7 @@ static int regcache_lzo_write(struct regmap *map,
}

/* set the bit so we know we have to sync this register */
set_bit(reg, lzo_block->sync_bmp);
set_bit(reg / map->reg_stride, lzo_block->sync_bmp);
kfree(tmp_dst);
kfree(lzo_block->src);
return 0;
Expand Down
40 changes: 23 additions & 17 deletions trunk/drivers/base/regmap/regcache-rbtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ struct regcache_rbtree_ctx {
};

static inline void regcache_rbtree_get_base_top_reg(
struct regmap *map,
struct regcache_rbtree_node *rbnode,
unsigned int *base, unsigned int *top)
{
*base = rbnode->base_reg;
*top = rbnode->base_reg + rbnode->blklen - 1;
*top = rbnode->base_reg + ((rbnode->blklen - 1) * map->reg_stride);
}

static unsigned int regcache_rbtree_get_register(
Expand All @@ -70,15 +71,17 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,

rbnode = rbtree_ctx->cached_rbnode;
if (rbnode) {
regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
&top_reg);
if (reg >= base_reg && reg <= top_reg)
return rbnode;
}

node = rbtree_ctx->root.rb_node;
while (node) {
rbnode = container_of(node, struct regcache_rbtree_node, node);
regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
&top_reg);
if (reg >= base_reg && reg <= top_reg) {
rbtree_ctx->cached_rbnode = rbnode;
return rbnode;
Expand All @@ -92,7 +95,7 @@ static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
return NULL;
}

static int regcache_rbtree_insert(struct rb_root *root,
static int regcache_rbtree_insert(struct regmap *map, struct rb_root *root,
struct regcache_rbtree_node *rbnode)
{
struct rb_node **new, *parent;
Expand All @@ -106,7 +109,7 @@ static int regcache_rbtree_insert(struct rb_root *root,
rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
node);
/* base and top registers of the current rbnode */
regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
regcache_rbtree_get_base_top_reg(map, rbnode_tmp, &base_reg_tmp,
&top_reg_tmp);
/* base register of the rbnode to be added */
base_reg = rbnode->base_reg;
Expand Down Expand Up @@ -138,19 +141,20 @@ static int rbtree_show(struct seq_file *s, void *ignored)
unsigned int base, top;
int nodes = 0;
int registers = 0;
int average;
int this_registers, average;

map->lock(map);

for (node = rb_first(&rbtree_ctx->root); node != NULL;
node = rb_next(node)) {
n = container_of(node, struct regcache_rbtree_node, node);

regcache_rbtree_get_base_top_reg(n, &base, &top);
seq_printf(s, "%x-%x (%d)\n", base, top, top - base + 1);
regcache_rbtree_get_base_top_reg(map, n, &base, &top);
this_registers = ((top - base) / map->reg_stride) + 1;
seq_printf(s, "%x-%x (%d)\n", base, top, this_registers);

nodes++;
registers += top - base + 1;
registers += this_registers;
}

if (nodes)
Expand Down Expand Up @@ -255,7 +259,7 @@ static int regcache_rbtree_read(struct regmap *map,

rbnode = regcache_rbtree_lookup(map, reg);
if (rbnode) {
reg_tmp = reg - rbnode->base_reg;
reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
*value = regcache_rbtree_get_register(rbnode, reg_tmp,
map->cache_word_size);
} else {
Expand Down Expand Up @@ -310,7 +314,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
*/
rbnode = regcache_rbtree_lookup(map, reg);
if (rbnode) {
reg_tmp = reg - rbnode->base_reg;
reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
val = regcache_rbtree_get_register(rbnode, reg_tmp,
map->cache_word_size);
if (val == value)
Expand All @@ -321,13 +325,15 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
/* look for an adjacent register to the one we are about to add */
for (node = rb_first(&rbtree_ctx->root); node;
node = rb_next(node)) {
rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node);
rbnode_tmp = rb_entry(node, struct regcache_rbtree_node,
node);
for (i = 0; i < rbnode_tmp->blklen; i++) {
reg_tmp = rbnode_tmp->base_reg + i;
if (abs(reg_tmp - reg) != 1)
reg_tmp = rbnode_tmp->base_reg +
(i * map->reg_stride);
if (abs(reg_tmp - reg) != map->reg_stride)
continue;
/* decide where in the block to place our register */
if (reg_tmp + 1 == reg)
if (reg_tmp + map->reg_stride == reg)
pos = i + 1;
else
pos = i;
Expand Down Expand Up @@ -357,7 +363,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
return -ENOMEM;
}
regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
regcache_rbtree_insert(&rbtree_ctx->root, rbnode);
regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
rbtree_ctx->cached_rbnode = rbnode;
}

Expand Down Expand Up @@ -397,7 +403,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
end = rbnode->blklen;

for (i = base; i < end; i++) {
regtmp = rbnode->base_reg + i;
regtmp = rbnode->base_reg + (i * map->reg_stride);
val = regcache_rbtree_get_register(rbnode, i,
map->cache_word_size);

Expand Down
14 changes: 11 additions & 3 deletions trunk/drivers/base/regmap/regcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static int regcache_hw_init(struct regmap *map)
for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
val = regcache_get_val(map->reg_defaults_raw,
i, map->cache_word_size);
if (regmap_volatile(map, i))
if (regmap_volatile(map, i * map->reg_stride))
continue;
count++;
}
Expand All @@ -76,9 +76,9 @@ static int regcache_hw_init(struct regmap *map)
for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
val = regcache_get_val(map->reg_defaults_raw,
i, map->cache_word_size);
if (regmap_volatile(map, i))
if (regmap_volatile(map, i * map->reg_stride))
continue;
map->reg_defaults[j].reg = i;
map->reg_defaults[j].reg = i * map->reg_stride;
map->reg_defaults[j].def = val;
j++;
}
Expand All @@ -98,6 +98,10 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
int i;
void *tmp_buf;

for (i = 0; i < config->num_reg_defaults; i++)
if (config->reg_defaults[i].reg % map->reg_stride)
return -EINVAL;

if (map->cache_type == REGCACHE_NONE) {
map->cache_bypass = true;
return 0;
Expand Down Expand Up @@ -278,6 +282,10 @@ int regcache_sync(struct regmap *map)
/* Apply any patch first */
map->cache_bypass = 1;
for (i = 0; i < map->patch_regs; i++) {
if (map->patch[i].reg % map->reg_stride) {
ret = -EINVAL;
goto out;
}
ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
if (ret != 0) {
dev_err(map->dev, "Failed to write %x = %x: %d\n",
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/base/regmap/regmap-debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
val_len = 2 * map->format.val_bytes;
tot_len = reg_len + val_len + 3; /* : \n */

for (i = 0; i < map->max_register + 1; i++) {
for (i = 0; i <= map->max_register; i += map->reg_stride) {
if (!regmap_readable(map, i))
continue;

Expand Down Expand Up @@ -197,7 +197,7 @@ static ssize_t regmap_access_read_file(struct file *file,
reg_len = regmap_calc_reg_len(map->max_register, buf, count);
tot_len = reg_len + 10; /* ': R W V P\n' */

for (i = 0; i < map->max_register + 1; i++) {
for (i = 0; i <= map->max_register; i += map->reg_stride) {
/* Ignore registers which are neither readable nor writable */
if (!regmap_readable(map, i) && !regmap_writeable(map, i))
continue;
Expand Down
34 changes: 23 additions & 11 deletions trunk/drivers/base/regmap/regmap-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,12 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
* suppress pointless writes.
*/
for (i = 0; i < d->chip->num_regs; i++) {
ret = regmap_update_bits(d->map, d->chip->mask_base + i,
ret = regmap_update_bits(d->map, d->chip->mask_base +
(i * map->map->reg_stride),
d->mask_buf_def[i], d->mask_buf[i]);
if (ret != 0)
dev_err(d->map->dev, "Failed to sync masks in %x\n",
d->chip->mask_base + i);
d->chip->mask_base + (i * map->reg_stride));
}

mutex_unlock(&d->lock);
Expand All @@ -73,15 +74,15 @@ static void regmap_irq_enable(struct irq_data *data)
struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq);

d->mask_buf[irq_data->reg_offset] &= ~irq_data->mask;
d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~irq_data->mask;
}

static void regmap_irq_disable(struct irq_data *data)
{
struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq);

d->mask_buf[irq_data->reg_offset] |= irq_data->mask;
d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
}

static struct irq_chip regmap_irq_chip = {
Expand Down Expand Up @@ -136,17 +137,19 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
data->status_buf[i] &= ~data->mask_buf[i];

if (data->status_buf[i] && chip->ack_base) {
ret = regmap_write(map, chip->ack_base + i,
ret = regmap_write(map, chip->ack_base +
(i * map->reg_stride),
data->status_buf[i]);
if (ret != 0)
dev_err(map->dev, "Failed to ack 0x%x: %d\n",
chip->ack_base + i, ret);
chip->ack_base + (i * map->reg_stride),
ret);
}
}

for (i = 0; i < chip->num_irqs; i++) {
if (data->status_buf[chip->irqs[i].reg_offset] &
chip->irqs[i].mask) {
if (data->status_buf[chip->irqs[i].reg_offset /
map->reg_stride] & chip->irqs[i].mask) {
handle_nested_irq(data->irq_base + i);
handled = true;
}
Expand Down Expand Up @@ -181,6 +184,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
int cur_irq, i;
int ret = -ENOMEM;

for (i = 0; i < chip->num_irqs; i++) {
if (chip->irqs[i].reg_offset % map->reg_stride)
return -EINVAL;
if (chip->irqs[i].reg_offset / map->reg_stride >=
chip->num_regs)
return -EINVAL;
}

irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0);
if (irq_base < 0) {
dev_warn(map->dev, "Failed to allocate IRQs: %d\n",
Expand Down Expand Up @@ -218,16 +229,17 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
mutex_init(&d->lock);

for (i = 0; i < chip->num_irqs; i++)
d->mask_buf_def[chip->irqs[i].reg_offset]
d->mask_buf_def[chip->irqs[i].reg_offset / map->reg_stride]
|= chip->irqs[i].mask;

/* Mask all the interrupts by default */
for (i = 0; i < chip->num_regs; i++) {
d->mask_buf[i] = d->mask_buf_def[i];
ret = regmap_write(map, chip->mask_base + i, d->mask_buf[i]);
ret = regmap_write(map, chip->mask_base + (i * map->reg_stride),
d->mask_buf[i]);
if (ret != 0) {
dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
chip->mask_base + i, ret);
chip->mask_base + (i * map->reg_stride), ret);
goto err_alloc;
}
}
Expand Down
13 changes: 13 additions & 0 deletions trunk/drivers/base/regmap/regmap-mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
const struct regmap_config *config)
{
struct regmap_mmio_context *ctx;
int min_stride;

if (config->reg_bits != 32)
return ERR_PTR(-EINVAL);
Expand All @@ -139,16 +140,28 @@ struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,

switch (config->val_bits) {
case 8:
/* The core treats 0 as 1 */
min_stride = 0;
break;
case 16:
min_stride = 2;
break;
case 32:
min_stride = 4;
break;
#ifdef CONFIG_64BIT
case 64:
min_stride = 8;
break;
#endif
break;
default:
return ERR_PTR(-EINVAL);
}

if (config->reg_stride < min_stride)
return ERR_PTR(-EINVAL);

ctx = kzalloc(GFP_KERNEL, sizeof(*ctx));
if (!ctx)
return ERR_PTR(-ENOMEM);
Expand Down
Loading

0 comments on commit 608155c

Please sign in to comment.