Merge branch 'fix/misc' into for-linus
[pandora-kernel.git] / arch / powerpc / include / asm / delay.h
index f9200a6..52e4d54 100644 (file)
@@ -2,8 +2,11 @@
 #define _ASM_POWERPC_DELAY_H
 #ifdef __KERNEL__
 
+#include <asm/time.h>
+
 /*
  * Copyright 1996, Paul Mackerras.
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -30,5 +33,40 @@ extern void udelay(unsigned long usecs);
 #define mdelay(n)      udelay((n) * 1000)
 #endif
 
+/**
+ * spin_event_timeout - spin until a condition gets true or a timeout elapses
+ * @condition: a C expression to evalate
+ * @timeout: timeout, in microseconds
+ * @delay: the number of microseconds to delay between each evaluation of
+ *         @condition
+ *
+ * The process spins until the condition evaluates to true (non-zero) or the
+ * timeout elapses.  The return value of this macro is the value of
+ * @condition when the loop terminates. This allows you to determine the cause
+ * of the loop terminates.  If the return value is zero, then you know a
+ * timeout has occurred.
+ *
+ * This primary purpose of this macro is to poll on a hardware register
+ * until a status bit changes.  The timeout ensures that the loop still
+ * terminates even if the bit never changes.  The delay is for devices that
+ * need a delay in between successive reads.
+ *
+ * gcc will optimize out the if-statement if @delay is a constant.
+ */
+#define spin_event_timeout(condition, timeout, delay)                          \
+({                                                                             \
+       typeof(condition) __ret;                                               \
+       unsigned long __loops = tb_ticks_per_usec * timeout;                   \
+       unsigned long __start = get_tbl();                                     \
+       while (!(__ret = (condition)) && (tb_ticks_since(__start) <= __loops)) \
+               if (delay)                                                     \
+                       udelay(delay);                                         \
+               else                                                           \
+                       cpu_relax();                                           \
+       if (!__ret)                                                            \
+               __ret = (condition);                                           \
+       __ret;                                                                 \
+})
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_DELAY_H */