Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Delay loops based on the OpenRISC implementation.
0004  *
0005  * Copyright (C) 2012 ARM Limited
0006  *
0007  * Author: Will Deacon <will.deacon@arm.com>
0008  */
0009 
0010 #include <linux/delay.h>
0011 #include <linux/init.h>
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/timex.h>
0015 
0016 #include <clocksource/arm_arch_timer.h>
0017 
0018 #define USECS_TO_CYCLES(time_usecs)         \
0019     xloops_to_cycles((time_usecs) * 0x10C7UL)
0020 
0021 static inline unsigned long xloops_to_cycles(unsigned long xloops)
0022 {
0023     return (xloops * loops_per_jiffy * HZ) >> 32;
0024 }
0025 
0026 void __delay(unsigned long cycles)
0027 {
0028     cycles_t start = get_cycles();
0029 
0030     if (cpus_have_const_cap(ARM64_HAS_WFXT)) {
0031         u64 end = start + cycles;
0032 
0033         /*
0034          * Start with WFIT. If an interrupt makes us resume
0035          * early, use a WFET loop to complete the delay.
0036          */
0037         wfit(end);
0038         while ((get_cycles() - start) < cycles)
0039             wfet(end);
0040     } else  if (arch_timer_evtstrm_available()) {
0041         const cycles_t timer_evt_period =
0042             USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US);
0043 
0044         while ((get_cycles() - start + timer_evt_period) < cycles)
0045             wfe();
0046     }
0047 
0048     while ((get_cycles() - start) < cycles)
0049         cpu_relax();
0050 }
0051 EXPORT_SYMBOL(__delay);
0052 
0053 inline void __const_udelay(unsigned long xloops)
0054 {
0055     __delay(xloops_to_cycles(xloops));
0056 }
0057 EXPORT_SYMBOL(__const_udelay);
0058 
0059 void __udelay(unsigned long usecs)
0060 {
0061     __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
0062 }
0063 EXPORT_SYMBOL(__udelay);
0064 
0065 void __ndelay(unsigned long nsecs)
0066 {
0067     __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
0068 }
0069 EXPORT_SYMBOL(__ndelay);