Commit e83a0ed2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -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);
}

static struct regmap_bus regmap_smbus_byte = {
static const struct regmap_bus regmap_smbus_byte = {
	.reg_write = regmap_smbus_byte_reg_write,
	.reg_read = regmap_smbus_byte_reg_read,
};
@@ -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);
}

static struct regmap_bus regmap_smbus_word = {
static const struct regmap_bus regmap_smbus_word = {
	.reg_write = regmap_smbus_word_reg_write,
	.reg_read = regmap_smbus_word_reg_read,
};
@@ -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);
}

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_read = regmap_smbus_word_read_swapped,
};
@@ -197,7 +197,7 @@ static int regmap_i2c_read(void *context,
		return -EIO;
}

static struct regmap_bus regmap_i2c = {
static const struct regmap_bus regmap_i2c = {
	.write = regmap_i2c_write,
	.gather_write = regmap_i2c_gather_write,
	.read = regmap_i2c_read,
@@ -239,7 +239,7 @@ static int regmap_i2c_smbus_i2c_read(void *context, const void *reg,
		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,
	.read = regmap_i2c_smbus_i2c_read,
	.max_raw_read = I2C_SMBUS_BLOCK_MAX,
+12 −5
Original line number Diff line number Diff line
@@ -1488,11 +1488,18 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,

	WARN_ON(!map->bus);

	/* Check for unwritable registers before we start */
	for (i = 0; i < val_len / map->format.val_bytes; i++)
		if (!regmap_writeable(map,
				     reg + regmap_get_offset(map, i)))
	/* Check for unwritable or noinc registers in range
	 * before we start
	 */
	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;
		}
	}

	if (!map->cache_bypass && map->format.parse_val) {
		unsigned int ival;
+45 −0
Original line number Diff line number Diff line
@@ -144,6 +144,51 @@ struct reg_sequence {
	__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
 *