2
* Copyright (C) 2009 Mathieu Desnoyers
4
* Trace clock ARM OMAP3 definitions.
7
#ifndef _ASM_ARM_TRACE_CLOCK_OMAP3_H
8
#define _ASM_ARM_TRACE_CLOCK_OMAP3_H
10
#include <linux/clk.h>
11
#include <linux/timer.h>
12
#include <linux/percpu.h>
13
#include <plat/clock.h>
16
* Number of hardware clock bits. The higher order bits are expected to be 0.
17
* If the hardware clock source has more than 32 bits, the bits higher than the
18
* 32nd will be truncated by a cast to a 32 bits unsigned. Range : 1 - 32.
19
* (too few bits would be unrealistic though, since we depend on the timer to
20
* detect the overflows).
21
* OMAP3-specific : we clear bit 31 periodically so it never overflows. There
22
* is a hardware bug with CP14 and CP15 being executed at the same time a ccnt
25
* Siarhei Siamashka <siarhei.siamashka@nokia.com> :
26
* Performance monitoring unit breaks if somebody is accessing CP14/CP15
27
* coprocessor register exactly at the same time as CCNT overflows (regardless
28
* of the fact if generation of interrupts is enabled or not). A workaround
29
* suggested by ARM was to never allow it to overflow and reset it
34
/* Expected maximum interrupt latency in ms : 15ms, *2 for security */
35
#define TC_EXPECTED_INTERRUPT_LATENCY 30
37
/* Resync with 32k clock each 100ms */
38
#define TC_RESYNC_PERIOD 100
41
u64 cur_cpu_freq; /* in khz */
42
/* cur time : (now - base) * (max_freq / cur_freq) + base */
43
u32 mul_fact; /* (max_cpu_freq << 10) / cur_freq */
44
u64 hw_base; /* stamp of last cpufreq change, hw cycles */
45
u64 virt_base; /* same as above, virtual trace clock cycles */
46
u64 floor; /* floor value, so time never go back */
49
/* 32KHz counter per-cpu count save upon PM sleep and cpufreq management */
50
struct pm_save_count {
51
struct tc_cur_freq cf[2]; /* rcu-protected */
52
unsigned int index; /* tc_cur_freq current read index */
54
* Is fast clock ready to be read ? Read with preemption off. Modified
55
* only by local CPU in thread and interrupt context or by start/stop
56
* when time is not read concurrently.
61
struct timer_list clear_ccnt_ms_timer;
62
struct timer_list clock_resync_timer;
66
raw_spinlock_t lock; /* spinlock only sync the refcount */
67
unsigned int dvfs_count; /* Number of DVFS updates in period */
68
/* cpufreq management */
69
u64 max_cpu_freq; /* in khz */
72
DECLARE_PER_CPU(struct pm_save_count, pm_save_count);
74
extern u64 trace_clock_read_synthetic_tsc(void);
75
extern void _trace_clock_write_synthetic_tsc(u64 value);
76
extern unsigned long long cpu_hz;
78
DECLARE_PER_CPU(int, fast_clock_ready);
79
extern u64 _trace_clock_read_slow(void);
82
* ARM OMAP3 timers only return 32-bits values. We ened to extend it to a
83
* 64-bit value, which is provided by trace-clock-32-to-64.
85
extern u64 trace_clock_async_tsc_read(void);
87
* Update done by the architecture upon wakeup.
89
extern void _trace_clock_write_synthetic_tsc(u64 value);
91
#ifdef CONFIG_DEBUG_TRACE_CLOCK
92
DECLARE_PER_CPU(unsigned int, last_clock_nest);
93
extern void trace_clock_debug(u64 value);
95
static inline void trace_clock_debug(u64 value)
100
static inline u32 read_ccnt(void)
103
__asm__ __volatile__ ("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
104
return val & ~(1 << TC_HW_BITS);
107
static inline u32 trace_clock_read32(void)
117
static inline u64 trace_clock_read64(void)
119
struct pm_save_count *pm_count;
120
struct tc_cur_freq *cf;
122
#ifdef CONFIG_DEBUG_TRACE_CLOCK
125
local_irq_save(flags);
126
per_cpu(last_clock_nest, smp_processor_id())++;
131
pm_count = &per_cpu(pm_save_count, smp_processor_id());
132
if (likely(pm_count->fast_clock_ready)) {
133
cf = &pm_count->cf[ACCESS_ONCE(pm_count->index)];
134
val = max((((trace_clock_read_synthetic_tsc() - cf->hw_base)
135
* cf->mul_fact) >> 10) + cf->virt_base, cf->floor);
137
val = _trace_clock_read_slow();
138
trace_clock_debug(val);
141
#ifdef CONFIG_DEBUG_TRACE_CLOCK
143
per_cpu(last_clock_nest, smp_processor_id())--;
144
local_irq_restore(flags);
149
static inline u64 trace_clock_frequency(void)
154
static inline u32 trace_clock_freq_scale(void)
159
extern int get_trace_clock(void);
160
extern void put_trace_clock(void);
161
extern void get_synthetic_tsc(void);
162
extern void put_synthetic_tsc(void);
164
extern void resync_trace_clock(void);
165
extern void save_sync_trace_clock(void);
166
extern void start_trace_clock(void);
167
extern void stop_trace_clock(void);
169
static inline void set_trace_clock_is_sync(int state)
172
#endif /* _ASM_MIPS_TRACE_CLOCK_OMAP3_H */