@@ -522,7 +522,8 @@ void __init orion_gpio_init(struct device_node *np,
ct->handler = handle_edge_irq;
ct->chip.name = ochip->chip.label;
- irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE,
+ irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE |
+ IRQ_GC_SEPARATE_MASK_REGISTERS,
IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
/* Setup irq domain on top of the generic chip. */
@@ -37,9 +37,11 @@ static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
static void s3c_irq_timer_ack(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_irq_chip_type(d);
+
u32 mask = (1 << 5) << (d->irq - gc->irq_base);
- irq_reg_writel(mask | gc->mask_cache, gc->reg_base);
+ irq_reg_writel(mask | *ct->pmask_cache, gc->reg_base);
}
/**
@@ -89,7 +91,7 @@ void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq)
irq_setup_generic_chip(s3c_tgc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
/* Clear the upper bits of the mask_cache*/
- s3c_tgc->mask_cache &= 0x1f;
+ *ct->pmask_cache &= 0x1f;
for (i = 0; i < num; i++, timer_irq++) {
irq_set_chained_handler(pirq[i], s3c_irq_demux_vic_timer);
@@ -68,7 +68,8 @@ void jz4740_irq_suspend(struct irq_data *data)
void jz4740_irq_resume(struct irq_data *data)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
- jz4740_irq_set_mask(gc, gc->mask_cache);
+ struct irq_chip_type *ct = irq_data_get_irq_chip_type(data);
+ jz4740_irq_set_mask(gc, *ct->pmask_cache);
}
static struct irqaction jz4740_cascade_action = {
@@ -301,48 +301,52 @@ static void mvebu_gpio_irq_ack(struct irq_data *d)
static void mvebu_gpio_edge_irq_mask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
struct mvebu_gpio_chip *mvchip = gc->private;
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache &= ~mask;
- writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+ *ct->pmask_cache &= ~mask;
+ writel_relaxed(*ct->pmask_cache, mvebu_gpioreg_edge_mask(mvchip));
irq_gc_unlock(gc);
}
static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
struct mvebu_gpio_chip *mvchip = gc->private;
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache |= mask;
- writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+ *ct->pmask_cache |= mask;
+ writel_relaxed(*ct->pmask_cache, mvebu_gpioreg_edge_mask(mvchip));
irq_gc_unlock(gc);
}
static void mvebu_gpio_level_irq_mask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
struct mvebu_gpio_chip *mvchip = gc->private;
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache &= ~mask;
- writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+ *ct->pmask_cache &= ~mask;
+ writel_relaxed(*ct->pmask_cache, mvebu_gpioreg_level_mask(mvchip));
irq_gc_unlock(gc);
}
static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
struct mvebu_gpio_chip *mvchip = gc->private;
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache |= mask;
- writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+ *ct->pmask_cache |= mask;
+ writel_relaxed(*ct->pmask_cache, mvebu_gpioreg_level_mask(mvchip));
irq_gc_unlock(gc);
}
@@ -649,7 +653,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
ct->handler = handle_edge_irq;
ct->chip.name = mvchip->chip.label;
- irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
+ irq_setup_generic_chip(gc, IRQ_MSK(ngpios),
+ IRQ_GC_SEPARATE_MASK_REGISTERS,
IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
/* Setup irq domain on top of the generic chip. */
@@ -636,6 +636,8 @@ struct irq_chip_regs {
* @regs: Register offsets for this chip
* @handler: Flow handler associated with this chip
* @type: Chip can handle these flow types
+ * @mask_cache: Cached mask register
+ * @pmask_cache: Pointer to cached mask register
*
* A irq_generic_chip can have several instances of irq_chip_type when
* it requires different functions and register offsets for different
@@ -646,6 +648,8 @@ struct irq_chip_type {
struct irq_chip_regs regs;
irq_flow_handler_t handler;
u32 type;
+ u32 mask_cache;
+ u32 *pmask_cache;
};
/**
@@ -654,7 +658,6 @@ struct irq_chip_type {
* @reg_base: Register base address (virtual)
* @irq_base: Interrupt base nr for this chip
* @irq_cnt: Number of interrupts handled by this chip
- * @mask_cache: Cached mask register
* @type_cache: Cached type register
* @polarity_cache: Cached polarity register
* @wake_enabled: Interrupt can wakeup from suspend
@@ -675,7 +678,6 @@ struct irq_chip_generic {
void __iomem *reg_base;
unsigned int irq_base;
unsigned int irq_cnt;
- u32 mask_cache;
u32 type_cache;
u32 polarity_cache;
u32 wake_enabled;
@@ -696,6 +698,7 @@ struct irq_chip_generic {
enum irq_gc_flags {
IRQ_GC_INIT_MASK_CACHE = 1 << 0,
IRQ_GC_INIT_NESTED_LOCK = 1 << 1,
+ IRQ_GC_SEPARATE_MASK_REGISTERS = 1 << 2,
};
/* Generic chip callback functions */
@@ -39,7 +39,7 @@ void irq_gc_mask_disable_reg(struct irq_data *d)
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.disable);
- gc->mask_cache &= ~mask;
+ *ct->pmask_cache &= ~mask;
irq_gc_unlock(gc);
}
@@ -57,8 +57,8 @@ void irq_gc_mask_set_bit(struct irq_data *d)
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache |= mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
+ *ct->pmask_cache |= mask;
+ irq_reg_writel(*ct->pmask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -76,8 +76,8 @@ void irq_gc_mask_clr_bit(struct irq_data *d)
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache &= ~mask;
- irq_reg_writel(gc->mask_cache, gc->reg_base + ct->regs.mask);
+ *ct->pmask_cache &= ~mask;
+ irq_reg_writel(*ct->pmask_cache, gc->reg_base + ct->regs.mask);
irq_gc_unlock(gc);
}
@@ -96,7 +96,7 @@ void irq_gc_unmask_enable_reg(struct irq_data *d)
irq_gc_lock(gc);
irq_reg_writel(mask, gc->reg_base + ct->regs.enable);
- gc->mask_cache |= mask;
+ *ct->pmask_cache |= mask;
irq_gc_unlock(gc);
}
@@ -246,9 +246,21 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
list_add_tail(&gc->list, &gc_list);
raw_spin_unlock(&gc_lock);
- /* Init mask cache ? */
- if (flags & IRQ_GC_INIT_MASK_CACHE)
- gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
+ for (i = 0; i < gc->num_ct; i++) {
+ if (flags & IRQ_GC_SEPARATE_MASK_REGISTERS)
+ /* Define mask cache pointer */
+ ct[i].pmask_cache = &ct[i].mask_cache;
+ else
+ /* They all point to the same mask cache */
+ ct[i].pmask_cache = &ct[0].mask_cache;
+
+ /* Init mask cache ? */
+ if ((flags & IRQ_GC_INIT_MASK_CACHE)
+ && ((flags & IRQ_GC_SEPARATE_MASK_REGISTER)
+ || (i == 0)))
+ *ct[i].pmask_cache =
+ irq_reg_readl(gc->reg_base + ct[i].regs.mask);
+ }
for (i = gc->irq_base; msk; msk >>= 1, i++) {
if (!(msk & 0x01))