aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2015-10-12 14:24:30 -0400
committerMark Brown <broonie@kernel.org>2015-10-12 14:24:30 -0400
commitba5890a0c7576776ada71a21d95833a2281695e2 (patch)
tree2d923158136d2e48ffb4c4a14eb2ee674fc2bad2 /drivers/base
parent25cb62b76430a91cc6195f902e61c2cb84ade622 (diff)
parenta650fdd9427f1f5236f83d2d8137bea9b452fa53 (diff)
Merge tag 'regmap-irq-unmask' into regmap-next
regmap: Support for split mask and unmask interrupt registers This branch adds an interface for supporting devices which have separate mask and unmask registers. # gpg: Signature made Thu 17 Sep 2015 11:52:20 BST using RSA key ID 5D5487D0 # gpg: Oops: keyid_from_fingerprint: no pubkey # gpg: Oops: keyid_from_fingerprint: no pubkey # gpg: key 00000000 occurs more than once in the trustdb # gpg: key 16005C11: no public key for trusted key - skipped # gpg: key 16005C11 marked as ultimately trusted # gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>" # gpg: aka "Mark Brown <broonie@debian.org>" # gpg: aka "Mark Brown <broonie@kernel.org>" # gpg: aka "Mark Brown <broonie@tardis.ed.ac.uk>" # gpg: aka "Mark Brown <broonie@linaro.org>" # gpg: aka "Mark Brown <Mark.Brown@linaro.org>"
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/regmap-irq.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 38d1f72d869c..8d16db533527 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -63,6 +63,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
63 struct regmap *map = d->map; 63 struct regmap *map = d->map;
64 int i, ret; 64 int i, ret;
65 u32 reg; 65 u32 reg;
66 u32 unmask_offset;
66 67
67 if (d->chip->runtime_pm) { 68 if (d->chip->runtime_pm) {
68 ret = pm_runtime_get_sync(map->dev); 69 ret = pm_runtime_get_sync(map->dev);
@@ -79,12 +80,28 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
79 for (i = 0; i < d->chip->num_regs; i++) { 80 for (i = 0; i < d->chip->num_regs; i++) {
80 reg = d->chip->mask_base + 81 reg = d->chip->mask_base +
81 (i * map->reg_stride * d->irq_reg_stride); 82 (i * map->reg_stride * d->irq_reg_stride);
82 if (d->chip->mask_invert) 83 if (d->chip->mask_invert) {
83 ret = regmap_update_bits(d->map, reg, 84 ret = regmap_update_bits(d->map, reg,
84 d->mask_buf_def[i], ~d->mask_buf[i]); 85 d->mask_buf_def[i], ~d->mask_buf[i]);
85 else 86 } else if (d->chip->unmask_base) {
87 /* set mask with mask_base register */
88 ret = regmap_update_bits(d->map, reg,
89 d->mask_buf_def[i], ~d->mask_buf[i]);
90 if (ret < 0)
91 dev_err(d->map->dev,
92 "Failed to sync unmasks in %x\n",
93 reg);
94 unmask_offset = d->chip->unmask_base -
95 d->chip->mask_base;
96 /* clear mask with unmask_base register */
97 ret = regmap_update_bits(d->map,
98 reg + unmask_offset,
99 d->mask_buf_def[i],
100 d->mask_buf[i]);
101 } else {
86 ret = regmap_update_bits(d->map, reg, 102 ret = regmap_update_bits(d->map, reg,
87 d->mask_buf_def[i], d->mask_buf[i]); 103 d->mask_buf_def[i], d->mask_buf[i]);
104 }
88 if (ret != 0) 105 if (ret != 0)
89 dev_err(d->map->dev, "Failed to sync masks in %x\n", 106 dev_err(d->map->dev, "Failed to sync masks in %x\n",
90 reg); 107 reg);
@@ -116,7 +133,11 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
116 if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) { 133 if (d->mask_buf[i] && (d->chip->ack_base || d->chip->use_ack)) {
117 reg = d->chip->ack_base + 134 reg = d->chip->ack_base +
118 (i * map->reg_stride * d->irq_reg_stride); 135 (i * map->reg_stride * d->irq_reg_stride);
119 ret = regmap_write(map, reg, d->mask_buf[i]); 136 /* some chips ack by write 0 */
137 if (d->chip->ack_invert)
138 ret = regmap_write(map, reg, ~d->mask_buf[i]);
139 else
140 ret = regmap_write(map, reg, d->mask_buf[i]);
120 if (ret != 0) 141 if (ret != 0)
121 dev_err(d->map->dev, "Failed to ack 0x%x: %d\n", 142 dev_err(d->map->dev, "Failed to ack 0x%x: %d\n",
122 reg, ret); 143 reg, ret);
@@ -339,6 +360,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
339 int i; 360 int i;
340 int ret = -ENOMEM; 361 int ret = -ENOMEM;
341 u32 reg; 362 u32 reg;
363 u32 unmask_offset;
342 364
343 if (chip->num_regs <= 0) 365 if (chip->num_regs <= 0)
344 return -EINVAL; 366 return -EINVAL;
@@ -420,7 +442,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
420 if (chip->mask_invert) 442 if (chip->mask_invert)
421 ret = regmap_update_bits(map, reg, 443 ret = regmap_update_bits(map, reg,
422 d->mask_buf[i], ~d->mask_buf[i]); 444 d->mask_buf[i], ~d->mask_buf[i]);
423 else 445 else if (d->chip->unmask_base) {
446 unmask_offset = d->chip->unmask_base -
447 d->chip->mask_base;
448 ret = regmap_update_bits(d->map,
449 reg + unmask_offset,
450 d->mask_buf[i],
451 d->mask_buf[i]);
452 } else
424 ret = regmap_update_bits(map, reg, 453 ret = regmap_update_bits(map, reg,
425 d->mask_buf[i], d->mask_buf[i]); 454 d->mask_buf[i], d->mask_buf[i]);
426 if (ret != 0) { 455 if (ret != 0) {
@@ -445,7 +474,11 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
445 if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { 474 if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) {
446 reg = chip->ack_base + 475 reg = chip->ack_base +
447 (i * map->reg_stride * d->irq_reg_stride); 476 (i * map->reg_stride * d->irq_reg_stride);
448 ret = regmap_write(map, reg, 477 if (chip->ack_invert)
478 ret = regmap_write(map, reg,
479 ~(d->status_buf[i] & d->mask_buf[i]));
480 else
481 ret = regmap_write(map, reg,
449 d->status_buf[i] & d->mask_buf[i]); 482 d->status_buf[i] & d->mask_buf[i]);
450 if (ret != 0) { 483 if (ret != 0) {
451 dev_err(map->dev, "Failed to ack 0x%x: %d\n", 484 dev_err(map->dev, "Failed to ack 0x%x: %d\n",