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