~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to arch/arm/plat-omap/include/plat/trace-clock.h

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2009 Mathieu Desnoyers
3
 
 *
4
 
 * Trace clock ARM OMAP3 definitions.
5
 
 */
6
 
 
7
 
#ifndef _ASM_ARM_TRACE_CLOCK_OMAP3_H
8
 
#define _ASM_ARM_TRACE_CLOCK_OMAP3_H
9
 
 
10
 
#include <linux/clk.h>
11
 
#include <linux/timer.h>
12
 
#include <linux/percpu.h>
13
 
#include <plat/clock.h>
14
 
 
15
 
/*
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
23
 
 * overflow occurs.
24
 
 *
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
30
 
 * periodically.
31
 
 */
32
 
#define TC_HW_BITS                      31
33
 
 
34
 
/* Expected maximum interrupt latency in ms : 15ms, *2 for security */
35
 
#define TC_EXPECTED_INTERRUPT_LATENCY   30
36
 
 
37
 
/* Resync with 32k clock each 100ms */
38
 
#define TC_RESYNC_PERIOD                100
39
 
 
40
 
struct tc_cur_freq {
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 */
47
 
};
48
 
 
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 */
53
 
        /*
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.
57
 
         */
58
 
        int fast_clock_ready;
59
 
 
60
 
        u64 int_fast_clock;
61
 
        struct timer_list clear_ccnt_ms_timer;
62
 
        struct timer_list clock_resync_timer;
63
 
        u32 ext_32k;
64
 
        int refcount;
65
 
        u32 init_clock;
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 */
70
 
};
71
 
 
72
 
DECLARE_PER_CPU(struct pm_save_count, pm_save_count);
73
 
 
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;
77
 
 
78
 
DECLARE_PER_CPU(int, fast_clock_ready);
79
 
extern u64 _trace_clock_read_slow(void);
80
 
 
81
 
/*
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.
84
 
 */
85
 
extern u64 trace_clock_async_tsc_read(void);
86
 
/*
87
 
 * Update done by the architecture upon wakeup.
88
 
 */
89
 
extern void _trace_clock_write_synthetic_tsc(u64 value);
90
 
 
91
 
#ifdef CONFIG_DEBUG_TRACE_CLOCK
92
 
DECLARE_PER_CPU(unsigned int, last_clock_nest);
93
 
extern void trace_clock_debug(u64 value);
94
 
#else
95
 
static inline void trace_clock_debug(u64 value)
96
 
{
97
 
}
98
 
#endif
99
 
 
100
 
static inline u32 read_ccnt(void)
101
 
{
102
 
        u32 val;
103
 
        __asm__ __volatile__ ("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
104
 
        return val & ~(1 << TC_HW_BITS);
105
 
}
106
 
 
107
 
static inline u32 trace_clock_read32(void)
108
 
{
109
 
        u32 val;
110
 
 
111
 
        isb();
112
 
        val = read_ccnt();
113
 
        isb();
114
 
        return val;
115
 
}
116
 
 
117
 
static inline u64 trace_clock_read64(void)
118
 
{
119
 
        struct pm_save_count *pm_count;
120
 
        struct tc_cur_freq *cf;
121
 
        u64 val;
122
 
#ifdef CONFIG_DEBUG_TRACE_CLOCK
123
 
        unsigned long flags;
124
 
 
125
 
        local_irq_save(flags);
126
 
        per_cpu(last_clock_nest, smp_processor_id())++;
127
 
        barrier();
128
 
#endif
129
 
 
130
 
        preempt_disable();
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);
136
 
        } else
137
 
                val = _trace_clock_read_slow();
138
 
        trace_clock_debug(val);
139
 
        preempt_enable();
140
 
 
141
 
#ifdef CONFIG_DEBUG_TRACE_CLOCK
142
 
        barrier();
143
 
        per_cpu(last_clock_nest, smp_processor_id())--;
144
 
        local_irq_restore(flags);
145
 
#endif
146
 
        return val;
147
 
}
148
 
 
149
 
static inline u64 trace_clock_frequency(void)
150
 
{
151
 
        return cpu_hz;
152
 
}
153
 
 
154
 
static inline u32 trace_clock_freq_scale(void)
155
 
{
156
 
        return 1;
157
 
}
158
 
 
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);
163
 
 
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);
168
 
 
169
 
static inline void set_trace_clock_is_sync(int state)
170
 
{
171
 
}
172
 
#endif /* _ASM_MIPS_TRACE_CLOCK_OMAP3_H */