Unverified Commit 3c1ff93b authored by Guenter Roeck's avatar Guenter Roeck Committed by Mark Brown
Browse files

regmap: Implement regmap_multi_reg_read()



regmap_multi_reg_read() is similar to regmap_bilk_read() but reads from
an array of non-sequential registers.

Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/r/20240710015622.1960522-2-linux@roeck-us.net


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent f2661062
Loading
Loading
Loading
Loading
+68 −35
Original line number Diff line number Diff line
@@ -3101,48 +3101,28 @@ int regmap_fields_read(struct regmap_field *field, unsigned int id,
}
EXPORT_SYMBOL_GPL(regmap_fields_read);

/**
 * regmap_bulk_read() - Read multiple registers from the device
 *
 * @map: Register map to read from
 * @reg: First register to be read from
 * @val: Pointer to store read value, in native register size for device
 * @val_count: Number of registers to read
 *
 * A value of zero will be returned on success, a negative errno will
 * be returned in error cases.
 */
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
		     size_t val_count)
static int _regmap_bulk_read(struct regmap *map, unsigned int reg,
			     unsigned int *regs, void *val, size_t val_count)
{
	int ret, i;
	size_t val_bytes = map->format.val_bytes;
	bool vol = regmap_volatile_range(map, reg, val_count);

	if (!IS_ALIGNED(reg, map->reg_stride))
		return -EINVAL;
	if (val_count == 0)
		return -EINVAL;

	if (map->read && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
		ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
		if (ret != 0)
			return ret;

		for (i = 0; i < val_count * val_bytes; i += val_bytes)
			map->format.parse_inplace(val + i);
	} else {
	u32 *u32 = val;
	u16 *u16 = val;
	u8 *u8 = val;
	int ret, i;

	map->lock(map->lock_arg);

	for (i = 0; i < val_count; i++) {
		unsigned int ival;

			ret = _regmap_read(map, reg + regmap_get_offset(map, i),
					   &ival);
		if (regs) {
			if (!IS_ALIGNED(regs[i], map->reg_stride)) {
				ret = -EINVAL;
				goto out;
			}
			ret = _regmap_read(map, regs[i], &ival);
		} else {
			ret = _regmap_read(map, reg + regmap_get_offset(map, i), &ival);
		}
		if (ret != 0)
			goto out;

@@ -3161,18 +3141,71 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
			goto out;
		}
	}

out:
	map->unlock(map->lock_arg);
	return ret;
}

/**
 * regmap_bulk_read() - Read multiple sequential registers from the device
 *
 * @map: Register map to read from
 * @reg: First register to be read from
 * @val: Pointer to store read value, in native register size for device
 * @val_count: Number of registers to read
 *
 * A value of zero will be returned on success, a negative errno will
 * be returned in error cases.
 */
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
		     size_t val_count)
{
	int ret, i;
	size_t val_bytes = map->format.val_bytes;
	bool vol = regmap_volatile_range(map, reg, val_count);

	if (!IS_ALIGNED(reg, map->reg_stride))
		return -EINVAL;
	if (val_count == 0)
		return -EINVAL;

	if (map->read && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
		ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
		if (ret != 0)
			return ret;

		for (i = 0; i < val_count * val_bytes; i += val_bytes)
			map->format.parse_inplace(val + i);
	} else {
		ret = _regmap_bulk_read(map, reg, NULL, val, val_count);
	}
	if (!ret)
		trace_regmap_bulk_read(map, reg, val, val_bytes * val_count);

	return ret;
}
EXPORT_SYMBOL_GPL(regmap_bulk_read);

/**
 * regmap_multi_reg_read() - Read multiple non-sequential registers from the device
 *
 * @map: Register map to read from
 * @regs: Array of registers to read from
 * @val: Pointer to store read value, in native register size for device
 * @val_count: Number of registers to read
 *
 * A value of zero will be returned on success, a negative errno will
 * be returned in error cases.
 */
int regmap_multi_reg_read(struct regmap *map, unsigned int *regs, void *val,
			  size_t val_count)
{
	if (val_count == 0)
		return -EINVAL;

	return _regmap_bulk_read(map, 0, regs, val, val_count);
}
EXPORT_SYMBOL_GPL(regmap_multi_reg_read);

static int _regmap_update_bits(struct regmap *map, unsigned int reg,
			       unsigned int mask, unsigned int val,
			       bool *change, bool force_write)
+2 −0
Original line number Diff line number Diff line
@@ -1237,6 +1237,8 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
		      void *val, size_t val_len);
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
		     size_t val_count);
int regmap_multi_reg_read(struct regmap *map, unsigned int *reg, void *val,
			  size_t val_count);
int regmap_update_bits_base(struct regmap *map, unsigned int reg,
			    unsigned int mask, unsigned int val,
			    bool *change, bool async, bool force);