18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *	Precise Delay Loops for SuperH
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *	Copyright (C) 1999 Niibe Yutaka & Kaz Kojima
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/sched.h>
98c2ecf20Sopenharmony_ci#include <linux/delay.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_civoid __delay(unsigned long loops)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	__asm__ __volatile__(
148c2ecf20Sopenharmony_ci		/*
158c2ecf20Sopenharmony_ci		 * ST40-300 appears to have an issue with this code,
168c2ecf20Sopenharmony_ci		 * normally taking two cycles each loop, as with all
178c2ecf20Sopenharmony_ci		 * other SH variants. If however the branch and the
188c2ecf20Sopenharmony_ci		 * delay slot straddle an 8 byte boundary, this increases
198c2ecf20Sopenharmony_ci		 * to 3 cycles.
208c2ecf20Sopenharmony_ci		 * This align directive ensures this doesn't occur.
218c2ecf20Sopenharmony_ci		 */
228c2ecf20Sopenharmony_ci		".balign 8\n\t"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci		"tst	%0, %0\n\t"
258c2ecf20Sopenharmony_ci		"1:\t"
268c2ecf20Sopenharmony_ci		"bf/s	1b\n\t"
278c2ecf20Sopenharmony_ci		" dt	%0"
288c2ecf20Sopenharmony_ci		: "=r" (loops)
298c2ecf20Sopenharmony_ci		: "0" (loops)
308c2ecf20Sopenharmony_ci		: "t");
318c2ecf20Sopenharmony_ci}
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ciinline void __const_udelay(unsigned long xloops)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	xloops *= 4;
368c2ecf20Sopenharmony_ci	__asm__("dmulu.l	%0, %2\n\t"
378c2ecf20Sopenharmony_ci		"sts	mach, %0"
388c2ecf20Sopenharmony_ci		: "=r" (xloops)
398c2ecf20Sopenharmony_ci		: "0" (xloops),
408c2ecf20Sopenharmony_ci		  "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4))
418c2ecf20Sopenharmony_ci		: "macl", "mach");
428c2ecf20Sopenharmony_ci	__delay(++xloops);
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_civoid __udelay(unsigned long usecs)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	__const_udelay(usecs * 0x000010c6);  /* 2**32 / 1000000 */
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_civoid __ndelay(unsigned long nsecs)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	__const_udelay(nsecs * 0x00000005);
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
55