Skip to content

Commit 7741c37

Browse files
ringlejdavem330
authored andcommitted
regmap: Allow installing custom reg_update_bits function
This commit allows installing a custom reg_update_bits function for cases where the hardware provides a mechanism to set or clear register bits without a read/modify/write cycle. Such is the case with the Microchip ENCX24J600. Signed-off-by: Jon Ringle <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 937317c commit 7741c37

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

drivers/base/regmap/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ struct regmap {
9898

9999
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
100100
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
101+
int (*reg_update_bits)(void *context, unsigned int reg,
102+
unsigned int mask, unsigned int val,
103+
bool *change, bool force_write);
101104

102105
bool defer_caching;
103106

drivers/base/regmap/regmap.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,7 @@ struct regmap *__regmap_init(struct device *dev,
619619
goto skip_format_initialization;
620620
} else {
621621
map->reg_read = _regmap_bus_read;
622+
map->reg_update_bits = bus->reg_update_bits;
622623
}
623624

624625
reg_endian = regmap_get_reg_endian(bus, config);
@@ -2509,6 +2510,30 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
25092510
int ret;
25102511
unsigned int tmp, orig;
25112512

2513+
if (map->reg_update_bits) {
2514+
ret = map->reg_update_bits(map->bus_context, reg, mask, val,
2515+
change, force_write);
2516+
if (ret != 0)
2517+
return ret;
2518+
2519+
/* Fix up the cache by read/modify/write */
2520+
if (!map->cache_bypass && !map->defer_caching) {
2521+
ret = regcache_read(map, reg, &orig);
2522+
if (ret != 0)
2523+
return ret;
2524+
2525+
tmp = orig & ~mask;
2526+
tmp |= val & mask;
2527+
2528+
ret = regcache_write(map, reg, tmp);
2529+
if (ret != 0)
2530+
return ret;
2531+
if (map->cache_only)
2532+
map->cache_dirty = true;
2533+
}
2534+
return ret;
2535+
}
2536+
25122537
ret = _regmap_read(map, reg, &orig);
25132538
if (ret != 0)
25142539
return ret;

include/linux/regmap.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,9 @@ typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg,
296296
unsigned int *val);
297297
typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg,
298298
unsigned int val);
299+
typedef int (*regmap_hw_reg_update_bits)(void *context, unsigned int reg,
300+
unsigned int mask, unsigned int val,
301+
bool *change, bool force_write);
299302
typedef struct regmap_async *(*regmap_hw_async_alloc)(void);
300303
typedef void (*regmap_hw_free_context)(void *context);
301304

@@ -335,6 +338,7 @@ struct regmap_bus {
335338
regmap_hw_gather_write gather_write;
336339
regmap_hw_async_write async_write;
337340
regmap_hw_reg_write reg_write;
341+
regmap_hw_reg_update_bits reg_update_bits;
338342
regmap_hw_read read;
339343
regmap_hw_reg_read reg_read;
340344
regmap_hw_free_context free_context;

0 commit comments

Comments
 (0)