1 /* 2 * SPEAr platform shared irq layer source file 3 * 4 * Copyright (C) 2009-2012 ST Microelectronics 5 * Viresh Kumar <viresh.linux@gmail.com> 6 * 7 * Copyright (C) 2012 ST Microelectronics 8 * Shiraz Hashim <shiraz.linux.kernel@gmail.com> 9 * 10 * This file is licensed under the terms of the GNU General Public 11 * License version 2. This program is licensed "as is" without any 12 * warranty of any kind, whether express or implied. 13 */ 14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 16 #include <linux/err.h> 17 #include <linux/export.h> 18 #include <linux/interrupt.h> 19 #include <linux/io.h> 20 #include <linux/irq.h> 21 #include <linux/irqdomain.h> 22 #include <linux/of.h> 23 #include <linux/of_address.h> 24 #include <linux/of_irq.h> 25 #include <linux/spinlock.h> 26 27 #include "irqchip.h" 28 29 /* 30 * struct shirq_regs: shared irq register configuration 31 * 32 * enb_reg: enable register offset 33 * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt 34 * status_reg: status register offset 35 * status_reg_mask: status register valid mask 36 * clear_reg: clear register offset 37 * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt 38 */ 39 struct shirq_regs { 40 u32 enb_reg; 41 u32 reset_to_enb; 42 u32 status_reg; 43 u32 clear_reg; 44 u32 reset_to_clear; 45 }; 46 47 /* 48 * struct spear_shirq: shared irq structure 49 * 50 * base: Base register address 51 * regs: Register configuration for shared irq block 52 * mask: Mask to apply to the status register 53 * virq_base: Base virtual interrupt number 54 * nr_irqs: Number of interrupts handled by this block 55 * offset: Bit offset of the first interrupt 56 * disabled: Group is disabled, but accounted 57 */ 58 struct spear_shirq { 59 void __iomem *base; 60 struct shirq_regs regs; 61 u32 mask; 62 u32 virq_base; 63 u32 nr_irqs; 64 u32 offset; 65 bool disabled; 66 }; 67 68 static DEFINE_SPINLOCK(lock); 69 70 /* spear300 shared irq registers offsets and masks */ 71 #define SPEAR300_INT_ENB_MASK_REG 0x54 72 #define SPEAR300_INT_STS_MASK_REG 0x58 73 74 static struct spear_shirq spear300_shirq_ras1 = { 75 .offset = 0, 76 .nr_irqs = 9, 77 .mask = ((0x1 << 9) - 1) << 0, 78 .regs = { 79 .enb_reg = SPEAR300_INT_ENB_MASK_REG, 80 .status_reg = SPEAR300_INT_STS_MASK_REG, 81 .clear_reg = -1, 82 }, 83 }; 84 85 static struct spear_shirq *spear300_shirq_blocks[] = { 86 &spear300_shirq_ras1, 87 }; 88 89 /* spear310 shared irq registers offsets and masks */ 90 #define SPEAR310_INT_STS_MASK_REG 0x04 91 92 static struct spear_shirq spear310_shirq_ras1 = { 93 .offset = 0, 94 .nr_irqs = 8, 95 .mask = ((0x1 << 8) - 1) << 0, 96 .regs = { 97 .enb_reg = -1, 98 .status_reg = SPEAR310_INT_STS_MASK_REG, 99 .clear_reg = -1, 100 }, 101 }; 102 103 static struct spear_shirq spear310_shirq_ras2 = { 104 .offset = 8, 105 .nr_irqs = 5, 106 .mask = ((0x1 << 5) - 1) << 8, 107 .regs = { 108 .enb_reg = -1, 109 .status_reg = SPEAR310_INT_STS_MASK_REG, 110 .clear_reg = -1, 111 }, 112 }; 113 114 static struct spear_shirq spear310_shirq_ras3 = { 115 .offset = 13, 116 .nr_irqs = 1, 117 .mask = ((0x1 << 1) - 1) << 13, 118 .regs = { 119 .enb_reg = -1, 120 .status_reg = SPEAR310_INT_STS_MASK_REG, 121 .clear_reg = -1, 122 }, 123 }; 124 125 static struct spear_shirq spear310_shirq_intrcomm_ras = { 126 .offset = 14, 127 .nr_irqs = 3, 128 .mask = ((0x1 << 3) - 1) << 14, 129 .regs = { 130 .enb_reg = -1, 131 .status_reg = SPEAR310_INT_STS_MASK_REG, 132 .clear_reg = -1, 133 }, 134 }; 135 136 static struct spear_shirq *spear310_shirq_blocks[] = { 137 &spear310_shirq_ras1, 138 &spear310_shirq_ras2, 139 &spear310_shirq_ras3, 140 &spear310_shirq_intrcomm_ras, 141 }; 142 143 /* spear320 shared irq registers offsets and masks */ 144 #define SPEAR320_INT_STS_MASK_REG 0x04 145 #define SPEAR320_INT_CLR_MASK_REG 0x04 146 #define SPEAR320_INT_ENB_MASK_REG 0x08 147 148 static struct spear_shirq spear320_shirq_ras3 = { 149 .offset = 0, 150 .nr_irqs = 7, 151 .mask = ((0x1 << 7) - 1) << 0, 152 .disabled = 1, 153 .regs = { 154 .enb_reg = SPEAR320_INT_ENB_MASK_REG, 155 .reset_to_enb = 1, 156 .status_reg = SPEAR320_INT_STS_MASK_REG, 157 .clear_reg = SPEAR320_INT_CLR_MASK_REG, 158 .reset_to_clear = 1, 159 }, 160 }; 161 162 static struct spear_shirq spear320_shirq_ras1 = { 163 .offset = 7, 164 .nr_irqs = 3, 165 .mask = ((0x1 << 3) - 1) << 7, 166 .regs = { 167 .enb_reg = -1, 168 .status_reg = SPEAR320_INT_STS_MASK_REG, 169 .clear_reg = SPEAR320_INT_CLR_MASK_REG, 170 .reset_to_clear = 1, 171 }, 172 }; 173 174 static struct spear_shirq spear320_shirq_ras2 = { 175 .offset = 10, 176 .nr_irqs = 1, 177 .mask = ((0x1 << 1) - 1) << 10, 178 .regs = { 179 .enb_reg = -1, 180 .status_reg = SPEAR320_INT_STS_MASK_REG, 181 .clear_reg = SPEAR320_INT_CLR_MASK_REG, 182 .reset_to_clear = 1, 183 }, 184 }; 185 186 static struct spear_shirq spear320_shirq_intrcomm_ras = { 187 .offset = 11, 188 .nr_irqs = 11, 189 .mask = ((0x1 << 11) - 1) << 11, 190 .regs = { 191 .enb_reg = -1, 192 .status_reg = SPEAR320_INT_STS_MASK_REG, 193 .clear_reg = SPEAR320_INT_CLR_MASK_REG, 194 .reset_to_clear = 1, 195 }, 196 }; 197 198 static struct spear_shirq *spear320_shirq_blocks[] = { 199 &spear320_shirq_ras3, 200 &spear320_shirq_ras1, 201 &spear320_shirq_ras2, 202 &spear320_shirq_intrcomm_ras, 203 }; 204 205 static void shirq_irq_mask_unmask(struct irq_data *d, bool mask) 206 { 207 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d); 208 u32 val, offset = d->irq - shirq->virq_base; 209 unsigned long flags; 210 211 if (shirq->regs.enb_reg == -1) 212 return; 213 214 spin_lock_irqsave(&lock, flags); 215 val = readl(shirq->base + shirq->regs.enb_reg); 216 217 if (mask ^ shirq->regs.reset_to_enb) 218 val &= ~(0x1 << shirq->offset << offset); 219 else 220 val |= 0x1 << shirq->offset << offset; 221 222 writel(val, shirq->base + shirq->regs.enb_reg); 223 spin_unlock_irqrestore(&lock, flags); 224 225 } 226 227 static void shirq_irq_mask(struct irq_data *d) 228 { 229 shirq_irq_mask_unmask(d, 1); 230 } 231 232 static void shirq_irq_unmask(struct irq_data *d) 233 { 234 shirq_irq_mask_unmask(d, 0); 235 } 236 237 static struct irq_chip shirq_chip = { 238 .name = "spear-shirq", 239 .irq_ack = shirq_irq_mask, 240 .irq_mask = shirq_irq_mask, 241 .irq_unmask = shirq_irq_unmask, 242 }; 243 244 static void shirq_handler(unsigned irq, struct irq_desc *desc) 245 { 246 struct spear_shirq *shirq = irq_get_handler_data(irq); 247 struct irq_data *idata = irq_desc_get_irq_data(desc); 248 struct irq_chip *chip = irq_data_get_irq_chip(idata); 249 u32 i, j, val, mask, tmp; 250 251 chip->irq_ack(idata); 252 253 mask = shirq->mask; 254 while ((val = readl(shirq->base + shirq->regs.status_reg) & 255 mask)) { 256 257 val >>= shirq->offset; 258 for (i = 0, j = 1; i < shirq->nr_irqs; i++, j <<= 1) { 259 260 if (!(j & val)) 261 continue; 262 263 generic_handle_irq(shirq->virq_base + i); 264 265 /* clear interrupt */ 266 if (shirq->regs.clear_reg == -1) 267 continue; 268 269 tmp = readl(shirq->base + shirq->regs.clear_reg); 270 if (shirq->regs.reset_to_clear) 271 tmp &= ~(j << shirq->offset); 272 else 273 tmp |= (j << shirq->offset); 274 writel(tmp, shirq->base + shirq->regs.clear_reg); 275 } 276 } 277 chip->irq_unmask(idata); 278 } 279 280 static void __init spear_shirq_register(struct spear_shirq *shirq, 281 int parent_irq) 282 { 283 int i; 284 285 if (shirq->disabled) 286 return; 287 288 irq_set_chained_handler(parent_irq, shirq_handler); 289 irq_set_handler_data(parent_irq, shirq); 290 291 for (i = 0; i < shirq->nr_irqs; i++) { 292 irq_set_chip_and_handler(shirq->virq_base + i, 293 &shirq_chip, handle_simple_irq); 294 set_irq_flags(shirq->virq_base + i, IRQF_VALID); 295 irq_set_chip_data(shirq->virq_base + i, shirq); 296 } 297 } 298 299 static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr, 300 struct device_node *np) 301 { 302 int i, parent_irq, virq_base, hwirq = 0, nr_irqs = 0; 303 struct irq_domain *shirq_domain; 304 void __iomem *base; 305 306 base = of_iomap(np, 0); 307 if (!base) { 308 pr_err("%s: failed to map shirq registers\n", __func__); 309 return -ENXIO; 310 } 311 312 for (i = 0; i < block_nr; i++) 313 nr_irqs += shirq_blocks[i]->nr_irqs; 314 315 virq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); 316 if (IS_ERR_VALUE(virq_base)) { 317 pr_err("%s: irq desc alloc failed\n", __func__); 318 goto err_unmap; 319 } 320 321 shirq_domain = irq_domain_add_legacy(np, nr_irqs, virq_base, 0, 322 &irq_domain_simple_ops, NULL); 323 if (WARN_ON(!shirq_domain)) { 324 pr_warn("%s: irq domain init failed\n", __func__); 325 goto err_free_desc; 326 } 327 328 for (i = 0; i < block_nr; i++) { 329 shirq_blocks[i]->base = base; 330 shirq_blocks[i]->virq_base = irq_find_mapping(shirq_domain, 331 hwirq); 332 333 parent_irq = irq_of_parse_and_map(np, i); 334 spear_shirq_register(shirq_blocks[i], parent_irq); 335 hwirq += shirq_blocks[i]->nr_irqs; 336 } 337 338 return 0; 339 340 err_free_desc: 341 irq_free_descs(virq_base, nr_irqs); 342 err_unmap: 343 iounmap(base); 344 return -ENXIO; 345 } 346 347 static int __init spear300_shirq_of_init(struct device_node *np, 348 struct device_node *parent) 349 { 350 return shirq_init(spear300_shirq_blocks, 351 ARRAY_SIZE(spear300_shirq_blocks), np); 352 } 353 IRQCHIP_DECLARE(spear300_shirq, "st,spear300-shirq", spear300_shirq_of_init); 354 355 static int __init spear310_shirq_of_init(struct device_node *np, 356 struct device_node *parent) 357 { 358 return shirq_init(spear310_shirq_blocks, 359 ARRAY_SIZE(spear310_shirq_blocks), np); 360 } 361 IRQCHIP_DECLARE(spear310_shirq, "st,spear310-shirq", spear310_shirq_of_init); 362 363 static int __init spear320_shirq_of_init(struct device_node *np, 364 struct device_node *parent) 365 { 366 return shirq_init(spear320_shirq_blocks, 367 ARRAY_SIZE(spear320_shirq_blocks), np); 368 } 369 IRQCHIP_DECLARE(spear320_shirq, "st,spear320-shirq", spear320_shirq_of_init); 370