aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ixp4xx/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ixp4xx/common.c')
-rw-r--r--arch/arm/mach-ixp4xx/common.c107
1 files changed, 67 insertions, 40 deletions
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index c7513f6eb50c..2ec9a9e9a04d 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -28,6 +28,7 @@
28#include <linux/timex.h> 28#include <linux/timex.h>
29#include <linux/clocksource.h> 29#include <linux/clocksource.h>
30 30
31#include <asm/arch/udc.h>
31#include <asm/hardware.h> 32#include <asm/hardware.h>
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
33#include <asm/io.h> 34#include <asm/io.h>
@@ -39,6 +40,8 @@
39#include <asm/mach/irq.h> 40#include <asm/mach/irq.h>
40#include <asm/mach/time.h> 41#include <asm/mach/time.h>
41 42
43static int __init ixp4xx_clocksource_init(void);
44
42/************************************************************************* 45/*************************************************************************
43 * IXP4xx chipset I/O mapping 46 * IXP4xx chipset I/O mapping
44 *************************************************************************/ 47 *************************************************************************/
@@ -86,7 +89,8 @@ enum ixp4xx_irq_type {
86 IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE 89 IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
87}; 90};
88 91
89static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); 92/* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */
93static unsigned long long ixp4xx_irq_edge = 0;
90 94
91/* 95/*
92 * IRQ -> GPIO mapping table 96 * IRQ -> GPIO mapping table
@@ -135,7 +139,11 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
135 default: 139 default:
136 return -EINVAL; 140 return -EINVAL;
137 } 141 }
138 ixp4xx_config_irq(irq, irq_type); 142
143 if (irq_type == IXP4XX_IRQ_EDGE)
144 ixp4xx_irq_edge |= (1 << irq);
145 else
146 ixp4xx_irq_edge &= ~(1 << irq);
139 147
140 if (line >= 8) { /* pins 8-15 */ 148 if (line >= 8) { /* pins 8-15 */
141 line -= 8; 149 line -= 8;
@@ -167,14 +175,6 @@ static void ixp4xx_irq_mask(unsigned int irq)
167 *IXP4XX_ICMR &= ~(1 << irq); 175 *IXP4XX_ICMR &= ~(1 << irq);
168} 176}
169 177
170static void ixp4xx_irq_unmask(unsigned int irq)
171{
172 if (cpu_is_ixp46x() && irq >= 32)
173 *IXP4XX_ICMR2 |= (1 << (irq - 32));
174 else
175 *IXP4XX_ICMR |= (1 << irq);
176}
177
178static void ixp4xx_irq_ack(unsigned int irq) 178static void ixp4xx_irq_ack(unsigned int irq)
179{ 179{
180 int line = (irq < 32) ? irq2gpio[irq] : -1; 180 int line = (irq < 32) ? irq2gpio[irq] : -1;
@@ -187,41 +187,25 @@ static void ixp4xx_irq_ack(unsigned int irq)
187 * Level triggered interrupts on GPIO lines can only be cleared when the 187 * Level triggered interrupts on GPIO lines can only be cleared when the
188 * interrupt condition disappears. 188 * interrupt condition disappears.
189 */ 189 */
190static void ixp4xx_irq_level_unmask(unsigned int irq) 190static void ixp4xx_irq_unmask(unsigned int irq)
191{ 191{
192 ixp4xx_irq_ack(irq); 192 if (!(ixp4xx_irq_edge & (1 << irq)))
193 ixp4xx_irq_unmask(irq); 193 ixp4xx_irq_ack(irq);
194}
195 194
196static struct irqchip ixp4xx_irq_level_chip = { 195 if (cpu_is_ixp46x() && irq >= 32)
197 .ack = ixp4xx_irq_mask, 196 *IXP4XX_ICMR2 |= (1 << (irq - 32));
198 .mask = ixp4xx_irq_mask, 197 else
199 .unmask = ixp4xx_irq_level_unmask, 198 *IXP4XX_ICMR |= (1 << irq);
200 .set_type = ixp4xx_set_irq_type, 199}
201};
202 200
203static struct irqchip ixp4xx_irq_edge_chip = { 201static struct irq_chip ixp4xx_irq_chip = {
202 .name = "IXP4xx",
204 .ack = ixp4xx_irq_ack, 203 .ack = ixp4xx_irq_ack,
205 .mask = ixp4xx_irq_mask, 204 .mask = ixp4xx_irq_mask,
206 .unmask = ixp4xx_irq_unmask, 205 .unmask = ixp4xx_irq_unmask,
207 .set_type = ixp4xx_set_irq_type, 206 .set_type = ixp4xx_set_irq_type,
208}; 207};
209 208
210static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
211{
212 switch (type) {
213 case IXP4XX_IRQ_LEVEL:
214 set_irq_chip(irq, &ixp4xx_irq_level_chip);
215 set_irq_handler(irq, do_level_IRQ);
216 break;
217 case IXP4XX_IRQ_EDGE:
218 set_irq_chip(irq, &ixp4xx_irq_edge_chip);
219 set_irq_handler(irq, do_edge_IRQ);
220 break;
221 }
222 set_irq_flags(irq, IRQF_VALID);
223}
224
225void __init ixp4xx_init_irq(void) 209void __init ixp4xx_init_irq(void)
226{ 210{
227 int i = 0; 211 int i = 0;
@@ -241,8 +225,11 @@ void __init ixp4xx_init_irq(void)
241 } 225 }
242 226
243 /* Default to all level triggered */ 227 /* Default to all level triggered */
244 for(i = 0; i < NR_IRQS; i++) 228 for(i = 0; i < NR_IRQS; i++) {
245 ixp4xx_config_irq(i, IXP4XX_IRQ_LEVEL); 229 set_irq_chip(i, &ixp4xx_irq_chip);
230 set_irq_handler(i, handle_level_irq);
231 set_irq_flags(i, IRQF_VALID);
232 }
246} 233}
247 234
248 235
@@ -296,12 +283,52 @@ static void __init ixp4xx_timer_init(void)
296 283
297 /* Connect the interrupt handler and enable the interrupt */ 284 /* Connect the interrupt handler and enable the interrupt */
298 setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); 285 setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
286
287 ixp4xx_clocksource_init();
299} 288}
300 289
301struct sys_timer ixp4xx_timer = { 290struct sys_timer ixp4xx_timer = {
302 .init = ixp4xx_timer_init, 291 .init = ixp4xx_timer_init,
303}; 292};
304 293
294static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
295
296void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info)
297{
298 memcpy(&ixp4xx_udc_info, info, sizeof *info);
299}
300
301static struct resource ixp4xx_udc_resources[] = {
302 [0] = {
303 .start = 0xc800b000,
304 .end = 0xc800bfff,
305 .flags = IORESOURCE_MEM,
306 },
307 [1] = {
308 .start = IRQ_IXP4XX_USB,
309 .end = IRQ_IXP4XX_USB,
310 .flags = IORESOURCE_IRQ,
311 },
312};
313
314/*
315 * USB device controller. The IXP4xx uses the same controller as PXA2XX,
316 * so we just use the same device.
317 */
318static struct platform_device ixp4xx_udc_device = {
319 .name = "pxa2xx-udc",
320 .id = -1,
321 .num_resources = 2,
322 .resource = ixp4xx_udc_resources,
323 .dev = {
324 .platform_data = &ixp4xx_udc_info,
325 },
326};
327
328static struct platform_device *ixp4xx_devices[] __initdata = {
329 &ixp4xx_udc_device,
330};
331
305static struct resource ixp46x_i2c_resources[] = { 332static struct resource ixp46x_i2c_resources[] = {
306 [0] = { 333 [0] = {
307 .start = 0xc8011000, 334 .start = 0xc8011000,
@@ -337,6 +364,8 @@ void __init ixp4xx_sys_init(void)
337{ 364{
338 ixp4xx_exp_bus_size = SZ_16M; 365 ixp4xx_exp_bus_size = SZ_16M;
339 366
367 platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices));
368
340 if (cpu_is_ixp46x()) { 369 if (cpu_is_ixp46x()) {
341 int region; 370 int region;
342 371
@@ -379,5 +408,3 @@ static int __init ixp4xx_clocksource_init(void)
379 408
380 return 0; 409 return 0;
381} 410}
382
383device_initcall(ixp4xx_clocksource_init);