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/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
  76void __delay(unsigned long cycles)
  77{
  78        u64 t0 = get_cycles();
  79
  80        while ((unsigned long)(get_cycles() - t0) < cycles)
  81                cpu_relax();
  82}
  83EXPORT_SYMBOL(__delay);
  84
  85void 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}
 100EXPORT_SYMBOL(udelay);
 101
 102void 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}
 111EXPORT_SYMBOL(ndelay);
 112