xref: /openbmc/linux/arch/arm/mach-pxa/irq.c (revision e3630db1)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  linux/arch/arm/mach-pxa/irq.c
31da177e4SLinus Torvalds  *
4e3630db1Seric miao  *  Generic PXA IRQ handling
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *  Author:	Nicolas Pitre
71da177e4SLinus Torvalds  *  Created:	Jun 15, 2001
81da177e4SLinus Torvalds  *  Copyright:	MontaVista Software Inc.
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  *  This program is free software; you can redistribute it and/or modify
111da177e4SLinus Torvalds  *  it under the terms of the GNU General Public License version 2 as
121da177e4SLinus Torvalds  *  published by the Free Software Foundation.
131da177e4SLinus Torvalds  */
141da177e4SLinus Torvalds 
151da177e4SLinus Torvalds #include <linux/init.h>
161da177e4SLinus Torvalds #include <linux/module.h>
171da177e4SLinus Torvalds #include <linux/interrupt.h>
18c0165504Seric miao #include <linux/sysdev.h>
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds #include <asm/hardware.h>
211da177e4SLinus Torvalds #include <asm/irq.h>
221da177e4SLinus Torvalds #include <asm/mach/irq.h>
231da177e4SLinus Torvalds #include <asm/arch/pxa-regs.h>
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds #include "generic.h"
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds /*
291da177e4SLinus Torvalds  * This is for peripheral IRQs internal to the PXA chip.
301da177e4SLinus Torvalds  */
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds static void pxa_mask_low_irq(unsigned int irq)
331da177e4SLinus Torvalds {
34486c9551SEric Miao 	ICMR &= ~(1 << irq);
351da177e4SLinus Torvalds }
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds static void pxa_unmask_low_irq(unsigned int irq)
381da177e4SLinus Torvalds {
39486c9551SEric Miao 	ICMR |= (1 << irq);
401da177e4SLinus Torvalds }
411da177e4SLinus Torvalds 
4238c677cbSDavid Brownell static struct irq_chip pxa_internal_chip_low = {
4338c677cbSDavid Brownell 	.name		= "SC",
441da177e4SLinus Torvalds 	.ack		= pxa_mask_low_irq,
451da177e4SLinus Torvalds 	.mask		= pxa_mask_low_irq,
461da177e4SLinus Torvalds 	.unmask		= pxa_unmask_low_irq,
471da177e4SLinus Torvalds };
481da177e4SLinus Torvalds 
4953665a50SEric Miao void __init pxa_init_irq_low(void)
5053665a50SEric Miao {
5153665a50SEric Miao 	int irq;
5253665a50SEric Miao 
5353665a50SEric Miao 	/* disable all IRQs */
5453665a50SEric Miao 	ICMR = 0;
5553665a50SEric Miao 
5653665a50SEric Miao 	/* all IRQs are IRQ, not FIQ */
5753665a50SEric Miao 	ICLR = 0;
5853665a50SEric Miao 
5953665a50SEric Miao 	/* only unmasked interrupts kick us out of idle */
6053665a50SEric Miao 	ICCR = 1;
6153665a50SEric Miao 
6253665a50SEric Miao 	for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
6353665a50SEric Miao 		set_irq_chip(irq, &pxa_internal_chip_low);
6453665a50SEric Miao 		set_irq_handler(irq, handle_level_irq);
6553665a50SEric Miao 		set_irq_flags(irq, IRQF_VALID);
6653665a50SEric Miao 	}
6753665a50SEric Miao }
6853665a50SEric Miao 
692c8086a5Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds /*
721da177e4SLinus Torvalds  * This is for the second set of internal IRQs as found on the PXA27x.
731da177e4SLinus Torvalds  */
741da177e4SLinus Torvalds 
751da177e4SLinus Torvalds static void pxa_mask_high_irq(unsigned int irq)
761da177e4SLinus Torvalds {
77486c9551SEric Miao 	ICMR2 &= ~(1 << (irq - 32));
781da177e4SLinus Torvalds }
791da177e4SLinus Torvalds 
801da177e4SLinus Torvalds static void pxa_unmask_high_irq(unsigned int irq)
811da177e4SLinus Torvalds {
82486c9551SEric Miao 	ICMR2 |= (1 << (irq - 32));
831da177e4SLinus Torvalds }
841da177e4SLinus Torvalds 
8538c677cbSDavid Brownell static struct irq_chip pxa_internal_chip_high = {
8638c677cbSDavid Brownell 	.name		= "SC-hi",
871da177e4SLinus Torvalds 	.ack		= pxa_mask_high_irq,
881da177e4SLinus Torvalds 	.mask		= pxa_mask_high_irq,
891da177e4SLinus Torvalds 	.unmask		= pxa_unmask_high_irq,
901da177e4SLinus Torvalds };
911da177e4SLinus Torvalds 
92c08b7b3eSEric Miao void __init pxa_init_irq_high(void)
93c08b7b3eSEric Miao {
94c08b7b3eSEric Miao 	int irq;
95c08b7b3eSEric Miao 
96c08b7b3eSEric Miao 	ICMR2 = 0;
97c08b7b3eSEric Miao 	ICLR2 = 0;
98c08b7b3eSEric Miao 
99c08b7b3eSEric Miao 	for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
100c08b7b3eSEric Miao 		set_irq_chip(irq, &pxa_internal_chip_high);
101c08b7b3eSEric Miao 		set_irq_handler(irq, handle_level_irq);
102c08b7b3eSEric Miao 		set_irq_flags(irq, IRQF_VALID);
103c08b7b3eSEric Miao 	}
104c08b7b3eSEric Miao }
1051da177e4SLinus Torvalds #endif
1061da177e4SLinus Torvalds 
107c95530c7Seric miao void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
108c95530c7Seric miao {
109c95530c7Seric miao 	pxa_internal_chip_low.set_wake = set_wake;
110c95530c7Seric miao #ifdef CONFIG_PXA27x
111c95530c7Seric miao 	pxa_internal_chip_high.set_wake = set_wake;
112c95530c7Seric miao #endif
113a7bf4dbaSeric miao 	pxa_init_gpio_set_wake(set_wake);
114c95530c7Seric miao }
115c0165504Seric miao 
116c0165504Seric miao #ifdef CONFIG_PM
117c0165504Seric miao static unsigned long saved_icmr[2];
118c0165504Seric miao 
119c0165504Seric miao static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
120c0165504Seric miao {
121c0165504Seric miao 	switch (dev->id) {
122c0165504Seric miao 	case 0:
123c0165504Seric miao 		saved_icmr[0] = ICMR;
124c0165504Seric miao 		ICMR = 0;
125c0165504Seric miao 		break;
126c0165504Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
127c0165504Seric miao 	case 1:
128c0165504Seric miao 		saved_icmr[1] = ICMR2;
129c0165504Seric miao 		ICMR2 = 0;
130c0165504Seric miao 		break;
131c0165504Seric miao #endif
132c0165504Seric miao 	default:
133c0165504Seric miao 		return -EINVAL;
134c0165504Seric miao 	}
135c0165504Seric miao 
136c0165504Seric miao 	return 0;
137c0165504Seric miao }
138c0165504Seric miao 
139c0165504Seric miao static int pxa_irq_resume(struct sys_device *dev)
140c0165504Seric miao {
141c0165504Seric miao 	switch (dev->id) {
142c0165504Seric miao 	case 0:
143c0165504Seric miao 		ICMR = saved_icmr[0];
144c0165504Seric miao 		ICLR = 0;
145c0165504Seric miao 		ICCR = 1;
146c0165504Seric miao 		break;
147c0165504Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
148c0165504Seric miao 	case 1:
149c0165504Seric miao 		ICMR2 = saved_icmr[1];
150c0165504Seric miao 		ICLR2 = 0;
151c0165504Seric miao 		break;
152c0165504Seric miao #endif
153c0165504Seric miao 	default:
154c0165504Seric miao 		return -EINVAL;
155c0165504Seric miao 	}
156c0165504Seric miao 
157c0165504Seric miao 	return 0;
158c0165504Seric miao }
159c0165504Seric miao #else
160c0165504Seric miao #define pxa_irq_suspend		NULL
161c0165504Seric miao #define pxa_irq_resume		NULL
162c0165504Seric miao #endif
163c0165504Seric miao 
164c0165504Seric miao struct sysdev_class pxa_irq_sysclass = {
165c0165504Seric miao 	.name		= "irq",
166c0165504Seric miao 	.suspend	= pxa_irq_suspend,
167c0165504Seric miao 	.resume		= pxa_irq_resume,
168c0165504Seric miao };
169c0165504Seric miao 
170c0165504Seric miao static int __init pxa_irq_init(void)
171c0165504Seric miao {
172c0165504Seric miao 	return sysdev_class_register(&pxa_irq_sysclass);
173c0165504Seric miao }
174c0165504Seric miao 
175c0165504Seric miao core_initcall(pxa_irq_init);
176