aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2013-09-01 23:30:50 -0400
committerMark Brown <broonie@linaro.org>2013-09-17 08:46:57 -0400
commita0102375ee82db1e08324b1a21484854cf2c1677 (patch)
treec24bd05318c5bb9211c0b38867dfa9d0eb99bd8d /drivers/base
parentfdf200290581150f7b69148abf6ca860684cbfbb (diff)
regmap: Add regmap_fields APIs
Current Linux kernel is supporting regmap_field method and it is very useful feature. It needs one regmap_filed for one register access. OTOH, there is multi port device which has many same registers in the market. The difference for each register access is only its address offset. Current API needs many regmap_field for such device, but it is not good. This patch adds new regmap_fileds API which can care about multi port/offset access via regmap. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/internal.h3
-rw-r--r--drivers/base/regmap/regmap.c83
2 files changed, 86 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 285afa7470c0..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/**
@@ -1389,6 +1391,54 @@ int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsi
1389} 1391}
1390EXPORT_SYMBOL_GPL(regmap_field_update_bits); 1392EXPORT_SYMBOL_GPL(regmap_field_update_bits);
1391 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
1392/* 1442/*
1393 * regmap_bulk_write(): Write multiple registers to the device 1443 * regmap_bulk_write(): Write multiple registers to the device
1394 * 1444 *
@@ -1697,6 +1747,39 @@ int regmap_field_read(struct regmap_field *field, unsigned int *val)
1697EXPORT_SYMBOL_GPL(regmap_field_read); 1747EXPORT_SYMBOL_GPL(regmap_field_read);
1698 1748
1699/** 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/**
1700 * regmap_bulk_read(): Read multiple registers from the device 1783 * regmap_bulk_read(): Read multiple registers from the device
1701 * 1784 *
1702 * @map: Register map to write to 1785 * @map: Register map to write to