Loading drivers/base/regmap/regmap-irq.c +99 −43 Original line number Diff line number Diff line Loading @@ -44,6 +44,8 @@ struct regmap_irq_chip_data { unsigned int irq_reg_stride; unsigned int type_reg_stride; bool clear_status:1; }; static inline const Loading Loading @@ -77,6 +79,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) int i, ret; u32 reg; u32 unmask_offset; u32 val; if (d->chip->runtime_pm) { ret = pm_runtime_get_sync(map->dev); Loading @@ -85,6 +88,20 @@ static void regmap_irq_sync_unlock(struct irq_data *data) ret); } 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); ret = regmap_read(map, reg, &val); if (ret) dev_err(d->map->dev, "Failed to clear the interrupt status bits\n"); } d->clear_status = false; } /* * If there's been a change in the mask write it back to the * hardware. We rely on the use of the regmap core cache to Loading Loading @@ -157,6 +174,8 @@ static void regmap_irq_sync_unlock(struct irq_data *data) } } /* Don't update the type bits if we're using mask bits for irq type. */ if (!d->chip->type_in_mask) { for (i = 0; i < d->chip->num_type_reg; i++) { if (!d->type_buf_def[i]) continue; Loading @@ -172,6 +191,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) dev_err(d->map->dev, "Failed to sync type in %x\n", reg); } } if (d->chip->runtime_pm) pm_runtime_put(map->dev); Loading @@ -194,8 +214,30 @@ static void regmap_irq_enable(struct irq_data *data) struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); struct regmap *map = d->map; const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); unsigned int mask, type; type = irq_data->type.type_falling_val | irq_data->type.type_rising_val; d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~irq_data->mask; /* * The type_in_mask flag means that the underlying hardware uses * separate mask bits for rising and falling edge interrupts, but * we want to make them into a single virtual interrupt with * configurable edge. * * If the interrupt we're enabling defines the falling or rising * masks then instead of using the regular mask bits for this * interrupt, use the value previously written to the type buffer * at the corresponding offset in regmap_irq_set_type(). */ if (d->chip->type_in_mask && type) mask = d->type_buf[irq_data->reg_offset / map->reg_stride]; else mask = irq_data->mask; if (d->chip->clear_on_unmask) d->clear_status = true; d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~mask; } static void regmap_irq_disable(struct irq_data *data) Loading @@ -212,27 +254,42 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type) struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); struct regmap *map = d->map; const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); int reg = irq_data->type_reg_offset / map->reg_stride; int reg; const struct regmap_irq_type *t = &irq_data->type; if (!(irq_data->type_rising_mask | irq_data->type_falling_mask)) return 0; if ((t->types_supported & type) != type) return -ENOTSUPP; d->type_buf[reg] &= ~(irq_data->type_falling_mask | irq_data->type_rising_mask); reg = t->type_reg_offset / map->reg_stride; if (t->type_reg_mask) d->type_buf[reg] &= ~t->type_reg_mask; else d->type_buf[reg] &= ~(t->type_falling_val | t->type_rising_val | t->type_level_low_val | t->type_level_high_val); switch (type) { case IRQ_TYPE_EDGE_FALLING: d->type_buf[reg] |= irq_data->type_falling_mask; d->type_buf[reg] |= t->type_falling_val; break; case IRQ_TYPE_EDGE_RISING: d->type_buf[reg] |= irq_data->type_rising_mask; d->type_buf[reg] |= t->type_rising_val; break; case IRQ_TYPE_EDGE_BOTH: d->type_buf[reg] |= (irq_data->type_falling_mask | irq_data->type_rising_mask); d->type_buf[reg] |= (t->type_falling_val | t->type_rising_val); break; case IRQ_TYPE_LEVEL_HIGH: d->type_buf[reg] |= t->type_level_high_val; break; case IRQ_TYPE_LEVEL_LOW: d->type_buf[reg] |= t->type_level_low_val; break; default: return -EINVAL; } Loading Loading @@ -430,12 +487,16 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, struct regmap_irq_chip_data *d; int i; int ret = -ENOMEM; int num_type_reg; u32 reg; u32 unmask_offset; if (chip->num_regs <= 0) return -EINVAL; if (chip->clear_on_unmask && (chip->ack_base || chip->use_ack)) return -EINVAL; for (i = 0; i < chip->num_irqs; i++) { if (chip->irqs[i].reg_offset % map->reg_stride) return -EINVAL; Loading Loading @@ -479,13 +540,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, goto err_alloc; } if (chip->num_type_reg) { d->type_buf_def = kcalloc(chip->num_type_reg, num_type_reg = chip->type_in_mask ? chip->num_regs : chip->num_type_reg; if (num_type_reg) { d->type_buf_def = kcalloc(num_type_reg, sizeof(unsigned int), GFP_KERNEL); if (!d->type_buf_def) goto err_alloc; d->type_buf = kcalloc(chip->num_type_reg, sizeof(unsigned int), d->type_buf = kcalloc(num_type_reg, sizeof(unsigned int), GFP_KERNEL); if (!d->type_buf) goto err_alloc; Loading Loading @@ -600,27 +662,21 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, } } if (chip->num_type_reg) { for (i = 0; i < chip->num_irqs; i++) { reg = chip->irqs[i].type_reg_offset / map->reg_stride; d->type_buf_def[reg] |= chip->irqs[i].type_rising_mask | chip->irqs[i].type_falling_mask; } if (chip->num_type_reg && !chip->type_in_mask) { for (i = 0; i < chip->num_type_reg; ++i) { if (!d->type_buf_def[i]) continue; reg = chip->type_base + (i * map->reg_stride * d->type_reg_stride); if (chip->type_invert) ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], 0xFF); else ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], 0x0); if (ret != 0) { dev_err(map->dev, "Failed to set type in 0x%x: %x\n", ret = regmap_read(map, reg, &d->type_buf_def[i]); if (d->chip->type_invert) d->type_buf_def[i] = ~d->type_buf_def[i]; if (ret) { dev_err(map->dev, "Failed to get type defaults at 0x%x: %d\n", reg, ret); goto err_alloc; } Loading drivers/gpio/gpio-max77620.c +64 −32 Original line number Diff line number Diff line Loading @@ -25,60 +25,92 @@ struct max77620_gpio { static const struct regmap_irq max77620_gpio_irqs[] = { [0] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE0, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE0, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 0, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [1] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE1, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE1, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 1, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [2] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE2, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE2, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 2, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [3] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE3, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE3, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 3, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [4] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE4, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE4, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 4, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [5] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE5, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE5, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 5, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [6] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE6, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE6, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 6, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [7] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE7, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE7, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 7, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, }; Loading include/linux/regmap.h +35 −6 Original line number Diff line number Diff line Loading @@ -1089,27 +1089,48 @@ int regmap_fields_read(struct regmap_field *field, unsigned int id, int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id, unsigned int mask, unsigned int val, bool *change, bool async, bool force); /** * struct regmap_irq_type - IRQ type definitions. * * @type_reg_offset: Offset register for the irq type setting. * @type_rising_val: Register value to configure RISING type irq. * @type_falling_val: Register value to configure FALLING type irq. * @type_level_low_val: Register value to configure LEVEL_LOW type irq. * @type_level_high_val: Register value to configure LEVEL_HIGH type irq. * @types_supported: logical OR of IRQ_TYPE_* flags indicating supported types. */ struct regmap_irq_type { unsigned int type_reg_offset; unsigned int type_reg_mask; unsigned int type_rising_val; unsigned int type_falling_val; unsigned int type_level_low_val; unsigned int type_level_high_val; unsigned int types_supported; }; /** * struct regmap_irq - Description of an IRQ for the generic regmap irq_chip. * * @reg_offset: Offset of the status/mask register within the bank * @mask: Mask used to flag/control the register. * @type_reg_offset: Offset register for the irq type setting. * @type_rising_mask: Mask bit to configure RISING type irq. * @type_falling_mask: Mask bit to configure FALLING type irq. * @type: IRQ trigger type setting details if supported. */ struct regmap_irq { unsigned int reg_offset; unsigned int mask; unsigned int type_reg_offset; unsigned int type_rising_mask; unsigned int type_falling_mask; struct regmap_irq_type type; }; #define REGMAP_IRQ_REG(_irq, _off, _mask) \ [_irq] = { .reg_offset = (_off), .mask = (_mask) } #define REGMAP_IRQ_REG_LINE(_id, _reg_bits) \ [_id] = { \ .mask = BIT((_id) % (_reg_bits)), \ .reg_offset = (_id) / (_reg_bits), \ } /** * struct regmap_irq_chip - Description of a generic regmap irq_chip. * Loading @@ -1131,6 +1152,12 @@ struct regmap_irq { * @ack_invert: Inverted ack register: cleared bits for ack. * @wake_invert: Inverted wake register: cleared bits are wake enabled. * @type_invert: Invert the type flags. * @type_in_mask: Use the mask registers for controlling irq type. For * interrupts defining type_rising/falling_mask use mask_base * for edge configuration and never update bits in type_base. * @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. * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * * @num_regs: Number of registers in each control bank. Loading Loading @@ -1169,6 +1196,8 @@ struct regmap_irq_chip { bool wake_invert:1; bool runtime_pm:1; bool type_invert:1; bool type_in_mask:1; bool clear_on_unmask:1; int num_regs; Loading Loading
drivers/base/regmap/regmap-irq.c +99 −43 Original line number Diff line number Diff line Loading @@ -44,6 +44,8 @@ struct regmap_irq_chip_data { unsigned int irq_reg_stride; unsigned int type_reg_stride; bool clear_status:1; }; static inline const Loading Loading @@ -77,6 +79,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) int i, ret; u32 reg; u32 unmask_offset; u32 val; if (d->chip->runtime_pm) { ret = pm_runtime_get_sync(map->dev); Loading @@ -85,6 +88,20 @@ static void regmap_irq_sync_unlock(struct irq_data *data) ret); } 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); ret = regmap_read(map, reg, &val); if (ret) dev_err(d->map->dev, "Failed to clear the interrupt status bits\n"); } d->clear_status = false; } /* * If there's been a change in the mask write it back to the * hardware. We rely on the use of the regmap core cache to Loading Loading @@ -157,6 +174,8 @@ static void regmap_irq_sync_unlock(struct irq_data *data) } } /* Don't update the type bits if we're using mask bits for irq type. */ if (!d->chip->type_in_mask) { for (i = 0; i < d->chip->num_type_reg; i++) { if (!d->type_buf_def[i]) continue; Loading @@ -172,6 +191,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data) dev_err(d->map->dev, "Failed to sync type in %x\n", reg); } } if (d->chip->runtime_pm) pm_runtime_put(map->dev); Loading @@ -194,8 +214,30 @@ static void regmap_irq_enable(struct irq_data *data) struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); struct regmap *map = d->map; const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); unsigned int mask, type; type = irq_data->type.type_falling_val | irq_data->type.type_rising_val; d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~irq_data->mask; /* * The type_in_mask flag means that the underlying hardware uses * separate mask bits for rising and falling edge interrupts, but * we want to make them into a single virtual interrupt with * configurable edge. * * If the interrupt we're enabling defines the falling or rising * masks then instead of using the regular mask bits for this * interrupt, use the value previously written to the type buffer * at the corresponding offset in regmap_irq_set_type(). */ if (d->chip->type_in_mask && type) mask = d->type_buf[irq_data->reg_offset / map->reg_stride]; else mask = irq_data->mask; if (d->chip->clear_on_unmask) d->clear_status = true; d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~mask; } static void regmap_irq_disable(struct irq_data *data) Loading @@ -212,27 +254,42 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type) struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); struct regmap *map = d->map; const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); int reg = irq_data->type_reg_offset / map->reg_stride; int reg; const struct regmap_irq_type *t = &irq_data->type; if (!(irq_data->type_rising_mask | irq_data->type_falling_mask)) return 0; if ((t->types_supported & type) != type) return -ENOTSUPP; d->type_buf[reg] &= ~(irq_data->type_falling_mask | irq_data->type_rising_mask); reg = t->type_reg_offset / map->reg_stride; if (t->type_reg_mask) d->type_buf[reg] &= ~t->type_reg_mask; else d->type_buf[reg] &= ~(t->type_falling_val | t->type_rising_val | t->type_level_low_val | t->type_level_high_val); switch (type) { case IRQ_TYPE_EDGE_FALLING: d->type_buf[reg] |= irq_data->type_falling_mask; d->type_buf[reg] |= t->type_falling_val; break; case IRQ_TYPE_EDGE_RISING: d->type_buf[reg] |= irq_data->type_rising_mask; d->type_buf[reg] |= t->type_rising_val; break; case IRQ_TYPE_EDGE_BOTH: d->type_buf[reg] |= (irq_data->type_falling_mask | irq_data->type_rising_mask); d->type_buf[reg] |= (t->type_falling_val | t->type_rising_val); break; case IRQ_TYPE_LEVEL_HIGH: d->type_buf[reg] |= t->type_level_high_val; break; case IRQ_TYPE_LEVEL_LOW: d->type_buf[reg] |= t->type_level_low_val; break; default: return -EINVAL; } Loading Loading @@ -430,12 +487,16 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, struct regmap_irq_chip_data *d; int i; int ret = -ENOMEM; int num_type_reg; u32 reg; u32 unmask_offset; if (chip->num_regs <= 0) return -EINVAL; if (chip->clear_on_unmask && (chip->ack_base || chip->use_ack)) return -EINVAL; for (i = 0; i < chip->num_irqs; i++) { if (chip->irqs[i].reg_offset % map->reg_stride) return -EINVAL; Loading Loading @@ -479,13 +540,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, goto err_alloc; } if (chip->num_type_reg) { d->type_buf_def = kcalloc(chip->num_type_reg, num_type_reg = chip->type_in_mask ? chip->num_regs : chip->num_type_reg; if (num_type_reg) { d->type_buf_def = kcalloc(num_type_reg, sizeof(unsigned int), GFP_KERNEL); if (!d->type_buf_def) goto err_alloc; d->type_buf = kcalloc(chip->num_type_reg, sizeof(unsigned int), d->type_buf = kcalloc(num_type_reg, sizeof(unsigned int), GFP_KERNEL); if (!d->type_buf) goto err_alloc; Loading Loading @@ -600,27 +662,21 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, } } if (chip->num_type_reg) { for (i = 0; i < chip->num_irqs; i++) { reg = chip->irqs[i].type_reg_offset / map->reg_stride; d->type_buf_def[reg] |= chip->irqs[i].type_rising_mask | chip->irqs[i].type_falling_mask; } if (chip->num_type_reg && !chip->type_in_mask) { for (i = 0; i < chip->num_type_reg; ++i) { if (!d->type_buf_def[i]) continue; reg = chip->type_base + (i * map->reg_stride * d->type_reg_stride); if (chip->type_invert) ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], 0xFF); else ret = regmap_irq_update_bits(d, reg, d->type_buf_def[i], 0x0); if (ret != 0) { dev_err(map->dev, "Failed to set type in 0x%x: %x\n", ret = regmap_read(map, reg, &d->type_buf_def[i]); if (d->chip->type_invert) d->type_buf_def[i] = ~d->type_buf_def[i]; if (ret) { dev_err(map->dev, "Failed to get type defaults at 0x%x: %d\n", reg, ret); goto err_alloc; } Loading
drivers/gpio/gpio-max77620.c +64 −32 Original line number Diff line number Diff line Loading @@ -25,60 +25,92 @@ struct max77620_gpio { static const struct regmap_irq max77620_gpio_irqs[] = { [0] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE0, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE0, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 0, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [1] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE1, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE1, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 1, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [2] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE2, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE2, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 2, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [3] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE3, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE3, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 3, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [4] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE4, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE4, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 4, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [5] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE5, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE5, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 5, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [6] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE6, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE6, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 6, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, [7] = { .mask = MAX77620_IRQ_LVL2_GPIO_EDGE7, .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, .reg_offset = 0, .mask = MAX77620_IRQ_LVL2_GPIO_EDGE7, .type = { .type_rising_val = MAX77620_CNFG_GPIO_INT_RISING, .type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING, .type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK, .type_reg_offset = 7, .types_supported = IRQ_TYPE_EDGE_BOTH, }, }, }; Loading
include/linux/regmap.h +35 −6 Original line number Diff line number Diff line Loading @@ -1089,27 +1089,48 @@ int regmap_fields_read(struct regmap_field *field, unsigned int id, int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id, unsigned int mask, unsigned int val, bool *change, bool async, bool force); /** * struct regmap_irq_type - IRQ type definitions. * * @type_reg_offset: Offset register for the irq type setting. * @type_rising_val: Register value to configure RISING type irq. * @type_falling_val: Register value to configure FALLING type irq. * @type_level_low_val: Register value to configure LEVEL_LOW type irq. * @type_level_high_val: Register value to configure LEVEL_HIGH type irq. * @types_supported: logical OR of IRQ_TYPE_* flags indicating supported types. */ struct regmap_irq_type { unsigned int type_reg_offset; unsigned int type_reg_mask; unsigned int type_rising_val; unsigned int type_falling_val; unsigned int type_level_low_val; unsigned int type_level_high_val; unsigned int types_supported; }; /** * struct regmap_irq - Description of an IRQ for the generic regmap irq_chip. * * @reg_offset: Offset of the status/mask register within the bank * @mask: Mask used to flag/control the register. * @type_reg_offset: Offset register for the irq type setting. * @type_rising_mask: Mask bit to configure RISING type irq. * @type_falling_mask: Mask bit to configure FALLING type irq. * @type: IRQ trigger type setting details if supported. */ struct regmap_irq { unsigned int reg_offset; unsigned int mask; unsigned int type_reg_offset; unsigned int type_rising_mask; unsigned int type_falling_mask; struct regmap_irq_type type; }; #define REGMAP_IRQ_REG(_irq, _off, _mask) \ [_irq] = { .reg_offset = (_off), .mask = (_mask) } #define REGMAP_IRQ_REG_LINE(_id, _reg_bits) \ [_id] = { \ .mask = BIT((_id) % (_reg_bits)), \ .reg_offset = (_id) / (_reg_bits), \ } /** * struct regmap_irq_chip - Description of a generic regmap irq_chip. * Loading @@ -1131,6 +1152,12 @@ struct regmap_irq { * @ack_invert: Inverted ack register: cleared bits for ack. * @wake_invert: Inverted wake register: cleared bits are wake enabled. * @type_invert: Invert the type flags. * @type_in_mask: Use the mask registers for controlling irq type. For * interrupts defining type_rising/falling_mask use mask_base * for edge configuration and never update bits in type_base. * @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. * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * * @num_regs: Number of registers in each control bank. Loading Loading @@ -1169,6 +1196,8 @@ struct regmap_irq_chip { bool wake_invert:1; bool runtime_pm:1; bool type_invert:1; bool type_in_mask:1; bool clear_on_unmask:1; int num_regs; Loading