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