diff options
author | Mark Brown <broonie@linaro.org> | 2013-06-30 07:40:03 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-06-30 07:40:03 -0400 |
commit | 7bc8c4c37aea74332b16ffb5412a8ad355d508ce (patch) | |
tree | ca37bdf59d25c68fe97a3894184aba79c4f1aa87 /drivers/base | |
parent | ad4f496b445eac30bb6ddc72599bf6dd73529cd2 (diff) | |
parent | 539fde59ebc615bcb9af373af8947e866dc072c7 (diff) |
Merge remote-tracking branch 'regmap/topic/field' into regmap-next
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/regmap/internal.h | 8 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 130 |
2 files changed, 138 insertions, 0 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index ae23d8391aa0..29c83160ca29 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -176,6 +176,14 @@ struct regmap_range_node { | |||
176 | unsigned int window_len; | 176 | unsigned int window_len; |
177 | }; | 177 | }; |
178 | 178 | ||
179 | struct regmap_field { | ||
180 | struct regmap *regmap; | ||
181 | unsigned int mask; | ||
182 | /* lsb */ | ||
183 | unsigned int shift; | ||
184 | unsigned int reg; | ||
185 | }; | ||
186 | |||
179 | #ifdef CONFIG_DEBUG_FS | 187 | #ifdef CONFIG_DEBUG_FS |
180 | extern void regmap_debugfs_initcall(void); | 188 | extern void regmap_debugfs_initcall(void); |
181 | extern void regmap_debugfs_init(struct regmap *map, const char *name); | 189 | extern 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 ed152e3d2d88..95920583e31e 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -807,6 +807,95 @@ struct regmap *devm_regmap_init(struct device *dev, | |||
807 | } | 807 | } |
808 | EXPORT_SYMBOL_GPL(devm_regmap_init); | 808 | EXPORT_SYMBOL_GPL(devm_regmap_init); |
809 | 809 | ||
810 | static void regmap_field_init(struct regmap_field *rm_field, | ||
811 | struct regmap *regmap, struct reg_field reg_field) | ||
812 | { | ||
813 | int field_bits = reg_field.msb - reg_field.lsb + 1; | ||
814 | rm_field->regmap = regmap; | ||
815 | rm_field->reg = reg_field.reg; | ||
816 | rm_field->shift = reg_field.lsb; | ||
817 | rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb); | ||
818 | } | ||
819 | |||
820 | /** | ||
821 | * devm_regmap_field_alloc(): Allocate and initialise a register field | ||
822 | * in a register map. | ||
823 | * | ||
824 | * @dev: Device that will be interacted with | ||
825 | * @regmap: regmap bank in which this register field is located. | ||
826 | * @reg_field: Register field with in the bank. | ||
827 | * | ||
828 | * The return value will be an ERR_PTR() on error or a valid pointer | ||
829 | * to a struct regmap_field. The regmap_field will be automatically freed | ||
830 | * by the device management code. | ||
831 | */ | ||
832 | struct regmap_field *devm_regmap_field_alloc(struct device *dev, | ||
833 | struct regmap *regmap, struct reg_field reg_field) | ||
834 | { | ||
835 | struct regmap_field *rm_field = devm_kzalloc(dev, | ||
836 | sizeof(*rm_field), GFP_KERNEL); | ||
837 | if (!rm_field) | ||
838 | return ERR_PTR(-ENOMEM); | ||
839 | |||
840 | regmap_field_init(rm_field, regmap, reg_field); | ||
841 | |||
842 | return rm_field; | ||
843 | |||
844 | } | ||
845 | EXPORT_SYMBOL_GPL(devm_regmap_field_alloc); | ||
846 | |||
847 | /** | ||
848 | * devm_regmap_field_free(): Free register field allocated using | ||
849 | * devm_regmap_field_alloc. Usally drivers need not call this function, | ||
850 | * as the memory allocated via devm will be freed as per device-driver | ||
851 | * life-cyle. | ||
852 | * | ||
853 | * @dev: Device that will be interacted with | ||
854 | * @field: regmap field which should be freed. | ||
855 | */ | ||
856 | void devm_regmap_field_free(struct device *dev, | ||
857 | struct regmap_field *field) | ||
858 | { | ||
859 | devm_kfree(dev, field); | ||
860 | } | ||
861 | EXPORT_SYMBOL_GPL(devm_regmap_field_free); | ||
862 | |||
863 | /** | ||
864 | * regmap_field_alloc(): Allocate and initialise a register field | ||
865 | * in a register map. | ||
866 | * | ||
867 | * @regmap: regmap bank in which this register field is located. | ||
868 | * @reg_field: Register field with in the bank. | ||
869 | * | ||
870 | * The return value will be an ERR_PTR() on error or a valid pointer | ||
871 | * to a struct regmap_field. The regmap_field should be freed by the | ||
872 | * user once its finished working with it using regmap_field_free(). | ||
873 | */ | ||
874 | struct regmap_field *regmap_field_alloc(struct regmap *regmap, | ||
875 | struct reg_field reg_field) | ||
876 | { | ||
877 | struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL); | ||
878 | |||
879 | if (!rm_field) | ||
880 | return ERR_PTR(-ENOMEM); | ||
881 | |||
882 | regmap_field_init(rm_field, regmap, reg_field); | ||
883 | |||
884 | return rm_field; | ||
885 | } | ||
886 | EXPORT_SYMBOL_GPL(regmap_field_alloc); | ||
887 | |||
888 | /** | ||
889 | * regmap_field_free(): Free register field allocated using regmap_field_alloc | ||
890 | * | ||
891 | * @field: regmap field which should be freed. | ||
892 | */ | ||
893 | void regmap_field_free(struct regmap_field *field) | ||
894 | { | ||
895 | kfree(field); | ||
896 | } | ||
897 | EXPORT_SYMBOL_GPL(regmap_field_free); | ||
898 | |||
810 | /** | 899 | /** |
811 | * regmap_reinit_cache(): Reinitialise the current register cache | 900 | * regmap_reinit_cache(): Reinitialise the current register cache |
812 | * | 901 | * |
@@ -1255,6 +1344,22 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, | |||
1255 | } | 1344 | } |
1256 | EXPORT_SYMBOL_GPL(regmap_raw_write); | 1345 | EXPORT_SYMBOL_GPL(regmap_raw_write); |
1257 | 1346 | ||
1347 | /** | ||
1348 | * regmap_field_write(): Write a value to a single register field | ||
1349 | * | ||
1350 | * @field: Register field to write to | ||
1351 | * @val: Value to be written | ||
1352 | * | ||
1353 | * A value of zero will be returned on success, a negative errno will | ||
1354 | * be returned in error cases. | ||
1355 | */ | ||
1356 | int regmap_field_write(struct regmap_field *field, unsigned int val) | ||
1357 | { | ||
1358 | return regmap_update_bits(field->regmap, field->reg, | ||
1359 | field->mask, val << field->shift); | ||
1360 | } | ||
1361 | EXPORT_SYMBOL_GPL(regmap_field_write); | ||
1362 | |||
1258 | /* | 1363 | /* |
1259 | * regmap_bulk_write(): Write multiple registers to the device | 1364 | * regmap_bulk_write(): Write multiple registers to the device |
1260 | * | 1365 | * |
@@ -1538,6 +1643,31 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
1538 | EXPORT_SYMBOL_GPL(regmap_raw_read); | 1643 | EXPORT_SYMBOL_GPL(regmap_raw_read); |
1539 | 1644 | ||
1540 | /** | 1645 | /** |
1646 | * regmap_field_read(): Read a value to a single register field | ||
1647 | * | ||
1648 | * @field: Register field to read from | ||
1649 | * @val: Pointer to store read value | ||
1650 | * | ||
1651 | * A value of zero will be returned on success, a negative errno will | ||
1652 | * be returned in error cases. | ||
1653 | */ | ||
1654 | int regmap_field_read(struct regmap_field *field, unsigned int *val) | ||
1655 | { | ||
1656 | int ret; | ||
1657 | unsigned int reg_val; | ||
1658 | ret = regmap_read(field->regmap, field->reg, ®_val); | ||
1659 | if (ret != 0) | ||
1660 | return ret; | ||
1661 | |||
1662 | reg_val &= field->mask; | ||
1663 | reg_val >>= field->shift; | ||
1664 | *val = reg_val; | ||
1665 | |||
1666 | return ret; | ||
1667 | } | ||
1668 | EXPORT_SYMBOL_GPL(regmap_field_read); | ||
1669 | |||
1670 | /** | ||
1541 | * regmap_bulk_read(): Read multiple registers from the device | 1671 | * regmap_bulk_read(): Read multiple registers from the device |
1542 | * | 1672 | * |
1543 | * @map: Register map to write to | 1673 | * @map: Register map to write to |