diff options
author | Mark Brown <broonie@kernel.org> | 2015-10-12 14:24:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-10-12 14:24:30 -0400 |
commit | ba5890a0c7576776ada71a21d95833a2281695e2 (patch) | |
tree | 2d923158136d2e48ffb4c4a14eb2ee674fc2bad2 /drivers/base | |
parent | 25cb62b76430a91cc6195f902e61c2cb84ade622 (diff) | |
parent | a650fdd9427f1f5236f83d2d8137bea9b452fa53 (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.c | 43 |
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", |