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(struct irq_data *d) 65{ 66 struct eic *eic = irq_data_get_irq_chip_data(d); 67 eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq)); 68} 69 70static void eic_mask_irq(struct irq_data *d) 71{ 72 struct eic *eic = irq_data_get_irq_chip_data(d); 73 eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq)); 74} 75 76static void eic_mask_ack_irq(struct irq_data *d) 77{ 78 struct eic *eic = irq_data_get_irq_chip_data(d); 79 eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq)); 80 eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq)); 81} 82 83static void eic_unmask_irq(struct irq_data *d) 84{ 85 struct eic *eic = irq_data_get_irq_chip_data(d); 86 eic_writel(eic, IER, 1 << (d->irq - eic->first_irq)); 87} 88 89static int eic_set_irq_type(struct irq_data *d, unsigned int flow_type) 90{ 91 struct eic *eic = irq_data_get_irq_chip_data(d); 92 unsigned int irq = d->irq; 93 unsigned int i = irq - eic->first_irq; 94 u32 mode, edge, level; 95 96 flow_type &= IRQ_TYPE_SENSE_MASK; 97 if (flow_type == IRQ_TYPE_NONE) 98 flow_type = IRQ_TYPE_LEVEL_LOW; 99 100 mode = eic_readl(eic, MODE); 101 edge = eic_readl(eic, EDGE); 102 level = eic_readl(eic, LEVEL); 103 104 switch (flow_type) { 105 case IRQ_TYPE_LEVEL_LOW: 106 mode |= 1 << i; 107 level &= ~(1 << i); 108 break; 109 case IRQ_TYPE_LEVEL_HIGH: 110 mode |= 1 << i; 111 level |= 1 << i; 112 break; 113 case IRQ_TYPE_EDGE_RISING: 114 mode &= ~(1 << i); 115 edge |= 1 << i; 116 break; 117 case IRQ_TYPE_EDGE_FALLING: 118 mode &= ~(1 << i); 119 edge &= ~(1 << i); 120 break; 121 default: 122 return -EINVAL; 123 } 124 125 eic_writel(eic, MODE, mode); 126 eic_writel(eic, EDGE, edge); 127 eic_writel(eic, LEVEL, level); 128 129 irqd_set_trigger_type(d, flow_type); 130 if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) 131 irq_set_handler_locked(d, handle_level_irq); 132 else 133 irq_set_handler_locked(d, handle_edge_irq); 134 135 return IRQ_SET_MASK_OK_NOCOPY; 136} 137 138static struct irq_chip eic_chip = { 139 .name = "eic", 140 .irq_ack = eic_ack_irq, 141 .irq_mask = eic_mask_irq, 142 .irq_mask_ack = eic_mask_ack_irq, 143 .irq_unmask = eic_unmask_irq, 144 .irq_set_type = eic_set_irq_type, 145}; 146 147static void demux_eic_irq(struct irq_desc *desc) 148{ 149 struct eic *eic = irq_desc_get_handler_data(desc); 150 unsigned long status, pending; 151 unsigned int i; 152 153 status = eic_readl(eic, ISR); 154 pending = status & eic_readl(eic, IMR); 155 156 while (pending) { 157 i = fls(pending) - 1; 158 pending &= ~(1 << i); 159 160 generic_handle_irq(i + eic->first_irq); 161 } 162} 163 164int nmi_enable(void) 165{ 166 nmi_enabled = true; 167 168 if (nmi_eic) 169 eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE); 170 171 return 0; 172} 173 174void nmi_disable(void) 175{ 176 if (nmi_eic) 177 eic_writel(nmi_eic, NMIC, 0); 178 179 nmi_enabled = false; 180} 181 182static int __init eic_probe(struct platform_device *pdev) 183{ 184 struct eic *eic; 185 struct resource *regs; 186 unsigned int i; 187 unsigned int nr_of_irqs; 188 unsigned int int_irq; 189 int ret; 190 u32 pattern; 191 192 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 193 int_irq = platform_get_irq(pdev, 0); 194 if (!regs || (int)int_irq <= 0) { 195 dev_dbg(&pdev->dev, "missing regs and/or irq resource\n"); 196 return -ENXIO; 197 } 198 199 ret = -ENOMEM; 200 eic = kzalloc(sizeof(struct eic), GFP_KERNEL); 201 if (!eic) { 202 dev_dbg(&pdev->dev, "no memory for eic structure\n"); 203 goto err_kzalloc; 204 } 205 206 eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id; 207 eic->regs = ioremap(regs->start, resource_size(regs)); 208 if (!eic->regs) { 209 dev_dbg(&pdev->dev, "failed to map regs\n"); 210 goto err_ioremap; 211 } 212 213 /* 214 * Find out how many interrupt lines that are actually 215 * implemented in hardware. 216 */ 217 eic_writel(eic, IDR, ~0UL); 218 eic_writel(eic, MODE, ~0UL); 219 pattern = eic_readl(eic, MODE); 220 nr_of_irqs = fls(pattern); 221 222 /* Trigger on low level unless overridden by driver */ 223 eic_writel(eic, EDGE, 0UL); 224 eic_writel(eic, LEVEL, 0UL); 225 226 eic->chip = &eic_chip; 227 228 for (i = 0; i < nr_of_irqs; i++) { 229 irq_set_chip_and_handler(eic->first_irq + i, &eic_chip, 230 handle_level_irq); 231 irq_set_chip_data(eic->first_irq + i, eic); 232 } 233 234 irq_set_chained_handler_and_data(int_irq, demux_eic_irq, eic); 235 236 if (pdev->id == 0) { 237 nmi_eic = eic; 238 if (nmi_enabled) 239 /* 240 * Someone tried to enable NMI before we were 241 * ready. Do it now. 242 */ 243 nmi_enable(); 244 } 245 246 dev_info(&pdev->dev, 247 "External Interrupt Controller at 0x%p, IRQ %u\n", 248 eic->regs, int_irq); 249 dev_info(&pdev->dev, 250 "Handling %u external IRQs, starting with IRQ %u\n", 251 nr_of_irqs, eic->first_irq); 252 253 return 0; 254 255err_ioremap: 256 kfree(eic); 257err_kzalloc: 258 return ret; 259} 260 261static struct platform_driver eic_driver = { 262 .driver = { 263 .name = "at32_eic", 264 }, 265}; 266 267static int __init eic_init(void) 268{ 269 return platform_driver_probe(&eic_driver, eic_probe); 270} 271arch_initcall(eic_init); 272