162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * include/asm-xtensa/delay.h
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
562306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
662306a36Sopenharmony_ci * for more details.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Copyright (C) 2001 - 2005 Tensilica Inc.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#ifndef _XTENSA_DELAY_H
1362306a36Sopenharmony_ci#define _XTENSA_DELAY_H
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <asm/timex.h>
1662306a36Sopenharmony_ci#include <asm/param.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciextern unsigned long loops_per_jiffy;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic inline void __delay(unsigned long loops)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	if (__builtin_constant_p(loops) && loops < 2)
2362306a36Sopenharmony_ci		__asm__ __volatile__ ("nop");
2462306a36Sopenharmony_ci	else if (loops >= 2)
2562306a36Sopenharmony_ci		/* 2 cycles per loop. */
2662306a36Sopenharmony_ci		__asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b"
2762306a36Sopenharmony_ci				: "+r" (loops));
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* Undefined function to get compile-time error */
3162306a36Sopenharmony_civoid __bad_udelay(void);
3262306a36Sopenharmony_civoid __bad_ndelay(void);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define __MAX_UDELAY 30000
3562306a36Sopenharmony_ci#define __MAX_NDELAY 30000
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic inline void __udelay(unsigned long usecs)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	unsigned long start = get_ccount();
4062306a36Sopenharmony_ci	unsigned long cycles = (usecs * (ccount_freq >> 15)) >> 5;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	/* Note: all variables are unsigned (can wrap around)! */
4362306a36Sopenharmony_ci	while (((unsigned long)get_ccount()) - start < cycles)
4462306a36Sopenharmony_ci		cpu_relax();
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic inline void udelay(unsigned long usec)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	if (__builtin_constant_p(usec) && usec >= __MAX_UDELAY)
5062306a36Sopenharmony_ci		__bad_udelay();
5162306a36Sopenharmony_ci	else
5262306a36Sopenharmony_ci		__udelay(usec);
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic inline void __ndelay(unsigned long nsec)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	/*
5862306a36Sopenharmony_ci	 * Inner shift makes sure multiplication doesn't overflow
5962306a36Sopenharmony_ci	 * for legitimate nsec values
6062306a36Sopenharmony_ci	 */
6162306a36Sopenharmony_ci	unsigned long cycles = (nsec * (ccount_freq >> 15)) >> 15;
6262306a36Sopenharmony_ci	__delay(cycles);
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#define ndelay(n) ndelay(n)
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic inline void ndelay(unsigned long nsec)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	if (__builtin_constant_p(nsec) && nsec >= __MAX_NDELAY)
7062306a36Sopenharmony_ci		__bad_ndelay();
7162306a36Sopenharmony_ci	else
7262306a36Sopenharmony_ci		__ndelay(nsec);
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci#endif
76