Skip to content

Commit ee19b52

Browse files
andredlag-linaro
authored andcommitted
mfd: sec: Use chained IRQs for s2mpg10
On S2MPG10 (and similar like S2MPG11), top-level interrupt status and mask registers exist which need to be unmasked to get the PMIC interrupts. This additional status doesn't seem to exist on other PMICs in the S2MP* family, and the S2MPG10 driver is manually dealing with masking and unmasking currently. The correct approach here is to register this hierarchy as chained interrupts, though, without any additional manual steps. Doing so will also simplify addition of other, similar, PMICs (like S2MPG11) in the future. Update the driver to do just that. Signed-off-by: André Draszik <andre.draszik@linaro.org> Link: https://patch.msgid.link/20251114-s2mpg10-chained-irq-v1-1-34ddfa49c4cd@linaro.org Signed-off-by: Lee Jones <lee@kernel.org>
1 parent 56c1245 commit ee19b52

3 files changed

Lines changed: 77 additions & 25 deletions

File tree

drivers/mfd/sec-acpm.c

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -325,11 +325,6 @@ static struct regmap *sec_pmic_acpm_regmap_init(struct device *dev,
325325
return regmap;
326326
}
327327

328-
static void sec_pmic_acpm_mask_common_irqs(void *regmap_common)
329-
{
330-
regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
331-
}
332-
333328
static int sec_pmic_acpm_probe(struct platform_device *pdev)
334329
{
335330
struct regmap *regmap_common, *regmap_pmic, *regmap;
@@ -360,15 +355,10 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
360355
shared_ctx->speedy_channel = pdata->speedy_channel;
361356

362357
regmap_common = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_COMMON,
363-
pdata->regmap_cfg_common, false);
358+
pdata->regmap_cfg_common, true);
364359
if (IS_ERR(regmap_common))
365360
return PTR_ERR(regmap_common);
366361

367-
/* Mask all interrupts from 'common' block, until successful init */
368-
ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
369-
if (ret)
370-
return dev_err_probe(dev, ret, "failed to mask common block interrupts\n");
371-
372362
regmap_pmic = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_PMIC,
373363
pdata->regmap_cfg_pmic, false);
374364
if (IS_ERR(regmap_pmic))
@@ -391,17 +381,6 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev)
391381
if (device_property_read_bool(dev, "wakeup-source"))
392382
devm_device_init_wakeup(dev);
393383

394-
/* Unmask PMIC interrupt from 'common' block, now that everything is in place. */
395-
ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
396-
S2MPG10_COMMON_INT_SRC_PMIC);
397-
if (ret)
398-
return dev_err_probe(dev, ret, "failed to unmask PMIC interrupt\n");
399-
400-
/* Mask all interrupts from 'common' block on shutdown */
401-
ret = devm_add_action_or_reset(dev, sec_pmic_acpm_mask_common_irqs, regmap_common);
402-
if (ret)
403-
return ret;
404-
405384
return 0;
406385
}
407386

drivers/mfd/sec-irq.c

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
#include "sec-core.h"
2121

