Loading drivers/base/regmap/regmap-irq.c +97 −29 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ struct regmap_irq_chip_data { unsigned int *wake_buf; unsigned int *type_buf; unsigned int *type_buf_def; unsigned int **virt_buf; unsigned int irq_reg_stride; unsigned int type_reg_stride; Loading @@ -45,6 +46,27 @@ struct regmap_irq_chip_data { bool clear_status:1; }; static int sub_irq_reg(struct regmap_irq_chip_data *data, unsigned int base_reg, int i) { const struct regmap_irq_chip *chip = data->chip; struct regmap *map = data->map; struct regmap_irq_sub_irq_map *subreg; unsigned int offset; int reg = 0; if (!chip->sub_reg_offsets || !chip->not_fixed_stride) { /* Assume linear mapping */ reg = base_reg + (i * map->reg_stride * data->irq_reg_stride); } else { subreg = &chip->sub_reg_offsets[i]; offset = subreg->offset[0]; reg = base_reg + offset; } return reg; } static inline const struct regmap_irq *irq_to_regmap_irq(struct regmap_irq_chip_data *data, int irq) Loading Loading @@ -73,7 +95,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) { struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); struct regmap *map = d->map; int i, ret; int i, j, ret; u32 reg; u32 unmask_offset; u32 val; Loading @@ -87,8 +109,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) if (d->clear_status) { for (i = 0; i < d->chip->num_regs; i++) { reg = d->chip->status_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->status_base, i); ret = regmap_read(map, reg, &val); if (ret) Loading @@ -108,8 +129,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) if (!d->chip->mask_base) continue; reg = d->chip->mask_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->mask_base, i); if (d->chip->mask_invert) { ret = regmap_irq_update_bits(d, reg, d->mask_buf_def[i], ~d->mask_buf[i]); Loading @@ -136,8 +156,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) dev_err(d->map->dev, "Failed to sync masks in %x\n", reg); reg = d->chip->wake_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->wake_base, i); if (d->wake_buf) { if (d->chip->wake_invert) ret = regmap_irq_update_bits(d, reg, Loading @@ -161,8 +180,8 @@ static void regmap_irq_sync_unlock(struct irq_data *data) * it'll be ignored in irq handler, then may introduce irq storm */ if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) { reg = d->chip->ack_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->ack_base, i); /* some chips ack by write 0 */ if (d->chip->ack_invert) ret = regmap_write(map, reg, ~d->mask_buf[i]); Loading @@ -187,8 +206,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) for (i = 0; i < d->chip->num_type_reg; i++) { if (!d->type_buf_def[i]) continue; reg = d->chip->type_base + (i * map->reg_stride * d->type_reg_stride); reg = sub_irq_reg(d, d->chip->type_base, i); if (d->chip->type_invert) ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], ~d->type_buf[i]); Loading @@ -201,6 +219,20 @@ static void regmap_irq_sync_unlock(struct irq_data *data) } } if (d->chip->num_virt_regs) { for (i = 0; i < d->chip->num_virt_regs; i++) { for (j = 0; j < d->chip->num_regs; j++) { reg = sub_irq_reg(d, d->chip->virt_reg_base[i], j); ret = regmap_write(map, reg, d->virt_buf[i][j]); if (ret != 0) dev_err(d->map->dev, "Failed to write virt 0x%x: %d\n", reg, ret); } } } if (d->chip->runtime_pm) pm_runtime_put(map->dev); Loading Loading @@ -301,6 +333,11 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type) default: return -EINVAL; } if (d->chip->set_type_virt) return d->chip->set_type_virt(d->virt_buf, type, data->hwirq, reg); return 0; } Loading Loading @@ -352,8 +389,15 @@ static inline int read_sub_irq_data(struct regmap_irq_chip_data *data, for (i = 0; i < subreg->num_regs; i++) { unsigned int offset = subreg->offset[i]; ret = regmap_read(map, chip->status_base + offset, if (chip->not_fixed_stride) ret = regmap_read(map, chip->status_base + offset, &data->status_buf[b]); else ret = regmap_read(map, chip->status_base + offset, &data->status_buf[offset]); if (ret) break; } Loading Loading @@ -474,10 +518,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } else { for (i = 0; i < data->chip->num_regs; i++) { ret = regmap_read(map, chip->status_base + (i * map->reg_stride * data->irq_reg_stride), &data->status_buf[i]); unsigned int reg = sub_irq_reg(data, data->chip->status_base, i); ret = regmap_read(map, reg, &data->status_buf[i]); if (ret != 0) { dev_err(map->dev, Loading @@ -499,8 +542,8 @@ 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 || chip->use_ack)) { reg = chip->ack_base + (i * map->reg_stride * data->irq_reg_stride); reg = sub_irq_reg(data, data->chip->ack_base, i); if (chip->ack_invert) ret = regmap_write(map, reg, ~data->status_buf[i]); Loading Loading @@ -605,6 +648,12 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, return -EINVAL; } if (chip->not_fixed_stride) { for (i = 0; i < chip->num_regs; i++) if (chip->sub_reg_offsets[i].num_regs != 1) return -EINVAL; } if (irq_base) { irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0); if (irq_base < 0) { Loading Loading @@ -662,6 +711,24 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, goto err_alloc; } if (chip->num_virt_regs) { /* * Create virt_buf[chip->num_extra_config_regs][chip->num_regs] */ d->virt_buf = kcalloc(chip->num_virt_regs, sizeof(*d->virt_buf), GFP_KERNEL); if (!d->virt_buf) goto err_alloc; for (i = 0; i < chip->num_virt_regs; i++) { d->virt_buf[i] = kcalloc(chip->num_regs, sizeof(unsigned int), GFP_KERNEL); if (!d->virt_buf[i]) goto err_alloc; } } d->irq_chip = regmap_irq_chip; d->irq_chip.name = chip->name; d->irq = irq; Loading Loading @@ -700,8 +767,8 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, if (!chip->mask_base) continue; reg = chip->mask_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->mask_base, i); if (chip->mask_invert) ret = regmap_irq_update_bits(d, reg, d->mask_buf[i], ~d->mask_buf[i]); Loading @@ -725,8 +792,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, continue; /* Ack masked but set interrupts */ reg = chip->status_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->status_base, i); ret = regmap_read(map, reg, &d->status_buf[i]); if (ret != 0) { dev_err(map->dev, "Failed to read IRQ status: %d\n", Loading @@ -735,8 +801,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, } if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { reg = chip->ack_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->ack_base, i); if (chip->ack_invert) ret = regmap_write(map, reg, ~(d->status_buf[i] & d->mask_buf[i])); Loading Loading @@ -765,8 +830,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, if (d->wake_buf) { for (i = 0; i < chip->num_regs; i++) { d->wake_buf[i] = d->mask_buf_def[i]; reg = chip->wake_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->wake_base, i); if (chip->wake_invert) ret = regmap_irq_update_bits(d, reg, Loading @@ -786,8 +850,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, if (chip->num_type_reg && !chip->type_in_mask) { for (i = 0; i < chip->num_type_reg; ++i) { reg = chip->type_base + (i * map->reg_stride * d->type_reg_stride); reg = sub_irq_reg(d, d->chip->type_base, i); ret = regmap_read(map, reg, &d->type_buf_def[i]); Loading Loading @@ -838,6 +901,11 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, kfree(d->mask_buf); kfree(d->status_buf); kfree(d->status_reg_buf); if (d->virt_buf) { for (i = 0; i < chip->num_virt_regs; i++) kfree(d->virt_buf[i]); kfree(d->virt_buf); } kfree(d); return ret; } Loading include/linux/regmap.h +16 −0 Original line number Diff line number Diff line Loading @@ -1378,6 +1378,9 @@ struct regmap_irq_sub_irq_map { * status_base. Should contain num_regs arrays. * Can be provided for chips with more complex mapping than * 1.st bit to 1.st sub-reg, 2.nd bit to 2.nd sub-reg, ... * When used with not_fixed_stride, each one-element array * member contains offset calculated as address from each * peripheral to first peripheral. * @num_main_regs: Number of 'main status' irq registers for chips which have * main_status set. * Loading @@ -1390,6 +1393,7 @@ struct regmap_irq_sub_irq_map { * Using zero value is possible with @use_ack bit. * @wake_base: Base address for wake enables. If zero unsupported. * @type_base: Base address for irq type. If zero unsupported. * @virt_reg_base: Base addresses for extra config regs. * @irq_reg_stride: Stride to use for chips where registers are not contiguous. * @init_ack_masked: Ack all masked interrupts once during initalization. * @mask_invert: Inverted mask register: cleared bits are masked out. Loading @@ -1404,6 +1408,9 @@ struct regmap_irq_sub_irq_map { * @clear_on_unmask: For chips with interrupts cleared on read: read the status * registers before unmasking interrupts to clear any bits * set when they were masked. * @not_fixed_stride: Used when chip peripherals are not laid out with fixed * stride. Must be used with sub_reg_offsets containing the * offsets to each peripheral. * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * * @num_regs: Number of registers in each control bank. Loading @@ -1411,12 +1418,16 @@ struct regmap_irq_sub_irq_map { * assigned based on the index in the array of the interrupt. * @num_irqs: Number of descriptors. * @num_type_reg: Number of type registers. * @num_virt_regs: Number of non-standard irq configuration registers. * If zero unsupported. * @type_reg_stride: Stride to use for chips where type registers are not * contiguous. * @handle_pre_irq: Driver specific callback to handle interrupt from device * before regmap_irq_handler process the interrupts. * @handle_post_irq: Driver specific callback to handle interrupt from device * after handling the interrupts in regmap_irq_handler(). * @set_type_virt: Driver specific callback to extend regmap_irq_set_type() * and configure virt regs. * @irq_drv_data: Driver specific IRQ data which is passed as parameter when * driver specific pre/post interrupt handler is called. * Loading @@ -1438,6 +1449,7 @@ struct regmap_irq_chip { unsigned int ack_base; unsigned int wake_base; unsigned int type_base; unsigned int *virt_reg_base; unsigned int irq_reg_stride; bool mask_writeonly:1; bool init_ack_masked:1; Loading @@ -1450,6 +1462,7 @@ struct regmap_irq_chip { bool type_invert:1; bool type_in_mask:1; bool clear_on_unmask:1; bool not_fixed_stride:1; int num_regs; Loading @@ -1457,10 +1470,13 @@ struct regmap_irq_chip { int num_irqs; int num_type_reg; int num_virt_regs; unsigned int type_reg_stride; int (*handle_pre_irq)(void *irq_drv_data); int (*handle_post_irq)(void *irq_drv_data); int (*set_type_virt)(unsigned int **buf, unsigned int type, unsigned long hwirq, int reg); void *irq_drv_data; }; Loading Loading
drivers/base/regmap/regmap-irq.c +97 −29 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ struct regmap_irq_chip_data { unsigned int *wake_buf; unsigned int *type_buf; unsigned int *type_buf_def; unsigned int **virt_buf; unsigned int irq_reg_stride; unsigned int type_reg_stride; Loading @@ -45,6 +46,27 @@ struct regmap_irq_chip_data { bool clear_status:1; }; static int sub_irq_reg(struct regmap_irq_chip_data *data, unsigned int base_reg, int i) { const struct regmap_irq_chip *chip = data->chip; struct regmap *map = data->map; struct regmap_irq_sub_irq_map *subreg; unsigned int offset; int reg = 0; if (!chip->sub_reg_offsets || !chip->not_fixed_stride) { /* Assume linear mapping */ reg = base_reg + (i * map->reg_stride * data->irq_reg_stride); } else { subreg = &chip->sub_reg_offsets[i]; offset = subreg->offset[0]; reg = base_reg + offset; } return reg; } static inline const struct regmap_irq *irq_to_regmap_irq(struct regmap_irq_chip_data *data, int irq) Loading Loading @@ -73,7 +95,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) { struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); struct regmap *map = d->map; int i, ret; int i, j, ret; u32 reg; u32 unmask_offset; u32 val; Loading @@ -87,8 +109,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) if (d->clear_status) { for (i = 0; i < d->chip->num_regs; i++) { reg = d->chip->status_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->status_base, i); ret = regmap_read(map, reg, &val); if (ret) Loading @@ -108,8 +129,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) if (!d->chip->mask_base) continue; reg = d->chip->mask_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->mask_base, i); if (d->chip->mask_invert) { ret = regmap_irq_update_bits(d, reg, d->mask_buf_def[i], ~d->mask_buf[i]); Loading @@ -136,8 +156,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) dev_err(d->map->dev, "Failed to sync masks in %x\n", reg); reg = d->chip->wake_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->wake_base, i); if (d->wake_buf) { if (d->chip->wake_invert) ret = regmap_irq_update_bits(d, reg, Loading @@ -161,8 +180,8 @@ static void regmap_irq_sync_unlock(struct irq_data *data) * it'll be ignored in irq handler, then may introduce irq storm */ if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) { reg = d->chip->ack_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->ack_base, i); /* some chips ack by write 0 */ if (d->chip->ack_invert) ret = regmap_write(map, reg, ~d->mask_buf[i]); Loading @@ -187,8 +206,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) for (i = 0; i < d->chip->num_type_reg; i++) { if (!d->type_buf_def[i]) continue; reg = d->chip->type_base + (i * map->reg_stride * d->type_reg_stride); reg = sub_irq_reg(d, d->chip->type_base, i); if (d->chip->type_invert) ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], ~d->type_buf[i]); Loading @@ -201,6 +219,20 @@ static void regmap_irq_sync_unlock(struct irq_data *data) } } if (d->chip->num_virt_regs) { for (i = 0; i < d->chip->num_virt_regs; i++) { for (j = 0; j < d->chip->num_regs; j++) { reg = sub_irq_reg(d, d->chip->virt_reg_base[i], j); ret = regmap_write(map, reg, d->virt_buf[i][j]); if (ret != 0) dev_err(d->map->dev, "Failed to write virt 0x%x: %d\n", reg, ret); } } } if (d->chip->runtime_pm) pm_runtime_put(map->dev); Loading Loading @@ -301,6 +333,11 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type) default: return -EINVAL; } if (d->chip->set_type_virt) return d->chip->set_type_virt(d->virt_buf, type, data->hwirq, reg); return 0; } Loading Loading @@ -352,8 +389,15 @@ static inline int read_sub_irq_data(struct regmap_irq_chip_data *data, for (i = 0; i < subreg->num_regs; i++) { unsigned int offset = subreg->offset[i]; ret = regmap_read(map, chip->status_base + offset, if (chip->not_fixed_stride) ret = regmap_read(map, chip->status_base + offset, &data->status_buf[b]); else ret = regmap_read(map, chip->status_base + offset, &data->status_buf[offset]); if (ret) break; } Loading Loading @@ -474,10 +518,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } else { for (i = 0; i < data->chip->num_regs; i++) { ret = regmap_read(map, chip->status_base + (i * map->reg_stride * data->irq_reg_stride), &data->status_buf[i]); unsigned int reg = sub_irq_reg(data, data->chip->status_base, i); ret = regmap_read(map, reg, &data->status_buf[i]); if (ret != 0) { dev_err(map->dev, Loading @@ -499,8 +542,8 @@ 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 || chip->use_ack)) { reg = chip->ack_base + (i * map->reg_stride * data->irq_reg_stride); reg = sub_irq_reg(data, data->chip->ack_base, i); if (chip->ack_invert) ret = regmap_write(map, reg, ~data->status_buf[i]); Loading Loading @@ -605,6 +648,12 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, return -EINVAL; } if (chip->not_fixed_stride) { for (i = 0; i < chip->num_regs; i++) if (chip->sub_reg_offsets[i].num_regs != 1) return -EINVAL; } if (irq_base) { irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0); if (irq_base < 0) { Loading Loading @@ -662,6 +711,24 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, goto err_alloc; } if (chip->num_virt_regs) { /* * Create virt_buf[chip->num_extra_config_regs][chip->num_regs] */ d->virt_buf = kcalloc(chip->num_virt_regs, sizeof(*d->virt_buf), GFP_KERNEL); if (!d->virt_buf) goto err_alloc; for (i = 0; i < chip->num_virt_regs; i++) { d->virt_buf[i] = kcalloc(chip->num_regs, sizeof(unsigned int), GFP_KERNEL); if (!d->virt_buf[i]) goto err_alloc; } } d->irq_chip = regmap_irq_chip; d->irq_chip.name = chip->name; d->irq = irq; Loading Loading @@ -700,8 +767,8 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, if (!chip->mask_base) continue; reg = chip->mask_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->mask_base, i); if (chip->mask_invert) ret = regmap_irq_update_bits(d, reg, d->mask_buf[i], ~d->mask_buf[i]); Loading @@ -725,8 +792,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, continue; /* Ack masked but set interrupts */ reg = chip->status_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->status_base, i); ret = regmap_read(map, reg, &d->status_buf[i]); if (ret != 0) { dev_err(map->dev, "Failed to read IRQ status: %d\n", Loading @@ -735,8 +801,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, } if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { reg = chip->ack_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->ack_base, i); if (chip->ack_invert) ret = regmap_write(map, reg, ~(d->status_buf[i] & d->mask_buf[i])); Loading Loading @@ -765,8 +830,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, if (d->wake_buf) { for (i = 0; i < chip->num_regs; i++) { d->wake_buf[i] = d->mask_buf_def[i]; reg = chip->wake_base + (i * map->reg_stride * d->irq_reg_stride); reg = sub_irq_reg(d, d->chip->wake_base, i); if (chip->wake_invert) ret = regmap_irq_update_bits(d, reg, Loading @@ -786,8 +850,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, if (chip->num_type_reg && !chip->type_in_mask) { for (i = 0; i < chip->num_type_reg; ++i) { reg = chip->type_base + (i * map->reg_stride * d->type_reg_stride); reg = sub_irq_reg(d, d->chip->type_base, i); ret = regmap_read(map, reg, &d->type_buf_def[i]); Loading Loading @@ -838,6 +901,11 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, kfree(d->mask_buf); kfree(d->status_buf); kfree(d->status_reg_buf); if (d->virt_buf) { for (i = 0; i < chip->num_virt_regs; i++) kfree(d->virt_buf[i]); kfree(d->virt_buf); } kfree(d); return ret; } Loading
include/linux/regmap.h +16 −0 Original line number Diff line number Diff line Loading @@ -1378,6 +1378,9 @@ struct regmap_irq_sub_irq_map { * status_base. Should contain num_regs arrays. * Can be provided for chips with more complex mapping than * 1.st bit to 1.st sub-reg, 2.nd bit to 2.nd sub-reg, ... * When used with not_fixed_stride, each one-element array * member contains offset calculated as address from each * peripheral to first peripheral. * @num_main_regs: Number of 'main status' irq registers for chips which have * main_status set. * Loading @@ -1390,6 +1393,7 @@ struct regmap_irq_sub_irq_map { * Using zero value is possible with @use_ack bit. * @wake_base: Base address for wake enables. If zero unsupported. * @type_base: Base address for irq type. If zero unsupported. * @virt_reg_base: Base addresses for extra config regs. * @irq_reg_stride: Stride to use for chips where registers are not contiguous. * @init_ack_masked: Ack all masked interrupts once during initalization. * @mask_invert: Inverted mask register: cleared bits are masked out. Loading @@ -1404,6 +1408,9 @@ struct regmap_irq_sub_irq_map { * @clear_on_unmask: For chips with interrupts cleared on read: read the status * registers before unmasking interrupts to clear any bits * set when they were masked. * @not_fixed_stride: Used when chip peripherals are not laid out with fixed * stride. Must be used with sub_reg_offsets containing the * offsets to each peripheral. * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * * @num_regs: Number of registers in each control bank. Loading @@ -1411,12 +1418,16 @@ struct regmap_irq_sub_irq_map { * assigned based on the index in the array of the interrupt. * @num_irqs: Number of descriptors. * @num_type_reg: Number of type registers. * @num_virt_regs: Number of non-standard irq configuration registers. * If zero unsupported. * @type_reg_stride: Stride to use for chips where type registers are not * contiguous. * @handle_pre_irq: Driver specific callback to handle interrupt from device * before regmap_irq_handler process the interrupts. * @handle_post_irq: Driver specific callback to handle interrupt from device * after handling the interrupts in regmap_irq_handler(). * @set_type_virt: Driver specific callback to extend regmap_irq_set_type() * and configure virt regs. * @irq_drv_data: Driver specific IRQ data which is passed as parameter when * driver specific pre/post interrupt handler is called. * Loading @@ -1438,6 +1449,7 @@ struct regmap_irq_chip { unsigned int ack_base; unsigned int wake_base; unsigned int type_base; unsigned int *virt_reg_base; unsigned int irq_reg_stride; bool mask_writeonly:1; bool init_ack_masked:1; Loading @@ -1450,6 +1462,7 @@ struct regmap_irq_chip { bool type_invert:1; bool type_in_mask:1; bool clear_on_unmask:1; bool not_fixed_stride:1; int num_regs; Loading @@ -1457,10 +1470,13 @@ struct regmap_irq_chip { int num_irqs; int num_type_reg; int num_virt_regs; unsigned int type_reg_stride; int (*handle_pre_irq)(void *irq_drv_data); int (*handle_post_irq)(void *irq_drv_data); int (*set_type_virt)(unsigned int **buf, unsigned int type, unsigned long hwirq, int reg); void *irq_drv_data; }; Loading