1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Copyright (C) 1993, 2000 Linus Torvalds
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Delay routines, using a pre-computed "loops_per_jiffy" value.
61da177e4SLinus Torvalds */
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds #include <linux/module.h>
91da177e4SLinus Torvalds #include <linux/sched.h> /* for udelay's use of smp_processor_id */
101da177e4SLinus Torvalds #include <asm/param.h>
111da177e4SLinus Torvalds #include <asm/smp.h>
121da177e4SLinus Torvalds #include <linux/delay.h>
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds /*
151da177e4SLinus Torvalds * Use only for very small delays (< 1 msec).
161da177e4SLinus Torvalds *
171da177e4SLinus Torvalds * The active part of our cycle counter is only 32-bits wide, and
181da177e4SLinus Torvalds * we're treating the difference between two marks as signed. On
191da177e4SLinus Torvalds * a 1GHz box, that's about 2 seconds.
201da177e4SLinus Torvalds */
211da177e4SLinus Torvalds
221da177e4SLinus Torvalds void
__delay(int loops)231da177e4SLinus Torvalds __delay(int loops)
241da177e4SLinus Torvalds {
251da177e4SLinus Torvalds int tmp;
261da177e4SLinus Torvalds __asm__ __volatile__(
271da177e4SLinus Torvalds " rpcc %0\n"
281da177e4SLinus Torvalds " addl %1,%0,%1\n"
291da177e4SLinus Torvalds "1: rpcc %0\n"
301da177e4SLinus Torvalds " subl %1,%0,%0\n"
311da177e4SLinus Torvalds " bgt %0,1b"
321da177e4SLinus Torvalds : "=&r" (tmp), "=r" (loops) : "1"(loops));
331da177e4SLinus Torvalds }
3414b97dedSSudip Mukherjee EXPORT_SYMBOL(__delay);
351da177e4SLinus Torvalds
361da177e4SLinus Torvalds #ifdef CONFIG_SMP
371da177e4SLinus Torvalds #define LPJ cpu_data[smp_processor_id()].loops_per_jiffy
381da177e4SLinus Torvalds #else
391da177e4SLinus Torvalds #define LPJ loops_per_jiffy
401da177e4SLinus Torvalds #endif
411da177e4SLinus Torvalds
421da177e4SLinus Torvalds void
udelay(unsigned long usecs)431da177e4SLinus Torvalds udelay(unsigned long usecs)
441da177e4SLinus Torvalds {
451da177e4SLinus Torvalds usecs *= (((unsigned long)HZ << 32) / 1000000) * LPJ;
461da177e4SLinus Torvalds __delay((long)usecs >> 32);
471da177e4SLinus Torvalds }
481da177e4SLinus Torvalds EXPORT_SYMBOL(udelay);
491da177e4SLinus Torvalds
501da177e4SLinus Torvalds void
ndelay(unsigned long nsecs)511da177e4SLinus Torvalds ndelay(unsigned long nsecs)
521da177e4SLinus Torvalds {
531da177e4SLinus Torvalds nsecs *= (((unsigned long)HZ << 32) / 1000000000) * LPJ;
541da177e4SLinus Torvalds __delay((long)nsecs >> 32);
551da177e4SLinus Torvalds }
561da177e4SLinus Torvalds EXPORT_SYMBOL(ndelay);
57