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