Commit e83a0ed2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'regmap-v5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap

Pull regmap updates from Mark Brown:
 "This is quite a busy release for a subsystem that's usually very
  quiet, though still a small set of updates in the grand scheme of
  things:

   - A fix for writes to non-incrementing registers.

   - An iopoll() style helper for use with atomic safe regmaps, making
     it easier to transition from raw memory mapped I/O.

   - Some constification"

* tag 'regmap-v5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
  regmap: fix writes to non incrementing registers
  regmap: add iopoll-like atomic polling macro
  regmap-i2c: constify regmap_bus structures
parents a5b871c9 ea876839
...@@ -43,7 +43,7 @@ static int regmap_smbus_byte_reg_write(void *context, unsigned int reg, ...@@ -43,7 +43,7 @@ static int regmap_smbus_byte_reg_write(void *context, unsigned int reg,
return i2c_smbus_write_byte_data(i2c, reg, val); return i2c_smbus_write_byte_data(i2c, reg, val);
} }
static struct regmap_bus regmap_smbus_byte = { static const struct regmap_bus regmap_smbus_byte = {
.reg_write = regmap_smbus_byte_reg_write, .reg_write = regmap_smbus_byte_reg_write,
.reg_read = regmap_smbus_byte_reg_read, .reg_read = regmap_smbus_byte_reg_read,
}; };
...@@ -79,7 +79,7 @@ static int regmap_smbus_word_reg_write(void *context, unsigned int reg, ...@@ -79,7 +79,7 @@ static int regmap_smbus_word_reg_write(void *context, unsigned int reg,
return i2c_smbus_write_word_data(i2c, reg, val); return i2c_smbus_write_word_data(i2c, reg, val);
} }
static struct regmap_bus regmap_smbus_word = { static const struct regmap_bus regmap_smbus_word = {
.reg_write = regmap_smbus_word_reg_write, .reg_write = regmap_smbus_word_reg_write,
.reg_read = regmap_smbus_word_reg_read, .reg_read = regmap_smbus_word_reg_read,
}; };
...@@ -115,7 +115,7 @@ static int regmap_smbus_word_write_swapped(void *context, unsigned int reg, ...@@ -115,7 +115,7 @@ static int regmap_smbus_word_write_swapped(void *context, unsigned int reg,
return i2c_smbus_write_word_swapped(i2c, reg, val); return i2c_smbus_write_word_swapped(i2c, reg, val);
} }
static struct regmap_bus regmap_smbus_word_swapped = { static const struct regmap_bus regmap_smbus_word_swapped = {
.reg_write = regmap_smbus_word_write_swapped, .reg_write = regmap_smbus_word_write_swapped,
.reg_read = regmap_smbus_word_read_swapped, .reg_read = regmap_smbus_word_read_swapped,
}; };
...@@ -197,7 +197,7 @@ static int regmap_i2c_read(void *context, ...@@ -197,7 +197,7 @@ static int regmap_i2c_read(void *context,
return -EIO; return -EIO;
} }
static struct regmap_bus regmap_i2c = { static const struct regmap_bus regmap_i2c = {
.write = regmap_i2c_write, .write = regmap_i2c_write,
.gather_write = regmap_i2c_gather_write, .gather_write = regmap_i2c_gather_write,
.read = regmap_i2c_read, .read = regmap_i2c_read,
...@@ -239,7 +239,7 @@ static int regmap_i2c_smbus_i2c_read(void *context, const void *reg, ...@@ -239,7 +239,7 @@ static int regmap_i2c_smbus_i2c_read(void *context, const void *reg,
return -EIO; return -EIO;
} }
static struct regmap_bus regmap_i2c_smbus_i2c_block = { static const struct regmap_bus regmap_i2c_smbus_i2c_block = {
.write = regmap_i2c_smbus_i2c_write, .write = regmap_i2c_smbus_i2c_write,
.read = regmap_i2c_smbus_i2c_read, .read = regmap_i2c_smbus_i2c_read,
.max_raw_read = I2C_SMBUS_BLOCK_MAX, .max_raw_read = I2C_SMBUS_BLOCK_MAX,
......
...@@ -1488,11 +1488,18 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, ...@@ -1488,11 +1488,18 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
WARN_ON(!map->bus); WARN_ON(!map->bus);
/* Check for unwritable registers before we start */ /* Check for unwritable or noinc registers in range
for (i = 0; i < val_len / map->format.val_bytes; i++) * before we start
if (!regmap_writeable(map, */
reg + regmap_get_offset(map, i))) if (!regmap_writeable_noinc(map, reg)) {
for (i = 0; i < val_len / map->format.val_bytes; i++) {
unsigned int element =
reg + regmap_get_offset(map, i);
if (!regmap_writeable(map, element) ||
regmap_writeable_noinc(map, element))
return -EINVAL; return -EINVAL;
}
}
if (!map->cache_bypass && map->format.parse_val) { if (!map->cache_bypass && map->format.parse_val) {
unsigned int ival; unsigned int ival;
......
...@@ -144,6 +144,51 @@ struct reg_sequence { ...@@ -144,6 +144,51 @@ struct reg_sequence {
__ret ?: ((cond) ? 0 : -ETIMEDOUT); \ __ret ?: ((cond) ? 0 : -ETIMEDOUT); \
}) })
/**
* 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 * regmap_field_read_poll_timeout - Poll until a condition is met or timeout
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment