aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-clps711x/common.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-11-05 13:38:32 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-11-17 12:09:30 -0500
commit3a083227a45cbbf5d29e6fe7c093af9e09905d4d (patch)
tree55c13a45961ffad90a4b15c2e1919c19bf3ed8ae /arch/arm/mach-clps711x/common.c
parent4e65331c6bb4a777bd61a4dac0daa9fc47777b63 (diff)
ARM: clps711x: consolidate irq/mm/time code into a single file
The separate files for clps711x which contain maybe one or two data structures or functions is an inefficient use of files, and encourages further small files as other changes happen. Collapse down these into a single core.c file. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-clps711x/common.c')
-rw-r--r--arch/arm/mach-clps711x/common.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
new file mode 100644
index 000000000000..ced2a4e406f4
--- /dev/null
+++ b/arch/arm/mach-clps711x/common.c
@@ -0,0 +1,222 @@
1/*
2 * linux/arch/arm/mach-clps711x/core.c
3 *
4 * Core support for the CLPS711x-based machines.
5 *
6 * Copyright (C) 2001,2011 Deep Blue Solutions Ltd
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22#include <linux/kernel.h>
23#include <linux/mm.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <linux/io.h>
27#include <linux/irq.h>
28#include <linux/sched.h>
29#include <linux/timex.h>
30
31#include <asm/sizes.h>
32#include <mach/hardware.h>
33#include <asm/irq.h>
34#include <asm/leds.h>
35#include <asm/pgtable.h>
36#include <asm/page.h>
37#include <asm/mach/map.h>
38#include <asm/mach/time.h>
39#include <asm/hardware/clps7111.h>
40
41/*
42 * This maps the generic CLPS711x registers
43 */
44static struct map_desc clps711x_io_desc[] __initdata = {
45 {
46 .virtual = CLPS7111_VIRT_BASE,
47 .pfn = __phys_to_pfn(CLPS7111_PHYS_BASE),
48 .length = SZ_1M,
49 .type = MT_DEVICE
50 }
51};
52
53void __init clps711x_map_io(void)
54{
55 iotable_init(clps711x_io_desc, ARRAY_SIZE(clps711x_io_desc));
56}
57
58static void int1_mask(struct irq_data *d)
59{
60 u32 intmr1;
61
62 intmr1 = clps_readl(INTMR1);
63 intmr1 &= ~(1 << d->irq);
64 clps_writel(intmr1, INTMR1);
65}
66
67static void int1_ack(struct irq_data *d)
68{
69 u32 intmr1;
70
71 intmr1 = clps_readl(INTMR1);
72 intmr1 &= ~(1 << d->irq);
73 clps_writel(intmr1, INTMR1);
74
75 switch (d->irq) {
76 case IRQ_CSINT: clps_writel(0, COEOI); break;
77 case IRQ_TC1OI: clps_writel(0, TC1EOI); break;
78 case IRQ_TC2OI: clps_writel(0, TC2EOI); break;
79 case IRQ_RTCMI: clps_writel(0, RTCEOI); break;
80 case IRQ_TINT: clps_writel(0, TEOI); break;
81 case IRQ_UMSINT: clps_writel(0, UMSEOI); break;
82 }
83}
84
85static void int1_unmask(struct irq_data *d)
86{
87 u32 intmr1;
88
89 intmr1 = clps_readl(INTMR1);
90 intmr1 |= 1 << d->irq;
91 clps_writel(intmr1, INTMR1);
92}
93
94static struct irq_chip int1_chip = {
95 .irq_ack = int1_ack,
96 .irq_mask = int1_mask,
97 .irq_unmask = int1_unmask,
98};
99
100static void int2_mask(struct irq_data *d)
101{
102 u32 intmr2;
103
104 intmr2 = clps_readl(INTMR2);
105 intmr2 &= ~(1 << (d->irq - 16));
106 clps_writel(intmr2, INTMR2);
107}
108
109static void int2_ack(struct irq_data *d)
110{
111 u32 intmr2;
112
113 intmr2 = clps_readl(INTMR2);
114 intmr2 &= ~(1 << (d->irq - 16));
115 clps_writel(intmr2, INTMR2);
116
117 switch (d->irq) {
118 case IRQ_KBDINT: clps_writel(0, KBDEOI); break;
119 }
120}
121
122static void int2_unmask(struct irq_data *d)
123{
124 u32 intmr2;
125
126 intmr2 = clps_readl(INTMR2);
127 intmr2 |= 1 << (d->irq - 16);
128 clps_writel(intmr2, INTMR2);
129}
130
131static struct irq_chip int2_chip = {
132 .irq_ack = int2_ack,
133 .irq_mask = int2_mask,
134 .irq_unmask = int2_unmask,
135};
136
137void __init clps711x_init_irq(void)
138{
139 unsigned int i;
140
141 for (i = 0; i < NR_IRQS; i++) {
142 if (INT1_IRQS & (1 << i)) {
143 irq_set_chip_and_handler(i, &int1_chip,
144 handle_level_irq);
145 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
146 }
147 if (INT2_IRQS & (1 << i)) {
148 irq_set_chip_and_handler(i, &int2_chip,
149 handle_level_irq);
150 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
151 }
152 }
153
154 /*
155 * Disable interrupts
156 */
157 clps_writel(0, INTMR1);
158 clps_writel(0, INTMR2);
159
160 /*
161 * Clear down any pending interrupts
162 */
163 clps_writel(0, COEOI);
164 clps_writel(0, TC1EOI);
165 clps_writel(0, TC2EOI);
166 clps_writel(0, RTCEOI);
167 clps_writel(0, TEOI);
168 clps_writel(0, UMSEOI);
169 clps_writel(0, SYNCIO);
170 clps_writel(0, KBDEOI);
171}
172
173/*
174 * gettimeoffset() returns time since last timer tick, in usecs.
175 *
176 * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
177 * 'tick' is usecs per jiffy.
178 */
179static unsigned long clps711x_gettimeoffset(void)
180{
181 unsigned long hwticks;
182 hwticks = LATCH - (clps_readl(TC2D) & 0xffff); /* since last underflow */
183 return (hwticks * (tick_nsec / 1000)) / LATCH;
184}
185
186/*
187 * IRQ handler for the timer
188 */
189static irqreturn_t p720t_timer_interrupt(int irq, void *dev_id)
190{
191 timer_tick();
192 return IRQ_HANDLED;
193}
194
195static struct irqaction clps711x_timer_irq = {
196 .name = "CLPS711x Timer Tick",
197 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
198 .handler = p720t_timer_interrupt,
199};
200
201static void __init clps711x_timer_init(void)
202{
203 struct timespec tv;
204 unsigned int syscon;
205
206 syscon = clps_readl(SYSCON1);
207 syscon |= SYSCON1_TC2S | SYSCON1_TC2M;
208 clps_writel(syscon, SYSCON1);
209
210 clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */
211
212 setup_irq(IRQ_TC2OI, &clps711x_timer_irq);
213
214 tv.tv_nsec = 0;
215 tv.tv_sec = clps_readl(RTCDR);
216 do_settimeofday(&tv);
217}
218
219struct sys_timer clps711x_timer = {
220 .init = clps711x_timer_init,
221 .offset = clps711x_gettimeoffset,
222};