Skip to content

Commit 6725228

Browse files
Srinivas-Kandagatlabroonie
authored andcommitted
regmap: Add regmap_field APIs
It is common to access regmap registers at bit level, using regmap_update_bits or regmap_read functions, however the end user has to take care of a mask or shifting. This becomes overhead when such use cases are high. Having a common function to do this is much convenient and less error prone. The idea of regmap_field is simple, regmap_field gives a logical structure to bits of the regmap register, and the driver can use this logical entity without the knowledge of the bit positions and masks all over the code. This way code looks much neat and it need not handle the masks, shifts every time it access the those entities. With this new regmap_field_read/write apis the end user can setup a regmap field using regmap_field_init and use the return regmap_field to read write the register field without worrying about the masks or shifts. Also this apis will be useful for drivers which are based on regmaps, like some clocks or pinctrls which can work on the regmap_fields directly without having to worry about bit positions. Signed-off-by: Srinivas Kandagatla <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 317ddd2 commit 6725228

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed

drivers/base/regmap/internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,14 @@ struct regmap_range_node {
174174
unsigned int window_len;
175175
};
176176

177+
struct regmap_field {
178+
struct regmap *regmap;
179+
unsigned int mask;
180+
/* lsb */
181+
unsigned int shift;
182+
unsigned int reg;
183+
};
184+
177185
#ifdef CONFIG_DEBUG_FS
178186
extern void regmap_debugfs_initcall(void);
179187
extern void regmap_debugfs_init(struct regmap *map, const char *name);

drivers/base/regmap/regmap.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,95 @@ struct regmap *devm_regmap_init(struct device *dev,
801801
}
802802
EXPORT_SYMBOL_GPL(devm_regmap_init);
803803

