regmap: irq: add support for chips who have separate unmask registers
Some chips have separate unmask registers from mask registers for some consideration of concurrency SMP write performance. And this patch adds a flag for it. An user will be CSR SiRFSoC ARM chips. Signed-off-by: Guo Zeng <Guo.Zeng@csr.com> Signed-off-by: Barry Song <Baohua.Song@csr.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Родитель
6ff33f3902
Коммит
7b7d1968e4
|
@ -63,6 +63,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
|
|||
struct regmap *map = d->map;
|
||||
int i, ret;
|
||||
u32 reg;
|
||||
u32 unmask_offset;
|
||||
|
||||
if (d->chip->runtime_pm) {
|
||||
ret = pm_runtime_get_sync(map->dev);
|
||||
|
@ -79,12 +80,28 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
|
|||
for (i = 0; i < d->chip->num_regs; i++) {
|
||||
reg = d->chip->mask_base +
|
||||
(i * map->reg_stride * d->irq_reg_stride);
|
||||
if (d->chip->mask_invert)
|
||||
if (d->chip->mask_invert) {
|
||||
ret = regmap_update_bits(d->map, reg,
|
||||
d->mask_buf_def[i], ~d->mask_buf[i]);
|
||||
else
|
||||
} else if (d->chip->unmask_base) {
|
||||
/* set mask with mask_base register */
|
||||
ret = regmap_update_bits(d->map, reg,
|
||||
d->mask_buf_def[i], ~d->mask_buf[i]);
|
||||
if (ret < 0)
|
||||
dev_err(d->map->dev,
|
||||
"Failed to sync unmasks in %x\n",
|
||||
reg);
|
||||
unmask_offset = d->chip->unmask_base -
|
||||
d->chip->mask_base;
|
||||
/* clear mask with unmask_base register */
|
||||
ret = regmap_update_bits(d->map,
|
||||
reg + unmask_offset,
|
||||
d->mask_buf_def[i],
|
||||
d->mask_buf[i]);
|
||||
} else {
|
||||
ret = regmap_update_bits(d->map, reg,
|
||||
d->mask_buf_def[i], d->mask_buf[i]);
|
||||
}
|
||||
if (ret != 0)
|
||||
dev_err(d->map->dev, "Failed to sync masks in %x\n",
|
||||
reg);
|
||||
|
@ -339,6 +356,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
|
|||
int i;
|
||||
int ret = -ENOMEM;
|
||||
u32 reg;
|
||||
u32 unmask_offset;
|
||||
|
||||
if (chip->num_regs <= 0)
|
||||
return -EINVAL;
|
||||
|
@ -420,7 +438,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
|
|||
if (chip->mask_invert)
|
||||
ret = regmap_update_bits(map, reg,
|
||||
d->mask_buf[i], ~d->mask_buf[i]);
|
||||
else
|
||||
else if (d->chip->unmask_base) {
|
||||
unmask_offset = d->chip->unmask_base -
|
||||
d->chip->mask_base;
|
||||
ret = regmap_update_bits(d->map,
|
||||
reg + unmask_offset,
|
||||
d->mask_buf[i],
|
||||
d->mask_buf[i]);
|
||||
} else
|
||||
ret = regmap_update_bits(map, reg,
|
||||
d->mask_buf[i], d->mask_buf[i]);
|
||||
if (ret != 0) {
|
||||
|
|
|
@ -800,6 +800,8 @@ struct regmap_irq {
|
|||
*
|
||||
* @status_base: Base status register address.
|
||||
* @mask_base: Base mask register address.
|
||||
* @unmask_base: Base unmask register address. for chips who have
|
||||
* separate mask and unmask registers
|
||||
* @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.
|
||||
|
@ -820,6 +822,7 @@ struct regmap_irq_chip {
|
|||
|
||||
unsigned int status_base;
|
||||
unsigned int mask_base;
|
||||
unsigned int unmask_base;
|
||||
unsigned int ack_base;
|
||||
unsigned int wake_base;
|
||||
unsigned int irq_reg_stride;
|
||||
|
|
Загрузка…
Ссылка в новой задаче