aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-davinci/Kconfig3
-rw-r--r--arch/arm/mach-davinci/Makefile1
-rw-r--r--arch/arm/mach-davinci/cp_intc.c161
-rw-r--r--arch/arm/mach-davinci/include/mach/cp_intc.h57
4 files changed, 222 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index a9c78bc72b84..56cd03f908e2 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -1,5 +1,8 @@
1if ARCH_DAVINCI 1if ARCH_DAVINCI
2 2
3config CP_INTC
4 bool
5
3menu "TI DaVinci Implementations" 6menu "TI DaVinci Implementations"
4 7
5comment "DaVinci Core Type" 8comment "DaVinci Core Type"
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index 1674661942f3..9a696ae60fca 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -8,6 +8,7 @@ obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \
8 gpio.o devices.o dma.o usb.o 8 gpio.o devices.o dma.o usb.o
9 9
10obj-$(CONFIG_DAVINCI_MUX) += mux.o 10obj-$(CONFIG_DAVINCI_MUX) += mux.o
11obj-$(CONFIG_CP_INTC) += cp_intc.o
11 12
12# Chip specific 13# Chip specific
13obj-$(CONFIG_ARCH_DAVINCI_DM644x) += dm644x.o 14obj-$(CONFIG_ARCH_DAVINCI_DM644x) += dm644x.o
diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c
new file mode 100644
index 000000000000..96c8e97a7deb
--- /dev/null
+++ b/arch/arm/mach-davinci/cp_intc.c
@@ -0,0 +1,161 @@
1/*
2 * TI Common Platform Interrupt Controller (cp_intc) driver
3 *
4 * Author: Steve Chen <schen@mvista.com>
5 * Copyright (C) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
6 *
7 * This file is licensed under the terms of the GNU General Public License
8 * version 2. This program is licensed "as is" without any warranty of any
9 * kind, whether express or implied.
10 */
11
12#include <linux/init.h>
13#include <linux/sched.h>
14#include <linux/interrupt.h>
15#include <linux/kernel.h>
16#include <linux/irq.h>
17#include <linux/io.h>
18
19#include <mach/cp_intc.h>
20
21static void __iomem *cp_intc_base;
22
23static inline unsigned int cp_intc_read(unsigned offset)
24{
25 return __raw_readl(cp_intc_base + offset);
26}
27
28static inline void cp_intc_write(unsigned long value, unsigned offset)
29{
30 __raw_writel(value, cp_intc_base + offset);
31}
32
33static void cp_intc_ack_irq(unsigned int irq)
34{
35 cp_intc_write(irq, CP_INTC_SYS_STAT_IDX_CLR);
36}
37
38/* Disable interrupt */
39static void cp_intc_mask_irq(unsigned int irq)
40{
41 /* XXX don't know why we need to disable nIRQ here... */
42 cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_CLR);
43 cp_intc_write(irq, CP_INTC_SYS_ENABLE_IDX_CLR);
44 cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET);
45}
46
47/* Enable interrupt */
48static void cp_intc_unmask_irq(unsigned int irq)
49{
50 cp_intc_write(irq, CP_INTC_SYS_ENABLE_IDX_SET);
51}
52
53static int cp_intc_set_irq_type(unsigned int irq, unsigned int flow_type)
54{
55 unsigned reg = BIT_WORD(irq);
56 unsigned mask = BIT_MASK(irq);
57 unsigned polarity = cp_intc_read(CP_INTC_SYS_POLARITY(reg));
58 unsigned type = cp_intc_read(CP_INTC_SYS_TYPE(reg));
59
60 switch (flow_type) {
61 case IRQ_TYPE_EDGE_RISING:
62 polarity |= mask;
63 type |= mask;
64 break;
65 case IRQ_TYPE_EDGE_FALLING:
66 polarity &= ~mask;
67 type |= mask;
68 break;
69 case IRQ_TYPE_LEVEL_HIGH:
70 polarity |= mask;
71 type &= ~mask;
72 break;
73 case IRQ_TYPE_LEVEL_LOW:
74 polarity &= ~mask;
75 type &= ~mask;
76 break;
77 default:
78 return -EINVAL;
79 }
80
81 cp_intc_write(polarity, CP_INTC_SYS_POLARITY(reg));
82 cp_intc_write(type, CP_INTC_SYS_TYPE(reg));
83
84 return 0;
85}
86
87static struct irq_chip cp_intc_irq_chip = {
88 .name = "cp_intc",
89 .ack = cp_intc_ack_irq,
90 .mask = cp_intc_mask_irq,
91 .unmask = cp_intc_unmask_irq,
92 .set_type = cp_intc_set_irq_type,
93};
94
95void __init cp_intc_init(void __iomem *base, unsigned short num_irq,
96 u8 *irq_prio)
97{
98 unsigned num_reg = BITS_TO_LONGS(num_irq);
99 int i;
100
101 cp_intc_base = base;
102
103 cp_intc_write(0, CP_INTC_GLOBAL_ENABLE);
104
105 /* Disable all host interrupts */
106 cp_intc_write(0, CP_INTC_HOST_ENABLE(0));
107
108 /* Disable system interrupts */
109 for (i = 0; i < num_reg; i++)
110 cp_intc_write(~0, CP_INTC_SYS_ENABLE_CLR(i));
111
112 /* Set to normal mode, no nesting, no priority hold */
113 cp_intc_write(0, CP_INTC_CTRL);
114 cp_intc_write(0, CP_INTC_HOST_CTRL);
115
116 /* Clear system interrupt status */
117 for (i = 0; i < num_reg; i++)
118 cp_intc_write(~0, CP_INTC_SYS_STAT_CLR(i));
119
120 /* Enable nIRQ (what about nFIQ?) */
121 cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET);
122
123 /*
124 * Priority is determined by host channel: lower channel number has
125 * higher priority i.e. channel 0 has highest priority and channel 31
126 * had the lowest priority.
127 */
128 num_reg = (num_irq + 3) >> 2; /* 4 channels per register */
129 if (irq_prio) {
130 unsigned j, k;
131 u32 val;
132
133 for (k = i = 0; i < num_reg; i++) {
134 for (val = j = 0; j < 4; j++, k++) {
135 val >>= 8;
136 if (k < num_irq)
137 val |= irq_prio[k] << 24;
138 }
139
140 cp_intc_write(val, CP_INTC_CHAN_MAP(i));
141 }
142 } else {
143 /*
144 * Default everything to channel 15 if priority not specified.
145 * Note that channel 0-1 are mapped to nFIQ and channels 2-31
146 * are mapped to nIRQ.
147 */
148 for (i = 0; i < num_reg; i++)
149 cp_intc_write(0x0f0f0f0f, CP_INTC_CHAN_MAP(i));
150 }
151
152 /* Set up genirq dispatching for cp_intc */
153 for (i = 0; i < num_irq; i++) {
154 set_irq_chip(i, &cp_intc_irq_chip);
155 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
156 set_irq_handler(i, handle_edge_irq);
157 }
158
159 /* Enable global interrupt */
160 cp_intc_write(1, CP_INTC_GLOBAL_ENABLE);
161}
diff --git a/arch/arm/mach-davinci/include/mach/cp_intc.h b/arch/arm/mach-davinci/include/mach/cp_intc.h
new file mode 100644
index 000000000000..c4d27eec8064
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/cp_intc.h
@@ -0,0 +1,57 @@
1/*
2 * TI Common Platform Interrupt Controller (cp_intc) definitions
3 *
4 * Author: Steve Chen <schen@mvista.com>
5 * Copyright (C) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
6 *
7 * This file is licensed under the terms of the GNU General Public License
8 * version 2. This program is licensed "as is" without any warranty of any
9 * kind, whether express or implied.
10 */
11#ifndef __ASM_HARDWARE_CP_INTC_H
12#define __ASM_HARDWARE_CP_INTC_H
13
14#define CP_INTC_REV 0x00
15#define CP_INTC_CTRL 0x04
16#define CP_INTC_HOST_CTRL 0x0C
17#define CP_INTC_GLOBAL_ENABLE 0x10
18#define CP_INTC_GLOBAL_NESTING_LEVEL 0x1C
19#define CP_INTC_SYS_STAT_IDX_SET 0x20
20#define CP_INTC_SYS_STAT_IDX_CLR 0x24
21#define CP_INTC_SYS_ENABLE_IDX_SET 0x28
22#define CP_INTC_SYS_ENABLE_IDX_CLR 0x2C
23#define CP_INTC_GLOBAL_WAKEUP_ENABLE 0x30
24#define CP_INTC_HOST_ENABLE_IDX_SET 0x34
25#define CP_INTC_HOST_ENABLE_IDX_CLR 0x38
26#define CP_INTC_PACING_PRESCALE 0x40
27#define CP_INTC_VECTOR_BASE 0x50
28#define CP_INTC_VECTOR_SIZE 0x54
29#define CP_INTC_VECTOR_NULL 0x58
30#define CP_INTC_PRIO_IDX 0x80
31#define CP_INTC_PRIO_VECTOR 0x84
32#define CP_INTC_SECURE_ENABLE 0x90
33#define CP_INTC_SECURE_PRIO_IDX 0x94
34#define CP_INTC_PACING_PARAM(n) (0x0100 + (n << 4))
35#define CP_INTC_PACING_DEC(n) (0x0104 + (n << 4))
36#define CP_INTC_PACING_MAP(n) (0x0108 + (n << 4))
37#define CP_INTC_SYS_RAW_STAT(n) (0x0200 + (n << 2))
38#define CP_INTC_SYS_STAT_CLR(n) (0x0280 + (n << 2))
39#define CP_INTC_SYS_ENABLE_SET(n) (0x0300 + (n << 2))
40#define CP_INTC_SYS_ENABLE_CLR(n) (0x0380 + (n << 2))
41#define CP_INTC_CHAN_MAP(n) (0x0400 + (n << 2))
42#define CP_INTC_HOST_MAP(n) (0x0800 + (n << 2))
43#define CP_INTC_HOST_PRIO_IDX(n) (0x0900 + (n << 2))
44#define CP_INTC_SYS_POLARITY(n) (0x0D00 + (n << 2))
45#define CP_INTC_SYS_TYPE(n) (0x0D80 + (n << 2))
46#define CP_INTC_WAKEUP_ENABLE(n) (0x0E00 + (n << 2))
47#define CP_INTC_DEBUG_SELECT(n) (0x0F00 + (n << 2))
48#define CP_INTC_SYS_SECURE_ENABLE(n) (0x1000 + (n << 2))
49#define CP_INTC_HOST_NESTING_LEVEL(n) (0x1100 + (n << 2))
50#define CP_INTC_HOST_ENABLE(n) (0x1500 + (n << 2))
51#define CP_INTC_HOST_PRIO_VECTOR(n) (0x1600 + (n << 2))
52#define CP_INTC_VECTOR_ADDR(n) (0x2000 + (n << 2))
53
54void __init cp_intc_init(void __iomem *base, unsigned short num_irq,
55 u8 *irq_prio);
56
57#endif /* __ASM_HARDWARE_CP_INTC_H */