804+
static void regmap_field_init(struct regmap_field *rm_field,
805+
struct regmap *regmap, struct reg_field reg_field)
806+
{
807+
int field_bits = reg_field.msb - reg_field.lsb + 1;
808+
rm_field->regmap = regmap;
809+
rm_field->reg = reg_field.reg;
810+
rm_field->shift = reg_field.lsb;
811+
rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb);
812+
}
813+
814+
/**
815+
* devm_regmap_field_alloc(): Allocate and initialise a register field
816+
* in a register map.
817+
*
818+
* @dev: Device that will be interacted with
819+
* @regmap: regmap bank in which this register field is located.
820+
* @reg_field: Register field with in the bank.
821+
*
822+
* The return value will be an ERR_PTR() on error or a valid pointer
823+
* to a struct regmap_field. The regmap_field will be automatically freed
824+
* by the device management code.
825+
*/
826+
struct regmap_field *devm_regmap_field_alloc(struct device *dev,
827+
struct regmap *regmap, struct reg_field reg_field)
828+
{
829+
struct regmap_field *rm_field = devm_kzalloc(dev,
830+
sizeof(*rm_field), GFP_KERNEL);
831+
if (!rm_field)
832+
return ERR_PTR(-ENOMEM);
833+
834+
regmap_field_init(rm_field, regmap, reg_field);
835+
836+
return rm_field;
837+
838+
}
839+
EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
840+
841+
/**
842+
* devm_regmap_field_free(): Free register field allocated using
843+
* devm_regmap_field_alloc. Usally drivers need not call this function,
844+
* as the memory allocated via devm will be freed as per device-driver
845+
* life-cyle.
846+
*
847+
* @dev: Device that will be interacted with
848+
* @field: regmap field which should be freed.
849+
*/
850+
void devm_regmap_field_free(struct device *dev,
851+
struct regmap_field *field)
852+
{
853+
devm_kfree(dev, field);
854+
}
855+
EXPORT_SYMBOL_GPL(devm_regmap_field_free);
856+
857+
/**
858+
* regmap_field_alloc(): Allocate and initialise a register field
859+
* in a register map.
860+
*
861+
* @regmap: regmap bank in which this register field is located.
862+
* @reg_field: Register field with in the bank.
863+
*
864+
* The return value will be an ERR_PTR() on error or a valid pointer
865+
* to a struct regmap_field. The regmap_field should be freed by the
866+
* user once its finished working with it using regmap_field_free().
867+
*/
868+
struct regmap_field *regmap_field_alloc(struct regmap *regmap,
869+
struct reg_field reg_field)
870+
{
871+
struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
872+
873+
if (!rm_field)
874+
return ERR_PTR(-ENOMEM);
875+
876+
regmap_field_init(rm_field, regmap, reg_field);
877+
878+
return rm_field;
879+
}
880+
EXPORT_SYMBOL_GPL(regmap_field_alloc);
881+
882+
/**
883+
* regmap_field_free(): Free register field allocated using regmap_field_alloc
884+
*
885+
* @field: regmap field which should be freed.
886+
*/
887+
void regmap_field_free(struct regmap_field *field)
888+
{
889+
kfree(field);
890+
}
891+
EXPORT_SYMBOL_GPL(regmap_field_free);
892+
804893
/**
805894
* regmap_reinit_cache(): Reinitialise the current register cache
806895
*
@@ -1249,6 +1338,22 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
12491338
}
12501339
EXPORT_SYMBOL_GPL(regmap_raw_write);
12511340

1341+
/**
1342+
* regmap_field_write(): Write a value to a single register field
1343+
*
1344+
* @field: Register field to write to
1345+
* @val: Value to be written
1346+
*
1347+
* A value of zero will be returned on success, a negative errno will
1348+
* be returned in error cases.
1349+
*/
1350+
int regmap_field_write(struct regmap_field *field, unsigned int val)
1351+
{
1352+
return regmap_update_bits(field->regmap, field->reg,
1353+
field->mask, val << field->shift);
1354+
}
1355+
EXPORT_SYMBOL_GPL(regmap_field_write);
1356+
12521357
/*
12531358
* regmap_bulk_write(): Write multiple registers to the device
12541359
*
@@ -1531,6 +1636,31 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
15311636
}
15321637
EXPORT_SYMBOL_GPL(regmap_raw_read);
15331638

1639+
/**
1640+
* regmap_field_read(): Read a value to a single register field
1641+
*
1642+
* @field: Register field to read from
1643+
* @val: Pointer to store read value
1644+
*
1645+
* A value of zero will be returned on success, a negative errno will
1646+
* be returned in error cases.
1647+
*/
1648+
int regmap_field_read(struct regmap_field *field, unsigned int *val)
1649+
{
1650+
int ret;
1651+
unsigned int reg_val;
1652+
ret = regmap_read(field->regmap, field->reg, &reg_val);
1653+
if (ret != 0)
1654+
return ret;
1655+
1656+
reg_val &= field->mask;
1657+
reg_val >>= field->shift;
1658+
*val = reg_val;
1659+
1660+
return ret;
1661+
}
1662+
EXPORT_SYMBOL_GPL(regmap_field_read);
1663+
15341664
/**
15351665
* regmap_bulk_read(): Read multiple registers from the device
15361666
*

include/linux/regmap.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct irq_domain;
2323
struct spi_device;
2424
struct regmap;
2525
struct regmap_range_cfg;
26+
struct regmap_field;
2627

2728
/* An enum of all the supported cache types */
2829
enum regcache_type {
@@ -411,6 +412,36 @@ bool regmap_reg_in_ranges(unsigned int reg,
411412
const struct regmap_range *ranges,
412413
unsigned int nranges);
413414

415+
/**
416+
* Description of an register field
417+
*
418+
* @reg: Offset of the register within the regmap bank
419+
* @lsb: lsb of the register field.
420+
* @reg: msb of the register field.
421+
*/
422+
struct reg_field {
423+
unsigned int reg;
424+
unsigned int lsb;
425+
unsigned int msb;
426+
};
427+
428+
#define REG_FIELD(_reg, _lsb, _msb) { \
429+
.reg = _reg, \
430+
.lsb = _lsb, \
431+
.msb = _msb, \
432+
}
433+
434+
struct regmap_field *regmap_field_alloc(struct regmap *regmap,
435+
struct reg_field reg_field);
436+
void regmap_field_free(struct regmap_field *field);
437+
438+
struct regmap_field *devm_regmap_field_alloc(struct device *dev,
439+
struct regmap *regmap, struct reg_field reg_field);
440+
void devm_regmap_field_free(struct device *dev, struct regmap_field *field);
441+
442+
int regmap_field_read(struct regmap_field *field, unsigned int *val);
443+
int regmap_field_write(struct regmap_field *field, unsigned int val);
444+
414445
/**
415446
* Description of an IRQ for the generic regmap irq_chip.
416447
*

0 commit comments

Comments
 (0)