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 17 static 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 36 static 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 55 static 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 74 static 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 99 static 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 110 static 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 117 static 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 125 static 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 135 static 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 144 static 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 153 static 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 159 static struct irq_chip iomd_chip_noclr = { 160 .irq_mask = iomd_irq_mask, 161 .irq_unmask = iomd_irq_unmask, 162 }; 163 164 extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end; 165 166 void __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 } 227
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.