1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Cristian Birsan <cristian.birsan@microchip.com> 4 * Joshua Henderson <joshua.henderson@microchip.com> 5 * Copyright (C) 2016 Microchip Technology Inc. All rights reserved. 6 */ 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/interrupt.h> 10 #include <linux/irqdomain.h> 11 #include <linux/of_address.h> 12 #include <linux/slab.h> 13 #include <linux/io.h> 14 #include <linux/irqchip.h> 15 #include <linux/irq.h> 16 17 #include <asm/irq.h> 18 #include <asm/traps.h> 19 #include <asm/mach-pic32/pic32.h> 20 21 #define REG_INTCON 0x0000 22 #define REG_INTSTAT 0x0020 23 #define REG_IFS_OFFSET 0x0040 24 #define REG_IEC_OFFSET 0x00C0 25 #define REG_IPC_OFFSET 0x0140 26 #define REG_OFF_OFFSET 0x0540 27 28 #define MAJPRI_MASK 0x07 29 #define SUBPRI_MASK 0x03 30 #define PRIORITY_MASK 0x1F 31 32 #define PIC32_INT_PRI(pri, subpri) \ 33 ((((pri) & MAJPRI_MASK) << 2) | ((subpri) & SUBPRI_MASK)) 34 35 struct evic_chip_data { 36 u32 irq_types[NR_IRQS]; 37 u32 ext_irqs[8]; 38 }; 39 40 static struct irq_domain *evic_irq_domain; 41 static void __iomem *evic_base; 42 43 asmlinkage void __weak plat_irq_dispatch(void) 44 { 45 unsigned int irq, hwirq; 46 47 hwirq = readl(evic_base + REG_INTSTAT) & 0xFF; 48 irq = irq_linear_revmap(evic_irq_domain, hwirq); 49 do_IRQ(irq); 50 } 51 52 static struct evic_chip_data *irqd_to_priv(struct irq_data *data) 53 { 54 return (struct evic_chip_data *)data->domain->host_data; 55 } 56 57 static int pic32_set_ext_polarity(int bit, u32 type) 58 { 59 /* 60 * External interrupts can be either edge rising or edge falling, 61 * but not both. 62 */ 63 switch (type) { 64 case IRQ_TYPE_EDGE_RISING: 65 writel(BIT(bit), evic_base + PIC32_SET(REG_INTCON)); 66 break; 67 case IRQ_TYPE_EDGE_FALLING: 68 writel(BIT(bit), evic_base + PIC32_CLR(REG_INTCON)); 69 break; 70 default: 71 return -EINVAL; 72 } 73 74 return 0; 75 } 76 77 static int pic32_set_type_edge(struct irq_data *data, 78 unsigned int flow_type) 79 { 80 struct evic_chip_data *priv = irqd_to_priv(data); 81 int ret; 82 int i; 83 84 if (!(flow_type & IRQ_TYPE_EDGE_BOTH)) 85 return -EBADR; 86 87 /* set polarity for external interrupts only */ 88 for (i = 0; i < ARRAY_SIZE(priv->ext_irqs); i++) { 89 if (priv->ext_irqs[i] == data->hwirq) { 90 ret = pic32_set_ext_polarity(i, flow_type); 91 if (ret) 92 return ret; 93 } 94 } 95 96 irqd_set_trigger_type(data, flow_type); 97 98 return IRQ_SET_MASK_OK; 99 } 100 101 static void pic32_bind_evic_interrupt(int irq, int set) 102 { 103 writel(set, evic_base + REG_OFF_OFFSET + irq * 4); 104 } 105 106 static void pic32_set_irq_priority(int irq, int priority) 107 { 108 u32 reg, shift; 109 110 reg = irq / 4; 111 shift = (irq % 4) * 8; 112 113 writel(PRIORITY_MASK << shift, 114 evic_base + PIC32_CLR(REG_IPC_OFFSET + reg * 0x10)); 115 writel(priority << shift, 116 evic_base + PIC32_SET(REG_IPC_OFFSET + reg * 0x10)); 117 } 118 119 #define IRQ_REG_MASK(_hwirq, _reg, _mask) \ 120 do { \ 121 _reg = _hwirq / 32; \ 122 _mask = 1 << (_hwirq % 32); \ 123 } while (0) 124 125 static int pic32_irq_domain_map(struct irq_domain *d, unsigned int virq, 126 irq_hw_number_t hw) 127 { 128 struct evic_chip_data *priv = d->host_data; 129 struct irq_data *data; 130 int ret; 131 u32 iecclr, ifsclr; 132 u32 reg, mask; 133 134 ret = irq_map_generic_chip(d, virq, hw); 135 if (ret) 136 return ret; 137 138 /* 139 * Piggyback on xlate function to move to an alternate chip as necessary 140 * at time of mapping instead of allowing the flow handler/chip to be 141 * changed later. This requires all interrupts to be configured through 142 * DT. 143 */ 144 if (priv->irq_types[hw] & IRQ_TYPE_SENSE_MASK) { 145 data = irq_domain_get_irq_data(d, virq); 146 irqd_set_trigger_type(data, priv->irq_types[hw]); 147 irq_setup_alt_chip(data, priv->irq_types[hw]); 148 } 149 150 IRQ_REG_MASK(hw, reg, mask); 151 152 iecclr = PIC32_CLR(REG_IEC_OFFSET + reg * 0x10); 153 ifsclr = PIC32_CLR(REG_IFS_OFFSET + reg * 0x10); 154 155 /* mask and clear flag */ 156 writel(mask, evic_base + iecclr); 157 writel(mask, evic_base + ifsclr); 158 159 /* default priority is required */ 160 pic32_set_irq_priority(hw, PIC32_INT_PRI(2, 0)); 161 162 return ret; 163 } 164 165 int pic32_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, 166 const u32 *intspec, unsigned int intsize, 167 irq_hw_number_t *out_hwirq, unsigned int *out_type) 168 { 169 struct evic_chip_data *priv = d->host_data; 170 171 if (WARN_ON(intsize < 2)) 172 return -EINVAL; 173 174 if (WARN_ON(intspec[0] >= NR_IRQS)) 175 return -EINVAL; 176 177 *out_hwirq = intspec[0]; 178 *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; 179 180 priv->irq_types[intspec[0]] = intspec[1] & IRQ_TYPE_SENSE_MASK; 181 182 return 0; 183 } 184 185 static const struct irq_domain_ops pic32_irq_domain_ops = { 186 .map = pic32_irq_domain_map, 187 .xlate = pic32_irq_domain_xlate, 188 }; 189 190 static void __init pic32_ext_irq_of_init(struct irq_domain *domain) 191 { 192 struct device_node *node = irq_domain_get_of_node(domain); 193 struct evic_chip_data *priv = domain->host_data; 194 struct property *prop; 195 const __le32 *p; 196 u32 hwirq; 197 int i = 0; 198 const char *pname = "microchip,external-irqs"; 199 200 of_property_for_each_u32(node, pname, prop, p, hwirq) { 201 if (i >= ARRAY_SIZE(priv->ext_irqs)) { 202 pr_warn("More than %d external irq, skip rest\n", 203 ARRAY_SIZE(priv->ext_irqs)); 204 break; 205 } 206 207 priv->ext_irqs[i] = hwirq; 208 i++; 209 } 210 } 211 212 static int __init pic32_of_init(struct device_node *node, 213 struct device_node *parent) 214 { 215 struct irq_chip_generic *gc; 216 struct evic_chip_data *priv; 217 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; 218 int nchips, ret; 219 int i; 220 221 nchips = DIV_ROUND_UP(NR_IRQS, 32); 222 223 evic_base = of_iomap(node, 0); 224 if (!evic_base) 225 return -ENOMEM; 226 227 priv = kcalloc(nchips, sizeof(*priv), GFP_KERNEL); 228 if (!priv) { 229 ret = -ENOMEM; 230 goto err_iounmap; 231 } 232 233 evic_irq_domain = irq_domain_add_linear(node, nchips * 32, 234 &pic32_irq_domain_ops, 235 priv); 236 if (!evic_irq_domain) { 237 ret = -ENOMEM; 238 goto err_free_priv; 239 } 240 241 /* 242 * The PIC32 EVIC has a linear list of irqs and the type of each 243 * irq is determined by the hardware peripheral the EVIC is arbitrating. 244 * These irq types are defined in the datasheet as "persistent" and 245 * "non-persistent" which are mapped here to level and edge 246 * respectively. To manage the different flow handler requirements of 247 * each irq type, different chip_types are used. 248 */ 249 ret = irq_alloc_domain_generic_chips(evic_irq_domain, 32, 2, 250 "evic-level", handle_level_irq, 251 clr, 0, 0); 252 if (ret) 253 goto err_domain_remove; 254 255 board_bind_eic_interrupt = &pic32_bind_evic_interrupt; 256 257 for (i = 0; i < nchips; i++) { 258 u32 ifsclr = PIC32_CLR(REG_IFS_OFFSET + (i * 0x10)); 259 u32 iec = REG_IEC_OFFSET + (i * 0x10); 260 261 gc = irq_get_domain_generic_chip(evic_irq_domain, i * 32); 262 263 gc->reg_base = evic_base; 264 gc->unused = 0; 265 266 /* 267 * Level/persistent interrupts have a special requirement that 268 * the condition generating the interrupt be cleared before the 269 * interrupt flag (ifs) can be cleared. chip.irq_eoi is used to 270 * complete the interrupt with an ack. 271 */ 272 gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK; 273 gc->chip_types[0].handler = handle_fasteoi_irq; 274 gc->chip_types[0].regs.ack = ifsclr; 275 gc->chip_types[0].regs.mask = iec; 276 gc->chip_types[0].chip.name = "evic-level"; 277 gc->chip_types[0].chip.irq_eoi = irq_gc_ack_set_bit; 278 gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; 279 gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; 280 gc->chip_types[0].chip.flags = IRQCHIP_SKIP_SET_WAKE; 281 282 /* Edge interrupts */ 283 gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH; 284 gc->chip_types[1].handler = handle_edge_irq; 285 gc->chip_types[1].regs.ack = ifsclr; 286 gc->chip_types[1].regs.mask = iec; 287 gc->chip_types[1].chip.name = "evic-edge"; 288 gc->chip_types[1].chip.irq_ack = irq_gc_ack_set_bit; 289 gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit; 290 gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit; 291 gc->chip_types[1].chip.irq_set_type = pic32_set_type_edge; 292 gc->chip_types[1].chip.flags = IRQCHIP_SKIP_SET_WAKE; 293 294 gc->private = &priv[i]; 295 } 296 297 irq_set_default_host(evic_irq_domain); 298 299 /* 300 * External interrupts have software configurable edge polarity. These 301 * interrupts are defined in DT allowing polarity to be configured only 302 * for these interrupts when requested. 303 */ 304 pic32_ext_irq_of_init(evic_irq_domain); 305 306 return 0; 307 308 err_domain_remove: 309 irq_domain_remove(evic_irq_domain); 310 311 err_free_priv: 312 kfree(priv); 313 314 err_iounmap: 315 iounmap(evic_base); 316 317 return ret; 318 } 319 320 IRQCHIP_DECLARE(pic32_evic, "microchip,pic32mzda-evic", pic32_of_init); 321