diff options
Diffstat (limited to 'include/linux/regmap.h')
-rw-r--r-- | include/linux/regmap.h | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index dfe493ac692d..f0a092a1a96d 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -145,6 +145,51 @@ struct reg_sequence { }) /** + * regmap_read_poll_timeout_atomic - Poll until a condition is met or a timeout occurs + * + * @map: Regmap to read from + * @addr: Address to poll + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @delay_us: Time to udelay between reads in us (0 tight-loops). + * Should be less than ~10us since udelay is used + * (see Documentation/timers/timers-howto.rst). + * @timeout_us: Timeout in us, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. + * + * This is modelled after the readx_poll_timeout_atomic macros in linux/iopoll.h. + * + * Note: In general regmap cannot be used in atomic context. If you want to use + * this macro then first setup your regmap for atomic use (flat or no cache + * and MMIO regmap). + */ +#define regmap_read_poll_timeout_atomic(map, addr, val, cond, delay_us, timeout_us) \ +({ \ + u64 __timeout_us = (timeout_us); \ + unsigned long __delay_us = (delay_us); \ + ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ + int __ret; \ + for (;;) { \ + __ret = regmap_read((map), (addr), &(val)); \ + if (__ret) \ + break; \ + if (cond) \ + break; \ + if ((__timeout_us) && \ + ktime_compare(ktime_get(), __timeout) > 0) { \ + __ret = regmap_read((map), (addr), &(val)); \ + break; \ + } \ + if (__delay_us) \ + udelay(__delay_us); \ + } \ + __ret ?: ((cond) ? 0 : -ETIMEDOUT); \ +}) + +/** * regmap_field_read_poll_timeout - Poll until a condition is met or timeout * * @field: Regmap field to read from |