diff options
| -rw-r--r-- | drivers/base/regmap/internal.h | 3 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 103 | ||||
| -rw-r--r-- | include/linux/regmap.h | 13 |
3 files changed, 119 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 |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index a10380bfbeac..a12bea07f79e 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
| @@ -425,11 +425,15 @@ bool regmap_reg_in_ranges(unsigned int reg, | |||
| 425 | * @reg: Offset of the register within the regmap bank | 425 | * @reg: Offset of the register within the regmap bank |
| 426 | * @lsb: lsb of the register field. | 426 | * @lsb: lsb of the register field. |
| 427 | * @reg: msb of the register field. | 427 | * @reg: msb of the register field. |
| 428 | * @id_size: port size if it has some ports | ||
| 429 | * @id_offset: address offset for each ports | ||
| 428 | */ | 430 | */ |
| 429 | struct reg_field { | 431 | struct reg_field { |
| 430 | unsigned int reg; | 432 | unsigned int reg; |
| 431 | unsigned int lsb; | 433 | unsigned int lsb; |
| 432 | unsigned int msb; | 434 | unsigned int msb; |
| 435 | unsigned int id_size; | ||
| 436 | unsigned int id_offset; | ||
| 433 | }; | 437 | }; |
| 434 | 438 | ||
| 435 | #define REG_FIELD(_reg, _lsb, _msb) { \ | 439 | #define REG_FIELD(_reg, _lsb, _msb) { \ |
| @@ -448,6 +452,15 @@ void devm_regmap_field_free(struct device *dev, struct regmap_field *field); | |||
| 448 | 452 | ||
| 449 | int regmap_field_read(struct regmap_field *field, unsigned int *val); | 453 | int regmap_field_read(struct regmap_field *field, unsigned int *val); |
| 450 | int regmap_field_write(struct regmap_field *field, unsigned int val); | 454 | int regmap_field_write(struct regmap_field *field, unsigned int val); |
| 455 | int regmap_field_update_bits(struct regmap_field *field, | ||
| 456 | unsigned int mask, unsigned int val); | ||
| 457 | |||
| 458 | int regmap_fields_write(struct regmap_field *field, unsigned int id, | ||
| 459 | unsigned int val); | ||
| 460 | int regmap_fields_read(struct regmap_field *field, unsigned int id, | ||
| 461 | unsigned int *val); | ||
| 462 | int regmap_fields_update_bits(struct regmap_field *field, unsigned int id, | ||
| 463 | unsigned int mask, unsigned int val); | ||
| 451 | 464 | ||
| 452 | /** | 465 | /** |
| 453 | * Description of an IRQ for the generic regmap irq_chip. | 466 | * Description of an IRQ for the generic regmap irq_chip. |
