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