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