aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/include/asm/timex.h
blob: 6c150979fa24ea50dddb87e0054f24680d8703cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1998, 1999, 2003 by Ralf Baechle
 */
#ifndef _ASM_TIMEX_H
#define _ASM_TIMEX_H

#ifdef __KERNEL__

#include <asm/mipsregs.h>

/*
 * This is the clock rate of the i8253 PIT.  A MIPS system may not have
 * a PIT by the symbol is used all over the kernel including some APIs.
 * So keeping it defined to the number for the PIT is the only sane thing
 * for now.
 */
#define CLOCK_TICK_RATE 1193182

extern unsigned int mips_hpt_frequency;

/*
 * Standard way to access the cycle counter.
 * Currently only used on SMP for scheduling.
 *
 * Only the low 32 bits are available as a continuously counting entity.
 * But this only means we'll force a reschedule every 8 seconds or so,
 * which isn't an evil thing.
 *
 * We know that all SMP capable CPUs have cycle counters.
 *
 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
 * HAVE_GET_CYCLES makes sure that this case is handled properly :
 *
 * Ralf Baechle <ralf@linux-mips.org> :
 * This avoids us executing an mfc0 c0_count instruction on processors which
 * don't have but also on certain R4000 and R4400 versions where reading from
 * the count register just in the very moment when its value equals c0_compare
 * will result in the timer interrupt getting lost.
 */

#ifdef CONFIG_HAVE_GET_CYCLES
# ifdef CONFIG_CPU_CAVIUM_OCTEON
typedef unsigned long cycles_t;

static inline cycles_t get_cycles(void)
{
	return read_c0_cvmcount();
}

static inline void get_cycles_barrier(void)
{
}

static inline cycles_t get_cycles_rate(void)
{
	return mips_hpt_frequency;
}

extern int test_tsc_synchronization(void);
extern int _tsc_is_sync;
static inline int tsc_is_sync(void)
{
	return _tsc_is_sync;
}
# else /* #ifdef CONFIG_CPU_CAVIUM_OCTEON */
#  error "64-bit get_cycles() supported only on Cavium Octeon MIPS architectures"
# endif /* #else #ifdef CONFIG_CPU_CAVIUM_OCTEON */
#elif defined(CONFIG_HAVE_GET_CYCLES_32)
typedef unsigned int cycles_t;

static inline cycles_t get_cycles(void)
{
	return read_c0_count();
}

static inline void get_cycles_barrier(void)
{
}

static inline cycles_t get_cycles_rate(void)
{
	return mips_hpt_frequency;
}

extern int test_tsc_synchronization(void);
extern int _tsc_is_sync;
static inline int tsc_is_sync(void)
{
	return _tsc_is_sync;
}
#else
typedef unsigned int cycles_t;

static inline cycles_t get_cycles(void)
{
	return 0;
}
static inline int test_tsc_synchronization(void)
{
	return 0;
}
static inline int tsc_is_sync(void)
{
	return 0;
}
#endif

#define DELAY_INTERRUPT 100
/*
 * Only updates 32 LSB.
 */
static inline void write_tsc(u32 val1, u32 val2)
{
	write_c0_count(val1);
	/* Arrange for an interrupt in a short while */
	write_c0_compare(read_c0_count() + DELAY_INTERRUPT);
}

/*
 * Currently unused, should update internal tsc-related timekeeping sources.
 */
static inline void mark_tsc_unstable(char *reason)
{
}

/*
 * Currently simply use the tsc_is_sync value.
 */
static inline int unsynchronized_tsc(void)
{
	return !tsc_is_sync();
}

#endif /* __KERNEL__ */

#endif /*  _ASM_TIMEX_H */