aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm/timer.c
diff options
context:
space:
mode:
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};