aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2016-08-16 05:35:04 -0400
committerThierry Reding <thierry.reding@gmail.com>2016-09-08 04:55:10 -0400
commit25eb53809674a875c64da7f6e1ab9695684e431a (patch)
treeb70addb8072a2fd143cf9aa04652887e1f99a1ea /drivers/pwm
parent3f0925b5a864abded423dcedf86ec118139aa047 (diff)
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 <lee.jones@linaro.org> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/pwm-sti.c92
1 files changed, 91 insertions, 1 deletions
diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c
index 6d3e3850923b..bd753fbad08a 100644
--- a/drivers/pwm/pwm-sti.c
+++ b/drivers/pwm/pwm-sti.c
@@ -91,7 +91,9 @@ struct sti_pwm_chip {
91 struct regmap_field *prescale_low; 91 struct regmap_field *prescale_low;
92 struct regmap_field *prescale_high; 92 struct regmap_field *prescale_high;
93 struct regmap_field *pwm_out_en; 93 struct regmap_field *pwm_out_en;
94 struct regmap_field *pwm_cpt_en;
94 struct regmap_field *pwm_cpt_int_en; 95 struct regmap_field *pwm_cpt_int_en;
96 struct regmap_field *pwm_cpt_int_stat;
95 struct pwm_chip chip; 97 struct pwm_chip chip;
96 struct pwm_device *cur; 98 struct pwm_device *cur;
97 unsigned long configured; 99 unsigned long configured;
@@ -311,6 +313,76 @@ static const struct pwm_ops sti_pwm_ops = {
311 .owner = THIS_MODULE, 313 .owner = THIS_MODULE,
312}; 314};
313 315
316static 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
314static int sti_pwm_probe_dt(struct sti_pwm_chip *pc) 386static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
315{ 387{
316 struct device *dev = pc->dev; 388 struct device *dev = pc->dev;
@@ -351,6 +423,11 @@ static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
351 if (IS_ERR(pc->pwm_cpt_int_en)) 423 if (IS_ERR(pc->pwm_cpt_int_en))
352 return PTR_ERR(pc->pwm_cpt_int_en); 424 return PTR_ERR(pc->pwm_cpt_int_en);
353 425
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
354 return 0; 431 return 0;
355} 432}
356 433
@@ -367,7 +444,7 @@ static int sti_pwm_probe(struct platform_device *pdev)
367 struct sti_pwm_chip *pc; 444 struct sti_pwm_chip *pc;
368 struct resource *res; 445 struct resource *res;
369 unsigned int i; 446 unsigned int i;
370 int ret; 447 int irq, ret;
371 448
372 pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); 449 pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
373 if (!pc) 450 if (!pc)
@@ -388,6 +465,19 @@ static int sti_pwm_probe(struct platform_device *pdev)
388 if (IS_ERR(pc->regmap)) 465 if (IS_ERR(pc->regmap))
389 return PTR_ERR(pc->regmap); 466 return PTR_ERR(pc->regmap);
390 467
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
391 /* 481 /*
392 * Setup PWM data with default values: some values could be replaced 482 * Setup PWM data with default values: some values could be replaced
393 * with specific ones provided from Device Tree. 483 * with specific ones provided from Device Tree.