diff options
Diffstat (limited to 'arch/avr32/mach-at32ap/extint.c')
-rw-r--r-- | arch/avr32/mach-at32ap/extint.c | 271 |
1 files changed, 0 insertions, 271 deletions
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c deleted file mode 100644 index 96cabad68489..000000000000 --- a/arch/avr32/mach-at32ap/extint.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * External interrupt handling for AT32AP CPUs - * - * Copyright (C) 2006 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/platform_device.h> -#include <linux/random.h> -#include <linux/slab.h> - -#include <asm/io.h> - -/* EIC register offsets */ -#define EIC_IER 0x0000 -#define EIC_IDR 0x0004 -#define EIC_IMR 0x0008 -#define EIC_ISR 0x000c -#define EIC_ICR 0x0010 -#define EIC_MODE 0x0014 -#define EIC_EDGE 0x0018 -#define EIC_LEVEL 0x001c -#define EIC_NMIC 0x0024 - -/* Bitfields in NMIC */ -#define EIC_NMIC_ENABLE (1 << 0) - -/* Bit manipulation macros */ -#define EIC_BIT(name) \ - (1 << EIC_##name##_OFFSET) -#define EIC_BF(name,value) \ - (((value) & ((1 << EIC_##name##_SIZE) - 1)) \ - << EIC_##name##_OFFSET) -#define EIC_BFEXT(name,value) \ - (((value) >> EIC_##name##_OFFSET) \ - & ((1 << EIC_##name##_SIZE) - 1)) -#define EIC_BFINS(name,value,old) \ - (((old) & ~(((1 << EIC_##name##_SIZE) - 1) \ - << EIC_##name##_OFFSET)) \ - | EIC_BF(name,value)) - -/* Register access macros */ -#define eic_readl(port,reg) \ - __raw_readl((port)->regs + EIC_##reg) -#define eic_writel(port,reg,value) \ - __raw_writel((value), (port)->regs + EIC_##reg) - -struct eic { - void __iomem *regs; - struct irq_chip *chip; - unsigned int first_irq; -}; - -static struct eic *nmi_eic; -static bool nmi_enabled; - -static void eic_ack_irq(struct irq_data *d) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq)); -} - -static void eic_mask_irq(struct irq_data *d) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq)); -} - -static void eic_mask_ack_irq(struct irq_data *d) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq)); - eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq)); -} - -static void eic_unmask_irq(struct irq_data *d) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - eic_writel(eic, IER, 1 << (d->irq - eic->first_irq)); -} - -static int eic_set_irq_type(struct irq_data *d, unsigned int flow_type) -{ - struct eic *eic = irq_data_get_irq_chip_data(d); - unsigned int irq = d->irq; - unsigned int i = irq - eic->first_irq; - u32 mode, edge, level; - - flow_type &= IRQ_TYPE_SENSE_MASK; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; - - mode = eic_readl(eic, MODE); - edge = eic_readl(eic, EDGE); - level = eic_readl(eic, LEVEL); - - switch (flow_type) { - case IRQ_TYPE_LEVEL_LOW: - mode |= 1 << i; - level &= ~(1 << i); - break; - case IRQ_TYPE_LEVEL_HIGH: - mode |= 1 << i; - level |= 1 << i; - break; - case IRQ_TYPE_EDGE_RISING: - mode &= ~(1 << i); - edge |= 1 << i; - break; - case IRQ_TYPE_EDGE_FALLING: - mode &= ~(1 << i); - edge &= ~(1 << i); - break; - default: - return -EINVAL; - } - - eic_writel(eic, MODE, mode); - eic_writel(eic, EDGE, edge); - eic_writel(eic, LEVEL, level); - - irqd_set_trigger_type(d, flow_type); - if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) - irq_set_handler_locked(d, handle_level_irq); - else - irq_set_handler_locked(d, handle_edge_irq); - - return IRQ_SET_MASK_OK_NOCOPY; -} - -static struct irq_chip eic_chip = { - .name = "eic", - .irq_ack = eic_ack_irq, - .irq_mask = eic_mask_irq, - .irq_mask_ack = eic_mask_ack_irq, - .irq_unmask = eic_unmask_irq, - .irq_set_type = eic_set_irq_type, -}; - -static void demux_eic_irq(struct irq_desc *desc) -{ - struct eic *eic = irq_desc_get_handler_data(desc); - unsigned long status, pending; - unsigned int i; - - status = eic_readl(eic, ISR); - pending = status & eic_readl(eic, IMR); - - while (pending) { - i = fls(pending) - 1; - pending &= ~(1 << i); - - generic_handle_irq(i + eic->first_irq); - } -} - -int nmi_enable(void) -{ - nmi_enabled = true; - - if (nmi_eic) - eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE); - - return 0; -} - -void nmi_disable(void) -{ - if (nmi_eic) - eic_writel(nmi_eic, NMIC, 0); - - nmi_enabled = false; -} - -static int __init eic_probe(struct platform_device *pdev) -{ - struct eic *eic; - struct resource *regs; - unsigned int i; - unsigned int nr_of_irqs; - unsigned int int_irq; - int ret; - u32 pattern; - - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - int_irq = platform_get_irq(pdev, 0); - if (!regs || (int)int_irq <= 0) { - dev_dbg(&pdev->dev, "missing regs and/or irq resource\n"); - return -ENXIO; - } - - ret = -ENOMEM; - eic = kzalloc(sizeof(struct eic), GFP_KERNEL); - if (!eic) { - dev_dbg(&pdev->dev, "no memory for eic structure\n"); - goto err_kzalloc; - } - - eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id; - eic->regs = ioremap(regs->start, resource_size(regs)); - if (!eic->regs) { - dev_dbg(&pdev->dev, "failed to map regs\n"); - goto err_ioremap; - } - - /* - * Find out how many interrupt lines that are actually - * implemented in hardware. - */ - eic_writel(eic, IDR, ~0UL); - eic_writel(eic, MODE, ~0UL); - pattern = eic_readl(eic, MODE); - nr_of_irqs = fls(pattern); - - /* Trigger on low level unless overridden by driver */ - eic_writel(eic, EDGE, 0UL); - eic_writel(eic, LEVEL, 0UL); - - eic->chip = &eic_chip; - - for (i = 0; i < nr_of_irqs; i++) { - irq_set_chip_and_handler(eic->first_irq + i, &eic_chip, - handle_level_irq); - irq_set_chip_data(eic->first_irq + i, eic); - } - - irq_set_chained_handler_and_data(int_irq, demux_eic_irq, eic); - - if (pdev->id == 0) { - nmi_eic = eic; - if (nmi_enabled) - /* - * Someone tried to enable NMI before we were - * ready. Do it now. - */ - nmi_enable(); - } - - dev_info(&pdev->dev, - "External Interrupt Controller at 0x%p, IRQ %u\n", - eic->regs, int_irq); - dev_info(&pdev->dev, - "Handling %u external IRQs, starting with IRQ %u\n", - nr_of_irqs, eic->first_irq); - - return 0; - -err_ioremap: - kfree(eic); -err_kzalloc: - return ret; -} - -static struct platform_driver eic_driver = { - .driver = { - .name = "at32_eic", - }, -}; - -static int __init eic_init(void) -{ - return platform_driver_probe(&eic_driver, eic_probe); -} -arch_initcall(eic_init); |