Commit bb1b6490 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'regmap-v3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap

Pull regmap updates from Mark Brown:
 "Nothing terribly exciting with regmap this release, mainly a few small
  extensions to allow more devices to be supported:

   - Allow the bulk I/O APIs to be used with no-bus regmaps
   - Support interrupt controllers with zero ack base
   - Warning and spelling fixes"

* tag 'regmap-v3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
  regmap: fix a couple of typos
  regmap: Allow regmap_bulk_write() to work for "no-bus" regmaps
  regmap: Allow regmap_bulk_read() to work for "no-bus" regmaps
  regmap: irq: Allow using zero value for ack_base
  regmap: Fix 'ret' would return an uninitialized value
parents 4ba9920e 86776fc1
...@@ -113,7 +113,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) ...@@ -113,7 +113,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
* OR if there is masked interrupt which hasn't been Acked, * OR if there is masked interrupt which hasn't been Acked,
* it'll be ignored in irq handler, then may introduce irq storm * it'll be ignored in irq handler, then may introduce irq storm
*/ */
if (d->mask_buf[i] && d->chip->ack_base) { if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) {
reg = d->chip->ack_base + reg = d->chip->ack_base +
(i * map->reg_stride * d->irq_reg_stride); (i * map->reg_stride * d->irq_reg_stride);
ret = regmap_write(map, reg, d->mask_buf[i]); ret = regmap_write(map, reg, d->mask_buf[i]);
...@@ -271,7 +271,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) ...@@ -271,7 +271,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
for (i = 0; i < data->chip->num_regs; i++) { for (i = 0; i < data->chip->num_regs; i++) {
data->status_buf[i] &= ~data->mask_buf[i]; data->status_buf[i] &= ~data->mask_buf[i];
if (data->status_buf[i] && chip->ack_base) { if (data->status_buf[i] && (chip->ack_base || chip->use_ack)) {
reg = chip->ack_base + reg = chip->ack_base +
(i * map->reg_stride * data->irq_reg_stride); (i * map->reg_stride * data->irq_reg_stride);
ret = regmap_write(map, reg, data->status_buf[i]); ret = regmap_write(map, reg, data->status_buf[i]);
...@@ -448,7 +448,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, ...@@ -448,7 +448,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
goto err_alloc; goto err_alloc;
} }
if (d->status_buf[i] && chip->ack_base) { if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) {
reg = chip->ack_base + reg = chip->ack_base +
(i * map->reg_stride * d->irq_reg_stride); (i * map->reg_stride * d->irq_reg_stride);
ret = regmap_write(map, reg, ret = regmap_write(map, reg,
......
...@@ -1514,21 +1514,49 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, ...@@ -1514,21 +1514,49 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
{ {
int ret = 0, i; int ret = 0, i;
size_t val_bytes = map->format.val_bytes; size_t val_bytes = map->format.val_bytes;
void *wval;
if (!map->bus) if (map->bus && !map->format.parse_inplace)
return -EINVAL;
if (!map->format.parse_inplace)
return -EINVAL; return -EINVAL;
if (reg % map->reg_stride) if (reg % map->reg_stride)
return -EINVAL; return -EINVAL;
map->lock(map->lock_arg); map->lock(map->lock_arg);
/*
* Some devices don't support bulk write, for
* them we have a series of single write operations.
*/
if (!map->bus || map->use_single_rw) {
for (i = 0; i < val_count; i++) {
unsigned int ival;
switch (val_bytes) {
case 1:
ival = *(u8 *)(val + (i * val_bytes));
break;
case 2:
ival = *(u16 *)(val + (i * val_bytes));
break;
case 4:
ival = *(u32 *)(val + (i * val_bytes));
break;
#ifdef CONFIG_64BIT
case 8:
ival = *(u64 *)(val + (i * val_bytes));
break;
#endif
default:
ret = -EINVAL;
goto out;
}
/* No formatting is require if val_byte is 1 */ ret = _regmap_write(map, reg + (i * map->reg_stride),
if (val_bytes == 1) { ival);
wval = (void *)val; if (ret != 0)
goto out;
}
} else { } else {
void *wval;
wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL);
if (!wval) { if (!wval) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1537,27 +1565,11 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, ...@@ -1537,27 +1565,11 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
} }
for (i = 0; i < val_count * val_bytes; i += val_bytes) for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_inplace(wval + i); map->format.parse_inplace(wval + i);
}
/*
* Some devices does not support bulk write, for
* them we have a series of single write operations.
*/
if (map->use_single_rw) {
for (i = 0; i < val_count; i++) {
ret = _regmap_raw_write(map,
reg + (i * map->reg_stride),
val + (i * val_bytes),
val_bytes);
if (ret != 0)
goto out;
}
} else {
ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
}
if (val_bytes != 1)
kfree(wval); kfree(wval);
}
out: out:
map->unlock(map->lock_arg); map->unlock(map->lock_arg);
return ret; return ret;
...@@ -1897,14 +1909,10 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, ...@@ -1897,14 +1909,10 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
size_t val_bytes = map->format.val_bytes; size_t val_bytes = map->format.val_bytes;
bool vol = regmap_volatile_range(map, reg, val_count); bool vol = regmap_volatile_range(map, reg, val_count);
if (!map->bus)
return -EINVAL;
if (!map->format.parse_inplace)
return -EINVAL;
if (reg % map->reg_stride) if (reg % map->reg_stride)
return -EINVAL; return -EINVAL;
if (vol || map->cache_type == REGCACHE_NONE) { if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
/* /*
* Some devices does not support bulk read, for * Some devices does not support bulk read, for
* them we have a series of single read operations. * them we have a series of single read operations.
...@@ -2173,6 +2181,10 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, ...@@ -2173,6 +2181,10 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
int i, ret; int i, ret;
bool bypass; bool bypass;
if (WARN_ONCE(num_regs <= 0, "invalid registers number (%d)\n",
num_regs))
return 0;
map->lock(map->lock_arg); map->lock(map->lock_arg);
bypass = map->cache_bypass; bypass = map->cache_bypass;
......
...@@ -122,9 +122,9 @@ typedef void (*regmap_unlock)(void *); ...@@ -122,9 +122,9 @@ typedef void (*regmap_unlock)(void *);
* volatile_table (see below) is not, the check is performed on * volatile_table (see below) is not, the check is performed on
* such table (a register is volatile if it belongs to one of * such table (a register is volatile if it belongs to one of
* the ranges specified by volatile_table). * the ranges specified by volatile_table).
* @precious_reg: Optional callback returning true if the rgister * @precious_reg: Optional callback returning true if the register
* should not be read outside of a call from the driver * should not be read outside of a call from the driver
* (eg, a clear on read interrupt status register). If this * (e.g., a clear on read interrupt status register). If this
* field is NULL but precious_table (see below) is not, the * field is NULL but precious_table (see below) is not, the
* check is performed on such table (a register is precious if * check is performed on such table (a register is precious if
* it belongs to one of the ranges specified by precious_table). * it belongs to one of the ranges specified by precious_table).
...@@ -136,9 +136,9 @@ typedef void (*regmap_unlock)(void *); ...@@ -136,9 +136,9 @@ typedef void (*regmap_unlock)(void *);
* are not overridden). * are not overridden).
* @reg_read: Optional callback that if filled will be used to perform * @reg_read: Optional callback that if filled will be used to perform
* all the reads from the registers. Should only be provided for * all the reads from the registers. Should only be provided for
* devices whos read operation cannot be represented as a simple read * devices whose read operation cannot be represented as a simple
* operation on a bus such as SPI, I2C, etc. Most of the devices do * read operation on a bus such as SPI, I2C, etc. Most of the
* not need this. * devices do not need this.
* @reg_write: Same as above for writing. * @reg_write: Same as above for writing.
* @fast_io: Register IO is fast. Use a spinlock instead of a mutex * @fast_io: Register IO is fast. Use a spinlock instead of a mutex
* to perform locking. This field is ignored if custom lock/unlock * to perform locking. This field is ignored if custom lock/unlock
...@@ -497,11 +497,13 @@ struct regmap_irq { ...@@ -497,11 +497,13 @@ struct regmap_irq {
* *
* @status_base: Base status register address. * @status_base: Base status register address.
* @mask_base: Base mask register address. * @mask_base: Base mask register address.
* @ack_base: Base ack address. If zero then the chip is clear on read. * @ack_base: Base ack address. If zero then the chip is clear on read.
* Using zero value is possible with @use_ack bit.
* @wake_base: Base address for wake enables. If zero unsupported. * @wake_base: Base address for wake enables. If zero unsupported.
* @irq_reg_stride: Stride to use for chips where registers are not contiguous. * @irq_reg_stride: Stride to use for chips where registers are not contiguous.
* @init_ack_masked: Ack all masked interrupts once during initalization. * @init_ack_masked: Ack all masked interrupts once during initalization.
* @mask_invert: Inverted mask register: cleared bits are masked out. * @mask_invert: Inverted mask register: cleared bits are masked out.
* @use_ack: Use @ack register even if it is zero.
* @wake_invert: Inverted wake register: cleared bits are wake enabled. * @wake_invert: Inverted wake register: cleared bits are wake enabled.
* @runtime_pm: Hold a runtime PM lock on the device when accessing it. * @runtime_pm: Hold a runtime PM lock on the device when accessing it.
* *
...@@ -520,6 +522,7 @@ struct regmap_irq_chip { ...@@ -520,6 +522,7 @@ struct regmap_irq_chip {
unsigned int irq_reg_stride; unsigned int irq_reg_stride;
bool init_ack_masked:1; bool init_ack_masked:1;
bool mask_invert:1; bool mask_invert:1;
bool use_ack:1;
bool wake_invert:1; bool wake_invert:1;
bool runtime_pm:1; bool runtime_pm:1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment