* Copyright (C) 1994 by Waldorf Electronics
* Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2007 Maciej W. Rozycki
*/
#ifndef _ASM_DELAY_H
#define _ASM_DELAY_H
-#include <linux/config.h>
#include <linux/param.h>
+#include <linux/smp.h>
#include <asm/compiler.h>
-
-extern unsigned long loops_per_jiffy;
+#include <asm/war.h>
static inline void __delay(unsigned long loops)
{
if (sizeof(long) == 4)
__asm__ __volatile__ (
- ".set\tnoreorder\n"
- "1:\tbnez\t%0,1b\n\t"
- "subu\t%0,1\n\t"
- ".set\treorder"
+ " .set noreorder \n"
+ " .align 3 \n"
+ "1: bnez %0, 1b \n"
+ " subu %0, 1 \n"
+ " .set reorder \n"
: "=r" (loops)
: "0" (loops));
- else if (sizeof(long) == 8)
+ else if (sizeof(long) == 8 && !DADDI_WAR)
__asm__ __volatile__ (
- ".set\tnoreorder\n"
- "1:\tbnez\t%0,1b\n\t"
- "dsubu\t%0,1\n\t"
- ".set\treorder"
- :"=r" (loops)
- :"0" (loops));
+ " .set noreorder \n"
+ " .align 3 \n"
+ "1: bnez %0, 1b \n"
+ " dsubu %0, 1 \n"
+ " .set reorder \n"
+ : "=r" (loops)
+ : "0" (loops));
+ else if (sizeof(long) == 8 && DADDI_WAR)
+ __asm__ __volatile__ (
+ " .set noreorder \n"
+ " .align 3 \n"
+ "1: bnez %0, 1b \n"
+ " dsubu %0, %2 \n"
+ " .set reorder \n"
+ : "=r" (loops)
+ : "0" (loops), "r" (1));
}
static inline void __udelay(unsigned long usecs, unsigned long lpj)
{
- unsigned long lo;
+ unsigned long hi, lo;
/*
- * The common rates of 1000 and 128 are rounded wrongly by the
- * catchall case for 64-bit. Excessive precission? Probably ...
+ * The rates of 128 is rounded wrongly by the catchall case
+ * for 64-bit. Excessive precission? Probably ...
*/
-#if defined(CONFIG_MIPS64) && (HZ == 128)
+#if defined(CONFIG_64BIT) && (HZ == 128)
usecs *= 0x0008637bd05af6c7UL; /* 2**64 / (1000000 / HZ) */
-#elif defined(CONFIG_MIPS64) && (HZ == 1000)
- usecs *= 0x004189374BC6A7f0UL; /* 2**64 / (1000000 / HZ) */
-#elif defined(CONFIG_MIPS64)
+#elif defined(CONFIG_64BIT)
usecs *= (0x8000000000000000UL / (500000 / HZ));
#else /* 32-bit junk follows here */
usecs *= (unsigned long) (((0x8000000000000000ULL / (500000 / HZ)) +
: "=h" (usecs), "=l" (lo)
: "r" (usecs), "r" (lpj)
: GCC_REG_ACCUM);
- else if (sizeof(long) == 8)
+ else if (sizeof(long) == 8 && !R4000_WAR)
__asm__("dmultu\t%2, %3"
: "=h" (usecs), "=l" (lo)
: "r" (usecs), "r" (lpj)
: GCC_REG_ACCUM);
+ else if (sizeof(long) == 8 && R4000_WAR)
+ __asm__("dmultu\t%3, %4\n\tmfhi\t%0"
+ : "=r" (usecs), "=h" (hi), "=l" (lo)
+ : "r" (usecs), "r" (lpj)
+ : GCC_REG_ACCUM);
__delay(usecs);
}
-#ifdef CONFIG_SMP
-#define __udelay_val cpu_data[smp_processor_id()].udelay_val
+#define __udelay_val cpu_data[raw_smp_processor_id()].udelay_val
+
+#define udelay(usecs) __udelay((usecs), __udelay_val)
+
+/* make sure "usecs *= ..." in udelay do not overflow. */
+#if HZ >= 1000
+#define MAX_UDELAY_MS 1
+#elif HZ <= 200
+#define MAX_UDELAY_MS 5
#else
-#define __udelay_val loops_per_jiffy
+#define MAX_UDELAY_MS (1000 / HZ)
#endif
-#define udelay(usecs) __udelay((usecs),__udelay_val)
-
#endif /* _ASM_DELAY_H */