diff options
Diffstat (limited to 'drivers/irqchip/irq-bcm2835.c')
| -rw-r--r-- | drivers/irqchip/irq-bcm2835.c | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c index 44d7c38dde47..1e384c870350 100644 --- a/drivers/irqchip/irq-bcm2835.c +++ b/drivers/irqchip/irq-bcm2835.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2010 Broadcom * Copyright 2012 Simon Arlott, Chris Boot, Stephen Warren * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * * Quirk 1: Shortcut interrupts don't set the bank 1/2 register pending bits * * If an interrupt fires on bank 1 that isn't in the shortcuts list, bit 8 @@ -70,6 +61,7 @@ | SHORTCUT1_MASK | SHORTCUT2_MASK) #define REG_FIQ_CONTROL 0x0c +#define FIQ_CONTROL_ENABLE BIT(7) #define NR_BANKS 3 #define IRQS_PER_BANK 32 @@ -110,7 +102,9 @@ static void armctrl_unmask_irq(struct irq_data *d) static struct irq_chip armctrl_chip = { .name = "ARMCTRL-level", .irq_mask = armctrl_mask_irq, - .irq_unmask = armctrl_unmask_irq + .irq_unmask = armctrl_unmask_irq, + .flags = IRQCHIP_MASK_ON_SUSPEND | + IRQCHIP_SKIP_SET_WAKE, }; static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, @@ -144,16 +138,16 @@ static int __init armctrl_of_init(struct device_node *node, { void __iomem *base; int irq, b, i; + u32 reg; base = of_iomap(node, 0); if (!base) - panic("%s: unable to map IC registers\n", - node->full_name); + panic("%pOF: unable to map IC registers\n", node); - intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0), + intc.domain = irq_domain_create_linear(of_fwnode_handle(node), MAKE_HWIRQ(NR_BANKS, 0), &armctrl_ops, NULL); if (!intc.domain) - panic("%s: unable to create IRQ domain\n", node->full_name); + panic("%pOF: unable to create IRQ domain\n", node); for (b = 0; b < NR_BANKS; b++) { intc.pending[b] = base + reg_pending[b]; @@ -167,14 +161,27 @@ static int __init armctrl_of_init(struct device_node *node, handle_level_irq); irq_set_probe(irq); } + + reg = readl_relaxed(intc.enable[b]); + if (reg) { + writel_relaxed(reg, intc.disable[b]); + pr_err(FW_BUG "Bootloader left irq enabled: " + "bank %d irq %*pbl\n", b, IRQS_PER_BANK, ®); + } + } + + reg = readl_relaxed(base + REG_FIQ_CONTROL); + if (reg & FIQ_CONTROL_ENABLE) { + writel_relaxed(0, base + REG_FIQ_CONTROL); + pr_err(FW_BUG "Bootloader left fiq enabled\n"); } if (is_2836) { int parent_irq = irq_of_parse_and_map(node, 0); if (!parent_irq) { - panic("%s: unable to get parent interrupt.\n", - node->full_name); + panic("%pOF: unable to get parent interrupt.\n", + node); } irq_set_chained_handler(parent_irq, bcm2836_chained_handle_irq); } else { @@ -241,7 +248,7 @@ static void __exception_irq_entry bcm2835_handle_irq( u32 hwirq; while ((hwirq = get_next_armctrl_hwirq()) != ~0) - handle_domain_irq(intc.domain, hwirq, regs); + generic_handle_domain_irq(intc.domain, hwirq); } static void bcm2836_chained_handle_irq(struct irq_desc *desc) @@ -249,7 +256,7 @@ static void bcm2836_chained_handle_irq(struct irq_desc *desc) u32 hwirq; while ((hwirq = get_next_armctrl_hwirq()) != ~0) - generic_handle_irq(irq_linear_revmap(intc.domain, hwirq)); + generic_handle_domain_irq(intc.domain, hwirq); } IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", |
