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/sysdev.h> 19 20 #include <asm/hardware.h> 21 #include <asm/irq.h> 22 #include <asm/mach/irq.h> 23 #include <asm/arch/pxa-regs.h> 24 25 #include "generic.h" 26 27 28 /* 29 * This is for peripheral IRQs internal to the PXA chip. 30 */ 31 32 static void pxa_mask_low_irq(unsigned int irq) 33 { 34 ICMR &= ~(1 << irq); 35 } 36 37 static void pxa_unmask_low_irq(unsigned int irq) 38 { 39 ICMR |= (1 << irq); 40 } 41 42 static struct irq_chip pxa_internal_chip_low = { 43 .name = "SC", 44 .ack = pxa_mask_low_irq, 45 .mask = pxa_mask_low_irq, 46 .unmask = pxa_unmask_low_irq, 47 }; 48 49 void __init pxa_init_irq_low(void) 50 { 51 int irq; 52 53 /* disable all IRQs */ 54 ICMR = 0; 55 56 /* all IRQs are IRQ, not FIQ */ 57 ICLR = 0; 58 59 /* only unmasked interrupts kick us out of idle */ 60 ICCR = 1; 61 62 for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) { 63 set_irq_chip(irq, &pxa_internal_chip_low); 64 set_irq_handler(irq, handle_level_irq); 65 set_irq_flags(irq, IRQF_VALID); 66 } 67 } 68 69 #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) 70 71 /* 72 * This is for the second set of internal IRQs as found on the PXA27x. 73 */ 74 75 static void pxa_mask_high_irq(unsigned int irq) 76 { 77 ICMR2 &= ~(1 << (irq - 32)); 78 } 79 80 static void pxa_unmask_high_irq(unsigned int irq) 81 { 82 ICMR2 |= (1 << (irq - 32)); 83 } 84 85 static struct irq_chip pxa_internal_chip_high = { 86 .name = "SC-hi", 87 .ack = pxa_mask_high_irq, 88 .mask = pxa_mask_high_irq, 89 .unmask = pxa_unmask_high_irq, 90 }; 91 92 void __init pxa_init_irq_high(void) 93 { 94 int irq; 95 96 ICMR2 = 0; 97 ICLR2 = 0; 98 99 for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) { 100 set_irq_chip(irq, &pxa_internal_chip_high); 101 set_irq_handler(irq, handle_level_irq); 102 set_irq_flags(irq, IRQF_VALID); 103 } 104 } 105 #endif 106 107 void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int)) 108 { 109 pxa_internal_chip_low.set_wake = set_wake; 110 #ifdef CONFIG_PXA27x 111 pxa_internal_chip_high.set_wake = set_wake; 112 #endif 113 pxa_init_gpio_set_wake(set_wake); 114 } 115 116 #ifdef CONFIG_PM 117 static unsigned long saved_icmr[2]; 118 119 static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) 120 { 121 switch (dev->id) { 122 case 0: 123 saved_icmr[0] = ICMR; 124 ICMR = 0; 125 break; 126 #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) 127 case 1: 128 saved_icmr[1] = ICMR2; 129 ICMR2 = 0; 130 break; 131 #endif 132 default: 133 return -EINVAL; 134 } 135 136 return 0; 137 } 138 139 static int pxa_irq_resume(struct sys_device *dev) 140 { 141 switch (dev->id) { 142 case 0: 143 ICMR = saved_icmr[0]; 144 ICLR = 0; 145 ICCR = 1; 146 break; 147 #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) 148 case 1: 149 ICMR2 = saved_icmr[1]; 150 ICLR2 = 0; 151 break; 152 #endif 153 default: 154 return -EINVAL; 155 } 156 157 return 0; 158 } 159 #else 160 #define pxa_irq_suspend NULL 161 #define pxa_irq_resume NULL 162 #endif 163 164 struct sysdev_class pxa_irq_sysclass = { 165 .name = "irq", 166 .suspend = pxa_irq_suspend, 167 .resume = pxa_irq_resume, 168 }; 169 170 static int __init pxa_irq_init(void) 171 { 172 return sysdev_class_register(&pxa_irq_sysclass); 173 } 174 175 core_initcall(pxa_irq_init); 176