2 * arch/arm/mach-vt8500/irq.c
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/irq.h>
23 #include <linux/interrupt.h>
29 #define VT8500_IC_DCTR 0x40 /* Destination control
31 #define VT8500_INT_ENABLE (1 << 3)
32 #define VT8500_TRIGGER_HIGH (0 << 4)
33 #define VT8500_TRIGGER_RISING (1 << 4)
34 #define VT8500_TRIGGER_FALLING (2 << 4)
35 #define VT8500_EDGE ( VT8500_TRIGGER_RISING \
36 | VT8500_TRIGGER_FALLING)
37 #define VT8500_IC_STATUS 0x80 /* Interrupt status, 2*u32 */
39 static void __iomem
*ic_regbase
;
40 static void __iomem
*sic_regbase
;
42 static void vt8500_irq_mask(unsigned int irq
)
44 void __iomem
*base
= ic_regbase
;
51 edge
= readb(base
+ VT8500_IC_DCTR
+ irq
) & VT8500_EDGE
;
53 void __iomem
*stat_reg
= base
+ VT8500_IC_STATUS
55 unsigned status
= readl(stat_reg
);
57 status
|= (1 << (irq
& 0x1f));
58 writel(status
, stat_reg
);
60 u8 dctr
= readb(base
+ VT8500_IC_DCTR
+ irq
);
62 dctr
&= ~VT8500_INT_ENABLE
;
63 writeb(dctr
, base
+ VT8500_IC_DCTR
+ irq
);
67 static void vt8500_irq_unmask(unsigned int irq
)
69 void __iomem
*base
= ic_regbase
;
76 dctr
= readb(base
+ VT8500_IC_DCTR
+ irq
);
77 dctr
|= VT8500_INT_ENABLE
;
78 writeb(dctr
, base
+ VT8500_IC_DCTR
+ irq
);
81 static int vt8500_irq_set_type(unsigned int irq
, unsigned int flow_type
)
83 void __iomem
*base
= ic_regbase
;
84 unsigned int orig_irq
= irq
;
92 dctr
= readb(base
+ VT8500_IC_DCTR
+ irq
);
96 case IRQF_TRIGGER_LOW
:
98 case IRQF_TRIGGER_HIGH
:
99 dctr
|= VT8500_TRIGGER_HIGH
;
100 irq_desc
[orig_irq
].handle_irq
= handle_level_irq
;
102 case IRQF_TRIGGER_FALLING
:
103 dctr
|= VT8500_TRIGGER_FALLING
;
104 irq_desc
[orig_irq
].handle_irq
= handle_edge_irq
;
106 case IRQF_TRIGGER_RISING
:
107 dctr
|= VT8500_TRIGGER_RISING
;
108 irq_desc
[orig_irq
].handle_irq
= handle_edge_irq
;
111 writeb(dctr
, base
+ VT8500_IC_DCTR
+ irq
);
116 static struct irq_chip vt8500_irq_chip
= {
118 .ack
= vt8500_irq_mask
,
119 .mask
= vt8500_irq_mask
,
120 .unmask
= vt8500_irq_unmask
,
121 .set_type
= vt8500_irq_set_type
,
124 void __init
vt8500_init_irq(void)
128 ic_regbase
= ioremap(wmt_ic_base
, SZ_64K
);
131 /* Enable rotating priority for IRQ */
132 writel((1 << 6), ic_regbase
+ 0x20);
133 writel(0, ic_regbase
+ 0x24);
135 for (i
= 0; i
< wmt_nr_irqs
; i
++) {
136 /* Disable all interrupts and route them to IRQ */
137 writeb(0x00, ic_regbase
+ VT8500_IC_DCTR
+ i
);
139 set_irq_chip(i
, &vt8500_irq_chip
);
140 set_irq_handler(i
, handle_level_irq
);
141 set_irq_flags(i
, IRQF_VALID
);
144 printk(KERN_ERR
"Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
148 void __init
wm8505_init_irq(void)
152 ic_regbase
= ioremap(wmt_ic_base
, SZ_64K
);
153 sic_regbase
= ioremap(wmt_sic_base
, SZ_64K
);
155 if (ic_regbase
&& sic_regbase
) {
156 /* Enable rotating priority for IRQ */
157 writel((1 << 6), ic_regbase
+ 0x20);
158 writel(0, ic_regbase
+ 0x24);
159 writel((1 << 6), sic_regbase
+ 0x20);
160 writel(0, sic_regbase
+ 0x24);
162 for (i
= 0; i
< wmt_nr_irqs
; i
++) {
163 /* Disable all interrupts and route them to IRQ */
165 writeb(0x00, ic_regbase
+ VT8500_IC_DCTR
+ i
);
167 writeb(0x00, sic_regbase
+ VT8500_IC_DCTR
170 set_irq_chip(i
, &vt8500_irq_chip
);
171 set_irq_handler(i
, handle_level_irq
);
172 set_irq_flags(i
, IRQF_VALID
);
175 printk(KERN_ERR
"Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");