aboutsummaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--drivers/base/regmap/internal.h3
-rw-r--r--drivers/base/regmap/regmap.c103
-rw-r--r--include/linux/regmap.h13
3 files changed, 119 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
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index a10380bfbeac..a12bea07f79e 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -425,11 +425,15 @@ bool regmap_reg_in_ranges(unsigned int reg,
425 * @reg: Offset of the register within the regmap bank 425 * @reg: Offset of the register within the regmap bank
426 * @lsb: lsb of the register field. 426 * @lsb: lsb of the register field.
427 * @reg: msb of the register field. 427 * @reg: msb of the register field.
428 * @id_size: port size if it has some ports
429 * @id_offset: address offset for each ports
428 */ 430 */
429struct reg_field { 431struct reg_field {
430 unsigned int reg; 432 unsigned int reg;
431 unsigned int lsb; 433 unsigned int lsb;
432 unsigned int msb; 434 unsigned int msb;
435 unsigned int id_size;
436 unsigned int id_offset;
433}; 437};
434 438
435#define REG_FIELD(_reg, _lsb, _msb) { \ 439#define REG_FIELD(_reg, _lsb, _msb) { \
@@ -448,6 +452,15 @@ void devm_regmap_field_free(struct device *dev, struct regmap_field *field);
448 452
449int regmap_field_read(struct regmap_field *field, unsigned int *val); 453int regmap_field_read(struct regmap_field *field, unsigned int *val);
450int regmap_field_write(struct regmap_field *field, unsigned int val); 454int regmap_field_write(struct regmap_field *field, unsigned int val);
455int regmap_field_update_bits(struct regmap_field *field,
456 unsigned int mask, unsigned int val);
457
458int regmap_fields_write(struct regmap_field *field, unsigned int id,
459 unsigned int val);
460int regmap_fields_read(struct regmap_field *field, unsigned int id,
461 unsigned int *val);
462int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
463 unsigned int mask, unsigned int val);
451 464
452/** 465/**
453 * Description of an IRQ for the generic regmap irq_chip. 466 * Description of an IRQ for the generic regmap irq_chip.