2222
static const struct regmap_irq s2mpg10_irqs[] = {
23+
REGMAP_IRQ_REG(S2MPG10_COMMON_IRQ_PMIC, 0, S2MPG10_COMMON_INT_SRC_PMIC),
24+
/* No documentation or other reference for remaining bits */
25+
REGMAP_IRQ_REG(S2MPG10_COMMON_IRQ_UNUSED, 0, GENMASK(7, 1)),
26+
};
27+
28+
static const struct regmap_irq s2mpg10_pmic_irqs[] = {
2329
REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONF, 0, S2MPG10_IRQ_PWRONF_MASK),
2430
REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONR, 0, S2MPG10_IRQ_PWRONR_MASK),
2531
REGMAP_IRQ_REG(S2MPG10_IRQ_JIGONBF, 0, S2MPG10_IRQ_JIGONBF_MASK),
@@ -183,11 +189,20 @@ static const struct regmap_irq s5m8767_irqs[] = {
183189
/* All S2MPG10 interrupt sources are read-only and don't require clearing */
184190
static const struct regmap_irq_chip s2mpg10_irq_chip = {
185191
.name = "s2mpg10",
192+
.status_base = S2MPG10_COMMON_INT,
193+
.mask_base = S2MPG10_COMMON_INT_MASK,
194+
.num_regs = 1,
186195
.irqs = s2mpg10_irqs,
187196
.num_irqs = ARRAY_SIZE(s2mpg10_irqs),
188-
.num_regs = 6,
197+
};
198+
199+
static const struct regmap_irq_chip s2mpg10_irq_chip_pmic = {
200+
.name = "s2mpg10-pmic",
189201
.status_base = S2MPG10_PMIC_INT1,
190202
.mask_base = S2MPG10_PMIC_INT1M,
203+
.num_regs = 6,
204+
.irqs = s2mpg10_pmic_irqs,
205+
.num_irqs = ARRAY_SIZE(s2mpg10_pmic_irqs),
191206
};
192207

193208
static const struct regmap_irq_chip s2mps11_irq_chip = {
@@ -253,6 +268,59 @@ static const struct regmap_irq_chip s5m8767_irq_chip = {
253268
.ack_base = S5M8767_REG_INT1,
254269
};
255270

271+
static int s2mpg1x_add_chained_irq_chip(struct device *dev, struct regmap *regmap, int pirq,
272+
struct regmap_irq_chip_data *parent,
273+
const struct regmap_irq_chip *chip,
274+
struct regmap_irq_chip_data **data)
275+
{
276+
int irq, ret;
277+
278+
irq = regmap_irq_get_virq(parent, pirq);
279+
if (irq < 0)
280+
return dev_err_probe(dev, irq, "Failed to get parent vIRQ(%d) for chip %s\n", pirq,
281+
chip->name);
282+
283+
ret = devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT | IRQF_SHARED, 0, chip, data);
284+
if (ret)
285+
return dev_err_probe(dev, ret, "Failed to add %s IRQ chip\n", chip->name);
286+
287+
return 0;
288+
}
289+
290+
static int sec_irq_init_s2mpg1x(struct sec_pmic_dev *sec_pmic)
291+
{
292+
const struct regmap_irq_chip *irq_chip, *chained_irq_chip;
293+
struct regmap_irq_chip_data *irq_data;
294+
struct regmap *regmap_common;
295+
int chained_pirq;
296+
int ret;
297+
298+
switch (sec_pmic->device_type) {
299+
case S2MPG10:
300+
irq_chip = &s2mpg10_irq_chip;
301+
chained_irq_chip = &s2mpg10_irq_chip_pmic;
302+
chained_pirq = S2MPG10_COMMON_IRQ_PMIC;
303+
break;
304+
default:
305+
return dev_err_probe(sec_pmic->dev, -EINVAL, "Unsupported device type %d\n",
306+
sec_pmic->device_type);
307+
};
308+
309+
regmap_common = dev_get_regmap(sec_pmic->dev, "common");
310+
if (!regmap_common)
311+
return dev_err_probe(sec_pmic->dev, -EINVAL, "No 'common' regmap %d\n",
312+
sec_pmic->device_type);
313+
314+
ret = devm_regmap_add_irq_chip(sec_pmic->dev, regmap_common, sec_pmic->irq, IRQF_ONESHOT, 0,
315+
irq_chip, &irq_data);
316+
if (ret)
317+
return dev_err_probe(sec_pmic->dev, ret, "Failed to add %s IRQ chip\n",
318+
irq_chip->name);
319+
320+
return s2mpg1x_add_chained_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic, chained_pirq,
321+
irq_data, chained_irq_chip, &sec_pmic->irq_data);
322+
}
323+
256324
int sec_irq_init(struct sec_pmic_dev *sec_pmic)
257325
{
258326
const struct regmap_irq_chip *sec_irq_chip;
@@ -268,8 +336,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
268336
sec_irq_chip = &s2mps14_irq_chip;
269337
break;
270338
case S2MPG10:
271-
sec_irq_chip = &s2mpg10_irq_chip;
272-
break;
339+
return sec_irq_init_s2mpg1x(sec_pmic);
273340
case S2MPS11X:
274341
sec_irq_chip = &s2mps11_irq_chip;
275342
break;

include/linux/mfd/samsung/irq.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ enum s2mpa01_irq {
5757
#define S2MPA01_IRQ_B24_TSD_MASK (1 << 4)
5858
#define S2MPA01_IRQ_B35_TSD_MASK (1 << 5)
5959

60+
enum s2mpg10_common_irq {
61+
/* Top-level (common) block */
62+
S2MPG10_COMMON_IRQ_PMIC,
63+
S2MPG10_COMMON_IRQ_UNUSED,
64+
};
65+
6066
enum s2mpg10_irq {
6167
/* PMIC */
6268
S2MPG10_IRQ_PWRONF,

0 commit comments

Comments
 (0)