]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/arm/mach-ks8695/irq.c
Merge branch 'spi/s3c64xx' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[karo-tx-linux.git] / arch / arm / mach-ks8695 / irq.c
1 /*
2  * arch/arm/mach-ks8695/irq.c
3  *
4  * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
5  * Copyright (C) 2006 Simtec Electronics
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <linux/interrupt.h>
25 #include <linux/ioport.h>
26 #include <linux/device.h>
27 #include <linux/io.h>
28
29 #include <mach/hardware.h>
30 #include <asm/irq.h>
31
32 #include <asm/mach/irq.h>
33
34 #include <mach/regs-irq.h>
35 #include <mach/regs-gpio.h>
36
37 static void ks8695_irq_mask(struct irq_data *d)
38 {
39         unsigned long inten;
40
41         inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
42         inten &= ~(1 << d->irq);
43
44         __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
45 }
46
47 static void ks8695_irq_unmask(struct irq_data *d)
48 {
49         unsigned long inten;
50
51         inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
52         inten |= (1 << d->irq);
53
54         __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
55 }
56
57 static void ks8695_irq_ack(struct irq_data *d)
58 {
59         __raw_writel((1 << d->irq), KS8695_IRQ_VA + KS8695_INTST);
60 }
61
62
63 static struct irq_chip ks8695_irq_level_chip;
64 static struct irq_chip ks8695_irq_edge_chip;
65
66
67 static int ks8695_irq_set_type(struct irq_data *d, unsigned int type)
68 {
69         unsigned long ctrl, mode;
70         unsigned short level_triggered = 0;
71
72         ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
73
74         switch (type) {
75                 case IRQ_TYPE_LEVEL_HIGH:
76                         mode = IOPC_TM_HIGH;
77                         level_triggered = 1;
78                         break;
79                 case IRQ_TYPE_LEVEL_LOW:
80                         mode = IOPC_TM_LOW;
81                         level_triggered = 1;
82                         break;
83                 case IRQ_TYPE_EDGE_RISING:
84                         mode = IOPC_TM_RISING;
85                         break;
86                 case IRQ_TYPE_EDGE_FALLING:
87                         mode = IOPC_TM_FALLING;
88                         break;
89                 case IRQ_TYPE_EDGE_BOTH:
90                         mode = IOPC_TM_EDGE;
91                         break;
92                 default:
93                         return -EINVAL;
94         }
95
96         switch (d->irq) {
97                 case KS8695_IRQ_EXTERN0:
98                         ctrl &= ~IOPC_IOEINT0TM;
99                         ctrl |= IOPC_IOEINT0_MODE(mode);
100                         break;
101                 case KS8695_IRQ_EXTERN1:
102                         ctrl &= ~IOPC_IOEINT1TM;
103                         ctrl |= IOPC_IOEINT1_MODE(mode);
104                         break;
105                 case KS8695_IRQ_EXTERN2:
106                         ctrl &= ~IOPC_IOEINT2TM;
107                         ctrl |= IOPC_IOEINT2_MODE(mode);
108                         break;
109                 case KS8695_IRQ_EXTERN3:
110                         ctrl &= ~IOPC_IOEINT3TM;
111                         ctrl |= IOPC_IOEINT3_MODE(mode);
112                         break;
113                 default:
114                         return -EINVAL;
115         }
116
117         if (level_triggered) {
118                 irq_set_chip_and_handler(d->irq, &ks8695_irq_level_chip,
119                                          handle_level_irq);
120         }
121         else {
122                 irq_set_chip_and_handler(d->irq, &ks8695_irq_edge_chip,
123                                          handle_edge_irq);
124         }
125
126         __raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC);
127         return 0;
128 }
129
130 static struct irq_chip ks8695_irq_level_chip = {
131         .irq_ack        = ks8695_irq_mask,
132         .irq_mask       = ks8695_irq_mask,
133         .irq_unmask     = ks8695_irq_unmask,
134         .irq_set_type   = ks8695_irq_set_type,
135 };
136
137 static struct irq_chip ks8695_irq_edge_chip = {
138         .irq_ack        = ks8695_irq_ack,
139         .irq_mask       = ks8695_irq_mask,
140         .irq_unmask     = ks8695_irq_unmask,
141         .irq_set_type   = ks8695_irq_set_type,
142 };
143
144 void __init ks8695_init_irq(void)
145 {
146         unsigned int irq;
147
148         /* Disable all interrupts initially */
149         __raw_writel(0, KS8695_IRQ_VA + KS8695_INTMC);
150         __raw_writel(0, KS8695_IRQ_VA + KS8695_INTEN);
151
152         for (irq = 0; irq < NR_IRQS; irq++) {
153                 switch (irq) {
154                         /* Level-triggered interrupts */
155                         case KS8695_IRQ_BUS_ERROR:
156                         case KS8695_IRQ_UART_MODEM_STATUS:
157                         case KS8695_IRQ_UART_LINE_STATUS:
158                         case KS8695_IRQ_UART_RX:
159                         case KS8695_IRQ_COMM_TX:
160                         case KS8695_IRQ_COMM_RX:
161                                 irq_set_chip_and_handler(irq,
162                                                          &ks8695_irq_level_chip,
163                                                          handle_level_irq);
164                                 break;
165
166                         /* Edge-triggered interrupts */
167                         default:
168                                 /* clear pending bit */
169                                 ks8695_irq_ack(irq_get_irq_data(irq));
170                                 irq_set_chip_and_handler(irq,
171                                                          &ks8695_irq_edge_chip,
172                                                          handle_edge_irq);
173                 }
174
175                 set_irq_flags(irq, IRQF_VALID);
176         }
177 }