18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
48c2ecf20Sopenharmony_ci * Mostly copied from arch/x86/lib/delay.c
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/export.h>
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/delay.h>
108c2ecf20Sopenharmony_ci#include <asm/param.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_civoid __delay(unsigned long loops)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	asm volatile(
158c2ecf20Sopenharmony_ci		"test %0,%0\n"
168c2ecf20Sopenharmony_ci		"jz 3f\n"
178c2ecf20Sopenharmony_ci		"jmp 1f\n"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci		".align 16\n"
208c2ecf20Sopenharmony_ci		"1: jmp 2f\n"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci		".align 16\n"
238c2ecf20Sopenharmony_ci		"2: dec %0\n"
248c2ecf20Sopenharmony_ci		" jnz 2b\n"
258c2ecf20Sopenharmony_ci		"3: dec %0\n"
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci		: /* we don't need output */
288c2ecf20Sopenharmony_ci		: "a" (loops)
298c2ecf20Sopenharmony_ci	);
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__delay);
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ciinline void __const_udelay(unsigned long xloops)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	int d0;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	xloops *= 4;
388c2ecf20Sopenharmony_ci	asm("mull %%edx"
398c2ecf20Sopenharmony_ci		: "=d" (xloops), "=&a" (d0)
408c2ecf20Sopenharmony_ci		: "1" (xloops), "0"
418c2ecf20Sopenharmony_ci		(loops_per_jiffy * (HZ/4)));
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	__delay(++xloops);
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__const_udelay);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_civoid __udelay(unsigned long usecs)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__udelay);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_civoid __ndelay(unsigned long nsecs)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__ndelay);
58