1/*
2 * @TAG(OTHER_GPL)
3 */
4/* SPDX-License-Identifier: GPL-2.0+ */
5/*
6 * Wait for bit with timeout and ctrlc
7 *
8 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
9 */
10
11#pragma once
12
13#include "../unimplemented.h"
14#include "../io.h"
15#include "tx2_configs.h"
16
17#define ETIMEDOUT       110
18
19/**
20 * wait_for_bit_x() waits for bit set/cleared in register
21 *
22 * Function polls register waiting for specific bit(s) change
23 * (either 0->1 or 1->0). It can fail under two conditions:
24 * - Timeout
25 * - User interaction (CTRL-C)
26 * Function succeeds only if all bits of masked register are set/cleared
27 * (depending on set option).
28 *
29 * @param reg       Register that will be read (using read_x())
30 * @param mask      Bit(s) of register that must be active
31 * @param set       Selects wait condition (bit set or clear)
32 * @param timeout_ms    Timeout (in milliseconds)
33 * @param breakable Enables CTRL-C interruption
34 * @return      0 on success, -ETIMEDOUT or -EINTR on failure
35 */
36
37#define BUILD_WAIT_FOR_BIT(sfx, type, read)             \
38                                    \
39static inline int wait_for_bit_##sfx(const void *reg,           \
40                     const type mask,           \
41                     const bool set,            \
42                     const unsigned int timeout_ms, \
43                     const bool breakable)      \
44{                                   \
45    type val;                           \
46    volatile unsigned long count = 0; \
47                                    \
48    while (count != timeout_ms) {                           \
49        val = *((type *)reg);                   \
50                                    \
51        if (!set)                       \
52            val = ~val;                 \
53                                    \
54        if ((val & mask) == mask)               \
55            return 0;                   \
56        \
57                                    \
58        udelay(1000);                       \
59        count++; \
60    }                               \
61                                    \
62                                    \
63    return -ETIMEDOUT;                      \
64}
65
66BUILD_WAIT_FOR_BIT(8, u8, readb)
67BUILD_WAIT_FOR_BIT(le16, u16, readw)
68#ifdef readw_be
69BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
70#endif
71BUILD_WAIT_FOR_BIT(le32, u32, readl)
72#ifdef readl_be
73BUILD_WAIT_FOR_BIT(be32, u32, readl_be)
74#endif
75