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 23aa456a6eSLennert Buytenhek static void pmu_irq_mask(struct irq_data *d) 24edabd38eSSaeed Bishara { 25aa456a6eSLennert Buytenhek int pin = irq_to_pmu(d->irq); 26edabd38eSSaeed Bishara u32 u; 27edabd38eSSaeed Bishara 28edabd38eSSaeed Bishara u = readl(PMU_INTERRUPT_MASK); 29edabd38eSSaeed Bishara u &= ~(1 << (pin & 31)); 30edabd38eSSaeed Bishara writel(u, PMU_INTERRUPT_MASK); 31edabd38eSSaeed Bishara } 32edabd38eSSaeed Bishara 33aa456a6eSLennert Buytenhek static void pmu_irq_unmask(struct irq_data *d) 34edabd38eSSaeed Bishara { 35aa456a6eSLennert Buytenhek int pin = irq_to_pmu(d->irq); 36edabd38eSSaeed Bishara u32 u; 37edabd38eSSaeed Bishara 38edabd38eSSaeed Bishara u = readl(PMU_INTERRUPT_MASK); 39edabd38eSSaeed Bishara u |= 1 << (pin & 31); 40edabd38eSSaeed Bishara writel(u, PMU_INTERRUPT_MASK); 41edabd38eSSaeed Bishara } 42edabd38eSSaeed Bishara 43aa456a6eSLennert Buytenhek static void pmu_irq_ack(struct irq_data *d) 44edabd38eSSaeed Bishara { 45aa456a6eSLennert Buytenhek int pin = irq_to_pmu(d->irq); 46edabd38eSSaeed Bishara u32 u; 47edabd38eSSaeed Bishara 48edabd38eSSaeed Bishara u = ~(1 << (pin & 31)); 49edabd38eSSaeed Bishara writel(u, PMU_INTERRUPT_CAUSE); 50edabd38eSSaeed Bishara } 51edabd38eSSaeed Bishara 52edabd38eSSaeed Bishara static struct irq_chip pmu_irq_chip = { 53edabd38eSSaeed Bishara .name = "pmu_irq", 54aa456a6eSLennert Buytenhek .irq_mask = pmu_irq_mask, 55aa456a6eSLennert Buytenhek .irq_unmask = pmu_irq_unmask, 56aa456a6eSLennert Buytenhek .irq_ack = pmu_irq_ack, 57edabd38eSSaeed Bishara }; 58edabd38eSSaeed Bishara 59edabd38eSSaeed Bishara static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc) 60edabd38eSSaeed Bishara { 61edabd38eSSaeed Bishara unsigned long cause = readl(PMU_INTERRUPT_CAUSE); 62edabd38eSSaeed Bishara 63edabd38eSSaeed Bishara cause &= readl(PMU_INTERRUPT_MASK); 64edabd38eSSaeed Bishara if (cause == 0) { 65edabd38eSSaeed Bishara do_bad_IRQ(irq, desc); 66edabd38eSSaeed Bishara return; 67edabd38eSSaeed Bishara } 68edabd38eSSaeed Bishara 69edabd38eSSaeed Bishara for (irq = 0; irq < NR_PMU_IRQS; irq++) { 70edabd38eSSaeed Bishara if (!(cause & (1 << irq))) 71edabd38eSSaeed Bishara continue; 72edabd38eSSaeed Bishara irq = pmu_to_irq(irq); 73cf0d6b76SThomas Gleixner generic_handle_irq(irq); 74edabd38eSSaeed Bishara } 75edabd38eSSaeed Bishara } 76edabd38eSSaeed Bishara 77278b45b0SAndrew Lunn static int __initdata gpio0_irqs[4] = { 78278b45b0SAndrew Lunn IRQ_DOVE_GPIO_0_7, 79278b45b0SAndrew Lunn IRQ_DOVE_GPIO_8_15, 80278b45b0SAndrew Lunn IRQ_DOVE_GPIO_16_23, 81278b45b0SAndrew Lunn IRQ_DOVE_GPIO_24_31, 82278b45b0SAndrew Lunn }; 83278b45b0SAndrew Lunn 84278b45b0SAndrew Lunn static int __initdata gpio1_irqs[4] = { 85278b45b0SAndrew Lunn IRQ_DOVE_HIGH_GPIO, 86278b45b0SAndrew Lunn 0, 87278b45b0SAndrew Lunn 0, 88278b45b0SAndrew Lunn 0, 89278b45b0SAndrew Lunn }; 90278b45b0SAndrew Lunn 91278b45b0SAndrew Lunn static int __initdata gpio2_irqs[4] = { 92278b45b0SAndrew Lunn 0, 93278b45b0SAndrew Lunn 0, 94278b45b0SAndrew Lunn 0, 95278b45b0SAndrew Lunn 0, 96278b45b0SAndrew Lunn }; 97278b45b0SAndrew Lunn 98edabd38eSSaeed Bishara void __init dove_init_irq(void) 99edabd38eSSaeed Bishara { 100edabd38eSSaeed Bishara int i; 101edabd38eSSaeed Bishara 102c3c5a281SThomas Petazzoni orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF); 103c3c5a281SThomas Petazzoni orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF); 104edabd38eSSaeed Bishara 105edabd38eSSaeed Bishara /* 1069eac6d0aSLennert Buytenhek * Initialize gpiolib for GPIOs 0-71. 107edabd38eSSaeed Bishara */ 108c3c5a281SThomas Petazzoni orion_gpio_init(NULL, 0, 32, DOVE_GPIO_LO_VIRT_BASE, 0, 109278b45b0SAndrew Lunn IRQ_DOVE_GPIO_START, gpio0_irqs); 1109eac6d0aSLennert Buytenhek 111c3c5a281SThomas Petazzoni orion_gpio_init(NULL, 32, 32, DOVE_GPIO_HI_VIRT_BASE, 0, 112278b45b0SAndrew Lunn IRQ_DOVE_GPIO_START + 32, gpio1_irqs); 1139eac6d0aSLennert Buytenhek 114c3c5a281SThomas Petazzoni orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0, 115278b45b0SAndrew Lunn IRQ_DOVE_GPIO_START + 64, gpio2_irqs); 116edabd38eSSaeed Bishara 117edabd38eSSaeed Bishara /* 118edabd38eSSaeed Bishara * Mask and clear PMU interrupts 119edabd38eSSaeed Bishara */ 120edabd38eSSaeed Bishara writel(0, PMU_INTERRUPT_MASK); 121edabd38eSSaeed Bishara writel(0, PMU_INTERRUPT_CAUSE); 122edabd38eSSaeed Bishara 123edabd38eSSaeed Bishara for (i = IRQ_DOVE_PMU_START; i < NR_IRQS; i++) { 124f38c02f3SThomas Gleixner irq_set_chip_and_handler(i, &pmu_irq_chip, handle_level_irq); 125cf0d6b76SThomas Gleixner irq_set_status_flags(i, IRQ_LEVEL); 126edabd38eSSaeed Bishara set_irq_flags(i, IRQF_VALID); 127edabd38eSSaeed Bishara } 1286845664aSThomas Gleixner irq_set_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler); 129edabd38eSSaeed Bishara } 130