xref: /openbmc/linux/arch/arm/mach-pxa/irq.c (revision c70f5a60)
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 <mach/hardware.h>
21 #include <asm/irq.h>
22 #include <asm/mach/irq.h>
23 #include <mach/gpio.h>
24 #include <mach/regs-intc.h>
25 
26 #include "generic.h"
27 
28 #define MAX_INTERNAL_IRQS	128
29 
30 #define IRQ_BIT(n)	(((n) - PXA_IRQ(0)) & 0x1f)
31 #define _ICMR(n)	(*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR))
32 #define _ICLR(n)	(*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR))
33 
34 /*
35  * This is for peripheral IRQs internal to the PXA chip.
36  */
37 
38 static int pxa_internal_irq_nr;
39 
40 static void pxa_mask_irq(unsigned int irq)
41 {
42 	_ICMR(irq) &= ~(1 << IRQ_BIT(irq));
43 }
44 
45 static void pxa_unmask_irq(unsigned int irq)
46 {
47 	_ICMR(irq) |= 1 << IRQ_BIT(irq);
48 }
49 
50 static struct irq_chip pxa_internal_irq_chip = {
51 	.name		= "SC",
52 	.ack		= pxa_mask_irq,
53 	.mask		= pxa_mask_irq,
54 	.unmask		= pxa_unmask_irq,
55 };
56 
57 /*
58  * GPIO IRQs for GPIO 0 and 1
59  */
60 static int pxa_set_low_gpio_type(unsigned int irq, unsigned int type)
61 {
62 	int gpio = irq - IRQ_GPIO0;
63 
64 	if (__gpio_is_occupied(gpio)) {
65 		pr_err("%s failed: GPIO is configured\n", __func__);
66 		return -EINVAL;
67 	}
68 
69 	if (type & IRQ_TYPE_EDGE_RISING)
70 		GRER0 |= GPIO_bit(gpio);
71 	else
72 		GRER0 &= ~GPIO_bit(gpio);
73 
74 	if (type & IRQ_TYPE_EDGE_FALLING)
75 		GFER0 |= GPIO_bit(gpio);
76 	else
77 		GFER0 &= ~GPIO_bit(gpio);
78 
79 	return 0;
80 }
81 
82 static void pxa_ack_low_gpio(unsigned int irq)
83 {
84 	GEDR0 = (1 << (irq - IRQ_GPIO0));
85 }
86 
87 static void pxa_mask_low_gpio(unsigned int irq)
88 {
89 	ICMR &= ~(1 << (irq - PXA_IRQ(0)));
90 }
91 
92 static void pxa_unmask_low_gpio(unsigned int irq)
93 {
94 	ICMR |= 1 << (irq - PXA_IRQ(0));
95 }
96 
97 static struct irq_chip pxa_low_gpio_chip = {
98 	.name		= "GPIO-l",
99 	.ack		= pxa_ack_low_gpio,
100 	.mask		= pxa_mask_low_gpio,
101 	.unmask		= pxa_unmask_low_gpio,
102 	.set_type	= pxa_set_low_gpio_type,
103 };
104 
105 static void __init pxa_init_low_gpio_irq(set_wake_t fn)
106 {
107 	int irq;
108 
109 	/* clear edge detection on GPIO 0 and 1 */
110 	GFER0 &= ~0x3;
111 	GRER0 &= ~0x3;
112 	GEDR0 = 0x3;
113 
114 	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
115 		set_irq_chip(irq, &pxa_low_gpio_chip);
116 		set_irq_handler(irq, handle_edge_irq);
117 		set_irq_flags(irq, IRQF_VALID);
118 	}
119 
120 	pxa_low_gpio_chip.set_wake = fn;
121 }
122 
123 void __init pxa_init_irq(int irq_nr, set_wake_t fn)
124 {
125 	int irq, i;
126 
127 	BUG_ON(irq_nr > MAX_INTERNAL_IRQS);
128 
129 	pxa_internal_irq_nr = irq_nr;
130 
131 	for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq += 32) {
132 		_ICMR(irq) = 0;	/* disable all IRQs */
133 		_ICLR(irq) = 0;	/* all IRQs are IRQ, not FIQ */
134 	}
135 
136 	/* initialize interrupt priority */
137 	if (cpu_is_pxa27x() || cpu_is_pxa3xx()) {
138 		for (i = 0; i < irq_nr; i++)
139 			IPR(i) = i | (1 << 31);
140 	}
141 
142 	/* only unmasked interrupts kick us out of idle */
143 	ICCR = 1;
144 
145 	for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) {
146 		set_irq_chip(irq, &pxa_internal_irq_chip);
147 		set_irq_handler(irq, handle_level_irq);
148 		set_irq_flags(irq, IRQF_VALID);
149 	}
150 
151 	pxa_internal_irq_chip.set_wake = fn;
152 	pxa_init_low_gpio_irq(fn);
153 }
154 
155 #ifdef CONFIG_PM
156 static unsigned long saved_icmr[MAX_INTERNAL_IRQS/32];
157 static unsigned long saved_ipr[MAX_INTERNAL_IRQS];
158 
159 static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
160 {
161 	int i, irq = PXA_IRQ(0);
162 
163 	for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
164 		saved_icmr[i] = _ICMR(irq);
165 		_ICMR(irq) = 0;
166 	}
167 
168 	if (cpu_is_pxa27x() || cpu_is_pxa3xx()) {
169 		for (i = 0; i < pxa_internal_irq_nr; i++)
170 			saved_ipr[i] = IPR(i);
171 	}
172 
173 	return 0;
174 }
175 
176 static int pxa_irq_resume(struct sys_device *dev)
177 {
178 	int i, irq = PXA_IRQ(0);
179 
180 	if (cpu_is_pxa27x() || cpu_is_pxa3xx()) {
181 		for (i = 0; i < pxa_internal_irq_nr; i++)
182 			IPR(i) = saved_ipr[i];
183 	}
184 
185 	for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
186 		_ICMR(irq) = saved_icmr[i];
187 		_ICLR(irq) = 0;
188 	}
189 
190 	ICCR = 1;
191 	return 0;
192 }
193 #else
194 #define pxa_irq_suspend		NULL
195 #define pxa_irq_resume		NULL
196 #endif
197 
198 struct sysdev_class pxa_irq_sysclass = {
199 	.name		= "irq",
200 	.suspend	= pxa_irq_suspend,
201 	.resume		= pxa_irq_resume,
202 };
203 
204 static int __init pxa_irq_init(void)
205 {
206 	return sysdev_class_register(&pxa_irq_sysclass);
207 }
208 
209 core_initcall(pxa_irq_init);
210