aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorTzachi Perelstein <tzachi@marvell.com>2007-10-23 15:14:42 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-26 10:03:47 -0500
commit3085de6a82821e3d227e8fae7403dc7a5dc27932 (patch)
treefd5ef97c3b06595e2dfab3fa1d3cb671e039f8fc /arch
parentb11e9e020c8c6cdd7e7cc6d5178cce2ad0ac0784 (diff)
[ARM] Orion: IRQ support
Signed-off-by: Tzachi Perelstein <tzachi@marvell.com> Reviewed-by: Nicolas Pitre <nico@marvell.com> Reviewed-by: Lennert Buytenhek <buytenh@marvell.com> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-orion/Makefile2
-rw-r--r--arch/arm/mach-orion/common.h1
-rw-r--r--arch/arm/mach-orion/irq.c160
3 files changed, 162 insertions, 1 deletions
diff --git a/arch/arm/mach-orion/Makefile b/arch/arm/mach-orion/Makefile
index d6a6c86faafc..57d459a2090e 100644
--- a/arch/arm/mach-orion/Makefile
+++ b/arch/arm/mach-orion/Makefile
@@ -1 +1 @@
obj-y += common.o addr-map.o pci.o gpio.o obj-y += common.o addr-map.o pci.o gpio.o irq.o
diff --git a/arch/arm/mach-orion/common.h b/arch/arm/mach-orion/common.h
index a6a7af189b0e..155371e1d672 100644
--- a/arch/arm/mach-orion/common.h
+++ b/arch/arm/mach-orion/common.h
@@ -6,6 +6,7 @@
6 */ 6 */
7 7
8void __init orion_map_io(void); 8void __init orion_map_io(void);
9void __init orion_init_irq(void);
9void __init orion_init(void); 10void __init orion_init(void);
10 11
11/* 12/*
diff --git a/arch/arm/mach-orion/irq.c b/arch/arm/mach-orion/irq.c
new file mode 100644
index 000000000000..585a0fb06262
--- /dev/null
+++ b/arch/arm/mach-orion/irq.c
@@ -0,0 +1,160 @@
1/*
2 * arch/arm/mach-orion/irq.c
3 *
4 * Core IRQ functions for Marvell Orion System On Chip
5 *
6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/irq.h>
16#include <asm/gpio.h>
17#include <asm/arch/orion.h>
18#include "common.h"
19
20/*****************************************************************************
21 * Orion GPIO IRQ
22 ****************************************************************************/
23static void orion_gpio_irq_mask(u32 irq)
24{
25 int pin = irq_to_gpio(irq);
26 orion_clrbits(GPIO_LEVEL_MASK, 1 << pin);
27}
28
29static void orion_gpio_irq_unmask(u32 irq)
30{
31 int pin = irq_to_gpio(irq);
32 orion_setbits(GPIO_LEVEL_MASK, 1 << pin);
33}
34
35static int orion_gpio_set_irq_type(u32 irq, u32 type)
36{
37 int pin = irq_to_gpio(irq);
38
39 if ((orion_read(GPIO_IO_CONF) & (1 << pin)) == 0) {
40 printk(KERN_ERR "orion_gpio_set_irq_type failed "
41 "(irq %d, pin %d).\n", irq, pin);
42 return -EINVAL;
43 }
44
45 switch (type) {
46 case IRQT_HIGH:
47 orion_clrbits(GPIO_IN_POL, (1 << pin));
48 break;
49 case IRQT_LOW:
50 orion_setbits(GPIO_IN_POL, (1 << pin));
51 break;
52 default:
53 printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
54 return -EINVAL;
55 }
56
57 return 0;
58}
59
60static struct irq_chip orion_gpio_irq_chip = {
61 .name = "Orion-IRQ-GPIO",
62 .ack = orion_gpio_irq_mask,
63 .mask = orion_gpio_irq_mask,
64 .unmask = orion_gpio_irq_unmask,
65 .set_type = orion_gpio_set_irq_type,
66};
67
68static void orion_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
69{
70 int i;
71 u32 cause, shift;
72
73 BUG_ON(irq < IRQ_ORION_GPIO_0_7 || irq > IRQ_ORION_GPIO_24_31);
74 shift = (irq - IRQ_ORION_GPIO_0_7) * 8;
75 cause = orion_read(GPIO_EDGE_CAUSE) & orion_read(GPIO_LEVEL_MASK);
76 cause &= (0xff << shift);
77
78 for (i = shift; i < shift + 8; i++) {
79 if (cause & (1 << i)) {
80 int gpio_irq = i + IRQ_ORION_GPIO_START;
81 if (gpio_irq > 0) {
82 desc = irq_desc + gpio_irq;
83 desc_handle_irq(gpio_irq, desc);
84 } else {
85 printk(KERN_ERR "orion_gpio_irq_handler error, "
86 "invalid irq %d\n", gpio_irq);
87 }
88 }
89 }
90}
91
92static void __init orion_init_gpio_irq(void)
93{
94 int i;
95
96 /*
97 * Mask and clear GPIO IRQ interrupts
98 */
99 orion_write(GPIO_LEVEL_MASK, 0x0);
100 orion_write(GPIO_EDGE_CAUSE, 0x0);
101
102 /*
103 * Register chained level handlers for GPIO IRQs
104 */
105 for (i = IRQ_ORION_GPIO_START; i < NR_IRQS; i++) {
106 set_irq_chip(i, &orion_gpio_irq_chip);
107 set_irq_handler(i, handle_level_irq);
108 set_irq_flags(i, IRQF_VALID);
109 }
110 set_irq_chained_handler(IRQ_ORION_GPIO_0_7, orion_gpio_irq_handler);
111 set_irq_chained_handler(IRQ_ORION_GPIO_8_15, orion_gpio_irq_handler);
112 set_irq_chained_handler(IRQ_ORION_GPIO_16_23, orion_gpio_irq_handler);
113 set_irq_chained_handler(IRQ_ORION_GPIO_24_31, orion_gpio_irq_handler);
114}
115
116/*****************************************************************************
117 * Orion Main IRQ
118 ****************************************************************************/
119static void orion_main_irq_mask(u32 irq)
120{
121 orion_clrbits(MAIN_IRQ_MASK, 1 << irq);
122}
123
124static void orion_main_irq_unmask(u32 irq)
125{
126 orion_setbits(MAIN_IRQ_MASK, 1 << irq);
127}
128
129static struct irq_chip orion_main_irq_chip = {
130 .name = "Orion-IRQ-Main",
131 .ack = orion_main_irq_mask,
132 .mask = orion_main_irq_mask,
133 .unmask = orion_main_irq_unmask,
134};
135
136static void __init orion_init_main_irq(void)
137{
138 int i;
139
140 /*
141 * Mask and clear Main IRQ interrupts
142 */
143 orion_write(MAIN_IRQ_MASK, 0x0);
144 orion_write(MAIN_IRQ_CAUSE, 0x0);
145
146 /*
147 * Register level handler for Main IRQs
148 */
149 for (i = 0; i < IRQ_ORION_GPIO_START; i++) {
150 set_irq_chip(i, &orion_main_irq_chip);
151 set_irq_handler(i, handle_level_irq);
152 set_irq_flags(i, IRQF_VALID);
153 }
154}
155
156void __init orion_init_irq(void)
157{
158 orion_init_main_irq();
159 orion_init_gpio_irq();
160}