aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pnx4008/irq.c
diff options
context:
space:
mode:
authorVitaly Wool <vwool@ru.mvista.com>2006-05-16 06:54:37 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-18 11:16:55 -0400
commit78818e477bf785391b02672d053fdbb2e111fb50 (patch)
treed1a43ddfb1b966fe981c10c874bae4faad070f29 /arch/arm/mach-pnx4008/irq.c
parenta5a503038e71a6b7d4bd9e596ac13087274e60c7 (diff)
[ARM] 3466/1: [2/3] Support for Philips PNX4008 platform: chip support
Patch from Vitaly Wool This patch adds basic chip support for PNX4008 ARM platform. It's basically the same as the previous one, but with the rmk's comments taken into account. Signed-off-by: Vitaly Wool <vwool@ru.mvista.com> Signed-off-by: Dmitry Pervushin <dpervushin@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-pnx4008/irq.c')
-rw-r--r--arch/arm/mach-pnx4008/irq.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/arch/arm/mach-pnx4008/irq.c b/arch/arm/mach-pnx4008/irq.c
new file mode 100644
index 000000000000..9b0a8e084e99
--- /dev/null
+++ b/arch/arm/mach-pnx4008/irq.c
@@ -0,0 +1,121 @@
1/*
2 * arch/arm/mach-pnx4008/irq.c
3 *
4 * PNX4008 IRQ controller driver
5 *
6 * Author: Dmitry Chigirev <source@mvista.com>
7 *
8 * Based on reference code received from Philips:
9 * Copyright (C) 2003 Philips Semiconductors
10 *
11 * 2005 (c) MontaVista Software, Inc. This file is licensed under
12 * the terms of the GNU General Public License version 2. This program
13 * is licensed "as is" without any warranty of any kind, whether express
14 * or implied.
15 */
16
17#include <linux/kernel.h>
18#include <linux/types.h>
19#include <linux/mm.h>
20#include <linux/interrupt.h>
21#include <linux/list.h>
22#include <linux/init.h>
23#include <linux/ioport.h>
24#include <linux/device.h>
25#include <asm/hardware.h>
26#include <asm/irq.h>
27#include <asm/io.h>
28#include <asm/setup.h>
29#include <asm/mach-types.h>
30#include <asm/pgtable.h>
31#include <asm/page.h>
32#include <asm/system.h>
33#include <asm/mach/arch.h>
34#include <asm/mach/irq.h>
35#include <asm/mach/map.h>
36#include <asm/arch/irq.h>
37
38static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES;
39
40static void pnx4008_mask_irq(unsigned int irq)
41{
42 __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */
43}
44
45static void pnx4008_unmask_irq(unsigned int irq)
46{
47 __raw_writel(__raw_readl(INTC_ER(irq)) | INTC_BIT(irq), INTC_ER(irq)); /* unmask interrupt */
48}
49
50static void pnx4008_mask_ack_irq(unsigned int irq)
51{
52 __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */
53 __raw_writel(INTC_BIT(irq), INTC_SR(irq)); /* clear interrupt status */
54}
55
56static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
57{
58 switch (type) {
59 case IRQT_RISING:
60 __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */
61 __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /*rising edge */
62 set_irq_handler(irq, do_edge_IRQ);
63 break;
64 case IRQT_FALLING:
65 __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */
66 __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*falling edge */
67 set_irq_handler(irq, do_edge_IRQ);
68 break;
69 case IRQT_LOW:
70 __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */
71 __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*low level */
72 set_irq_handler(irq, do_level_IRQ);
73 break;
74 case IRQT_HIGH:
75 __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */
76 __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /* high level */
77 set_irq_handler(irq, do_level_IRQ);
78 break;
79
80 /* IRQT_BOTHEDGE is not supported */
81 default:
82 printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
83 return -1;
84 }
85 return 0;
86}
87
88static struct irqchip pnx4008_irq_chip = {
89 .ack = pnx4008_mask_ack_irq,
90 .mask = pnx4008_mask_irq,
91 .unmask = pnx4008_unmask_irq,
92 .set_type = pnx4008_set_irq_type,
93};
94
95void __init pnx4008_init_irq(void)
96{
97 unsigned int i;
98
99 /* configure and enable IRQ 0,1,30,31 (cascade interrupts) mask all others */
100 pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]);
101 pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]);
102 pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]);
103 pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]);
104
105 __raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) |
106 (1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N),
107 INTC_ER(MAIN_BASE_INT));
108 __raw_writel(0, INTC_ER(SIC1_BASE_INT));
109 __raw_writel(0, INTC_ER(SIC2_BASE_INT));
110
111 /* configure all other IRQ's */
112 for (i = 0; i < NR_IRQS; i++) {
113 if (i == SUB2_FIQ_N || i == SUB1_FIQ_N ||
114 i == SUB2_IRQ_N || i == SUB1_IRQ_N)
115 continue;
116 set_irq_flags(i, IRQF_VALID);
117 set_irq_chip(i, &pnx4008_irq_chip);
118 pnx4008_set_irq_type(i, pnx4008_irq_type[i]);
119 }
120}
121