Skip to content

Commit 3c1ff93

Browse files
groeckbroonie
authored andcommitted
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: Guenter Roeck <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent f266106 commit 3c1ff93

File tree

2 files changed

+70
-35
lines changed

2 files changed

+70
-35
lines changed

drivers/base/regmap/regmap.c

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3101,8 +3101,53 @@ int regmap_fields_read(struct regmap_field *field, unsigned int id,
31013101
}
31023102
EXPORT_SYMBOL_GPL(regmap_fields_read);
31033103

3104+
static int _regmap_bulk_read(struct regmap *map, unsigned int reg,
3105+
unsigned int *regs, void *val, size_t val_count)
3106+
{
3107+
u32 *u32 = val;
3108+
u16 *u16 = val;
3109+
u8 *u8 = val;
3110+
int ret, i;
3111+
3112+
map->lock(map->lock_arg);
3113+
3114+
for (i = 0; i < val_count; i++) {
3115+
unsigned int ival;
3116+
3117+
if (regs) {
3118+
if (!IS_ALIGNED(regs[i], map->reg_stride)) {
3119+
ret = -EINVAL;
3120+
goto out;
3121+
}
3122+
ret = _regmap_read(map, regs[i], &ival);
3123+
} else {
3124+
ret = _regmap_read(map, reg + regmap_get_offset(map, i), &ival);
3125+
}
3126+
if (ret != 0)
3127+
goto out;
3128+
3129+
switch (map->format.val_bytes) {
3130+
case 4:
3131+
u32[i] = ival;
3132+
break;
3133+
case 2:
3134+
u16[i] = ival;
3135+
break;
3136+
case 1:
3137+
u8[i] = ival;
3138+
break;
3139+
default:
3140+
ret = -EINVAL;
3141+
goto out;
3142+
}
3143+
}
3144+
out:
3145+
map->unlock(map->lock_arg);
3146+
return ret;
3147+
}
3148+
31043149
/**
3105-
* regmap_bulk_read() - Read multiple registers from the device
3150+
* regmap_bulk_read() - Read multiple sequential registers from the device
31063151
*
31073152
* @map: Register map to read from
31083153
* @reg: First register to be read from
@@ -3132,47 +3177,35 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
31323177
for (i = 0; i < val_count * val_bytes; i += val_bytes)
31333178
map->format.parse_inplace(val + i);
31343179
} else {
3135-
u32 *u32 = val;
3136-
u16 *u16 = val;
3137-
u8 *u8 = val;
3138-
3139-
map->lock(map->lock_arg);
3140-
3141-
for (i = 0; i < val_count; i++) {
3142-
unsigned int ival;
3143-
3144-
ret = _regmap_read(map, reg + regmap_get_offset(map, i),
3145-
&ival);
3146-
if (ret != 0)
3147-
goto out;
3148-
3149-
switch (map->format.val_bytes) {
3150-
case 4:
3151-
u32[i] = ival;
3152-
break;
3153-
case 2:
3154-
u16[i] = ival;
3155-
break;
3156-
case 1:
3157-
u8[i] = ival;
3158-
break;
3159-
default:
3160-
ret = -EINVAL;
3161-
goto out;
3162-
}
3163-
}
3164-
3165-
out:
3166-
map->unlock(map->lock_arg);
3180+
ret = _regmap_bulk_read(map, reg, NULL, val, val_count);
31673181
}
3168-
31693182
if (!ret)
31703183
trace_regmap_bulk_read(map, reg, val, val_bytes * val_count);
3171-
31723184
return ret;
31733185
}
31743186
EXPORT_SYMBOL_GPL(regmap_bulk_read);
31753187

3188+
/**
3189+
* regmap_multi_reg_read() - Read multiple non-sequential registers from the device
3190+
*
3191+
* @map: Register map to read from
3192+
* @regs: Array of registers to read from
3193+
* @val: Pointer to store read value, in native register size for device
3194+
* @val_count: Number of registers to read
3195+
*
3196+
* A value of zero will be returned on success, a negative errno will
3197+
* be returned in error cases.
3198+
*/
3199+
int regmap_multi_reg_read(struct regmap *map, unsigned int *regs, void *val,
3200+
size_t val_count)
3201+
{
3202+
if (val_count == 0)
3203+
return -EINVAL;
3204+
3205+
return _regmap_bulk_read(map, 0, regs, val, val_count);
3206+
}
3207+
EXPORT_SYMBOL_GPL(regmap_multi_reg_read);
3208+
31763209
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
31773210
unsigned int mask, unsigned int val,
31783211
bool *change, bool force_write)

include/linux/regmap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,8 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
12371237
void *val, size_t val_len);
12381238
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
12391239
size_t val_count);
1240+
int regmap_multi_reg_read(struct regmap *map, unsigned int *reg, void *val,
1241+
size_t val_count);
12401242
int regmap_update_bits_base(struct regmap *map, unsigned int reg,
12411243
unsigned int mask, unsigned int val,
12421244
bool *change, bool async, bool force);

0 commit comments

Comments
 (0)