0001
0002
0003
0004
0005
0006
0007
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
0035
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);
0062 }
0063 EXPORT_SYMBOL(__udelay);
0064
0065 void __ndelay(unsigned long nsecs)
0066 {
0067 __const_udelay(nsecs * 0x5UL);
0068 }
0069 EXPORT_SYMBOL(__ndelay);