1/* 2 * External interrupt handling for AT32AP CPUs 3 * 4 * Copyright (C) 2006 Atmel Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11#include <linux/errno.h> 12#include <linux/init.h> 13#include <linux/interrupt.h> 14#include <linux/irq.h> 15#include <linux/platform_device.h> 16#include <linux/random.h> 17#include <linux/slab.h> 18 19#include <asm/io.h> 20 21/* EIC register offsets */ 22#define EIC_IER 0x0000 23#define EIC_IDR 0x0004 24#define EIC_IMR 0x0008 25#define EIC_ISR 0x000c 26#define EIC_ICR 0x0010 27#define EIC_MODE 0x0014 28#define EIC_EDGE 0x0018 29#define EIC_LEVEL 0x001c 30#define EIC_NMIC 0x0024 31 32/* Bitfields in NMIC */ 33#define EIC_NMIC_ENABLE (1 << 0) 34 35/* Bit manipulation macros */ 36#define EIC_BIT(name) \ 37 (1 << EIC_##name##_OFFSET) 38#define EIC_BF(name,value) \ 39 (((value) & ((1 << EIC_##name##_SIZE) - 1)) \ 40 << EIC_##name##_OFFSET) 41#define EIC_BFEXT(name,value) \ 42 (((value) >> EIC_##name##_OFFSET) \ 43 & ((1 << EIC_##name##_SIZE) - 1)) 44#define EIC_BFINS(name,value,old) \ 45 (((old) & ~(((1 << EIC_##name##_SIZE) - 1) \ 46 << EIC_##name##_OFFSET)) \ 47 | EIC_BF(name,value)) 48 49/* Register access macros */ 50#define eic_readl(port,reg) \ 51 __raw_readl((port)->regs + EIC_##reg) 52#define eic_writel(port,reg,value) \ 53 __raw_writel((value), (port)->regs + EIC_##reg) 54 55struct eic { 56 void __iomem *regs; 57 struct irq_chip *chip; 58 unsigned int first_irq; 59}; 60 61static struct eic *nmi_eic; 62static bool nmi_enabled; 63 64static void eic_ack_irq(unsigned int irq) 65{ 66 struct eic *eic = get_irq_chip_data(irq); 67 eic_writel(eic, ICR, 1 << (irq - eic->first_irq)); 68} 69 70static void eic_mask_irq(unsigned int irq) 71{ 72 struct eic *eic = get_irq_chip_data(irq); 73 eic_writel(eic, IDR, 1 << (irq - eic->first_irq)); 74} 75 76static void eic_mask_ack_irq(unsigned int irq) 77{ 78 struct eic *eic = get_irq_chip_data(irq); 79 eic_writel(eic, ICR, 1 << (irq - eic->first_irq)); 80 eic_writel(eic, IDR, 1 << (irq - eic->first_irq)); 81} 82 83static void eic_unmask_irq(unsigned int irq) 84{ 85 struct eic *eic = get_irq_chip_data(irq); 86 eic_writel(eic, IER, 1 << (irq - eic->first_irq)); 87} 88 89static int eic_set_irq_type(unsigned int irq, unsigned int flow_type) 90{ 91 struct eic *eic = get_irq_chip_data(irq); 92 struct irq_desc *desc; 93 unsigned int i = irq - eic->first_irq; 94 u32 mode, edge, level; 95 int ret = 0; 96 97 flow_type &= IRQ_TYPE_SENSE_MASK; 98 if (flow_type == IRQ_TYPE_NONE) 99 flow_type = IRQ_TYPE_LEVEL_LOW; 100 101 desc = &irq_desc[irq]; 102 103 mode = eic_readl(eic, MODE); 104 edge = eic_readl(eic, EDGE); 105 level = eic_readl(eic, LEVEL); 106 107 switch (flow_type) { 108 case IRQ_TYPE_LEVEL_LOW: 109 mode |= 1 << i; 110 level &= ~(1 << i); 111 break; 112 case IRQ_TYPE_LEVEL_HIGH: 113 mode |= 1 << i; 114 level |= 1 << i; 115 break; 116 case IRQ_TYPE_EDGE_RISING: 117 mode &= ~(1 << i); 118 edge |= 1 << i; 119 break; 120 case IRQ_TYPE_EDGE_FALLING: 121 mode &= ~(1 << i); 122 edge &= ~(1 << i); 123 break; 124 default: 125 ret = -EINVAL; 126 break; 127 } 128 129 if (ret == 0) { 130 eic_writel(eic, MODE, mode); 131 eic_writel(eic, EDGE, edge); 132 eic_writel(eic, LEVEL, level); 133 134 if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) { 135 flow_type |= IRQ_LEVEL; 136 __set_irq_handler_unlocked(irq, handle_level_irq); 137 } else 138 __set_irq_handler_unlocked(irq, handle_edge_irq); 139 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); 140 desc->status |= flow_type; 141 } 142 143 return ret; 144} 145 146static struct irq_chip eic_chip = { 147 .name = "eic", 148 .ack = eic_ack_irq, 149 .mask = eic_mask_irq, 150 .mask_ack = eic_mask_ack_irq, 151 .unmask = eic_unmask_irq, 152 .set_type = eic_set_irq_type, 153}; 154 155static void demux_eic_irq(unsigned int irq, struct irq_desc *desc) 156{ 157 struct eic *eic = desc->handler_data; 158 unsigned long status, pending; 159 unsigned int i; 160 161 status = eic_readl(eic, ISR); 162 pending = status & eic_readl(eic, IMR); 163 164 while (pending) { 165 i = fls(pending) - 1; 166 pending &= ~(1 << i); 167 168 generic_handle_irq(i + eic->first_irq); 169 } 170} 171 172int nmi_enable(void) 173{ 174 nmi_enabled = true; 175 176 if (nmi_eic) 177 eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE); 178 179 return 0; 180} 181 182void nmi_disable(void) 183{ 184 if (nmi_eic) 185 eic_writel(nmi_eic, NMIC, 0); 186 187 nmi_enabled = false; 188} 189 190static int __init eic_probe(struct platform_device *pdev) 191{ 192 struct eic *eic; 193 struct resource *regs; 194 unsigned int i; 195 unsigned int nr_of_irqs; 196 unsigned int int_irq; 197 int ret; 198 u32 pattern; 199 200 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 201 int_irq = platform_get_irq(pdev, 0); 202 if (!regs || !int_irq) { 203 dev_dbg(&pdev->dev, "missing regs and/or irq resource\n"); 204 return -ENXIO; 205 } 206 207 ret = -ENOMEM; 208 eic = kzalloc(sizeof(struct eic), GFP_KERNEL); 209 if (!eic) { 210 dev_dbg(&pdev->dev, "no memory for eic structure\n"); 211 goto err_kzalloc; 212 } 213 214 eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id; 215 eic->regs = ioremap(regs->start, regs->end - regs->start + 1); 216 if (!eic->regs) { 217 dev_dbg(&pdev->dev, "failed to map regs\n"); 218 goto err_ioremap; 219 } 220 221 /* 222 * Find out how many interrupt lines that are actually 223 * implemented in hardware. 224 */ 225 eic_writel(eic, IDR, ~0UL); 226 eic_writel(eic, MODE, ~0UL); 227 pattern = eic_readl(eic, MODE); 228 nr_of_irqs = fls(pattern); 229 230 /* Trigger on low level unless overridden by driver */ 231 eic_writel(eic, EDGE, 0UL); 232 eic_writel(eic, LEVEL, 0UL); 233 234 eic->chip = &eic_chip; 235 236 for (i = 0; i < nr_of_irqs; i++) { 237 set_irq_chip_and_handler(eic->first_irq + i, &eic_chip, 238 handle_level_irq); 239 set_irq_chip_data(eic->first_irq + i, eic); 240 } 241 242 set_irq_chained_handler(int_irq, demux_eic_irq); 243 set_irq_data(int_irq, eic); 244 245 if (pdev->id == 0) { 246 nmi_eic = eic; 247 if (nmi_enabled) 248 /* 249 * Someone tried to enable NMI before we were 250 * ready. Do it now. 251 */ 252 nmi_enable(); 253 } 254 255 dev_info(&pdev->dev, 256 "External Interrupt Controller at 0x%p, IRQ %u\n", 257 eic->regs, int_irq); 258 dev_info(&pdev->dev, 259 "Handling %u external IRQs, starting with IRQ %u\n", 260 nr_of_irqs, eic->first_irq); 261 262 return 0; 263 264err_ioremap: 265 kfree(eic); 266err_kzalloc: 267 return ret; 268} 269 270static struct platform_driver eic_driver = { 271 .driver = { 272 .name = "at32_eic", 273 }, 274}; 275 276static int __init eic_init(void) 277{ 278 return platform_driver_probe(&eic_driver, eic_probe); 279} 280arch_initcall(eic_init); 281