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

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.netSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent f2661062
......@@ -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)
......
......@@ -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);
......
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