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 #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 
cpu_has_ipr(void)51 static inline int cpu_has_ipr(void)
52 {
53 	return !cpu_is_pxa25x();
54 }
55 
irq_base(int i)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 
pxa_mask_irq(struct irq_data * d)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 
pxa_unmask_irq(struct irq_data * d)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  */
pxa_set_low_gpio_type(struct irq_data * d,unsigned int type)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 
pxa_ack_low_gpio(struct irq_data * d)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 
pxa_init_low_gpio_irq(set_wake_t fn)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 
pxa_init_irq(int irq_nr,set_wake_t fn)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 
pxa_irq_suspend(struct sys_device * dev,pm_message_t state)186 static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
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 
pxa_irq_resume(struct sys_device * dev)205 static int pxa_irq_resume(struct sys_device *dev)
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 	return 0;
222 }
223 #else
224 #define pxa_irq_suspend		NULL
225 #define pxa_irq_resume		NULL
226 #endif
227 
228 struct sysdev_class pxa_irq_sysclass = {
229 	.name		= "irq",
230 	.suspend	= pxa_irq_suspend,
231 	.resume		= pxa_irq_resume,
232 };
233 
pxa_irq_init(void)234 static int __init pxa_irq_init(void)
235 {
236 	return sysdev_class_register(&pxa_irq_sysclass);
237 }
238 
239 core_initcall(pxa_irq_init);
240