aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2014-02-25 08:45:50 -0500
committerMark Brown <broonie@linaro.org>2014-02-25 18:58:40 -0500
commit1d5b40bccf04994248b39e8ce234a7c1f3235cf5 (patch)
tree6e8ee018b8df6c8a9da8caa1c98492f4a36f9eff
parentf7e2cec02b0e5bfe2180f09de9b0bc724774c51a (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.c75
-rw-r--r--include/linux/regmap.h3
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}
1577EXPORT_SYMBOL_GPL(regmap_bulk_write); 1577EXPORT_SYMBOL_GPL(regmap_bulk_write);
1578 1578
1579static 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);
1595int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, 1615int 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 }
1613out:
1614 map->unlock(map->lock_arg); 1624 map->unlock(map->lock_arg);
1615 1625
1616 return ret; 1626 return ret;
1617} 1627}
1618EXPORT_SYMBOL_GPL(regmap_multi_reg_write); 1628EXPORT_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 */
1647int 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}
1667EXPORT_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);
389int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, 389int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs,
390 int num_regs); 390 int num_regs);
391int regmap_multi_reg_write_bypassed(struct regmap *map,
392 const struct reg_default *regs,
393 int num_regs);
391int regmap_raw_write_async(struct regmap *map, unsigned int reg, 394int 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);
393int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); 396int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);