xref: /kernel/linux/linux-5.10/arch/arm64/lib/delay.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Delay loops based on the OpenRISC implementation.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2012 ARM Limited
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Author: Will Deacon <will.deacon@arm.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/delay.h>
118c2ecf20Sopenharmony_ci#include <linux/init.h>
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/timex.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <clocksource/arm_arch_timer.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define USECS_TO_CYCLES(time_usecs)			\
198c2ecf20Sopenharmony_ci	xloops_to_cycles((time_usecs) * 0x10C7UL)
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistatic inline unsigned long xloops_to_cycles(unsigned long xloops)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	return (xloops * loops_per_jiffy * HZ) >> 32;
248c2ecf20Sopenharmony_ci}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_civoid __delay(unsigned long cycles)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	cycles_t start = get_cycles();
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	if (arch_timer_evtstrm_available()) {
318c2ecf20Sopenharmony_ci		const cycles_t timer_evt_period =
328c2ecf20Sopenharmony_ci			USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US);
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci		while ((get_cycles() - start + timer_evt_period) < cycles)
358c2ecf20Sopenharmony_ci			wfe();
368c2ecf20Sopenharmony_ci	}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	while ((get_cycles() - start) < cycles)
398c2ecf20Sopenharmony_ci		cpu_relax();
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__delay);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ciinline void __const_udelay(unsigned long xloops)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	__delay(xloops_to_cycles(xloops));
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__const_udelay);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_civoid __udelay(unsigned long usecs)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	__const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__udelay);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_civoid __ndelay(unsigned long nsecs)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	__const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__ndelay);
60