aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/exynos_mct.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource/exynos_mct.c')
-rw-r--r--drivers/clocksource/exynos_mct.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 2df03e238c1b..9403061a2acc 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -162,7 +162,17 @@ static void exynos4_mct_frc_start(void)
162 exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON); 162 exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
163} 163}
164 164
165static cycle_t notrace _exynos4_frc_read(void) 165/**
166 * exynos4_read_count_64 - Read all 64-bits of the global counter
167 *
168 * This will read all 64-bits of the global counter taking care to make sure
169 * that the upper and lower half match. Note that reading the MCT can be quite
170 * slow (hundreds of nanoseconds) so you should use the 32-bit (lower half
171 * only) version when possible.
172 *
173 * Returns the number of cycles in the global counter.
174 */
175static u64 exynos4_read_count_64(void)
166{ 176{
167 unsigned int lo, hi; 177 unsigned int lo, hi;
168 u32 hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U); 178 u32 hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U);
@@ -176,9 +186,22 @@ static cycle_t notrace _exynos4_frc_read(void)
176 return ((cycle_t)hi << 32) | lo; 186 return ((cycle_t)hi << 32) | lo;
177} 187}
178 188
189/**
190 * exynos4_read_count_32 - Read the lower 32-bits of the global counter
191 *
192 * This will read just the lower 32-bits of the global counter. This is marked
193 * as notrace so it can be used by the scheduler clock.
194 *
195 * Returns the number of cycles in the global counter (lower 32 bits).
196 */
197static u32 notrace exynos4_read_count_32(void)
198{
199 return readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L);
200}
201
179static cycle_t exynos4_frc_read(struct clocksource *cs) 202static cycle_t exynos4_frc_read(struct clocksource *cs)
180{ 203{
181 return _exynos4_frc_read(); 204 return exynos4_read_count_32();
182} 205}
183 206
184static void exynos4_frc_resume(struct clocksource *cs) 207static void exynos4_frc_resume(struct clocksource *cs)
@@ -190,21 +213,23 @@ struct clocksource mct_frc = {
190 .name = "mct-frc", 213 .name = "mct-frc",
191 .rating = 400, 214 .rating = 400,
192 .read = exynos4_frc_read, 215 .read = exynos4_frc_read,
193 .mask = CLOCKSOURCE_MASK(64), 216 .mask = CLOCKSOURCE_MASK(32),
194 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 217 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
195 .resume = exynos4_frc_resume, 218 .resume = exynos4_frc_resume,
196}; 219};
197 220
198static u64 notrace exynos4_read_sched_clock(void) 221static u64 notrace exynos4_read_sched_clock(void)
199{ 222{
200 return _exynos4_frc_read(); 223 return exynos4_read_count_32();
201} 224}
202 225
203static struct delay_timer exynos4_delay_timer; 226static struct delay_timer exynos4_delay_timer;
204 227
205static cycles_t exynos4_read_current_timer(void) 228static cycles_t exynos4_read_current_timer(void)
206{ 229{
207 return _exynos4_frc_read(); 230 BUILD_BUG_ON_MSG(sizeof(cycles_t) != sizeof(u32),
231 "cycles_t needs to move to 32-bit for ARM64 usage");
232 return exynos4_read_count_32();
208} 233}
209 234
210static void __init exynos4_clocksource_init(void) 235static void __init exynos4_clocksource_init(void)
@@ -218,7 +243,7 @@ static void __init exynos4_clocksource_init(void)
218 if (clocksource_register_hz(&mct_frc, clk_rate)) 243 if (clocksource_register_hz(&mct_frc, clk_rate))
219 panic("%s: can't register clocksource\n", mct_frc.name); 244 panic("%s: can't register clocksource\n", mct_frc.name);
220 245
221 sched_clock_register(exynos4_read_sched_clock, 64, clk_rate); 246 sched_clock_register(exynos4_read_sched_clock, 32, clk_rate);
222} 247}
223 248
224static void exynos4_mct_comp0_stop(void) 249static void exynos4_mct_comp0_stop(void)
@@ -245,7 +270,7 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode,
245 exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR); 270 exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
246 } 271 }
247 272
248 comp_cycle = exynos4_frc_read(&mct_frc) + cycles; 273 comp_cycle = exynos4_read_count_64() + cycles;
249 exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L); 274 exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
250 exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U); 275 exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
251 276