]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-ks8695/irq.c
Merge git://git.infradead.org/mtd-2.6
[linux-2.6-omap-h63xx.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/ptrace.h>
27 #include <linux/sysdev.h>
28
29 #include <asm/hardware.h>
30 #include <asm/irq.h>
31 #include <asm/io.h>
32
33 #include <asm/mach/irq.h>
34
35 #include <asm/arch/regs-irq.h>
36 #include <asm/arch/regs-gpio.h>
37
38 static void ks8695_irq_mask(unsigned int irqno)
39 {
40         unsigned long inten;
41
42         inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
43         inten &= ~(1 << irqno);
44
45         __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
46 }
47
48 static void ks8695_irq_unmask(unsigned int irqno)
49 {
50         unsigned long inten;
51
52         inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
53         inten |= (1 << irqno);
54
55         __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN);
56 }
57
58 static void ks8695_irq_ack(unsigned int irqno)
59 {
60         __raw_writel((1 << irqno), KS8695_IRQ_VA + KS8695_INTST);
61 }
62
63
64 static struct irq_chip ks8695_irq_level_chip;
65 static struct irq_chip ks8695_irq_edge_chip;
66
67
68 static int ks8695_irq_set_type(unsigned int irqno, unsigned int type)
69 {
70         unsigned long ctrl, mode;
71         unsigned short level_triggered = 0;
72
73         ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
74
75         switch (type) {
76                 case IRQT_HIGH:
77                         mode = IOPC_TM_HIGH;
78                         level_triggered = 1;
79                         break;
80                 case IRQT_LOW:
81                         mode = IOPC_TM_LOW;
82                         level_triggered = 1;
83                         break;
84                 case IRQT_RISING:
85                         mode = IOPC_TM_RISING;
86                         break;
87                 case IRQT_FALLING:
88                         mode = IOPC_TM_FALLING;
89                         break;
90                 case IRQT_BOTHEDGE:
91                         mode = IOPC_TM_EDGE;
92                         break;
93                 default:
94                         return -EINVAL;
95         }
96
97         switch (irqno) {
98                 case KS8695_IRQ_EXTERN0:
99                         ctrl &= ~IOPC_IOEINT0TM;
100                         ctrl |= IOPC_IOEINT0_MODE(mode);
101                         break;
102                 case KS8695_IRQ_EXTERN1:
103                         ctrl &= ~IOPC_IOEINT1TM;
104                         ctrl |= IOPC_IOEINT1_MODE(mode);
105                         break;
106                 case KS8695_IRQ_EXTERN2:
107                         ctrl &= ~IOPC_IOEINT2TM;
108                         ctrl |= IOPC_IOEINT2_MODE(mode);
109                         break;
110                 case KS8695_IRQ_EXTERN3:
111                         ctrl &= ~IOPC_IOEINT3TM;
112                         ctrl |= IOPC_IOEINT3_MODE(mode);
113                         break;
114                 default:
115                         return -EINVAL;
116         }
117
118         if (level_triggered) {
119                 set_irq_chip(irqno, &ks8695_irq_level_chip);
120                 set_irq_handler(irqno, handle_level_irq);
121         }
122         else {
123                 set_irq_chip(irqno, &ks8695_irq_edge_chip);
124                 set_irq_handler(irqno, handle_edge_irq);
125         }
126
127         __raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC);
128         return 0;
129 }
130
131 static struct irq_chip ks8695_irq_level_chip = {
132         .ack            = ks8695_irq_mask,
133         .mask           = ks8695_irq_mask,
134         .unmask         = ks8695_irq_unmask,
135         .set_type       = ks8695_irq_set_type,
136 };
137
138 static struct irq_chip ks8695_irq_edge_chip = {
139         .ack            = ks8695_irq_ack,
140         .mask           = ks8695_irq_mask,
141         .unmask         = ks8695_irq_unmask,
142         .set_type       = ks8695_irq_set_type,
143 };
144
145 void __init ks8695_init_irq(void)
146 {
147         unsigned int irq;
148
149         /* Disable all interrupts initially */
150         __raw_writel(0, KS8695_IRQ_VA + KS8695_INTMC);
151         __raw_writel(0, KS8695_IRQ_VA + KS8695_INTEN);
152
153         for (irq = 0; irq < NR_IRQS; irq++) {
154                 switch (irq) {
155                         /* Level-triggered interrupts */
156                         case KS8695_IRQ_BUS_ERROR:
157                         case KS8695_IRQ_UART_MODEM_STATUS:
158                         case KS8695_IRQ_UART_LINE_STATUS:
159                         case KS8695_IRQ_UART_RX:
160                         case KS8695_IRQ_COMM_TX:
161                         case KS8695_IRQ_COMM_RX:
162                                 set_irq_chip(irq, &ks8695_irq_level_chip);
163                                 set_irq_handler(irq, handle_level_irq);
164                                 break;
165
166                         /* Edge-triggered interrupts */
167                         default:
168                                 ks8695_irq_ack(irq);    /* clear pending bit */
169                                 set_irq_chip(irq, &ks8695_irq_edge_chip);
170                                 set_irq_handler(irq, handle_edge_irq);
171                 }
172
173                 set_irq_flags(irq, IRQF_VALID);
174         }
175 }