13070Spst/* SPDX-License-Identifier: GPL-2.0-or-later */
23070Spst#ifndef _ASM_POWERPC_DELAY_H
33070Spst#define _ASM_POWERPC_DELAY_H
43070Spst#ifdef __KERNEL__
53070Spst
63070Spst#include <linux/processor.h>
73070Spst#include <asm/time.h>
83070Spst
93070Spst/*
103070Spst * Copyright 1996, Paul Mackerras.
113070Spst * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
123070Spst *
133070Spst * PPC64 Support added by Dave Engebretsen, Todd Inglett, Mike Corrigan,
143070Spst * Anton Blanchard.
153070Spst */
163070Spst
173070Spstextern void __delay(unsigned long loops);
183070Spstextern void udelay(unsigned long usecs);
193070Spst
203070Spst/*
213070Spst * On shared processor machines the generic implementation of mdelay can
223070Spst * result in large errors. While each iteration of the loop inside mdelay
233070Spst * is supposed to take 1ms, the hypervisor could sleep our partition for
243070Spst * longer (eg 10ms). With the right timing these errors can add up.
253070Spst *
263070Spst * Since there is no 32bit overflow issue on 64bit kernels, just call
273070Spst * udelay directly.
283070Spst */
293070Spst#ifdef CONFIG_PPC64
308870Srgrimes#define mdelay(n)	udelay((n) * 1000)
313070Spst#endif
323070Spst
333070Spst/**
343070Spst * spin_event_timeout - spin until a condition gets true or a timeout elapses
353070Spst * @condition: a C expression to evalate
363070Spst * @timeout: timeout, in microseconds
378870Srgrimes * @delay: the number of microseconds to delay between each evaluation of
383070Spst *         @condition
393070Spst *
403070Spst * The process spins until the condition evaluates to true (non-zero) or the
413070Spst * timeout elapses.  The return value of this macro is the value of
423070Spst * @condition when the loop terminates. This allows you to determine the cause
433070Spst * of the loop terminates.  If the return value is zero, then you know a
443070Spst * timeout has occurred.
453070Spst *
463070Spst * This primary purpose of this macro is to poll on a hardware register
473070Spst * until a status bit changes.  The timeout ensures that the loop still
483070Spst * terminates even if the bit never changes.  The delay is for devices that
4913408Speter * need a delay in between successive reads.
5013408Speter *
5113408Speter * gcc will optimize out the if-statement if @delay is a constant.
5213408Speter */
5313408Speter#define spin_event_timeout(condition, timeout, delay)                          \
5413408Speter({                                                                             \
5513408Speter	typeof(condition) __ret;                                               \
563070Spst	unsigned long __loops = tb_ticks_per_usec * timeout;                   \
573070Spst	unsigned long __start = mftb();                                     \
583070Spst                                                                               \
593070Spst	if (delay) {                                                           \
6092986Sobrien		while (!(__ret = (condition)) &&                               \
6192986Sobrien				(tb_ticks_since(__start) <= __loops))          \
623070Spst			udelay(delay);                                         \
633070Spst	} else {                                                               \
643070Spst		spin_begin();                                                  \
653070Spst		while (!(__ret = (condition)) &&                               \
663070Spst				(tb_ticks_since(__start) <= __loops))          \
673070Spst			spin_cpu_relax();                                      \
6813408Speter		spin_end();                                                    \
69125555Sdds	}                                                                      \
7013408Speter	if (!__ret)                                                            \
71104415Sume		__ret = (condition);                                           \
723070Spst	__ret;		                                                       \
733070Spst})
743070Spst
753070Spst#endif /* __KERNEL__ */
7613408Speter#endif /* _ASM_POWERPC_DELAY_H */
773070Spst