Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Atmel AT91 AIC (Advanced Interrupt Controller) driver
0003  *
0004  *  Copyright (C) 2004 SAN People
0005  *  Copyright (C) 2004 ATMEL
0006  *  Copyright (C) Rick Bronson
0007  *  Copyright (C) 2014 Free Electrons
0008  *
0009  *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
0010  *
0011  * This file is licensed under the terms of the GNU General Public
0012  * License version 2.  This program is licensed "as is" without any
0013  * warranty of any kind, whether express or implied.
0014  */
0015 
0016 #include <linux/init.h>
0017 #include <linux/module.h>
0018 #include <linux/mm.h>
0019 #include <linux/bitmap.h>
0020 #include <linux/types.h>
0021 #include <linux/irq.h>
0022 #include <linux/irqchip.h>
0023 #include <linux/of.h>
0024 #include <linux/of_address.h>
0025 #include <linux/of_irq.h>
0026 #include <linux/irqdomain.h>
0027 #include <linux/err.h>
0028 #include <linux/slab.h>
0029 #include <linux/io.h>
0030 
0031 #include <asm/exception.h>
0032 #include <asm/mach/irq.h>
0033 
0034 #include "irq-atmel-aic-common.h"
0035 
0036 /* Number of irq lines managed by AIC */
0037 #define NR_AIC_IRQS 32
0038 
0039 #define AT91_AIC_SMR(n)         ((n) * 4)
0040 
0041 #define AT91_AIC_SVR(n)         (0x80 + ((n) * 4))
0042 #define AT91_AIC_IVR            0x100
0043 #define AT91_AIC_FVR            0x104
0044 #define AT91_AIC_ISR            0x108
0045 
0046 #define AT91_AIC_IPR            0x10c
0047 #define AT91_AIC_IMR            0x110
0048 #define AT91_AIC_CISR           0x114
0049 
0050 #define AT91_AIC_IECR           0x120
0051 #define AT91_AIC_IDCR           0x124
0052 #define AT91_AIC_ICCR           0x128
0053 #define AT91_AIC_ISCR           0x12c
0054 #define AT91_AIC_EOICR          0x130
0055 #define AT91_AIC_SPU            0x134
0056 #define AT91_AIC_DCR            0x138
0057 
0058 static struct irq_domain *aic_domain;
0059 
0060 static asmlinkage void __exception_irq_entry
0061 aic_handle(struct pt_regs *regs)
0062 {
0063     struct irq_domain_chip_generic *dgc = aic_domain->gc;
0064     struct irq_chip_generic *gc = dgc->gc[0];
0065     u32 irqnr;
0066     u32 irqstat;
0067 
0068     irqnr = irq_reg_readl(gc, AT91_AIC_IVR);
0069     irqstat = irq_reg_readl(gc, AT91_AIC_ISR);
0070 
0071     if (!irqstat)
0072         irq_reg_writel(gc, 0, AT91_AIC_EOICR);
0073     else
0074         generic_handle_domain_irq(aic_domain, irqnr);
0075 }
0076 
0077 static int aic_retrigger(struct irq_data *d)
0078 {
0079     struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0080 
0081     /* Enable interrupt on AIC5 */
0082     irq_gc_lock(gc);
0083     irq_reg_writel(gc, d->mask, AT91_AIC_ISCR);
0084     irq_gc_unlock(gc);
0085 
0086     return 1;
0087 }
0088 
0089 static int aic_set_type(struct irq_data *d, unsigned type)
0090 {
0091     struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0092     unsigned int smr;
0093     int ret;
0094 
0095     smr = irq_reg_readl(gc, AT91_AIC_SMR(d->hwirq));
0096     ret = aic_common_set_type(d, type, &smr);
0097     if (ret)
0098         return ret;
0099 
0100     irq_reg_writel(gc, smr, AT91_AIC_SMR(d->hwirq));
0101 
0102     return 0;
0103 }
0104 
0105 #ifdef CONFIG_PM
0106 static void aic_suspend(struct irq_data *d)
0107 {
0108     struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0109 
0110     irq_gc_lock(gc);
0111     irq_reg_writel(gc, gc->mask_cache, AT91_AIC_IDCR);
0112     irq_reg_writel(gc, gc->wake_active, AT91_AIC_IECR);
0113     irq_gc_unlock(gc);
0114 }
0115 
0116 static void aic_resume(struct irq_data *d)
0117 {
0118     struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0119 
0120     irq_gc_lock(gc);
0121     irq_reg_writel(gc, gc->wake_active, AT91_AIC_IDCR);
0122     irq_reg_writel(gc, gc->mask_cache, AT91_AIC_IECR);
0123     irq_gc_unlock(gc);
0124 }
0125 
0126 static void aic_pm_shutdown(struct irq_data *d)
0127 {
0128     struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0129 
0130     irq_gc_lock(gc);
0131     irq_reg_writel(gc, 0xffffffff, AT91_AIC_IDCR);
0132     irq_reg_writel(gc, 0xffffffff, AT91_AIC_ICCR);
0133     irq_gc_unlock(gc);
0134 }
0135 #else
0136 #define aic_suspend     NULL
0137 #define aic_resume      NULL
0138 #define aic_pm_shutdown     NULL
0139 #endif /* CONFIG_PM */
0140 
0141 static void __init aic_hw_init(struct irq_domain *domain)
0142 {
0143     struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
0144     int i;
0145 
0146     /*
0147      * Perform 8 End Of Interrupt Command to make sure AIC
0148      * will not Lock out nIRQ
0149      */
0150     for (i = 0; i < 8; i++)
0151         irq_reg_writel(gc, 0, AT91_AIC_EOICR);
0152 
0153     /*
0154      * Spurious Interrupt ID in Spurious Vector Register.
0155      * When there is no current interrupt, the IRQ Vector Register
0156      * reads the value stored in AIC_SPU
0157      */
0158     irq_reg_writel(gc, 0xffffffff, AT91_AIC_SPU);
0159 
0160     /* No debugging in AIC: Debug (Protect) Control Register */
0161     irq_reg_writel(gc, 0, AT91_AIC_DCR);
0162 
0163     /* Disable and clear all interrupts initially */
0164     irq_reg_writel(gc, 0xffffffff, AT91_AIC_IDCR);
0165     irq_reg_writel(gc, 0xffffffff, AT91_AIC_ICCR);
0166 
0167     for (i = 0; i < 32; i++)
0168         irq_reg_writel(gc, i, AT91_AIC_SVR(i));
0169 }
0170 
0171 static int aic_irq_domain_xlate(struct irq_domain *d,
0172                 struct device_node *ctrlr,
0173                 const u32 *intspec, unsigned int intsize,
0174                 irq_hw_number_t *out_hwirq,
0175                 unsigned int *out_type)
0176 {
0177     struct irq_domain_chip_generic *dgc = d->gc;
0178     struct irq_chip_generic *gc;
0179     unsigned long flags;
0180     unsigned smr;
0181     int idx;
0182     int ret;
0183 
0184     if (!dgc)
0185         return -EINVAL;
0186 
0187     ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
0188                       out_hwirq, out_type);
0189     if (ret)
0190         return ret;
0191 
0192     idx = intspec[0] / dgc->irqs_per_chip;
0193     if (idx >= dgc->num_chips)
0194         return -EINVAL;
0195 
0196     gc = dgc->gc[idx];
0197 
0198     irq_gc_lock_irqsave(gc, flags);
0199     smr = irq_reg_readl(gc, AT91_AIC_SMR(*out_hwirq));
0200     aic_common_set_priority(intspec[2], &smr);
0201     irq_reg_writel(gc, smr, AT91_AIC_SMR(*out_hwirq));
0202     irq_gc_unlock_irqrestore(gc, flags);
0203 
0204     return ret;
0205 }
0206 
0207 static const struct irq_domain_ops aic_irq_ops = {
0208     .map    = irq_map_generic_chip,
0209     .xlate  = aic_irq_domain_xlate,
0210 };
0211 
0212 static void __init at91rm9200_aic_irq_fixup(void)
0213 {
0214     aic_common_rtc_irq_fixup();
0215 }
0216 
0217 static void __init at91sam9260_aic_irq_fixup(void)
0218 {
0219     aic_common_rtt_irq_fixup();
0220 }
0221 
0222 static void __init at91sam9g45_aic_irq_fixup(void)
0223 {
0224     aic_common_rtc_irq_fixup();
0225     aic_common_rtt_irq_fixup();
0226 }
0227 
0228 static const struct of_device_id aic_irq_fixups[] __initconst = {
0229     { .compatible = "atmel,at91rm9200", .data = at91rm9200_aic_irq_fixup },
0230     { .compatible = "atmel,at91sam9g45", .data = at91sam9g45_aic_irq_fixup },
0231     { .compatible = "atmel,at91sam9n12", .data = at91rm9200_aic_irq_fixup },
0232     { .compatible = "atmel,at91sam9rl", .data = at91sam9g45_aic_irq_fixup },
0233     { .compatible = "atmel,at91sam9x5", .data = at91rm9200_aic_irq_fixup },
0234     { .compatible = "atmel,at91sam9260", .data = at91sam9260_aic_irq_fixup },
0235     { .compatible = "atmel,at91sam9261", .data = at91sam9260_aic_irq_fixup },
0236     { .compatible = "atmel,at91sam9263", .data = at91sam9260_aic_irq_fixup },
0237     { .compatible = "atmel,at91sam9g20", .data = at91sam9260_aic_irq_fixup },
0238     { /* sentinel */ },
0239 };
0240 
0241 static int __init aic_of_init(struct device_node *node,
0242                   struct device_node *parent)
0243 {
0244     struct irq_chip_generic *gc;
0245     struct irq_domain *domain;
0246 
0247     if (aic_domain)
0248         return -EEXIST;
0249 
0250     domain = aic_common_of_init(node, &aic_irq_ops, "atmel-aic",
0251                     NR_AIC_IRQS, aic_irq_fixups);
0252     if (IS_ERR(domain))
0253         return PTR_ERR(domain);
0254 
0255     aic_domain = domain;
0256     gc = irq_get_domain_generic_chip(domain, 0);
0257 
0258     gc->chip_types[0].regs.eoi = AT91_AIC_EOICR;
0259     gc->chip_types[0].regs.enable = AT91_AIC_IECR;
0260     gc->chip_types[0].regs.disable = AT91_AIC_IDCR;
0261     gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
0262     gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
0263     gc->chip_types[0].chip.irq_retrigger = aic_retrigger;
0264     gc->chip_types[0].chip.irq_set_type = aic_set_type;
0265     gc->chip_types[0].chip.irq_suspend = aic_suspend;
0266     gc->chip_types[0].chip.irq_resume = aic_resume;
0267     gc->chip_types[0].chip.irq_pm_shutdown = aic_pm_shutdown;
0268 
0269     aic_hw_init(domain);
0270     set_handle_irq(aic_handle);
0271 
0272     return 0;
0273 }
0274 IRQCHIP_DECLARE(at91rm9200_aic, "atmel,at91rm9200-aic", aic_of_init);