Skip to content

Commit a71411d

Browse files
mgrzeschikbroonie
authored andcommitted
regmap: irq: add chip option mask_writeonly
Some irq controllers have writeonly/multipurpose register layouts. In those cases we read invalid data back. Here we add the option mask_writeonly as masking option. Signed-off-by: Michael Grzeschik <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 63c73b0 commit a71411d

File tree

2 files changed

+27
-15
lines changed

2 files changed

+27
-15
lines changed

drivers/base/regmap/regmap-irq.c

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ static void regmap_irq_lock(struct irq_data *data)
6060
mutex_lock(&d->lock);
6161
}
6262

63+
static int regmap_irq_update_bits(struct regmap_irq_chip_data *d,
64+
unsigned int reg, unsigned int mask,
65+
unsigned int val)
66+
{
67+
if (d->chip->mask_writeonly)
68+
return regmap_write_bits(d->map, reg, mask, val);
69+
else
70+
return regmap_update_bits(d->map, reg, mask, val);
71+
}
72+
6373
static void regmap_irq_sync_unlock(struct irq_data *data)
6474
{
6575
struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
@@ -84,11 +94,11 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
8494
reg = d->chip->mask_base +
8595
(i * map->reg_stride * d->irq_reg_stride);
8696
if (d->chip->mask_invert) {
87-
ret = regmap_update_bits(d->map, reg,
97+
ret = regmap_irq_update_bits(d, reg,
8898
d->mask_buf_def[i], ~d->mask_buf[i]);
8999
} else if (d->chip->unmask_base) {
90100
/* set mask with mask_base register */
91-
ret = regmap_update_bits(d->map, reg,
101+
ret = regmap_irq_update_bits(d, reg,
92102
d->mask_buf_def[i], ~d->mask_buf[i]);
93103
if (ret < 0)
94104
dev_err(d->map->dev,
@@ -97,12 +107,12 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
97107
unmask_offset = d->chip->unmask_base -
98108
d->chip->mask_base;
99109
/* clear mask with unmask_base register */
100-
ret = regmap_update_bits(d->map,
110+
ret = regmap_irq_update_bits(d,
101111
reg + unmask_offset,
102112
d->mask_buf_def[i],
103113
d->mask_buf[i]);
104114
} else {
105-
ret = regmap_update_bits(d->map, reg,
115+
ret = regmap_irq_update_bits(d, reg,
106116
d->mask_buf_def[i], d->mask_buf[i]);
107117
}
108118
if (ret != 0)
@@ -113,11 +123,11 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
113123
(i * map->reg_stride * d->irq_reg_stride);
114124
if (d->wake_buf) {
115125
if (d->chip->wake_invert)
116-
ret = regmap_update_bits(d->map, reg,
126+
ret = regmap_irq_update_bits(d, reg,
117127
d->mask_buf_def[i],
118128
~d->wake_buf[i]);
119129
else
120-
ret = regmap_update_bits(d->map, reg,
130+
ret = regmap_irq_update_bits(d, reg,
121131
d->mask_buf_def[i],
122132
d->wake_buf[i]);
123133
if (ret != 0)
@@ -153,10 +163,10 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
153163
reg = d->chip->type_base +
154164
(i * map->reg_stride * d->type_reg_stride);
155165
if (d->chip->type_invert)
156-
ret = regmap_update_bits(d->map, reg,
166+
ret = regmap_irq_update_bits(d, reg,
157167
d->type_buf_def[i], ~d->type_buf[i]);
158168
else
159-
ret = regmap_update_bits(d->map, reg,
169+
ret = regmap_irq_update_bits(d, reg,
160170
d->type_buf_def[i], d->type_buf[i]);
161171
if (ret != 0)
162172
dev_err(d->map->dev, "Failed to sync type in %x\n",
@@ -519,17 +529,17 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
519529
reg = chip->mask_base +
520530
(i * map->reg_stride * d->irq_reg_stride);
521531
if (chip->mask_invert)
522-
ret = regmap_update_bits(map, reg,
532+
ret = regmap_irq_update_bits(d, reg,
523533
d->mask_buf[i], ~d->mask_buf[i]);
524534
else if (d->chip->unmask_base) {
525535
unmask_offset = d->chip->unmask_base -
526536
d->chip->mask_base;
527-
ret = regmap_update_bits(d->map,
537+
ret = regmap_irq_update_bits(d,
528538
reg + unmask_offset,
529539
d->mask_buf[i],
530540
d->mask_buf[i]);
531541
} else
532-
ret = regmap_update_bits(map, reg,
542+
ret = regmap_irq_update_bits(d, reg,
533543
d->mask_buf[i], d->mask_buf[i]);
534544
if (ret != 0) {
535545
dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
@@ -575,11 +585,11 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
575585
(i * map->reg_stride * d->irq_reg_stride);
576586

577587
if (chip->wake_invert)
578-
ret = regmap_update_bits(map, reg,
588+
ret = regmap_irq_update_bits(d, reg,
579589
d->mask_buf_def[i],
580590
0);
581591
else
582-
ret = regmap_update_bits(map, reg,
592+
ret = regmap_irq_update_bits(d, reg,
583593
d->mask_buf_def[i],
584594
d->wake_buf[i]);
585595
if (ret != 0) {
@@ -603,10 +613,10 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
603613
reg = chip->type_base +
604614
(i * map->reg_stride * d->type_reg_stride);
605615
if (chip->type_invert)
606-
ret = regmap_update_bits(map, reg,
616+
ret = regmap_irq_update_bits(d, reg,
607617
d->type_buf_def[i], 0xFF);
608618
else
609-
ret = regmap_update_bits(map, reg,
619+
ret = regmap_irq_update_bits(d, reg,
610620
d->type_buf_def[i], 0x0);
611621
if (ret != 0) {
612622
dev_err(map->dev,

include/linux/regmap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ struct regmap_irq {
884884
*
885885
* @status_base: Base status register address.
886886
* @mask_base: Base mask register address.
887+
* @mask_writeonly: Base mask register is write only.
887888
* @unmask_base: Base unmask register address. for chips who have
888889
* separate mask and unmask registers
889890
* @ack_base: Base ack address. If zero then the chip is clear on read.
@@ -927,6 +928,7 @@ struct regmap_irq_chip {
927928
unsigned int wake_base;
928929
unsigned int type_base;
929930
unsigned int irq_reg_stride;
931+
bool mask_writeonly:1;
930932
bool init_ack_masked:1;
931933
bool mask_invert:1;
932934
bool use_ack:1;

0 commit comments

Comments
 (0)