1 /* 2 * linux/arch/arm/mach-pxa/irq.c 3 * 4 * Generic PXA IRQ handling 5 * 6 * Author: Nicolas Pitre 7 * Created: Jun 15, 2001 8 * Copyright: MontaVista Software Inc. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15 #include <linux/init.h> 16 #include <linux/module.h> 17 #include <linux/interrupt.h> 18 #include <linux/syscore_ops.h> 19 #include <linux/io.h> 20 #include <linux/irq.h> 21 22 #include <mach/hardware.h> 23 #include <mach/irqs.h> 24 #include <mach/gpio.h> 25 26 #include "generic.h" 27 28 #define IRQ_BASE (void __iomem *)io_p2v(0x40d00000) 29 30 #define ICIP (0x000) 31 #define ICMR (0x004) 32 #define ICLR (0x008) 33 #define ICFR (0x00c) 34 #define ICPR (0x010) 35 #define ICCR (0x014) 36 #define ICHP (0x018) 37 #define IPR(i) (((i) < 32) ? (0x01c + ((i) << 2)) : \ 38 ((i) < 64) ? (0x0b0 + (((i) - 32) << 2)) : \ 39 (0x144 + (((i) - 64) << 2))) 40 #define IPR_VALID (1 << 31) 41 #define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f) 42 43 #define MAX_INTERNAL_IRQS 128 44 45 /* 46 * This is for peripheral IRQs internal to the PXA chip. 47 */ 48 49 static int pxa_internal_irq_nr; 50 51 static inline int cpu_has_ipr(void) 52 { 53 return !cpu_is_pxa25x(); 54 } 55 56 static inline void __iomem *irq_base(int i) 57 { 58 static unsigned long phys_base[] = { 59 0x40d00000, 60 0x40d0009c, 61 0x40d00130, 62 }; 63 64 return (void __iomem *)io_p2v(phys_base[i]); 65 } 66 67 static void pxa_mask_irq(struct irq_data *d) 68 { 69 void __iomem *base = irq_data_get_irq_chip_data(d); 70 uint32_t icmr = __raw_readl(base + ICMR); 71 72 icmr &= ~(1 << IRQ_BIT(d->irq)); 73 __raw_writel(icmr, base + ICMR); 74 } 75 76 static void pxa_unmask_irq(struct irq_data *d) 77 { 78 void __iomem *base = irq_data_get_irq_chip_data(d); 79 uint32_t icmr = __raw_readl(base + ICMR); 80 81 icmr |= 1 << IRQ_BIT(d->irq); 82 __raw_writel(icmr, base + ICMR); 83 } 84 85 static struct irq_chip pxa_internal_irq_chip = { 86 .name = "SC", 87 .irq_ack = pxa_mask_irq, 88 .irq_mask = pxa_mask_irq, 89 .irq_unmask = pxa_unmask_irq, 90 }; 91 92 /* 93 * GPIO IRQs for GPIO 0 and 1 94 */ 95 static int pxa_set_low_gpio_type(struct irq_data *d, unsigned int type) 96 { 97 int gpio = d->irq - IRQ_GPIO0; 98 99 if (__gpio_is_occupied(gpio)) { 100 pr_err("%s failed: GPIO is configured\n", __func__); 101 return -EINVAL; 102 } 103 104 if (type & IRQ_TYPE_EDGE_RISING) 105 GRER0 |= GPIO_bit(gpio); 106 else 107 GRER0 &= ~GPIO_bit(gpio); 108 109 if (type & IRQ_TYPE_EDGE_FALLING) 110 GFER0 |= GPIO_bit(gpio); 111 else 112 GFER0 &= ~GPIO_bit(gpio); 113 114 return 0; 115 } 116 117 static void pxa_ack_low_gpio(struct irq_data *d) 118 { 119 GEDR0 = (1 << (d->irq - IRQ_GPIO0)); 120 } 121 122 static struct irq_chip pxa_low_gpio_chip = { 123 .name = "GPIO-l", 124 .irq_ack = pxa_ack_low_gpio, 125 .irq_mask = pxa_mask_irq, 126 .irq_unmask = pxa_unmask_irq, 127 .irq_set_type = pxa_set_low_gpio_type, 128 }; 129 130 static void __init pxa_init_low_gpio_irq(set_wake_t fn) 131 { 132 int irq; 133 134 /* clear edge detection on GPIO 0 and 1 */ 135 GFER0 &= ~0x3; 136 GRER0 &= ~0x3; 137 GEDR0 = 0x3; 138 139 for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { 140 irq_set_chip_and_handler(irq, &pxa_low_gpio_chip, 141 handle_edge_irq); 142 irq_set_chip_data(irq, irq_base(0)); 143 set_irq_flags(irq, IRQF_VALID); 144 } 145 146 pxa_low_gpio_chip.irq_set_wake = fn; 147 } 148 149 void __init pxa_init_irq(int irq_nr, set_wake_t fn) 150 { 151 int irq, i, n; 152 153 BUG_ON(irq_nr > MAX_INTERNAL_IRQS); 154 155 pxa_internal_irq_nr = irq_nr; 156 157 for (n = 0; n < irq_nr; n += 32) { 158 void __iomem *base = irq_base(n >> 5); 159 160 __raw_writel(0, base + ICMR); /* disable all IRQs */ 161 __raw_writel(0, base + ICLR); /* all IRQs are IRQ, not FIQ */ 162 for (i = n; (i < (n + 32)) && (i < irq_nr); i++) { 163 /* initialize interrupt priority */ 164 if (cpu_has_ipr()) 165 __raw_writel(i | IPR_VALID, IRQ_BASE + IPR(i)); 166 167 irq = PXA_IRQ(i); 168 irq_set_chip_and_handler(irq, &pxa_internal_irq_chip, 169 handle_level_irq); 170 irq_set_chip_data(irq, base); 171 set_irq_flags(irq, IRQF_VALID); 172 } 173 } 174 175 /* only unmasked interrupts kick us out of idle */ 176 __raw_writel(1, irq_base(0) + ICCR); 177 178 pxa_internal_irq_chip.irq_set_wake = fn; 179 pxa_init_low_gpio_irq(fn); 180 } 181 182 #ifdef CONFIG_PM 183 static unsigned long saved_icmr[MAX_INTERNAL_IRQS/32]; 184 static unsigned long saved_ipr[MAX_INTERNAL_IRQS]; 185 186 static int pxa_irq_suspend(void) 187 { 188 int i; 189 190 for (i = 0; i < pxa_internal_irq_nr / 32; i++) { 191 void __iomem *base = irq_base(i); 192 193 saved_icmr[i] = __raw_readl(base + ICMR); 194 __raw_writel(0, base + ICMR); 195 } 196 197 if (cpu_has_ipr()) { 198 for (i = 0; i < pxa_internal_irq_nr; i++) 199 saved_ipr[i] = __raw_readl(IRQ_BASE + IPR(i)); 200 } 201 202 return 0; 203 } 204 205 static void pxa_irq_resume(void) 206 { 207 int i; 208 209 for (i = 0; i < pxa_internal_irq_nr / 32; i++) { 210 void __iomem *base = irq_base(i); 211 212 __raw_writel(saved_icmr[i], base + ICMR); 213 __raw_writel(0, base + ICLR); 214 } 215 216 if (cpu_has_ipr()) 217 for (i = 0; i < pxa_internal_irq_nr; i++) 218 __raw_writel(saved_ipr[i], IRQ_BASE + IPR(i)); 219 220 __raw_writel(1, IRQ_BASE + ICCR); 221 } 222 #else 223 #define pxa_irq_suspend NULL 224 #define pxa_irq_resume NULL 225 #endif 226 227 struct syscore_ops pxa_irq_syscore_ops = { 228 .suspend = pxa_irq_suspend, 229 .resume = pxa_irq_resume, 230 }; 231