1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2008 Ilya Yanok, Emcraft Systems 4 */ 5 6 #include <linux/irq.h> 7 #include <linux/of_address.h> 8 #include <linux/of_irq.h> 9 #include <linux/io.h> 10 11 /* 12 * The FPGA supports 9 interrupt sources, which can be routed to 3 13 * interrupt request lines of the MPIC. The line to be used can be 14 * specified through the third cell of FDT property "interrupts". 15 */ 16 17 #define SOCRATES_FPGA_NUM_IRQS 9 18 19 #define FPGA_PIC_IRQCFG (0x0) 20 #define FPGA_PIC_IRQMASK(n) (0x4 + 0x4 * (n)) 21 22 #define SOCRATES_FPGA_IRQ_MASK ((1 << SOCRATES_FPGA_NUM_IRQS) - 1) 23 24 struct socrates_fpga_irq_info { 25 unsigned int irq_line; 26 int type; 27 }; 28 29 /* 30 * Interrupt routing and type table 31 * 32 * IRQ_TYPE_NONE means the interrupt type is configurable, 33 * otherwise it's fixed to the specified value. 34 */ 35 static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = { 36 [0] = {0, IRQ_TYPE_NONE}, 37 [1] = {0, IRQ_TYPE_LEVEL_HIGH}, 38 [2] = {0, IRQ_TYPE_LEVEL_LOW}, 39 [3] = {0, IRQ_TYPE_NONE}, 40 [4] = {0, IRQ_TYPE_NONE}, 41 [5] = {0, IRQ_TYPE_NONE}, 42 [6] = {0, IRQ_TYPE_NONE}, 43 [7] = {0, IRQ_TYPE_NONE}, 44 [8] = {0, IRQ_TYPE_LEVEL_HIGH}, 45 }; 46 47 static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock); 48 49 static void __iomem *socrates_fpga_pic_iobase; 50 static struct irq_domain *socrates_fpga_pic_irq_host; 51 static unsigned int socrates_fpga_irqs[3]; 52 53 static inline uint32_t socrates_fpga_pic_read(int reg) 54 { 55 return in_be32(socrates_fpga_pic_iobase + reg); 56 } 57 58 static inline void socrates_fpga_pic_write(int reg, uint32_t val) 59 { 60 out_be32(socrates_fpga_pic_iobase + reg, val); 61 } 62 63 static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq) 64 { 65 uint32_t cause; 66 unsigned long flags; 67 int i; 68 69 /* Check irq line routed to the MPIC */ 70 for (i = 0; i < 3; i++) { 71 if (irq == socrates_fpga_irqs[i]) 72 break; 73 } 74 if (i == 3) 75 return 0; 76 77 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags); 78 cause = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i)); 79 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags); 80 for (i = SOCRATES_FPGA_NUM_IRQS - 1; i >= 0; i--) { 81 if (cause >> (i + 16)) 82 break; 83 } 84 return irq_linear_revmap(socrates_fpga_pic_irq_host, 85 (irq_hw_number_t)i); 86 } 87 88 static void socrates_fpga_pic_cascade(struct irq_desc *desc) 89 { 90 struct irq_chip *chip = irq_desc_get_chip(desc); 91 unsigned int irq = irq_desc_get_irq(desc); 92 unsigned int cascade_irq; 93 94 /* 95 * See if we actually have an interrupt, call generic handling code if 96 * we do. 97 */ 98 cascade_irq = socrates_fpga_pic_get_irq(irq); 99 100 if (cascade_irq) 101 generic_handle_irq(cascade_irq); 102 chip->irq_eoi(&desc->irq_data); 103 } 104 105 static void socrates_fpga_pic_ack(struct irq_data *d) 106 { 107 unsigned long flags; 108 unsigned int irq_line, hwirq = irqd_to_hwirq(d); 109 uint32_t mask; 110 111 irq_line = fpga_irqs[hwirq].irq_line; 112 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags); 113 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line)) 114 & SOCRATES_FPGA_IRQ_MASK; 115 mask |= (1 << (hwirq + 16)); 116 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask); 117 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags); 118 } 119 120 static void socrates_fpga_pic_mask(struct irq_data *d) 121 { 122 unsigned long flags; 123 unsigned int hwirq = irqd_to_hwirq(d); 124 int irq_line; 125 u32 mask; 126 127 irq_line = fpga_irqs[hwirq].irq_line; 128 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags); 129 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line)) 130 & SOCRATES_FPGA_IRQ_MASK; 131 mask &= ~(1 << hwirq); 132 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask); 133 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags); 134 } 135 136 static void socrates_fpga_pic_mask_ack(struct irq_data *d) 137 { 138 unsigned long flags; 139 unsigned int hwirq = irqd_to_hwirq(d); 140 int irq_line; 141 u32 mask; 142 143 irq_line = fpga_irqs[hwirq].irq_line; 144 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags); 145 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line)) 146 & SOCRATES_FPGA_IRQ_MASK; 147 mask &= ~(1 << hwirq); 148 mask |= (1 << (hwirq + 16)); 149 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask); 150 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags); 151 } 152 153 static void socrates_fpga_pic_unmask(struct irq_data *d) 154 { 155 unsigned long flags; 156 unsigned int hwirq = irqd_to_hwirq(d); 157 int irq_line; 158 u32 mask; 159 160 irq_line = fpga_irqs[hwirq].irq_line; 161 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags); 162 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line)) 163 & SOCRATES_FPGA_IRQ_MASK; 164 mask |= (1 << hwirq); 165 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask); 166 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags); 167 } 168 169 static void socrates_fpga_pic_eoi(struct irq_data *d) 170 { 171 unsigned long flags; 172 unsigned int hwirq = irqd_to_hwirq(d); 173 int irq_line; 174 u32 mask; 175 176 irq_line = fpga_irqs[hwirq].irq_line; 177 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags); 178 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line)) 179 & SOCRATES_FPGA_IRQ_MASK; 180 mask |= (1 << (hwirq + 16)); 181 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask); 182 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags); 183 } 184 185 static int socrates_fpga_pic_set_type(struct irq_data *d, 186 unsigned int flow_type) 187 { 188 unsigned long flags; 189 unsigned int hwirq = irqd_to_hwirq(d); 190 int polarity; 191 u32 mask; 192 193 if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE) 194 return -EINVAL; 195 196 switch (flow_type & IRQ_TYPE_SENSE_MASK) { 197 case IRQ_TYPE_LEVEL_HIGH: 198 polarity = 1; 199 break; 200 case IRQ_TYPE_LEVEL_LOW: 201 polarity = 0; 202 break; 203 default: 204 return -EINVAL; 205 } 206 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags); 207 mask = socrates_fpga_pic_read(FPGA_PIC_IRQCFG); 208 if (polarity) 209 mask |= (1 << hwirq); 210 else 211 mask &= ~(1 << hwirq); 212 socrates_fpga_pic_write(FPGA_PIC_IRQCFG, mask); 213 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags); 214 return 0; 215 } 216 217 static struct irq_chip socrates_fpga_pic_chip = { 218 .name = "FPGA-PIC", 219 .irq_ack = socrates_fpga_pic_ack, 220 .irq_mask = socrates_fpga_pic_mask, 221 .irq_mask_ack = socrates_fpga_pic_mask_ack, 222 .irq_unmask = socrates_fpga_pic_unmask, 223 .irq_eoi = socrates_fpga_pic_eoi, 224 .irq_set_type = socrates_fpga_pic_set_type, 225 }; 226 227 static int socrates_fpga_pic_host_map(struct irq_domain *h, unsigned int virq, 228 irq_hw_number_t hwirq) 229 { 230 /* All interrupts are LEVEL sensitive */ 231 irq_set_status_flags(virq, IRQ_LEVEL); 232 irq_set_chip_and_handler(virq, &socrates_fpga_pic_chip, 233 handle_fasteoi_irq); 234 235 return 0; 236 } 237 238 static int socrates_fpga_pic_host_xlate(struct irq_domain *h, 239 struct device_node *ct, const u32 *intspec, unsigned int intsize, 240 irq_hw_number_t *out_hwirq, unsigned int *out_flags) 241 { 242 struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]]; 243 244 *out_hwirq = intspec[0]; 245 if (fpga_irq->type == IRQ_TYPE_NONE) { 246 /* type is configurable */ 247 if (intspec[1] != IRQ_TYPE_LEVEL_LOW && 248 intspec[1] != IRQ_TYPE_LEVEL_HIGH) { 249 pr_warn("FPGA PIC: invalid irq type, setting default active low\n"); 250 *out_flags = IRQ_TYPE_LEVEL_LOW; 251 } else { 252 *out_flags = intspec[1]; 253 } 254 } else { 255 /* type is fixed */ 256 *out_flags = fpga_irq->type; 257 } 258 259 /* Use specified interrupt routing */ 260 if (intspec[2] <= 2) 261 fpga_irq->irq_line = intspec[2]; 262 else 263 pr_warn("FPGA PIC: invalid irq routing\n"); 264 265 return 0; 266 } 267 268 static const struct irq_domain_ops socrates_fpga_pic_host_ops = { 269 .map = socrates_fpga_pic_host_map, 270 .xlate = socrates_fpga_pic_host_xlate, 271 }; 272 273 void __init socrates_fpga_pic_init(struct device_node *pic) 274 { 275 unsigned long flags; 276 int i; 277 278 /* Setup an irq_domain structure */ 279 socrates_fpga_pic_irq_host = irq_domain_add_linear(pic, 280 SOCRATES_FPGA_NUM_IRQS, &socrates_fpga_pic_host_ops, NULL); 281 if (socrates_fpga_pic_irq_host == NULL) { 282 pr_err("FPGA PIC: Unable to allocate host\n"); 283 return; 284 } 285 286 for (i = 0; i < 3; i++) { 287 socrates_fpga_irqs[i] = irq_of_parse_and_map(pic, i); 288 if (!socrates_fpga_irqs[i]) { 289 pr_warn("FPGA PIC: can't get irq%d\n", i); 290 continue; 291 } 292 irq_set_chained_handler(socrates_fpga_irqs[i], 293 socrates_fpga_pic_cascade); 294 } 295 296 socrates_fpga_pic_iobase = of_iomap(pic, 0); 297 298 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags); 299 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0), 300 SOCRATES_FPGA_IRQ_MASK << 16); 301 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1), 302 SOCRATES_FPGA_IRQ_MASK << 16); 303 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2), 304 SOCRATES_FPGA_IRQ_MASK << 16); 305 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags); 306 307 pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n"); 308 } 309