irq.c (6121B)
1// SPDX-License-Identifier: GPL-2.0 2#include <linux/init.h> 3#include <linux/list.h> 4#include <linux/io.h> 5 6#include <asm/mach/irq.h> 7#include <asm/hardware/iomd.h> 8#include <asm/irq.h> 9#include <asm/fiq.h> 10 11// These are offsets from the stat register for each IRQ bank 12#define STAT 0x00 13#define REQ 0x04 14#define CLR 0x04 15#define MASK 0x08 16 17static const u8 irq_prio_h[256] = { 18 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10, 19 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10, 20 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10, 21 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10, 22 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10, 23 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10, 24 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10, 25 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10, 26 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10, 27 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10, 28 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10, 29 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10, 30 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10, 31 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10, 32 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10, 33 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10, 34}; 35 36static const u8 irq_prio_d[256] = { 37 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 38 20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 39 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 40 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 41 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 42 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 43 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 44 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 45 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 46 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 47 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 48 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 49 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 50 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 51 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 52 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16, 53}; 54 55static const u8 irq_prio_l[256] = { 56 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 57 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 58 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 59 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 60 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 61 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 62 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 63 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 64 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 65 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 66 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 67 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 68 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 69 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 70 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 71 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 72}; 73 74static int iomd_get_irq_nr(void) 75{ 76 int irq; 77 u8 reg; 78 79 /* get highest priority first */ 80 reg = readb(IOC_BASE + IOMD_IRQREQB); 81 irq = irq_prio_h[reg]; 82 if (irq) 83 return irq; 84 85 /* get DMA */ 86 reg = readb(IOC_BASE + IOMD_DMAREQ); 87 irq = irq_prio_d[reg]; 88 if (irq) 89 return irq; 90 91 /* get low priority */ 92 reg = readb(IOC_BASE + IOMD_IRQREQA); 93 irq = irq_prio_l[reg]; 94 if (irq) 95 return irq; 96 return 0; 97} 98 99static void iomd_handle_irq(struct pt_regs *regs) 100{ 101 int irq; 102 103 do { 104 irq = iomd_get_irq_nr(); 105 if (irq) 106 generic_handle_irq(irq); 107 } while (irq); 108} 109 110static void __iomem *iomd_get_base(struct irq_data *d) 111{ 112 void *cd = irq_data_get_irq_chip_data(d); 113 114 return (void __iomem *)(unsigned long)cd; 115} 116 117static void iomd_set_base_mask(unsigned int irq, void __iomem *base, u32 mask) 118{ 119 struct irq_data *d = irq_get_irq_data(irq); 120 121 d->mask = mask; 122 irq_set_chip_data(irq, (void *)(unsigned long)base); 123} 124 125static void iomd_irq_mask_ack(struct irq_data *d) 126{ 127 void __iomem *base = iomd_get_base(d); 128 unsigned int val, mask = d->mask; 129 130 val = readb(base + MASK); 131 writeb(val & ~mask, base + MASK); 132 writeb(mask, base + CLR); 133} 134 135static void iomd_irq_mask(struct irq_data *d) 136{ 137 void __iomem *base = iomd_get_base(d); 138 unsigned int val, mask = d->mask; 139 140 val = readb(base + MASK); 141 writeb(val & ~mask, base + MASK); 142} 143 144static void iomd_irq_unmask(struct irq_data *d) 145{ 146 void __iomem *base = iomd_get_base(d); 147 unsigned int val, mask = d->mask; 148 149 val = readb(base + MASK); 150 writeb(val | mask, base + MASK); 151} 152 153static struct irq_chip iomd_chip_clr = { 154 .irq_mask_ack = iomd_irq_mask_ack, 155 .irq_mask = iomd_irq_mask, 156 .irq_unmask = iomd_irq_unmask, 157}; 158 159static struct irq_chip iomd_chip_noclr = { 160 .irq_mask = iomd_irq_mask, 161 .irq_unmask = iomd_irq_unmask, 162}; 163 164extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end; 165 166void __init rpc_init_irq(void) 167{ 168 unsigned int irq, clr, set; 169 170 iomd_writeb(0, IOMD_IRQMASKA); 171 iomd_writeb(0, IOMD_IRQMASKB); 172 iomd_writeb(0, IOMD_FIQMASK); 173 iomd_writeb(0, IOMD_DMAMASK); 174 175 set_fiq_handler(&rpc_default_fiq_start, 176 &rpc_default_fiq_end - &rpc_default_fiq_start); 177 178 set_handle_irq(iomd_handle_irq); 179 180 for (irq = 0; irq < NR_IRQS; irq++) { 181 clr = IRQ_NOREQUEST; 182 set = 0; 183 184 if (irq <= 6 || (irq >= 9 && irq <= 15)) 185 clr |= IRQ_NOPROBE; 186 187 if (irq == 21 || (irq >= 16 && irq <= 19) || 188 irq == IRQ_KEYBOARDTX) 189 set |= IRQ_NOAUTOEN; 190 191 switch (irq) { 192 case 0 ... 7: 193 irq_set_chip_and_handler(irq, &iomd_chip_clr, 194 handle_level_irq); 195 irq_modify_status(irq, clr, set); 196 iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATA, 197 BIT(irq)); 198 break; 199 200 case 8 ... 15: 201 irq_set_chip_and_handler(irq, &iomd_chip_noclr, 202 handle_level_irq); 203 irq_modify_status(irq, clr, set); 204 iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATB, 205 BIT(irq - 8)); 206 break; 207 208 case 16 ... 21: 209 irq_set_chip_and_handler(irq, &iomd_chip_noclr, 210 handle_level_irq); 211 irq_modify_status(irq, clr, set); 212 iomd_set_base_mask(irq, IOMD_BASE + IOMD_DMASTAT, 213 BIT(irq - 16)); 214 break; 215 216 case 64 ... 71: 217 irq_set_chip(irq, &iomd_chip_noclr); 218 irq_modify_status(irq, clr, set); 219 iomd_set_base_mask(irq, IOMD_BASE + IOMD_FIQSTAT, 220 BIT(irq - 64)); 221 break; 222 } 223 } 224 225 init_FIQ(FIQ_START); 226}