diff options
author | Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | 2014-02-25 08:45:50 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-02-25 18:58:40 -0500 |
commit | 1d5b40bccf04994248b39e8ce234a7c1f3235cf5 (patch) | |
tree | 6e8ee018b8df6c8a9da8caa1c98492f4a36f9eff | |
parent | f7e2cec02b0e5bfe2180f09de9b0bc724774c51a (diff) |
regmap: Add bypassed version of regmap_multi_reg_write
Devices with more complex boot proceedures may occasionally apply the
register patch manual. regmap_multi_reg_write is a logical way to do so,
however the patch must be applied with cache bypass on, such that it
doesn't override any user settings. This patch adds a
regmap_multi_reg_write_bypassed function that applies a set of writes
with the bypass enabled.
Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | drivers/base/regmap/regmap.c | 75 | ||||
-rw-r--r-- | include/linux/regmap.h | 3 |
2 files changed, 65 insertions, 13 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 1e3934aea56a..e6a2c29c0be4 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -1576,6 +1576,26 @@ out: | |||
1576 | } | 1576 | } |
1577 | EXPORT_SYMBOL_GPL(regmap_bulk_write); | 1577 | EXPORT_SYMBOL_GPL(regmap_bulk_write); |
1578 | 1578 | ||
1579 | static int _regmap_multi_reg_write(struct regmap *map, | ||
1580 | const struct reg_default *regs, | ||
1581 | int num_regs) | ||
1582 | { | ||
1583 | int i, ret; | ||
1584 | |||
1585 | for (i = 0; i < num_regs; i++) { | ||
1586 | if (regs[i].reg % map->reg_stride) | ||
1587 | return -EINVAL; | ||
1588 | ret = _regmap_write(map, regs[i].reg, regs[i].def); | ||
1589 | if (ret != 0) { | ||
1590 | dev_err(map->dev, "Failed to write %x = %x: %d\n", | ||
1591 | regs[i].reg, regs[i].def, ret); | ||
1592 | return ret; | ||
1593 | } | ||
1594 | } | ||
1595 | |||
1596 | return 0; | ||
1597 | } | ||
1598 | |||
1579 | /* | 1599 | /* |
1580 | * regmap_multi_reg_write(): Write multiple registers to the device | 1600 | * regmap_multi_reg_write(): Write multiple registers to the device |
1581 | * | 1601 | * |
@@ -1595,28 +1615,57 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write); | |||
1595 | int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, | 1615 | int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, |
1596 | int num_regs) | 1616 | int num_regs) |
1597 | { | 1617 | { |
1598 | int ret = 0, i; | 1618 | int ret; |
1599 | |||
1600 | for (i = 0; i < num_regs; i++) { | ||
1601 | int reg = regs[i].reg; | ||
1602 | if (reg % map->reg_stride) | ||
1603 | return -EINVAL; | ||
1604 | } | ||
1605 | 1619 | ||
1606 | map->lock(map->lock_arg); | 1620 | map->lock(map->lock_arg); |
1607 | 1621 | ||
1608 | for (i = 0; i < num_regs; i++) { | 1622 | ret = _regmap_multi_reg_write(map, regs, num_regs); |
1609 | ret = _regmap_write(map, regs[i].reg, regs[i].def); | 1623 | |
1610 | if (ret != 0) | ||
1611 | goto out; | ||
1612 | } | ||
1613 | out: | ||
1614 | map->unlock(map->lock_arg); | 1624 | map->unlock(map->lock_arg); |
1615 | 1625 | ||
1616 | return ret; | 1626 | return ret; |
1617 | } | 1627 | } |
1618 | EXPORT_SYMBOL_GPL(regmap_multi_reg_write); | 1628 | EXPORT_SYMBOL_GPL(regmap_multi_reg_write); |
1619 | 1629 | ||
1630 | /* | ||
1631 | * regmap_multi_reg_write_bypassed(): Write multiple registers to the | ||
1632 | * device but not the cache | ||
1633 | * | ||
1634 | * where the set of register are supplied in any order | ||
1635 | * | ||
1636 | * @map: Register map to write to | ||
1637 | * @regs: Array of structures containing register,value to be written | ||
1638 | * @num_regs: Number of registers to write | ||
1639 | * | ||
1640 | * This function is intended to be used for writing a large block of data | ||
1641 | * atomically to the device in single transfer for those I2C client devices | ||
1642 | * that implement this alternative block write mode. | ||
1643 | * | ||
1644 | * A value of zero will be returned on success, a negative errno will | ||
1645 | * be returned in error cases. | ||
1646 | */ | ||
1647 | int regmap_multi_reg_write_bypassed(struct regmap *map, | ||
1648 | const struct reg_default *regs, | ||
1649 | int num_regs) | ||
1650 | { | ||
1651 | int ret; | ||
1652 | bool bypass; | ||
1653 | |||
1654 | map->lock(map->lock_arg); | ||
1655 | |||
1656 | bypass = map->cache_bypass; | ||
1657 | map->cache_bypass = true; | ||
1658 | |||
1659 | ret = _regmap_multi_reg_write(map, regs, num_regs); | ||
1660 | |||
1661 | map->cache_bypass = bypass; | ||
1662 | |||
1663 | map->unlock(map->lock_arg); | ||
1664 | |||
1665 | return ret; | ||
1666 | } | ||
1667 | EXPORT_SYMBOL_GPL(regmap_multi_reg_write_bypassed); | ||
1668 | |||
1620 | /** | 1669 | /** |
1621 | * regmap_raw_write_async(): Write raw values to one or more registers | 1670 | * regmap_raw_write_async(): Write raw values to one or more registers |
1622 | * asynchronously | 1671 | * asynchronously |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index e97ac6c8b7be..ca2272fbd014 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
@@ -388,6 +388,9 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
388 | size_t val_count); | 388 | size_t val_count); |
389 | int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, | 389 | int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, |
390 | int num_regs); | 390 | int num_regs); |
391 | int regmap_multi_reg_write_bypassed(struct regmap *map, | ||
392 | const struct reg_default *regs, | ||
393 | int num_regs); | ||
391 | int regmap_raw_write_async(struct regmap *map, unsigned int reg, | 394 | int regmap_raw_write_async(struct regmap *map, unsigned int reg, |
392 | const void *val, size_t val_len); | 395 | const void *val, size_t val_len); |
393 | int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); | 396 | int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); |