aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-09-24 14:53:26 -0400
committerMark Brown <broonie@linaro.org>2013-09-24 14:53:26 -0400
commitef85b642460a4cc84086a7fe20915dae58dabcb2 (patch)
tree20cb7e3610702c0afb334907b9f93a0c32ad01d3 /drivers
parentd3be689e6a07c00123786659b4429b07cf4272ac (diff)
parenta0102375ee82db1e08324b1a21484854cf2c1677 (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.h3
-rw-r--r--drivers/base/regmap/regmap.c103
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}
1370EXPORT_SYMBOL_GPL(regmap_field_write); 1372EXPORT_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 */
1385int 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}
1392EXPORT_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 */
1404int 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}
1414EXPORT_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 */
1428int 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}
1440EXPORT_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)
1677EXPORT_SYMBOL_GPL(regmap_field_read); 1747EXPORT_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 */
1759int 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 &reg_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}
1780EXPORT_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