|
35 | 35 | #define PWM_SR 0x0C
|
36 | 36 | #define PWM_ISR 0x1C
|
37 | 37 | /* Bit field in SR */
|
38 |
| -#define PWM_SR_ALL_CH_ON 0x0F |
| 38 | +#define PWM_SR_ALL_CH_MASK 0x0F |
39 | 39 |
|
40 | 40 | /* The following register is PWM channel related registers */
|
41 | 41 | #define PWM_CH_REG_OFFSET 0x200
|
@@ -463,6 +463,42 @@ static const struct of_device_id atmel_pwm_dt_ids[] = {
|
463 | 463 | };
|
464 | 464 | MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids);
|
465 | 465 |
|
| 466 | +static int atmel_pwm_enable_clk_if_on(struct atmel_pwm_chip *atmel_pwm, bool on) |
| 467 | +{ |
| 468 | + unsigned int i, cnt = 0; |
| 469 | + unsigned long sr; |
| 470 | + int ret = 0; |
| 471 | + |
| 472 | + sr = atmel_pwm_readl(atmel_pwm, PWM_SR) & PWM_SR_ALL_CH_MASK; |
| 473 | + if (!sr) |
| 474 | + return 0; |
| 475 | + |
| 476 | + cnt = bitmap_weight(&sr, atmel_pwm->chip.npwm); |
| 477 | + |
| 478 | + if (!on) |
| 479 | + goto disable_clk; |
| 480 | + |
| 481 | + for (i = 0; i < cnt; i++) { |
| 482 | + ret = clk_enable(atmel_pwm->clk); |
| 483 | + if (ret) { |
| 484 | + dev_err(atmel_pwm->chip.dev, |
| 485 | + "failed to enable clock for pwm %pe\n", |
| 486 | + ERR_PTR(ret)); |
| 487 | + |
| 488 | + cnt = i; |
| 489 | + goto disable_clk; |
| 490 | + } |
| 491 | + } |
| 492 | + |
| 493 | + return 0; |
| 494 | + |
| 495 | +disable_clk: |
| 496 | + while (cnt--) |
| 497 | + clk_disable(atmel_pwm->clk); |
| 498 | + |
| 499 | + return ret; |
| 500 | +} |
| 501 | + |
466 | 502 | static int atmel_pwm_probe(struct platform_device *pdev)
|
467 | 503 | {
|
468 | 504 | struct atmel_pwm_chip *atmel_pwm;
|
@@ -495,16 +531,23 @@ static int atmel_pwm_probe(struct platform_device *pdev)
|
495 | 531 | atmel_pwm->chip.ops = &atmel_pwm_ops;
|
496 | 532 | atmel_pwm->chip.npwm = 4;
|
497 | 533 |
|
| 534 | + ret = atmel_pwm_enable_clk_if_on(atmel_pwm, true); |
| 535 | + if (ret < 0) |
| 536 | + goto unprepare_clk; |
| 537 | + |
498 | 538 | ret = pwmchip_add(&atmel_pwm->chip);
|
499 | 539 | if (ret < 0) {
|
500 | 540 | dev_err(&pdev->dev, "failed to add PWM chip %d\n", ret);
|
501 |
| - goto unprepare_clk; |
| 541 | + goto disable_clk; |
502 | 542 | }
|
503 | 543 |
|
504 | 544 | platform_set_drvdata(pdev, atmel_pwm);
|
505 | 545 |
|
506 | 546 | return ret;
|
507 | 547 |
|
| 548 | +disable_clk: |
| 549 | + atmel_pwm_enable_clk_if_on(atmel_pwm, false); |
| 550 | + |
508 | 551 | unprepare_clk:
|
509 | 552 | clk_unprepare(atmel_pwm->clk);
|
510 | 553 | return ret;
|
|
0 commit comments