diff options
| author | Mark Brown <broonie@linaro.org> | 2013-09-24 14:53:26 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2013-09-24 14:53:26 -0400 |
| commit | ef85b642460a4cc84086a7fe20915dae58dabcb2 (patch) | |
| tree | 20cb7e3610702c0afb334907b9f93a0c32ad01d3 /drivers | |
| parent | d3be689e6a07c00123786659b4429b07cf4272ac (diff) | |
| parent | a0102375ee82db1e08324b1a21484854cf2c1677 (diff) | |
Merge tag 'regmap-fields' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap into asoc-rcar
regmap: Add support for repeated blocks of fields
Save duplication for devices using the regmap field APIs by allowing
repeated blocks to be described once and referred to with an index.
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/base/regmap/internal.h | 3 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 103 |
2 files changed, 106 insertions, 0 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 57f777835d97..9010614f7793 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
| @@ -179,6 +179,9 @@ struct regmap_field { | |||
| 179 | /* lsb */ | 179 | /* lsb */ |
| 180 | unsigned int shift; | 180 | unsigned int shift; |
| 181 | unsigned int reg; | 181 | unsigned int reg; |
| 182 | |||
| 183 | unsigned int id_size; | ||
| 184 | unsigned int id_offset; | ||
| 182 | }; | 185 | }; |
| 183 | 186 | ||
| 184 | #ifdef CONFIG_DEBUG_FS | 187 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 7d689a15c500..00152bf7ab12 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
| @@ -821,6 +821,8 @@ static void regmap_field_init(struct regmap_field *rm_field, | |||
| 821 | rm_field->reg = reg_field.reg; | 821 | rm_field->reg = reg_field.reg; |
| 822 | rm_field->shift = reg_field.lsb; | 822 | rm_field->shift = reg_field.lsb; |
| 823 | rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb); | 823 | rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb); |
| 824 | rm_field->id_size = reg_field.id_size; | ||
| 825 | rm_field->id_offset = reg_field.id_offset; | ||
| 824 | } | 826 | } |
| 825 | 827 | ||
| 826 | /** | 828 | /** |
| @@ -1369,6 +1371,74 @@ int regmap_field_write(struct regmap_field *field, unsigned int val) | |||
| 1369 | } | 1371 | } |
| 1370 | EXPORT_SYMBOL_GPL(regmap_field_write); | 1372 | EXPORT_SYMBOL_GPL(regmap_field_write); |
| 1371 | 1373 | ||
| 1374 | /** | ||
| 1375 | * regmap_field_update_bits(): Perform a read/modify/write cycle | ||
| 1376 | * on the register field | ||
| 1377 | * | ||
| 1378 | * @field: Register field to write to | ||
| 1379 | * @mask: Bitmask to change | ||
| 1380 | * @val: Value to be written | ||
| 1381 | * | ||
| 1382 | * A value of zero will be returned on success, a negative errno will | ||
| 1383 | * be returned in error cases. | ||
| 1384 | */ | ||
| 1385 | int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val) | ||
| 1386 | { | ||
| 1387 | mask = (mask << field->shift) & field->mask; | ||
| 1388 | |||
| 1389 | return regmap_update_bits(field->regmap, field->reg, | ||
| 1390 | mask, val << field->shift); | ||
| 1391 | } | ||
| 1392 | EXPORT_SYMBOL_GPL(regmap_field_update_bits); | ||
| 1393 | |||
| 1394 | /** | ||
| 1395 | * regmap_fields_write(): Write a value to a single register field with port ID | ||
| 1396 | * | ||
| 1397 | * @field: Register field to write to | ||
| 1398 | * @id: port ID | ||
| 1399 | * @val: Value to be written | ||
| 1400 | * | ||
| 1401 | * A value of zero will be returned on success, a negative errno will | ||
| 1402 | * be returned in error cases. | ||
| 1403 | */ | ||
| 1404 | int regmap_fields_write(struct regmap_field *field, unsigned int id, | ||
| 1405 | unsigned int val) | ||
| 1406 | { | ||
| 1407 | if (id >= field->id_size) | ||
| 1408 | return -EINVAL; | ||
| 1409 | |||
| 1410 | return regmap_update_bits(field->regmap, | ||
| 1411 | field->reg + (field->id_offset * id), | ||
| 1412 | field->mask, val << field->shift); | ||
| 1413 | } | ||
| 1414 | EXPORT_SYMBOL_GPL(regmap_fields_write); | ||
| 1415 | |||
| 1416 | /** | ||
| 1417 | * regmap_fields_update_bits(): Perform a read/modify/write cycle | ||
| 1418 | * on the register field | ||
| 1419 | * | ||
| 1420 | * @field: Register field to write to | ||
| 1421 | * @id: port ID | ||
| 1422 | * @mask: Bitmask to change | ||
| 1423 | * @val: Value to be written | ||
| 1424 | * | ||
| 1425 | * A value of zero will be returned on success, a negative errno will | ||
| 1426 | * be returned in error cases. | ||
| 1427 | */ | ||
| 1428 | int regmap_fields_update_bits(struct regmap_field *field, unsigned int id, | ||
| 1429 | unsigned int mask, unsigned int val) | ||
| 1430 | { | ||
| 1431 | if (id >= field->id_size) | ||
| 1432 | return -EINVAL; | ||
| 1433 | |||
| 1434 | mask = (mask << field->shift) & field->mask; | ||
| 1435 | |||
| 1436 | return regmap_update_bits(field->regmap, | ||
| 1437 | field->reg + (field->id_offset * id), | ||
| 1438 | mask, val << field->shift); | ||
| 1439 | } | ||
| 1440 | EXPORT_SYMBOL_GPL(regmap_fields_update_bits); | ||
| 1441 | |||
| 1372 | /* | 1442 | /* |
| 1373 | * regmap_bulk_write(): Write multiple registers to the device | 1443 | * regmap_bulk_write(): Write multiple registers to the device |
| 1374 | * | 1444 | * |
| @@ -1677,6 +1747,39 @@ int regmap_field_read(struct regmap_field *field, unsigned int *val) | |||
| 1677 | EXPORT_SYMBOL_GPL(regmap_field_read); | 1747 | EXPORT_SYMBOL_GPL(regmap_field_read); |
| 1678 | 1748 | ||
| 1679 | /** | 1749 | /** |
| 1750 | * regmap_fields_read(): Read a value to a single register field with port ID | ||
| 1751 | * | ||
| 1752 | * @field: Register field to read from | ||
| 1753 | * @id: port ID | ||
| 1754 | * @val: Pointer to store read value | ||
| 1755 | * | ||
| 1756 | * A value of zero will be returned on success, a negative errno will | ||
| 1757 | * be returned in error cases. | ||
| 1758 | */ | ||
| 1759 | int regmap_fields_read(struct regmap_field *field, unsigned int id, | ||
| 1760 | unsigned int *val) | ||
| 1761 | { | ||
| 1762 | int ret; | ||
| 1763 | unsigned int reg_val; | ||
| 1764 | |||
| 1765 | if (id >= field->id_size) | ||
| 1766 | return -EINVAL; | ||
| 1767 | |||
| 1768 | ret = regmap_read(field->regmap, | ||
| 1769 | field->reg + (field->id_offset * id), | ||
| 1770 | ®_val); | ||
| 1771 | if (ret != 0) | ||
| 1772 | return ret; | ||
| 1773 | |||
| 1774 | reg_val &= field->mask; | ||
| 1775 | reg_val >>= field->shift; | ||
| 1776 | *val = reg_val; | ||
| 1777 | |||
| 1778 | return ret; | ||
| 1779 | } | ||
| 1780 | EXPORT_SYMBOL_GPL(regmap_fields_read); | ||
| 1781 | |||
| 1782 | /** | ||
| 1680 | * regmap_bulk_read(): Read multiple registers from the device | 1783 | * regmap_bulk_read(): Read multiple registers from the device |
| 1681 | * | 1784 | * |
| 1682 | * @map: Register map to write to | 1785 | * @map: Register map to write to |
