forked from Minki/linux
irqchip/stm32: Add falling pending register support
This patch adds support of rising/falling pending registers. Falling pending register (fpr) is needed for next revision. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
parent
ea80aa2a1a
commit
be6230f0c2
@ -23,16 +23,20 @@ struct stm32_exti_bank {
|
|||||||
u32 rtsr_ofst;
|
u32 rtsr_ofst;
|
||||||
u32 ftsr_ofst;
|
u32 ftsr_ofst;
|
||||||
u32 swier_ofst;
|
u32 swier_ofst;
|
||||||
u32 pr_ofst;
|
u32 rpr_ofst;
|
||||||
|
u32 fpr_ofst;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define UNDEF_REG ~0
|
||||||
|
|
||||||
static const struct stm32_exti_bank stm32f4xx_exti_b1 = {
|
static const struct stm32_exti_bank stm32f4xx_exti_b1 = {
|
||||||
.imr_ofst = 0x00,
|
.imr_ofst = 0x00,
|
||||||
.emr_ofst = 0x04,
|
.emr_ofst = 0x04,
|
||||||
.rtsr_ofst = 0x08,
|
.rtsr_ofst = 0x08,
|
||||||
.ftsr_ofst = 0x0C,
|
.ftsr_ofst = 0x0C,
|
||||||
.swier_ofst = 0x10,
|
.swier_ofst = 0x10,
|
||||||
.pr_ofst = 0x14,
|
.rpr_ofst = 0x14,
|
||||||
|
.fpr_ofst = UNDEF_REG,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = {
|
static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = {
|
||||||
@ -45,7 +49,8 @@ static const struct stm32_exti_bank stm32h7xx_exti_b1 = {
|
|||||||
.rtsr_ofst = 0x00,
|
.rtsr_ofst = 0x00,
|
||||||
.ftsr_ofst = 0x04,
|
.ftsr_ofst = 0x04,
|
||||||
.swier_ofst = 0x08,
|
.swier_ofst = 0x08,
|
||||||
.pr_ofst = 0x88,
|
.rpr_ofst = 0x88,
|
||||||
|
.fpr_ofst = UNDEF_REG,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct stm32_exti_bank stm32h7xx_exti_b2 = {
|
static const struct stm32_exti_bank stm32h7xx_exti_b2 = {
|
||||||
@ -54,7 +59,8 @@ static const struct stm32_exti_bank stm32h7xx_exti_b2 = {
|
|||||||
.rtsr_ofst = 0x20,
|
.rtsr_ofst = 0x20,
|
||||||
.ftsr_ofst = 0x24,
|
.ftsr_ofst = 0x24,
|
||||||
.swier_ofst = 0x28,
|
.swier_ofst = 0x28,
|
||||||
.pr_ofst = 0x98,
|
.rpr_ofst = 0x98,
|
||||||
|
.fpr_ofst = UNDEF_REG,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct stm32_exti_bank stm32h7xx_exti_b3 = {
|
static const struct stm32_exti_bank stm32h7xx_exti_b3 = {
|
||||||
@ -63,7 +69,8 @@ static const struct stm32_exti_bank stm32h7xx_exti_b3 = {
|
|||||||
.rtsr_ofst = 0x40,
|
.rtsr_ofst = 0x40,
|
||||||
.ftsr_ofst = 0x44,
|
.ftsr_ofst = 0x44,
|
||||||
.swier_ofst = 0x48,
|
.swier_ofst = 0x48,
|
||||||
.pr_ofst = 0xA8,
|
.rpr_ofst = 0xA8,
|
||||||
|
.fpr_ofst = UNDEF_REG,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = {
|
static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = {
|
||||||
@ -75,8 +82,13 @@ static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = {
|
|||||||
static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
|
static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
|
||||||
{
|
{
|
||||||
const struct stm32_exti_bank *stm32_bank = gc->private;
|
const struct stm32_exti_bank *stm32_bank = gc->private;
|
||||||
|
unsigned long pending;
|
||||||
|
|
||||||
return irq_reg_readl(gc, stm32_bank->pr_ofst);
|
pending = irq_reg_readl(gc, stm32_bank->rpr_ofst);
|
||||||
|
if (stm32_bank->fpr_ofst != UNDEF_REG)
|
||||||
|
pending |= irq_reg_readl(gc, stm32_bank->fpr_ofst);
|
||||||
|
|
||||||
|
return pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stm32_irq_handler(struct irq_desc *desc)
|
static void stm32_irq_handler(struct irq_desc *desc)
|
||||||
@ -85,7 +97,6 @@ static void stm32_irq_handler(struct irq_desc *desc)
|
|||||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||||
unsigned int virq, nbanks = domain->gc->num_chips;
|
unsigned int virq, nbanks = domain->gc->num_chips;
|
||||||
struct irq_chip_generic *gc;
|
struct irq_chip_generic *gc;
|
||||||
const struct stm32_exti_bank *stm32_bank;
|
|
||||||
unsigned long pending;
|
unsigned long pending;
|
||||||
int n, i, irq_base = 0;
|
int n, i, irq_base = 0;
|
||||||
|
|
||||||
@ -93,7 +104,6 @@ static void stm32_irq_handler(struct irq_desc *desc)
|
|||||||
|
|
||||||
for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) {
|
for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) {
|
||||||
gc = irq_get_domain_generic_chip(domain, irq_base);
|
gc = irq_get_domain_generic_chip(domain, irq_base);
|
||||||
stm32_bank = gc->private;
|
|
||||||
|
|
||||||
while ((pending = stm32_exti_pending(gc))) {
|
while ((pending = stm32_exti_pending(gc))) {
|
||||||
for_each_set_bit(n, &pending, IRQS_PER_BANK) {
|
for_each_set_bit(n, &pending, IRQS_PER_BANK) {
|
||||||
@ -192,6 +202,20 @@ static const struct irq_domain_ops irq_exti_domain_ops = {
|
|||||||
.free = stm32_exti_free,
|
.free = stm32_exti_free,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void stm32_irq_ack(struct irq_data *d)
|
||||||
|
{
|
||||||
|
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||||
|
const struct stm32_exti_bank *stm32_bank = gc->private;
|
||||||
|
|
||||||
|
irq_gc_lock(gc);
|
||||||
|
|
||||||
|
irq_reg_writel(gc, d->mask, stm32_bank->rpr_ofst);
|
||||||
|
if (stm32_bank->fpr_ofst != UNDEF_REG)
|
||||||
|
irq_reg_writel(gc, d->mask, stm32_bank->fpr_ofst);
|
||||||
|
|
||||||
|
irq_gc_unlock(gc);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
__init stm32_exti_init(const struct stm32_exti_bank **stm32_exti_banks,
|
__init stm32_exti_init(const struct stm32_exti_bank **stm32_exti_banks,
|
||||||
int bank_nr, struct device_node *node)
|
int bank_nr, struct device_node *node)
|
||||||
@ -233,12 +257,11 @@ __init stm32_exti_init(const struct stm32_exti_bank **stm32_exti_banks,
|
|||||||
|
|
||||||
gc->reg_base = base;
|
gc->reg_base = base;
|
||||||
gc->chip_types->type = IRQ_TYPE_EDGE_BOTH;
|
gc->chip_types->type = IRQ_TYPE_EDGE_BOTH;
|
||||||
gc->chip_types->chip.irq_ack = irq_gc_ack_set_bit;
|
gc->chip_types->chip.irq_ack = stm32_irq_ack;
|
||||||
gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit;
|
gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit;
|
||||||
gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit;
|
gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit;
|
||||||
gc->chip_types->chip.irq_set_type = stm32_irq_set_type;
|
gc->chip_types->chip.irq_set_type = stm32_irq_set_type;
|
||||||
gc->chip_types->chip.irq_set_wake = stm32_irq_set_wake;
|
gc->chip_types->chip.irq_set_wake = stm32_irq_set_wake;
|
||||||
gc->chip_types->regs.ack = stm32_bank->pr_ofst;
|
|
||||||
gc->chip_types->regs.mask = stm32_bank->imr_ofst;
|
gc->chip_types->regs.mask = stm32_bank->imr_ofst;
|
||||||
gc->private = (void *)stm32_bank;
|
gc->private = (void *)stm32_bank;
|
||||||
|
|
||||||
@ -255,7 +278,9 @@ __init stm32_exti_init(const struct stm32_exti_bank **stm32_exti_banks,
|
|||||||
writel_relaxed(0, base + stm32_bank->emr_ofst);
|
writel_relaxed(0, base + stm32_bank->emr_ofst);
|
||||||
writel_relaxed(0, base + stm32_bank->rtsr_ofst);
|
writel_relaxed(0, base + stm32_bank->rtsr_ofst);
|
||||||
writel_relaxed(0, base + stm32_bank->ftsr_ofst);
|
writel_relaxed(0, base + stm32_bank->ftsr_ofst);
|
||||||
writel_relaxed(~0UL, base + stm32_bank->pr_ofst);
|
writel_relaxed(~0UL, base + stm32_bank->rpr_ofst);
|
||||||
|
if (stm32_bank->fpr_ofst != UNDEF_REG)
|
||||||
|
writel_relaxed(~0UL, base + stm32_bank->fpr_ofst);
|
||||||
|
|
||||||
pr_info("%s: bank%d, External IRQs available:%#x\n",
|
pr_info("%s: bank%d, External IRQs available:%#x\n",
|
||||||
node->full_name, i, irqs_mask);
|
node->full_name, i, irqs_mask);
|
||||||
|
Loading…
Reference in New Issue
Block a user