aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorOpensource [Anthony Olech] <anthony.olech.opensource@diasemi.com>2014-03-04 08:54:02 -0500
committerMark Brown <broonie@linaro.org>2014-03-10 13:09:32 -0400
commite894c3f46c302716d2f156b1f3339e2f96ceb65c (patch)
treed051cf7865aa21b8af4dd6a921c71efde418cfa1 /drivers/base/regmap
parent1c18d2ca104c36fc2ce147cce053c62f61d2ea68 (diff)
regmap: Implementation for regmap_multi_reg_write
This is the implementation of regmap_multi_reg_write() There is a new capability 'can_multi_write' that device drivers must set in order to use this multi reg write mode. This replaces the first definition, which just defined the API. Signed-off-by: Anthony Olech <anthony.olech.opensource@diasemi.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/internal.h2
-rw-r--r--drivers/base/regmap/regmap.c188
2 files changed, 174 insertions, 16 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 33414b1de201..7d1326985bee 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -134,6 +134,8 @@ struct regmap {
134 134
135 /* if set, converts bulk rw to single rw */ 135 /* if set, converts bulk rw to single rw */
136 bool use_single_rw; 136 bool use_single_rw;
137 /* if set, the device supports multi write mode */
138 bool can_multi_write;
137 139
138 struct rb_root range_tree; 140 struct rb_root range_tree;
139 void *selector_work_buf; /* Scratch buffer used for selector */ 141 void *selector_work_buf; /* Scratch buffer used for selector */
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 35ab7baffcc5..c69bbc06dfbb 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -439,6 +439,7 @@ struct regmap *regmap_init(struct device *dev,
439 else 439 else
440 map->reg_stride = 1; 440 map->reg_stride = 1;
441 map->use_single_rw = config->use_single_rw; 441 map->use_single_rw = config->use_single_rw;
442 map->can_multi_write = config->can_multi_write;
442 map->dev = dev; 443 map->dev = dev;
443 map->bus = bus; 444 map->bus = bus;
444 map->bus_context = bus_context; 445 map->bus_context = bus_context;
@@ -1576,41 +1577,196 @@ out:
1576} 1577}
1577EXPORT_SYMBOL_GPL(regmap_bulk_write); 1578EXPORT_SYMBOL_GPL(regmap_bulk_write);
1578 1579
1580/*
1581 * _regmap_raw_multi_reg_write()
1582 *
1583 * the (register,newvalue) pairs in regs have not been formatted, but
1584 * they are all in the same page and have been changed to being page
1585 * relative. The page register has been written if that was neccessary.
1586 */
1587static int _regmap_raw_multi_reg_write(struct regmap *map,
1588 const struct reg_default *regs,
1589 size_t num_regs)
1590{
1591 int ret;
1592 void *buf;
1593 int i;
1594 u8 *u8;
1595 size_t val_bytes = map->format.val_bytes;
1596 size_t reg_bytes = map->format.reg_bytes;
1597 size_t pad_bytes = map->format.pad_bytes;
1598 size_t pair_size = reg_bytes + pad_bytes + val_bytes;
1599 size_t len = pair_size * num_regs;
1600
1601 buf = kzalloc(len, GFP_KERNEL);
1602 if (!buf)
1603 return -ENOMEM;
1604
1605 /* We have to linearise by hand. */
1606
1607 u8 = buf;
1608
1609 for (i = 0; i < num_regs; i++) {
1610 int reg = regs[i].reg;
1611 int val = regs[i].def;
1612 trace_regmap_hw_write_start(map->dev, reg, 1);
1613 map->format.format_reg(u8, reg, map->reg_shift);
1614 u8 += reg_bytes + pad_bytes;
1615 map->format.format_val(u8, val, 0);
1616 u8 += val_bytes;
1617 }
1618 u8 = buf;
1619 *u8 |= map->write_flag_mask;
1620
1621 ret = map->bus->write(map->bus_context, buf, len);
1622
1623 kfree(buf);
1624
1625 for (i = 0; i < num_regs; i++) {
1626 int reg = regs[i].reg;
1627 trace_regmap_hw_write_done(map->dev, reg, 1);
1628 }
1629 return ret;
1630}
1631
1632static unsigned int _regmap_register_page(struct regmap *map,
1633 unsigned int reg,
1634 struct regmap_range_node *range)
1635{
1636 unsigned int win_page = (reg - range->range_min) / range->window_len;
1637
1638 return win_page;
1639}
1640
1641static int _regmap_range_multi_paged_reg_write(struct regmap *map,
1642 struct reg_default *regs,
1643 size_t num_regs)
1644{
1645 int ret;
1646 int i, n;
1647 struct reg_default *base;
1648 unsigned int this_page;
1649 /*
1650 * the set of registers are not neccessarily in order, but
1651 * since the order of write must be preserved this algorithm
1652 * chops the set each time the page changes
1653 */
1654 base = regs;
1655 for (i = 0, n = 0; i < num_regs; i++, n++) {
1656 unsigned int reg = regs[i].reg;
1657 struct regmap_range_node *range;
1658
1659 range = _regmap_range_lookup(map, reg);
1660 if (range) {
1661 unsigned int win_page = _regmap_register_page(map, reg,
1662 range);
1663
1664 if (i == 0)
1665 this_page = win_page;
1666 if (win_page != this_page) {
1667 this_page = win_page;
1668 ret = _regmap_raw_multi_reg_write(map, base, n);
1669 if (ret != 0)
1670 return ret;
1671 base += n;
1672 n = 0;
1673 }
1674 ret = _regmap_select_page(map, &base[n].reg, range, 1);
1675 if (ret != 0)
1676 return ret;
1677 }
1678 }
1679 if (n > 0)
1680 return _regmap_raw_multi_reg_write(map, base, n);
1681 return 0;
1682}
1683
1579static int _regmap_multi_reg_write(struct regmap *map, 1684static int _regmap_multi_reg_write(struct regmap *map,
1580 const struct reg_default *regs, 1685 const struct reg_default *regs,
1581 int num_regs) 1686 size_t num_regs)
1582{ 1687{
1583 int i, ret; 1688 int i;
1689 int ret;
1690
1691 if (!map->can_multi_write) {
1692 for (i = 0; i < num_regs; i++) {
1693 ret = _regmap_write(map, regs[i].reg, regs[i].def);
1694 if (ret != 0)
1695 return ret;
1696 }
1697 return 0;
1698 }
1699
1700 if (!map->format.parse_inplace)
1701 return -EINVAL;
1702
1703 if (map->writeable_reg)
1704 for (i = 0; i < num_regs; i++) {
1705 int reg = regs[i].reg;
1706 if (!map->writeable_reg(map->dev, reg))
1707 return -EINVAL;
1708 if (reg % map->reg_stride)
1709 return -EINVAL;
1710 }
1711
1712 if (!map->cache_bypass) {
1713 for (i = 0; i < num_regs; i++) {
1714 unsigned int val = regs[i].def;
1715 unsigned int reg = regs[i].reg;
1716 ret = regcache_write(map, reg, val);
1717 if (ret) {
1718 dev_err(map->dev,
1719 "Error in caching of register: %x ret: %d\n",
1720 reg, ret);
1721 return ret;
1722 }
1723 }
1724 if (map->cache_only) {
1725 map->cache_dirty = true;
1726 return 0;
1727 }
1728 }
1729
1730 WARN_ON(!map->bus);
1584 1731
1585 for (i = 0; i < num_regs; i++) { 1732 for (i = 0; i < num_regs; i++) {
1586 if (regs[i].reg % map->reg_stride) 1733 unsigned int reg = regs[i].reg;
1587 return -EINVAL; 1734 struct regmap_range_node *range;
1588 ret = _regmap_write(map, regs[i].reg, regs[i].def); 1735 range = _regmap_range_lookup(map, reg);
1589 if (ret != 0) { 1736 if (range) {
1590 dev_err(map->dev, "Failed to write %x = %x: %d\n", 1737 size_t len = sizeof(struct reg_default)*num_regs;
1591 regs[i].reg, regs[i].def, ret); 1738 struct reg_default *base = kmemdup(regs, len,
1739 GFP_KERNEL);
1740 if (!base)
1741 return -ENOMEM;
1742 ret = _regmap_range_multi_paged_reg_write(map, base,
1743 num_regs);
1744 kfree(base);
1745
1592 return ret; 1746 return ret;
1593 } 1747 }
1594 } 1748 }
1595 1749 return _regmap_raw_multi_reg_write(map, regs, num_regs);
1596 return 0;
1597} 1750}
1598 1751
1599/* 1752/*
1600 * regmap_multi_reg_write(): Write multiple registers to the device 1753 * regmap_multi_reg_write(): Write multiple registers to the device
1601 * 1754 *
1602 * where the set of register are supplied in any order 1755 * where the set of register,value pairs are supplied in any order,
1756 * possibly not all in a single range.
1603 * 1757 *
1604 * @map: Register map to write to 1758 * @map: Register map to write to
1605 * @regs: Array of structures containing register,value to be written 1759 * @regs: Array of structures containing register,value to be written
1606 * @num_regs: Number of registers to write 1760 * @num_regs: Number of registers to write
1607 * 1761 *
1608 * This function is intended to be used for writing a large block of data 1762 * The 'normal' block write mode will send ultimately send data on the
1609 * atomically to the device in single transfer for those I2C client devices 1763 * target bus as R,V1,V2,V3,..,Vn where successively higer registers are
1610 * that implement this alternative block write mode. 1764 * addressed. However, this alternative block multi write mode will send
1765 * the data as R1,V1,R2,V2,..,Rn,Vn on the target bus. The target device
1766 * must of course support the mode.
1611 * 1767 *
1612 * A value of zero will be returned on success, a negative errno will 1768 * A value of zero will be returned on success, a negative errno will be
1613 * be returned in error cases. 1769 * returned in error cases.
1614 */ 1770 */
1615int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, 1771int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs,
1616 int num_regs) 1772 int num_regs)