blob: 0ee2bddaa83369ec681f8fd2c92ca7e7cb69f111 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0 */
Masahiro Yamada6569c0d2016-12-28 00:36:03 +09002/*
3 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
Masahiro Yamada6569c0d2016-12-28 00:36:03 +09004 */
5
6#ifndef _LINUX_IOPOLL_H
7#define _LINUX_IOPOLL_H
8
Jagan Tekic094e212020-05-02 12:45:02 +05309#include <linux/delay.h>
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090010#include <linux/errno.h>
11#include <linux/io.h>
12#include <time.h>
13
14/**
Jagan Teki54232472020-05-02 12:45:01 +053015 * read_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090016 * @op: accessor function (takes @addr as its only argument)
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090017 * @val: Variable to read the value into
18 * @cond: Break condition (usually involving @val)
Jagan Tekic094e212020-05-02 12:45:02 +053019 * @sleep_us: Maximum time to sleep in us
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090020 * @timeout_us: Timeout in us, 0 means never timeout
Ariel D'Alessandrod7db0e62022-04-12 10:31:35 -030021 * @args: arguments for @op poll
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090022 *
23 * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
24 * case, the last read value at @addr is stored in @val.
25 *
26 * When available, you'll probably want to use one of the specialized
27 * macros defined below rather than this macro directly.
28 */
Ariel D'Alessandrod7db0e62022-04-12 10:31:35 -030029#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, args...) \
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090030({ \
31 unsigned long timeout = timer_get_us() + timeout_us; \
32 for (;;) { \
Ariel D'Alessandrod7db0e62022-04-12 10:31:35 -030033 (val) = op(args); \
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090034 if (cond) \
35 break; \
36 if (timeout_us && time_after(timer_get_us(), timeout)) { \
Ariel D'Alessandrod7db0e62022-04-12 10:31:35 -030037 (val) = op(args); \
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090038 break; \
39 } \
Jagan Tekic094e212020-05-02 12:45:02 +053040 if (sleep_us) \
41 udelay(sleep_us); \
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090042 } \
43 (cond) ? 0 : -ETIMEDOUT; \
44})
45
Jagan Tekice786ae2020-05-02 12:45:03 +053046#define readx_poll_sleep_timeout(op, addr, val, cond, sleep_us, timeout_us) \
Ariel D'Alessandrod7db0e62022-04-12 10:31:35 -030047 read_poll_timeout(op, val, cond, sleep_us, timeout_us, addr)
Jagan Tekice786ae2020-05-02 12:45:03 +053048
49#define readl_poll_sleep_timeout(addr, val, cond, sleep_us, timeout_us) \
50 readx_poll_sleep_timeout(readl, addr, val, cond, sleep_us, timeout_us)
51
Jagan Teki54232472020-05-02 12:45:01 +053052#define readx_poll_timeout(op, addr, val, cond, timeout_us) \
Ariel D'Alessandrod7db0e62022-04-12 10:31:35 -030053 read_poll_timeout(op, val, cond, false, timeout_us, addr)
Masahiro Yamada6569c0d2016-12-28 00:36:03 +090054
55#define readb_poll_timeout(addr, val, cond, timeout_us) \
56 readx_poll_timeout(readb, addr, val, cond, timeout_us)
57
58#define readw_poll_timeout(addr, val, cond, timeout_us) \
59 readx_poll_timeout(readw, addr, val, cond, timeout_us)
60
61#define readl_poll_timeout(addr, val, cond, timeout_us) \
62 readx_poll_timeout(readl, addr, val, cond, timeout_us)
63
64#define readq_poll_timeout(addr, val, cond, timeout_us) \
65 readx_poll_timeout(readq, addr, val, cond, timeout_us)
66
67#define readb_relaxed_poll_timeout(addr, val, cond, timeout_us) \
68 readx_poll_timeout(readb_relaxed, addr, val, cond, timeout_us)
69
70#define readw_relaxed_poll_timeout(addr, val, cond, timeout_us) \
71 readx_poll_timeout(readw_relaxed, addr, val, cond, timeout_us)
72
73#define readl_relaxed_poll_timeout(addr, val, cond, timeout_us) \
74 readx_poll_timeout(readl_relaxed, addr, val, cond, timeout_us)
75
76#define readq_relaxed_poll_timeout(addr, val, cond, timeout_us) \
77 readx_poll_timeout(readq_relaxed, addr, val, cond, timeout_us)
78
79#endif /* _LINUX_IOPOLL_H */