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