1*384740dcSRalf Baechle /* 2*384740dcSRalf Baechle * This file is subject to the terms and conditions of the GNU General Public 3*384740dcSRalf Baechle * License. See the file "COPYING" in the main directory of this archive 4*384740dcSRalf Baechle * for more details. 5*384740dcSRalf Baechle * 6*384740dcSRalf Baechle * Copyright (C) 1994 by Waldorf Electronics 7*384740dcSRalf Baechle * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle 8*384740dcSRalf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 9*384740dcSRalf Baechle * Copyright (C) 2007 Maciej W. Rozycki 10*384740dcSRalf Baechle */ 11*384740dcSRalf Baechle #ifndef _ASM_DELAY_H 12*384740dcSRalf Baechle #define _ASM_DELAY_H 13*384740dcSRalf Baechle 14*384740dcSRalf Baechle #include <linux/param.h> 15*384740dcSRalf Baechle #include <linux/smp.h> 16*384740dcSRalf Baechle 17*384740dcSRalf Baechle #include <asm/compiler.h> 18*384740dcSRalf Baechle #include <asm/war.h> 19*384740dcSRalf Baechle 20*384740dcSRalf Baechle static inline void __delay(unsigned long loops) 21*384740dcSRalf Baechle { 22*384740dcSRalf Baechle if (sizeof(long) == 4) 23*384740dcSRalf Baechle __asm__ __volatile__ ( 24*384740dcSRalf Baechle " .set noreorder \n" 25*384740dcSRalf Baechle " .align 3 \n" 26*384740dcSRalf Baechle "1: bnez %0, 1b \n" 27*384740dcSRalf Baechle " subu %0, 1 \n" 28*384740dcSRalf Baechle " .set reorder \n" 29*384740dcSRalf Baechle : "=r" (loops) 30*384740dcSRalf Baechle : "0" (loops)); 31*384740dcSRalf Baechle else if (sizeof(long) == 8 && !DADDI_WAR) 32*384740dcSRalf Baechle __asm__ __volatile__ ( 33*384740dcSRalf Baechle " .set noreorder \n" 34*384740dcSRalf Baechle " .align 3 \n" 35*384740dcSRalf Baechle "1: bnez %0, 1b \n" 36*384740dcSRalf Baechle " dsubu %0, 1 \n" 37*384740dcSRalf Baechle " .set reorder \n" 38*384740dcSRalf Baechle : "=r" (loops) 39*384740dcSRalf Baechle : "0" (loops)); 40*384740dcSRalf Baechle else if (sizeof(long) == 8 && DADDI_WAR) 41*384740dcSRalf Baechle __asm__ __volatile__ ( 42*384740dcSRalf Baechle " .set noreorder \n" 43*384740dcSRalf Baechle " .align 3 \n" 44*384740dcSRalf Baechle "1: bnez %0, 1b \n" 45*384740dcSRalf Baechle " dsubu %0, %2 \n" 46*384740dcSRalf Baechle " .set reorder \n" 47*384740dcSRalf Baechle : "=r" (loops) 48*384740dcSRalf Baechle : "0" (loops), "r" (1)); 49*384740dcSRalf Baechle } 50*384740dcSRalf Baechle 51*384740dcSRalf Baechle 52*384740dcSRalf Baechle /* 53*384740dcSRalf Baechle * Division by multiplication: you don't have to worry about 54*384740dcSRalf Baechle * loss of precision. 55*384740dcSRalf Baechle * 56*384740dcSRalf Baechle * Use only for very small delays ( < 1 msec). Should probably use a 57*384740dcSRalf Baechle * lookup table, really, as the multiplications take much too long with 58*384740dcSRalf Baechle * short delays. This is a "reasonable" implementation, though (and the 59*384740dcSRalf Baechle * first constant multiplications gets optimized away if the delay is 60*384740dcSRalf Baechle * a constant) 61*384740dcSRalf Baechle */ 62*384740dcSRalf Baechle 63*384740dcSRalf Baechle static inline void __udelay(unsigned long usecs, unsigned long lpj) 64*384740dcSRalf Baechle { 65*384740dcSRalf Baechle unsigned long hi, lo; 66*384740dcSRalf Baechle 67*384740dcSRalf Baechle /* 68*384740dcSRalf Baechle * The rates of 128 is rounded wrongly by the catchall case 69*384740dcSRalf Baechle * for 64-bit. Excessive precission? Probably ... 70*384740dcSRalf Baechle */ 71*384740dcSRalf Baechle #if defined(CONFIG_64BIT) && (HZ == 128) 72*384740dcSRalf Baechle usecs *= 0x0008637bd05af6c7UL; /* 2**64 / (1000000 / HZ) */ 73*384740dcSRalf Baechle #elif defined(CONFIG_64BIT) 74*384740dcSRalf Baechle usecs *= (0x8000000000000000UL / (500000 / HZ)); 75*384740dcSRalf Baechle #else /* 32-bit junk follows here */ 76*384740dcSRalf Baechle usecs *= (unsigned long) (((0x8000000000000000ULL / (500000 / HZ)) + 77*384740dcSRalf Baechle 0x80000000ULL) >> 32); 78*384740dcSRalf Baechle #endif 79*384740dcSRalf Baechle 80*384740dcSRalf Baechle if (sizeof(long) == 4) 81*384740dcSRalf Baechle __asm__("multu\t%2, %3" 82*384740dcSRalf Baechle : "=h" (usecs), "=l" (lo) 83*384740dcSRalf Baechle : "r" (usecs), "r" (lpj) 84*384740dcSRalf Baechle : GCC_REG_ACCUM); 85*384740dcSRalf Baechle else if (sizeof(long) == 8 && !R4000_WAR) 86*384740dcSRalf Baechle __asm__("dmultu\t%2, %3" 87*384740dcSRalf Baechle : "=h" (usecs), "=l" (lo) 88*384740dcSRalf Baechle : "r" (usecs), "r" (lpj) 89*384740dcSRalf Baechle : GCC_REG_ACCUM); 90*384740dcSRalf Baechle else if (sizeof(long) == 8 && R4000_WAR) 91*384740dcSRalf Baechle __asm__("dmultu\t%3, %4\n\tmfhi\t%0" 92*384740dcSRalf Baechle : "=r" (usecs), "=h" (hi), "=l" (lo) 93*384740dcSRalf Baechle : "r" (usecs), "r" (lpj) 94*384740dcSRalf Baechle : GCC_REG_ACCUM); 95*384740dcSRalf Baechle 96*384740dcSRalf Baechle __delay(usecs); 97*384740dcSRalf Baechle } 98*384740dcSRalf Baechle 99*384740dcSRalf Baechle #define __udelay_val cpu_data[raw_smp_processor_id()].udelay_val 100*384740dcSRalf Baechle 101*384740dcSRalf Baechle #define udelay(usecs) __udelay((usecs), __udelay_val) 102*384740dcSRalf Baechle 103*384740dcSRalf Baechle /* make sure "usecs *= ..." in udelay do not overflow. */ 104*384740dcSRalf Baechle #if HZ >= 1000 105*384740dcSRalf Baechle #define MAX_UDELAY_MS 1 106*384740dcSRalf Baechle #elif HZ <= 200 107*384740dcSRalf Baechle #define MAX_UDELAY_MS 5 108*384740dcSRalf Baechle #else 109*384740dcSRalf Baechle #define MAX_UDELAY_MS (1000 / HZ) 110*384740dcSRalf Baechle #endif 111*384740dcSRalf Baechle 112*384740dcSRalf Baechle #endif /* _ASM_DELAY_H */ 113