aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@st.com>2013-06-11 08:18:15 -0400
committerMark Brown <broonie@linaro.org>2013-06-12 11:27:44 -0400
commit67252287871113deba96adf7e4df1752f3f08688 (patch)
tree8fd124b776d577d4d8dd0fa48b6c1a2df3be7ca3 /drivers/base/regmap
parent317ddd256b9c24b0d78fa8018f80f1e495481a10 (diff)
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 <srinivas.kandagatla@st.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/internal.h8
-rw-r--r--drivers/base/regmap/regmap.c130
2 files changed, 138 insertions, 0 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index c130536e0ab0..c5f6ebd0466d 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -174,6 +174,14 @@ struct regmap_range_node {
174 unsigned int window_len; 174 unsigned int window_len;
175}; 175};
176 176
177struct regmap_field {
178 struct regmap *regmap;
179 unsigned int mask;
180 /* lsb */
181 unsigned int shift;
182 unsigned int reg;
183};
184
177#ifdef CONFIG_DEBUG_FS 185#ifdef CONFIG_DEBUG_FS
178extern void regmap_debugfs_initcall(void); 186extern void regmap_debugfs_initcall(void);
179extern void regmap_debugfs_init(struct regmap *map, const char *name); 187extern void regmap_debugfs_init(struct regmap *map, const char *name);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index a941dcfe7590..fef6f13b96bb 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -801,6 +801,95 @@ struct regmap *devm_regmap_init(struct device *dev,
801} 801}
802EXPORT_SYMBOL_GPL(devm_regmap_init); 802EXPORT_SYMBOL_GPL(devm_regmap_init);
803 803
804static 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 */
826struct 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}
839EXPORT_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 */
850void devm_regmap_field_free(struct device *dev,
851 struct regmap_field *field)
852{
853 devm_kfree(dev, field);
854}
855EXPORT_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 */
868struct 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}
880EXPORT_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 */
887void regmap_field_free(struct regmap_field *field)
888{
889 kfree(field);
890}
891EXPORT_SYMBOL_GPL(regmap_field_free);
892
804/** 893/**
805 * regmap_reinit_cache(): Reinitialise the current register cache 894 * regmap_reinit_cache(): Reinitialise the current register cache
806 * 895 *
@@ -1249,6 +1338,22 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
1249} 1338}
1250EXPORT_SYMBOL_GPL(regmap_raw_write); 1339EXPORT_SYMBOL_GPL(regmap_raw_write);
1251 1340
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 */
1350int 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}
1355EXPORT_SYMBOL_GPL(regmap_field_write);
1356
1252/* 1357/*
1253 * regmap_bulk_write(): Write multiple registers to the device 1358 * regmap_bulk_write(): Write multiple registers to the device
1254 * 1359 *
@@ -1532,6 +1637,31 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
1532EXPORT_SYMBOL_GPL(regmap_raw_read); 1637EXPORT_SYMBOL_GPL(regmap_raw_read);
1533 1638
1534/** 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 */
1648int 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}
1662EXPORT_SYMBOL_GPL(regmap_field_read);
1663
1664/**
1535 * regmap_bulk_read(): Read multiple registers from the device 1665 * regmap_bulk_read(): Read multiple registers from the device
1536 * 1666 *
1537 * @map: Register map to write to 1667 * @map: Register map to write to