^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <asm/mach/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <asm/hardware/iomd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/fiq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // These are offsets from the stat register for each IRQ bank
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define STAT 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define REQ 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define CLR 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define MASK 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static void __iomem *iomd_get_base(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) void *cd = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) return (void __iomem *)(unsigned long)cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static void iomd_set_base_mask(unsigned int irq, void __iomem *base, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct irq_data *d = irq_get_irq_data(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) d->mask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) irq_set_chip_data(irq, (void *)(unsigned long)base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void iomd_irq_mask_ack(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) void __iomem *base = iomd_get_base(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned int val, mask = d->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) val = readb(base + MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) writeb(val & ~mask, base + MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) writeb(mask, base + CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static void iomd_irq_mask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) void __iomem *base = iomd_get_base(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned int val, mask = d->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) val = readb(base + MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) writeb(val & ~mask, base + MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static void iomd_irq_unmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) void __iomem *base = iomd_get_base(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned int val, mask = d->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) val = readb(base + MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) writeb(val | mask, base + MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static struct irq_chip iomd_chip_clr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .irq_mask_ack = iomd_irq_mask_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .irq_mask = iomd_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .irq_unmask = iomd_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static struct irq_chip iomd_chip_noclr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .irq_mask = iomd_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .irq_unmask = iomd_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) void __init rpc_init_irq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned int irq, clr, set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) iomd_writeb(0, IOMD_IRQMASKA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) iomd_writeb(0, IOMD_IRQMASKB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) iomd_writeb(0, IOMD_FIQMASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) iomd_writeb(0, IOMD_DMAMASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) set_fiq_handler(&rpc_default_fiq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) &rpc_default_fiq_end - &rpc_default_fiq_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) for (irq = 0; irq < NR_IRQS; irq++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) clr = IRQ_NOREQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) set = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (irq <= 6 || (irq >= 9 && irq <= 15))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) clr |= IRQ_NOPROBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (irq == 21 || (irq >= 16 && irq <= 19) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) irq == IRQ_KEYBOARDTX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) set |= IRQ_NOAUTOEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) switch (irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case 0 ... 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) irq_set_chip_and_handler(irq, &iomd_chip_clr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) irq_modify_status(irq, clr, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) BIT(irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) case 8 ... 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) irq_set_chip_and_handler(irq, &iomd_chip_noclr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) irq_modify_status(irq, clr, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) BIT(irq - 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) case 16 ... 21:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) irq_set_chip_and_handler(irq, &iomd_chip_noclr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) irq_modify_status(irq, clr, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) iomd_set_base_mask(irq, IOMD_BASE + IOMD_DMASTAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) BIT(irq - 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case 64 ... 71:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) irq_set_chip(irq, &iomd_chip_noclr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) irq_modify_status(irq, clr, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) iomd_set_base_mask(irq, IOMD_BASE + IOMD_FIQSTAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) BIT(irq - 64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) init_FIQ(FIQ_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }