Skip to content

Commit 25eb538

Browse files
Lee Jonesthierryreding
authored andcommitted
pwm: sti: Add support for PWM capture interrupts
Here we're requesting the PWM capture IRQ and supplying the handler that will be called in the event of an interrupt to handle it. Signed-off-by: Lee Jones <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent 3f0925b commit 25eb538

File tree

1 file changed

+91
-1
lines changed

1 file changed

+91
-1
lines changed

drivers/pwm/pwm-sti.c

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ struct sti_pwm_chip {
9191
struct regmap_field *prescale_low;
9292
struct regmap_field *prescale_high;
9393
struct regmap_field *pwm_out_en;
94+
struct regmap_field *pwm_cpt_en;
9495
struct regmap_field *pwm_cpt_int_en;
96+
struct regmap_field *pwm_cpt_int_stat;
9597
struct pwm_chip chip;
9698
struct pwm_device *cur;
9799
unsigned long configured;
@@ -311,6 +313,76 @@ static const struct pwm_ops sti_pwm_ops = {
311313
.owner = THIS_MODULE,
312314
};
313315

316+
static irqreturn_t sti_pwm_interrupt(int irq, void *data)
317+
{
318+
struct sti_pwm_chip *pc = data;
319+
struct device *dev = pc->dev;
320+
struct sti_cpt_ddata *ddata;
321+
int devicenum;
322+
unsigned int cpt_int_stat;
323+
unsigned int reg;
324+
int ret = IRQ_NONE;
325+
326+
ret = regmap_field_read(pc->pwm_cpt_int_stat, &cpt_int_stat);
327+
if (ret)
328+
return ret;
329+
330+
while (cpt_int_stat) {
331+
devicenum = ffs(cpt_int_stat) - 1;
332+
333+
ddata = pwm_get_chip_data(&pc->chip.pwms[devicenum]);
334+
335+
/*
336+
* Capture input:
337+
* _______ _______
338+
* | | | |
339+
* __| |_________________| |________
340+
* ^0 ^1 ^2
341+
*
342+
* Capture start by the first available rising edge
343+
* When a capture event occurs, capture value (CPT_VALx)
344+
* is stored, index incremented, capture edge changed.
345+
*
346+
* After the capture, if the index > 1, we have collected
347+
* the necessary data so we signal the thread waiting for it
348+
* and disable the capture by setting capture edge to none
349+
*
350+
*/
351+
352+
regmap_read(pc->regmap,
353+
PWM_CPT_VAL(devicenum),
354+
&ddata->snapshot[ddata->index]);
355+
356+
switch (ddata->index) {
357+
case 0:
358+
case 1:
359+
regmap_read(pc->regmap, PWM_CPT_EDGE(devicenum), &reg);
360+
reg ^= PWM_CPT_EDGE_MASK;
361+
regmap_write(pc->regmap, PWM_CPT_EDGE(devicenum), reg);
362+
363+
ddata->index++;
364+
break;
365+
case 2:
366+
regmap_write(pc->regmap,
367+
PWM_CPT_EDGE(devicenum),
368+
CPT_EDGE_DISABLED);
369+
wake_up(&ddata->wait);
370+
break;
371+
default:
372+
dev_err(dev, "Internal error\n");
373+
}
374+
375+
cpt_int_stat &= ~BIT_MASK(devicenum);
376+
377+
ret = IRQ_HANDLED;
378+
}
379+
380+
/* Just ACK everything */
381+
regmap_write(pc->regmap, PWM_INT_ACK, PWM_INT_ACK_MASK);
382+
383+
return ret;
384+
}
385+
314386
static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
315387
{
316388
struct device *dev = pc->dev;
@@ -351,6 +423,11 @@ static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
351423
if (IS_ERR(pc->pwm_cpt_int_en))
352424
return PTR_ERR(pc->pwm_cpt_int_en);
353425

426+
pc->pwm_cpt_int_stat = devm_regmap_field_alloc(dev, pc->regmap,
427+
reg_fields[PWM_CPT_INT_STAT]);
428+
if (PTR_ERR_OR_ZERO(pc->pwm_cpt_int_stat))
429+
return PTR_ERR(pc->pwm_cpt_int_stat);
430+
354431
return 0;
355432
}
356433

@@ -367,7 +444,7 @@ static int sti_pwm_probe(struct platform_device *pdev)
367444
struct sti_pwm_chip *pc;
368445
struct resource *res;
369446
unsigned int i;
370-
int ret;
447+
int irq, ret;
371448

372449
pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
373450
if (!pc)
@@ -388,6 +465,19 @@ static int sti_pwm_probe(struct platform_device *pdev)
388465
if (IS_ERR(pc->regmap))
389466
return PTR_ERR(pc->regmap);
390467

468+
irq = platform_get_irq(pdev, 0);
469+
if (irq < 0) {
470+
dev_err(&pdev->dev, "Failed to obtain IRQ\n");
471+
return irq;
472+
}
473+
474+
ret = devm_request_irq(&pdev->dev, irq, sti_pwm_interrupt, 0,
475+
pdev->name, pc);
476+
if (ret < 0) {
477+
dev_err(&pdev->dev, "Failed to request IRQ\n");
478+
return ret;
479+
}
480+
391481
/*
392482
* Setup PWM data with default values: some values could be replaced
393483
* with specific ones provided from Device Tree.

0 commit comments

Comments
 (0)