diff options
Diffstat (limited to 'arch/arm/mach-iop32x/irq.c')
-rw-r--r-- | arch/arm/mach-iop32x/irq.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c new file mode 100644 index 000000000..6dca7e97d --- /dev/null +++ b/arch/arm/mach-iop32x/irq.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-iop32x/irq.c + * + * Generic IOP32X IRQ handling functionality + * + * Author: Rory Bolt <rorybolt@pacbell.net> + * Copyright (C) 2002 Rory Bolt + */ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <asm/mach/irq.h> +#include <asm/irq.h> +#include <asm/mach-types.h> + +#include "hardware.h" + +static u32 iop32x_mask; + +static void intctl_write(u32 val) +{ + asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val)); +} + +static void intstr_write(u32 val) +{ + asm volatile("mcr p6, 0, %0, c4, c0, 0" : : "r" (val)); +} + +static u32 iintsrc_read(void) +{ + int irq; + + asm volatile("mrc p6, 0, %0, c8, c0, 0" : "=r" (irq)); + + return irq; +} + +static void +iop32x_irq_mask(struct irq_data *d) +{ + iop32x_mask &= ~(1 << (d->irq - 1)); + intctl_write(iop32x_mask); +} + +static void +iop32x_irq_unmask(struct irq_data *d) +{ + iop32x_mask |= 1 << (d->irq - 1); + intctl_write(iop32x_mask); +} + +struct irq_chip ext_chip = { + .name = "IOP32x", + .irq_ack = iop32x_irq_mask, + .irq_mask = iop32x_irq_mask, + .irq_unmask = iop32x_irq_unmask, +}; + +static void iop_handle_irq(struct pt_regs *regs) +{ + u32 mask; + + iop_enable_cp6(); + + do { + mask = iintsrc_read(); + if (mask) + generic_handle_irq(fls(mask)); + } while (mask); +} + +void __init iop32x_init_irq(void) +{ + int i; + + iop_init_cp6_handler(); + set_handle_irq(iop_handle_irq); + + intctl_write(0); + intstr_write(0); + if (machine_is_glantank() || + machine_is_iq80321() || + machine_is_iq31244() || + machine_is_n2100() || + machine_is_em7210()) + *IOP3XX_PCIIRSR = 0x0f; + + for (i = 1; i < NR_IRQS; i++) { + irq_set_chip_and_handler(i, &ext_chip, handle_level_irq); + irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE); + } +} |