1edabd38eSSaeed Bishara /* 2edabd38eSSaeed Bishara * arch/arm/mach-dove/irq.c 3edabd38eSSaeed Bishara * 4edabd38eSSaeed Bishara * Dove IRQ handling. 5edabd38eSSaeed Bishara * 6edabd38eSSaeed Bishara * This file is licensed under the terms of the GNU General Public 7edabd38eSSaeed Bishara * License version 2. This program is licensed "as is" without any 8edabd38eSSaeed Bishara * warranty of any kind, whether express or implied. 9edabd38eSSaeed Bishara */ 10edabd38eSSaeed Bishara 11edabd38eSSaeed Bishara #include <linux/kernel.h> 12edabd38eSSaeed Bishara #include <linux/init.h> 13edabd38eSSaeed Bishara #include <linux/irq.h> 14edabd38eSSaeed Bishara #include <linux/gpio.h> 15edabd38eSSaeed Bishara #include <linux/io.h> 16edabd38eSSaeed Bishara #include <asm/mach/arch.h> 17edabd38eSSaeed Bishara #include <plat/irq.h> 18edabd38eSSaeed Bishara #include <asm/mach/irq.h> 19edabd38eSSaeed Bishara #include <mach/pm.h> 20edabd38eSSaeed Bishara #include <mach/bridge-regs.h> 21edabd38eSSaeed Bishara #include "common.h" 22edabd38eSSaeed Bishara 23edabd38eSSaeed Bishara static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 24edabd38eSSaeed Bishara { 25edabd38eSSaeed Bishara int irqoff; 26edabd38eSSaeed Bishara BUG_ON(irq < IRQ_DOVE_GPIO_0_7 || irq > IRQ_DOVE_HIGH_GPIO); 27edabd38eSSaeed Bishara 28edabd38eSSaeed Bishara irqoff = irq <= IRQ_DOVE_GPIO_16_23 ? irq - IRQ_DOVE_GPIO_0_7 : 29edabd38eSSaeed Bishara 3 + irq - IRQ_DOVE_GPIO_24_31; 30edabd38eSSaeed Bishara 31edabd38eSSaeed Bishara orion_gpio_irq_handler(irqoff << 3); 32edabd38eSSaeed Bishara if (irq == IRQ_DOVE_HIGH_GPIO) { 33edabd38eSSaeed Bishara orion_gpio_irq_handler(40); 34edabd38eSSaeed Bishara orion_gpio_irq_handler(48); 35edabd38eSSaeed Bishara orion_gpio_irq_handler(56); 36edabd38eSSaeed Bishara } 37edabd38eSSaeed Bishara } 38edabd38eSSaeed Bishara 39aa456a6eSLennert Buytenhek static void pmu_irq_mask(struct irq_data *d) 40edabd38eSSaeed Bishara { 41aa456a6eSLennert Buytenhek int pin = irq_to_pmu(d->irq); 42edabd38eSSaeed Bishara u32 u; 43edabd38eSSaeed Bishara 44edabd38eSSaeed Bishara u = readl(PMU_INTERRUPT_MASK); 45edabd38eSSaeed Bishara u &= ~(1 << (pin & 31)); 46edabd38eSSaeed Bishara writel(u, PMU_INTERRUPT_MASK); 47edabd38eSSaeed Bishara } 48edabd38eSSaeed Bishara 49aa456a6eSLennert Buytenhek static void pmu_irq_unmask(struct irq_data *d) 50edabd38eSSaeed Bishara { 51aa456a6eSLennert Buytenhek int pin = irq_to_pmu(d->irq); 52edabd38eSSaeed Bishara u32 u; 53edabd38eSSaeed Bishara 54edabd38eSSaeed Bishara u = readl(PMU_INTERRUPT_MASK); 55edabd38eSSaeed Bishara u |= 1 << (pin & 31); 56edabd38eSSaeed Bishara writel(u, PMU_INTERRUPT_MASK); 57edabd38eSSaeed Bishara } 58edabd38eSSaeed Bishara 59aa456a6eSLennert Buytenhek static void pmu_irq_ack(struct irq_data *d) 60edabd38eSSaeed Bishara { 61aa456a6eSLennert Buytenhek int pin = irq_to_pmu(d->irq); 62edabd38eSSaeed Bishara u32 u; 63edabd38eSSaeed Bishara 64edabd38eSSaeed Bishara u = ~(1 << (pin & 31)); 65edabd38eSSaeed Bishara writel(u, PMU_INTERRUPT_CAUSE); 66edabd38eSSaeed Bishara } 67edabd38eSSaeed Bishara 68edabd38eSSaeed Bishara static struct irq_chip pmu_irq_chip = { 69edabd38eSSaeed Bishara .name = "pmu_irq", 70aa456a6eSLennert Buytenhek .irq_mask = pmu_irq_mask, 71aa456a6eSLennert Buytenhek .irq_unmask = pmu_irq_unmask, 72aa456a6eSLennert Buytenhek .irq_ack = pmu_irq_ack, 73edabd38eSSaeed Bishara }; 74edabd38eSSaeed Bishara 75edabd38eSSaeed Bishara static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc) 76edabd38eSSaeed Bishara { 77edabd38eSSaeed Bishara unsigned long cause = readl(PMU_INTERRUPT_CAUSE); 78edabd38eSSaeed Bishara 79edabd38eSSaeed Bishara cause &= readl(PMU_INTERRUPT_MASK); 80edabd38eSSaeed Bishara if (cause == 0) { 81edabd38eSSaeed Bishara do_bad_IRQ(irq, desc); 82edabd38eSSaeed Bishara return; 83edabd38eSSaeed Bishara } 84edabd38eSSaeed Bishara 85edabd38eSSaeed Bishara for (irq = 0; irq < NR_PMU_IRQS; irq++) { 86edabd38eSSaeed Bishara if (!(cause & (1 << irq))) 87edabd38eSSaeed Bishara continue; 88edabd38eSSaeed Bishara irq = pmu_to_irq(irq); 89edabd38eSSaeed Bishara desc = irq_desc + irq; 90edabd38eSSaeed Bishara desc_handle_irq(irq, desc); 91edabd38eSSaeed Bishara } 92edabd38eSSaeed Bishara } 93edabd38eSSaeed Bishara 94edabd38eSSaeed Bishara void __init dove_init_irq(void) 95edabd38eSSaeed Bishara { 96edabd38eSSaeed Bishara int i; 97edabd38eSSaeed Bishara 98edabd38eSSaeed Bishara orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF)); 99edabd38eSSaeed Bishara orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF)); 100edabd38eSSaeed Bishara 101edabd38eSSaeed Bishara /* 102edabd38eSSaeed Bishara * Mask and clear GPIO IRQ interrupts. 103edabd38eSSaeed Bishara */ 104edabd38eSSaeed Bishara writel(0, GPIO_LEVEL_MASK(0)); 105edabd38eSSaeed Bishara writel(0, GPIO_EDGE_MASK(0)); 106edabd38eSSaeed Bishara writel(0, GPIO_EDGE_CAUSE(0)); 107edabd38eSSaeed Bishara 108edabd38eSSaeed Bishara /* 109edabd38eSSaeed Bishara * Mask and clear PMU interrupts 110edabd38eSSaeed Bishara */ 111edabd38eSSaeed Bishara writel(0, PMU_INTERRUPT_MASK); 112edabd38eSSaeed Bishara writel(0, PMU_INTERRUPT_CAUSE); 113edabd38eSSaeed Bishara 114edabd38eSSaeed Bishara for (i = IRQ_DOVE_GPIO_START; i < IRQ_DOVE_PMU_START; i++) { 115edabd38eSSaeed Bishara set_irq_chip(i, &orion_gpio_irq_chip); 116edabd38eSSaeed Bishara set_irq_handler(i, handle_level_irq); 117edabd38eSSaeed Bishara irq_desc[i].status |= IRQ_LEVEL; 118edabd38eSSaeed Bishara set_irq_flags(i, IRQF_VALID); 119edabd38eSSaeed Bishara } 120edabd38eSSaeed Bishara set_irq_chained_handler(IRQ_DOVE_GPIO_0_7, gpio_irq_handler); 121edabd38eSSaeed Bishara set_irq_chained_handler(IRQ_DOVE_GPIO_8_15, gpio_irq_handler); 122edabd38eSSaeed Bishara set_irq_chained_handler(IRQ_DOVE_GPIO_16_23, gpio_irq_handler); 123edabd38eSSaeed Bishara set_irq_chained_handler(IRQ_DOVE_GPIO_24_31, gpio_irq_handler); 124edabd38eSSaeed Bishara set_irq_chained_handler(IRQ_DOVE_HIGH_GPIO, gpio_irq_handler); 125edabd38eSSaeed Bishara 126edabd38eSSaeed Bishara for (i = IRQ_DOVE_PMU_START; i < NR_IRQS; i++) { 127edabd38eSSaeed Bishara set_irq_chip(i, &pmu_irq_chip); 128edabd38eSSaeed Bishara set_irq_handler(i, handle_level_irq); 129edabd38eSSaeed Bishara irq_desc[i].status |= IRQ_LEVEL; 130edabd38eSSaeed Bishara set_irq_flags(i, IRQF_VALID); 131edabd38eSSaeed Bishara } 132edabd38eSSaeed Bishara set_irq_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler); 133edabd38eSSaeed Bishara } 134