Commit 8480ca47 authored by Doug Berger's avatar Doug Berger Committed by Marc Zyngier

irqchip/brcmstb-l2: Abstract register accesses

Added register block offsets to the brcmstb_l2_intc_data structure
for the status and mask registers to support reading the active
interupts in an abstracted way.  It seems like an irq_chip method
should have been provided for this, but it's not there yet.

Abstracted the implementation of the handler, suspend, and resume
functions to not use any hard coded register offsets.
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDoug Berger <opendmb@gmail.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 49aa6ef0
......@@ -43,6 +43,8 @@
struct brcmstb_l2_intc_data {
struct irq_domain *domain;
struct irq_chip_generic *gc;
int status_offset;
int mask_offset;
bool can_wake;
u32 saved_mask; /* for suspend/resume */
};
......@@ -82,8 +84,8 @@ static void brcmstb_l2_intc_irq_handle(struct irq_desc *desc)
chained_irq_enter(chip, desc);
status = irq_reg_readl(b->gc, CPU_STATUS) &
~(irq_reg_readl(b->gc, CPU_MASK_STATUS));
status = irq_reg_readl(b->gc, b->status_offset) &
~(irq_reg_readl(b->gc, b->mask_offset));
if (status == 0) {
raw_spin_lock(&desc->lock);
......@@ -104,16 +106,17 @@ static void brcmstb_l2_intc_irq_handle(struct irq_desc *desc)
static void brcmstb_l2_intc_suspend(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 brcmstb_l2_intc_data *b = gc->private;
irq_gc_lock(gc);
/* Save the current mask */
b->saved_mask = irq_reg_readl(gc, CPU_MASK_STATUS);
b->saved_mask = irq_reg_readl(gc, ct->regs.mask);
if (b->can_wake) {
/* Program the wakeup mask */
irq_reg_writel(gc, ~gc->wake_active, CPU_MASK_SET);
irq_reg_writel(gc, gc->wake_active, CPU_MASK_CLEAR);
irq_reg_writel(gc, ~gc->wake_active, ct->regs.disable);
irq_reg_writel(gc, gc->wake_active, ct->regs.enable);
}
irq_gc_unlock(gc);
}
......@@ -121,15 +124,19 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d)
static void brcmstb_l2_intc_resume(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 brcmstb_l2_intc_data *b = gc->private;
irq_gc_lock(gc);
/* Clear unmasked non-wakeup interrupts */
irq_reg_writel(gc, ~b->saved_mask & ~gc->wake_active, CPU_CLEAR);
if (ct->chip.irq_ack != irq_gc_noop) {
/* Clear unmasked non-wakeup interrupts */
irq_reg_writel(gc, ~b->saved_mask & ~gc->wake_active,
ct->regs.ack);
}
/* Restore the saved mask */
irq_reg_writel(gc, b->saved_mask, CPU_MASK_SET);
irq_reg_writel(gc, ~b->saved_mask, CPU_MASK_CLEAR);
irq_reg_writel(gc, b->saved_mask, ct->regs.disable);
irq_reg_writel(gc, ~b->saved_mask, ct->regs.enable);
irq_gc_unlock(gc);
}
......@@ -199,6 +206,9 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np,
data->gc = irq_get_domain_generic_chip(data->domain, 0);
data->gc->reg_base = base;
data->gc->private = data;
data->status_offset = CPU_STATUS;
data->mask_offset = CPU_MASK_STATUS;
ct = data->gc->chip_types;
ct->chip.irq_ack = irq_gc_ack_set_bit;
......@@ -207,6 +217,7 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np,
ct->chip.irq_mask = irq_gc_mask_disable_reg;
ct->chip.irq_mask_ack = brcmstb_l2_mask_and_ack;
ct->regs.disable = CPU_MASK_SET;
ct->regs.mask = CPU_MASK_STATUS;
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
ct->regs.enable = CPU_MASK_CLEAR;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment