1 /* 2 * Atmel AT91 AIC (Advanced Interrupt Controller) driver 3 * 4 * Copyright (C) 2004 SAN People 5 * Copyright (C) 2004 ATMEL 6 * Copyright (C) Rick Bronson 7 * Copyright (C) 2014 Free Electrons 8 * 9 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> 10 * 11 * This file is licensed under the terms of the GNU General Public 12 * License version 2. This program is licensed "as is" without any 13 * warranty of any kind, whether express or implied. 14 */ 15 16 #include <linux/init.h> 17 #include <linux/module.h> 18 #include <linux/mm.h> 19 #include <linux/bitmap.h> 20 #include <linux/types.h> 21 #include <linux/irq.h> 22 #include <linux/of.h> 23 #include <linux/of_address.h> 24 #include <linux/of_irq.h> 25 #include <linux/irqdomain.h> 26 #include <linux/err.h> 27 #include <linux/slab.h> 28 #include <linux/io.h> 29 30 #include <asm/exception.h> 31 #include <asm/mach/irq.h> 32 33 #include "irq-atmel-aic-common.h" 34 #include "irqchip.h" 35 36 /* Number of irq lines managed by AIC */ 37 #define NR_AIC_IRQS 32 38 39 #define AT91_AIC_SMR(n) ((n) * 4) 40 41 #define AT91_AIC_SVR(n) (0x80 + ((n) * 4)) 42 #define AT91_AIC_IVR 0x100 43 #define AT91_AIC_FVR 0x104 44 #define AT91_AIC_ISR 0x108 45 46 #define AT91_AIC_IPR 0x10c 47 #define AT91_AIC_IMR 0x110 48 #define AT91_AIC_CISR 0x114 49 50 #define AT91_AIC_IECR 0x120 51 #define AT91_AIC_IDCR 0x124 52 #define AT91_AIC_ICCR 0x128 53 #define AT91_AIC_ISCR 0x12c 54 #define AT91_AIC_EOICR 0x130 55 #define AT91_AIC_SPU 0x134 56 #define AT91_AIC_DCR 0x138 57 58 static struct irq_domain *aic_domain; 59 60 static asmlinkage void __exception_irq_entry 61 aic_handle(struct pt_regs *regs) 62 { 63 struct irq_domain_chip_generic *dgc = aic_domain->gc; 64 struct irq_chip_generic *gc = dgc->gc[0]; 65 u32 irqnr; 66 u32 irqstat; 67 68 irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR); 69 irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR); 70 71 irqnr = irq_find_mapping(aic_domain, irqnr); 72 73 if (!irqstat) 74 irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR); 75 else 76 handle_IRQ(irqnr, regs); 77 } 78 79 static int aic_retrigger(struct irq_data *d) 80 { 81 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 82 83 /* Enable interrupt on AIC5 */ 84 irq_gc_lock(gc); 85 irq_reg_writel(d->mask, gc->reg_base + AT91_AIC_ISCR); 86 irq_gc_unlock(gc); 87 88 return 0; 89 } 90 91 static int aic_set_type(struct irq_data *d, unsigned type) 92 { 93 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 94 unsigned int smr; 95 int ret; 96 97 smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(d->hwirq)); 98 ret = aic_common_set_type(d, type, &smr); 99 if (ret) 100 return ret; 101 102 irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(d->hwirq)); 103 104 return 0; 105 } 106 107 #ifdef CONFIG_PM 108 static void aic_suspend(struct irq_data *d) 109 { 110 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 111 112 irq_gc_lock(gc); 113 irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IDCR); 114 irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IECR); 115 irq_gc_unlock(gc); 116 } 117 118 static void aic_resume(struct irq_data *d) 119 { 120 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 121 122 irq_gc_lock(gc); 123 irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IDCR); 124 irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IECR); 125 irq_gc_unlock(gc); 126 } 127 128 static void aic_pm_shutdown(struct irq_data *d) 129 { 130 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 131 132 irq_gc_lock(gc); 133 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR); 134 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR); 135 irq_gc_unlock(gc); 136 } 137 #else 138 #define aic_suspend NULL 139 #define aic_resume NULL 140 #define aic_pm_shutdown NULL 141 #endif /* CONFIG_PM */ 142 143 static void __init aic_hw_init(struct irq_domain *domain) 144 { 145 struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0); 146 int i; 147 148 /* 149 * Perform 8 End Of Interrupt Command to make sure AIC 150 * will not Lock out nIRQ 151 */ 152 for (i = 0; i < 8; i++) 153 irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR); 154 155 /* 156 * Spurious Interrupt ID in Spurious Vector Register. 157 * When there is no current interrupt, the IRQ Vector Register 158 * reads the value stored in AIC_SPU 159 */ 160 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_SPU); 161 162 /* No debugging in AIC: Debug (Protect) Control Register */ 163 irq_reg_writel(0, gc->reg_base + AT91_AIC_DCR); 164 165 /* Disable and clear all interrupts initially */ 166 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR); 167 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR); 168 169 for (i = 0; i < 32; i++) 170 irq_reg_writel(i, gc->reg_base + AT91_AIC_SVR(i)); 171 } 172 173 static int aic_irq_domain_xlate(struct irq_domain *d, 174 struct device_node *ctrlr, 175 const u32 *intspec, unsigned int intsize, 176 irq_hw_number_t *out_hwirq, 177 unsigned int *out_type) 178 { 179 struct irq_domain_chip_generic *dgc = d->gc; 180 struct irq_chip_generic *gc; 181 unsigned smr; 182 int idx; 183 int ret; 184 185 if (!dgc) 186 return -EINVAL; 187 188 ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize, 189 out_hwirq, out_type); 190 if (ret) 191 return ret; 192 193 idx = intspec[0] / dgc->irqs_per_chip; 194 if (idx >= dgc->num_chips) 195 return -EINVAL; 196 197 gc = dgc->gc[idx]; 198 199 irq_gc_lock(gc); 200 smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(*out_hwirq)); 201 ret = aic_common_set_priority(intspec[2], &smr); 202 if (!ret) 203 irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(*out_hwirq)); 204 irq_gc_unlock(gc); 205 206 return ret; 207 } 208 209 static const struct irq_domain_ops aic_irq_ops = { 210 .map = irq_map_generic_chip, 211 .xlate = aic_irq_domain_xlate, 212 }; 213 214 static void __init at91sam9_aic_irq_fixup(struct device_node *root) 215 { 216 aic_common_rtc_irq_fixup(root); 217 } 218 219 static const struct of_device_id __initdata aic_irq_fixups[] = { 220 { .compatible = "atmel,at91sam9g45", .data = at91sam9_aic_irq_fixup }, 221 { .compatible = "atmel,at91sam9n12", .data = at91sam9_aic_irq_fixup }, 222 { .compatible = "atmel,at91sam9rl", .data = at91sam9_aic_irq_fixup }, 223 { .compatible = "atmel,at91sam9x5", .data = at91sam9_aic_irq_fixup }, 224 { /* sentinel */ }, 225 }; 226 227 static int __init aic_of_init(struct device_node *node, 228 struct device_node *parent) 229 { 230 struct irq_chip_generic *gc; 231 struct irq_domain *domain; 232 233 if (aic_domain) 234 return -EEXIST; 235 236 domain = aic_common_of_init(node, &aic_irq_ops, "atmel-aic", 237 NR_AIC_IRQS); 238 if (IS_ERR(domain)) 239 return PTR_ERR(domain); 240 241 aic_common_irq_fixup(aic_irq_fixups); 242 243 aic_domain = domain; 244 gc = irq_get_domain_generic_chip(domain, 0); 245 246 gc->chip_types[0].regs.eoi = AT91_AIC_EOICR; 247 gc->chip_types[0].regs.enable = AT91_AIC_IECR; 248 gc->chip_types[0].regs.disable = AT91_AIC_IDCR; 249 gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg; 250 gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg; 251 gc->chip_types[0].chip.irq_retrigger = aic_retrigger; 252 gc->chip_types[0].chip.irq_set_type = aic_set_type; 253 gc->chip_types[0].chip.irq_suspend = aic_suspend; 254 gc->chip_types[0].chip.irq_resume = aic_resume; 255 gc->chip_types[0].chip.irq_pm_shutdown = aic_pm_shutdown; 256 257 aic_hw_init(domain); 258 set_handle_irq(aic_handle); 259 260 return 0; 261 } 262 IRQCHIP_DECLARE(at91rm9200_aic, "atmel,at91rm9200-aic", aic_of_init); 263