Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/riscv/lib/delay.c
26439 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (C) 2012 Regents of the University of California
4
*/
5
6
#include <linux/delay.h>
7
#include <linux/math.h>
8
#include <linux/param.h>
9
#include <linux/timex.h>
10
#include <linux/types.h>
11
#include <linux/export.h>
12
13
#include <asm/processor.h>
14
15
/*
16
* This is copies from arch/arm/include/asm/delay.h
17
*
18
* Loop (or tick) based delay:
19
*
20
* loops = loops_per_jiffy * jiffies_per_sec * delay_us / us_per_sec
21
*
22
* where:
23
*
24
* jiffies_per_sec = HZ
25
* us_per_sec = 1000000
26
*
27
* Therefore the constant part is HZ / 1000000 which is a small
28
* fractional number. To make this usable with integer math, we
29
* scale up this constant by 2^31, perform the actual multiplication,
30
* and scale the result back down by 2^31 with a simple shift:
31
*
32
* loops = (loops_per_jiffy * delay_us * UDELAY_MULT) >> 31
33
*
34
* where:
35
*
36
* UDELAY_MULT = 2^31 * HZ / 1000000
37
* = (2^31 / 1000000) * HZ
38
* = 2147.483648 * HZ
39
* = 2147 * HZ + 483648 * HZ / 1000000
40
*
41
* 31 is the biggest scale shift value that won't overflow 32 bits for
42
* delay_us * UDELAY_MULT assuming HZ <= 1000 and delay_us <= 2000.
43
*/
44
#define MAX_UDELAY_US 2000
45
#define MAX_UDELAY_HZ 1000
46
#define UDELAY_MULT (2147UL * HZ + 483648UL * HZ / 1000000UL)
47
#define UDELAY_SHIFT 31
48
49
#if HZ > MAX_UDELAY_HZ
50
#error "HZ > MAX_UDELAY_HZ"
51
#endif
52
53
/*
54
* RISC-V supports both UDELAY and NDELAY. This is largely the same as above,
55
* but with different constants. I added 10 bits to the shift to get this, but
56
* the result is that I need a 64-bit multiply, which is slow on 32-bit
57
* platforms.
58
*
59
* NDELAY_MULT = 2^41 * HZ / 1000000000
60
* = (2^41 / 1000000000) * HZ
61
* = 2199.02325555 * HZ
62
* = 2199 * HZ + 23255550 * HZ / 1000000000
63
*
64
* The maximum here is to avoid 64-bit overflow, but it isn't checked as it
65
* won't happen.
66
*/
67
#define MAX_NDELAY_NS (1ULL << 42)
68
#define MAX_NDELAY_HZ MAX_UDELAY_HZ
69
#define NDELAY_MULT ((unsigned long long)(2199ULL * HZ + 23255550ULL * HZ / 1000000000ULL))
70
#define NDELAY_SHIFT 41
71
72
#if HZ > MAX_NDELAY_HZ
73
#error "HZ > MAX_NDELAY_HZ"
74
#endif
75
76
void __delay(unsigned long cycles)
77
{
78
u64 t0 = get_cycles();
79
80
while ((unsigned long)(get_cycles() - t0) < cycles)
81
cpu_relax();
82
}
83
EXPORT_SYMBOL(__delay);
84
85
void udelay(unsigned long usecs)
86
{
87
u64 ucycles = (u64)usecs * lpj_fine * UDELAY_MULT;
88
u64 n;
89
90
if (unlikely(usecs > MAX_UDELAY_US)) {
91
n = (u64)usecs * riscv_timebase;
92
do_div(n, 1000000);
93
94
__delay(n);
95
return;
96
}
97
98
__delay(ucycles >> UDELAY_SHIFT);
99
}
100
EXPORT_SYMBOL(udelay);
101
102
void ndelay(unsigned long nsecs)
103
{
104
/*
105
* This doesn't bother checking for overflow, as it won't happen (it's
106
* an hour) of delay.
107
*/
108
unsigned long long ncycles = nsecs * lpj_fine * NDELAY_MULT;
109
__delay(ncycles >> NDELAY_SHIFT);
110
}
111
EXPORT_SYMBOL(ndelay);
112
113