aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm/timer.c
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2012-09-05 15:28:52 -0400
committerDavid Brown <davidb@codeaurora.org>2012-09-13 14:14:37 -0400
commit4312a7ef9cd744849e16ef4bdeb7ca6beec9ec76 (patch)
tree6e42fe0cfabf49a6126954b5b726c8a448169c85 /arch/arm/mach-msm/timer.c
parent66a8950949c12a2600ff62e78b24f42ef8f6d28e (diff)
ARM: msm: Allow timer.c to compile on multiple targets
The timer code relies on #defines from mach/iomap.h, cpu_is_*() checks, and a global irq #define. All this makes this file impossible to compile in a mult-target build. Therefore, make a sys_timer struct for each SoC so that machine descriptors can reference the correct timer. Then go through and replace all the defines with raw values that are passed to a common initialization function. This paves the way to adding DT support to this code as well as allows us to compile this file on multiple targets at the same time. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: David Brown <davidb@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-msm/timer.c')
-rw-r--r--arch/arm/mach-msm/timer.c120
1 files changed, 84 insertions, 36 deletions
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 36bbc60b699f..ddb870117659 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * 2 *
3 * Copyright (C) 2007 Google, Inc. 3 * Copyright (C) 2007 Google, Inc.
4 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. 4 * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This software is licensed under the terms of the GNU General Public 6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and 7 * License version 2, as published by the Free Software Foundation, and
@@ -26,9 +26,7 @@
26#include <asm/localtimer.h> 26#include <asm/localtimer.h>
27#include <asm/sched_clock.h> 27#include <asm/sched_clock.h>
28 28
29#include <mach/msm_iomap.h> 29#include "common.h"
30#include <mach/cpu.h>
31#include <mach/board.h>
32 30
33#define TIMER_MATCH_VAL 0x0000 31#define TIMER_MATCH_VAL 0x0000
34#define TIMER_COUNT_VAL 0x0004 32#define TIMER_COUNT_VAL 0x0004
@@ -36,7 +34,7 @@
36#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) 34#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1)
37#define TIMER_ENABLE_EN BIT(0) 35#define TIMER_ENABLE_EN BIT(0)
38#define TIMER_CLEAR 0x000C 36#define TIMER_CLEAR 0x000C
39#define DGT_CLK_CTL 0x0034 37#define DGT_CLK_CTL 0x0030
40#define DGT_CLK_CTL_DIV_4 0x3 38#define DGT_CLK_CTL_DIV_4 0x3
41 39
42#define GPT_HZ 32768 40#define GPT_HZ 32768
@@ -172,44 +170,21 @@ static notrace u32 msm_sched_clock_read(void)
172 return msm_clocksource.read(&msm_clocksource); 170 return msm_clocksource.read(&msm_clocksource);
173} 171}
174 172
175static void __init msm_timer_init(void) 173static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
174 bool percpu)
176{ 175{
177 struct clock_event_device *ce = &msm_clockevent; 176 struct clock_event_device *ce = &msm_clockevent;
178 struct clocksource *cs = &msm_clocksource; 177 struct clocksource *cs = &msm_clocksource;
179 int res; 178 int res;
180 u32 dgt_hz;
181
182 if (cpu_is_msm7x01()) {
183 event_base = MSM_CSR_BASE;
184 source_base = MSM_CSR_BASE + 0x10;
185 dgt_hz = 19200000 >> MSM_DGT_SHIFT; /* 600 KHz */
186 cs->read = msm_read_timer_count_shift;
187 cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
188 } else if (cpu_is_msm7x30()) {
189 event_base = MSM_CSR_BASE + 0x04;
190 source_base = MSM_CSR_BASE + 0x24;
191 dgt_hz = 24576000 / 4;
192 } else if (cpu_is_qsd8x50()) {
193 event_base = MSM_CSR_BASE;
194 source_base = MSM_CSR_BASE + 0x10;
195 dgt_hz = 19200000 / 4;
196 } else if (cpu_is_msm8x60() || cpu_is_msm8960()) {
197 event_base = MSM_TMR_BASE + 0x04;
198 /* Use CPU0's timer as the global clock source. */
199 source_base = MSM_TMR0_BASE + 0x24;
200 dgt_hz = 27000000 / 4;
201 writel_relaxed(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
202 } else
203 BUG();
204 179
205 writel_relaxed(0, event_base + TIMER_ENABLE); 180 writel_relaxed(0, event_base + TIMER_ENABLE);
206 writel_relaxed(0, event_base + TIMER_CLEAR); 181 writel_relaxed(0, event_base + TIMER_CLEAR);
207 writel_relaxed(~0, event_base + TIMER_MATCH_VAL); 182 writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
208 ce->cpumask = cpumask_of(0); 183 ce->cpumask = cpumask_of(0);
184 ce->irq = irq;
209 185
210 ce->irq = INT_GP_TIMER_EXP;
211 clockevents_config_and_register(ce, GPT_HZ, 4, 0xffffffff); 186 clockevents_config_and_register(ce, GPT_HZ, 4, 0xffffffff);
212 if (cpu_is_msm8x60() || cpu_is_msm8960()) { 187 if (percpu) {
213 msm_evt.percpu_evt = alloc_percpu(struct clock_event_device *); 188 msm_evt.percpu_evt = alloc_percpu(struct clock_event_device *);
214 if (!msm_evt.percpu_evt) { 189 if (!msm_evt.percpu_evt) {
215 pr_err("memory allocation failed for %s\n", ce->name); 190 pr_err("memory allocation failed for %s\n", ce->name);
@@ -238,10 +213,83 @@ err:
238 res = clocksource_register_hz(cs, dgt_hz); 213 res = clocksource_register_hz(cs, dgt_hz);
239 if (res) 214 if (res)
240 pr_err("clocksource_register failed\n"); 215 pr_err("clocksource_register failed\n");
241 setup_sched_clock(msm_sched_clock_read, 216 setup_sched_clock(msm_sched_clock_read, sched_bits, dgt_hz);
242 cpu_is_msm7x01() ? 32 - MSM_DGT_SHIFT : 32, dgt_hz);
243} 217}
244 218
245struct sys_timer msm_timer = { 219static int __init msm_timer_map(phys_addr_t event, phys_addr_t source)
246 .init = msm_timer_init 220{
221 event_base = ioremap(event, SZ_64);
222 if (!event_base) {
223 pr_err("Failed to map event base\n");
224 return 1;
225 }
226 source_base = ioremap(source, SZ_64);
227 if (!source_base) {
228 pr_err("Failed to map source base\n");
229 return 1;
230 }
231 return 0;
232}
233
234static void __init msm7x01_timer_init(void)
235{
236 struct clocksource *cs = &msm_clocksource;
237
238 if (msm_timer_map(0xc0100000, 0xc0100010))
239 return;
240 cs->read = msm_read_timer_count_shift;
241 cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
242 /* 600 KHz */
243 msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7,
244 false);
245}
246
247struct sys_timer msm7x01_timer = {
248 .init = msm7x01_timer_init
249};
250
251static void __init msm7x30_timer_init(void)
252{
253 if (msm_timer_map(0xc0100004, 0xc0100024))
254 return;
255 msm_timer_init(24576000 / 4, 32, 1, false);
256}
257
258struct sys_timer msm7x30_timer = {
259 .init = msm7x30_timer_init
260};
261
262static void __init msm8x60_timer_init(void)
263{
264 if (msm_timer_map(0x02000004, 0x02040024))
265 return;
266 writel_relaxed(DGT_CLK_CTL_DIV_4, event_base + DGT_CLK_CTL);
267 msm_timer_init(27000000 / 4, 32, 17, true);
268}
269
270struct sys_timer msm8x60_timer = {
271 .init = msm8x60_timer_init
272};
273
274static void __init msm8960_timer_init(void)
275{
276 if (msm_timer_map(0x0200A004, 0x0208A024))
277 return;
278 writel_relaxed(DGT_CLK_CTL_DIV_4, event_base + DGT_CLK_CTL);
279 msm_timer_init(27000000 / 4, 32, 17, true);
280}
281
282struct sys_timer msm8960_timer = {
283 .init = msm8960_timer_init
284};
285
286static void __init qsd8x50_timer_init(void)
287{
288 if (msm_timer_map(0xAC100000, 0xAC100010))
289 return;
290 msm_timer_init(19200000 / 4, 32, 7, false);
291}
292
293struct sys_timer qsd8x50_timer = {
294 .init = qsd8x50_timer_init
247}; 295};