Skip to content

Commit 4c50144

Browse files
Guru Das Srinageshbroonie
authored andcommitted
regmap-irq: Introduce virtual regs to handle more config regs
Add "virtual" registers support to handle any irq configuration registers in addition to the ones the framework currently supports (status, mask, unmask, wake, type and ack). These are non-standard registers that further configure irq type on some devices, so enable the framework to add a variable number of them. Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org> Link: https://lore.kernel.org/r/a1787067004b0e11cb960319082764397469215a.1616613838.git.gurus@codeaurora.org Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 1066cfb commit 4c50144

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

drivers/base/regmap/regmap-irq.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct regmap_irq_chip_data {
3838
unsigned int *wake_buf;
3939
unsigned int *type_buf;
4040
unsigned int *type_buf_def;
41+
unsigned int **virt_buf;
4142

4243
unsigned int irq_reg_stride;
4344
unsigned int type_reg_stride;
@@ -94,7 +95,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
9495
{
9596
struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
9697
struct regmap *map = d->map;
97-
int i, ret;
98+
int i, j, ret;
9899
u32 reg;
99100
u32 unmask_offset;
100101
u32 val;
@@ -218,6 +219,20 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
218219
}
219220
}
220221

222+
if (d->chip->num_virt_regs) {
223+
for (i = 0; i < d->chip->num_virt_regs; i++) {
224+
for (j = 0; j < d->chip->num_regs; j++) {
225+
reg = sub_irq_reg(d, d->chip->virt_reg_base[i],
226+
j);
227+
ret = regmap_write(map, reg, d->virt_buf[i][j]);
228+
if (ret != 0)
229+
dev_err(d->map->dev,
230+
"Failed to write virt 0x%x: %d\n",
231+
reg, ret);
232+
}
233+
}
234+
}
235+
221236
if (d->chip->runtime_pm)
222237
pm_runtime_put(map->dev);
223238

@@ -691,6 +706,24 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
691706
goto err_alloc;
692707
}
693708

709+
if (chip->num_virt_regs) {
710+
/*
711+
* Create virt_buf[chip->num_extra_config_regs][chip->num_regs]
712+
*/
713+
d->virt_buf = kcalloc(chip->num_virt_regs, sizeof(*d->virt_buf),
714+
GFP_KERNEL);
715+
if (!d->virt_buf)
716+
goto err_alloc;
717+
718+
for (i = 0; i < chip->num_virt_regs; i++) {
719+
d->virt_buf[i] = kcalloc(chip->num_regs,
720+
sizeof(unsigned int),
721+
GFP_KERNEL);
722+
if (!d->virt_buf[i])
723+
goto err_alloc;
724+
}
725+
}
726+
694727
d->irq_chip = regmap_irq_chip;
695728
d->irq_chip.name = chip->name;
696729
d->irq = irq;
@@ -863,6 +896,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
863896
kfree(d->mask_buf);
864897
kfree(d->status_buf);
865898
kfree(d->status_reg_buf);
899+
for (i = 0; i < chip->num_virt_regs; i++)
900+
kfree(d->virt_buf[i]);
901+
kfree(d->virt_buf);
866902
kfree(d);
867903
return ret;
868904
}

include/linux/regmap.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,7 @@ struct regmap_irq_sub_irq_map {
13931393
* Using zero value is possible with @use_ack bit.
13941394
* @wake_base: Base address for wake enables. If zero unsupported.
13951395
* @type_base: Base address for irq type. If zero unsupported.
1396+
* @virt_reg_base: Base addresses for extra config regs.
13961397
* @irq_reg_stride: Stride to use for chips where registers are not contiguous.
13971398
* @init_ack_masked: Ack all masked interrupts once during initalization.
13981399
* @mask_invert: Inverted mask register: cleared bits are masked out.
@@ -1417,6 +1418,8 @@ struct regmap_irq_sub_irq_map {
14171418
* assigned based on the index in the array of the interrupt.
14181419
* @num_irqs: Number of descriptors.
14191420
* @num_type_reg: Number of type registers.
1421+
* @num_virt_regs: Number of non-standard irq configuration registers.
1422+
* If zero unsupported.
14201423
* @type_reg_stride: Stride to use for chips where type registers are not
14211424
* contiguous.
14221425
* @handle_pre_irq: Driver specific callback to handle interrupt from device
@@ -1444,6 +1447,7 @@ struct regmap_irq_chip {
14441447
unsigned int ack_base;
14451448
unsigned int wake_base;
14461449
unsigned int type_base;
1450+
unsigned int *virt_reg_base;
14471451
unsigned int irq_reg_stride;
14481452
bool mask_writeonly:1;
14491453
bool init_ack_masked:1;
@@ -1464,6 +1468,7 @@ struct regmap_irq_chip {
14641468
int num_irqs;
14651469

14661470
int num_type_reg;
1471+
int num_virt_regs;
14671472
unsigned int type_reg_stride;
14681473

14691474
int (*handle_pre_irq)(void *irq_drv_data);

0 commit comments

Comments
 (0)