aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-tiehrpwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pwm/pwm-tiehrpwm.c')
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index 9ffd389d0c8b..72a6dd40c9ec 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -25,6 +25,10 @@
25#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/clk.h> 26#include <linux/clk.h>
27#include <linux/pm_runtime.h> 27#include <linux/pm_runtime.h>
28#include <linux/of_device.h>
29#include <linux/pinctrl/consumer.h>
30
31#include "pwm-tipwmss.h"
28 32
29/* EHRPWM registers and bits definitions */ 33/* EHRPWM registers and bits definitions */
30 34
@@ -115,6 +119,7 @@ struct ehrpwm_pwm_chip {
115 void __iomem *mmio_base; 119 void __iomem *mmio_base;
116 unsigned long period_cycles[NUM_PWM_CHANNEL]; 120 unsigned long period_cycles[NUM_PWM_CHANNEL];
117 enum pwm_polarity polarity[NUM_PWM_CHANNEL]; 121 enum pwm_polarity polarity[NUM_PWM_CHANNEL];
122 struct clk *tbclk;
118}; 123};
119 124
120static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) 125static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
@@ -335,6 +340,9 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
335 /* Channels polarity can be configured from action qualifier module */ 340 /* Channels polarity can be configured from action qualifier module */
336 configure_polarity(pc, pwm->hwpwm); 341 configure_polarity(pc, pwm->hwpwm);
337 342
343 /* Enable TBCLK before enabling PWM device */
344 clk_enable(pc->tbclk);
345
338 /* Enable time counter for free_run */ 346 /* Enable time counter for free_run */
339 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); 347 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
340 return 0; 348 return 0;
@@ -363,6 +371,9 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
363 371
364 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); 372 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
365 373
374 /* Disabling TBCLK on PWM disable */
375 clk_disable(pc->tbclk);
376
366 /* Stop Time base counter */ 377 /* Stop Time base counter */
367 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT); 378 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
368 379
@@ -392,12 +403,24 @@ static const struct pwm_ops ehrpwm_pwm_ops = {
392 .owner = THIS_MODULE, 403 .owner = THIS_MODULE,
393}; 404};
394 405
406static const struct of_device_id ehrpwm_of_match[] = {
407 { .compatible = "ti,am33xx-ehrpwm" },
408 {},
409};
410MODULE_DEVICE_TABLE(of, ehrpwm_of_match);
411
395static int ehrpwm_pwm_probe(struct platform_device *pdev) 412static int ehrpwm_pwm_probe(struct platform_device *pdev)
396{ 413{
397 int ret; 414 int ret;
398 struct resource *r; 415 struct resource *r;
399 struct clk *clk; 416 struct clk *clk;
400 struct ehrpwm_pwm_chip *pc; 417 struct ehrpwm_pwm_chip *pc;
418 u16 status;
419 struct pinctrl *pinctrl;
420
421 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
422 if (IS_ERR(pinctrl))
423 dev_warn(&pdev->dev, "unable to select pin group\n");
401 424
402 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); 425 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
403 if (!pc) { 426 if (!pc) {
@@ -419,6 +442,8 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
419 442
420 pc->chip.dev = &pdev->dev; 443 pc->chip.dev = &pdev->dev;
421 pc->chip.ops = &ehrpwm_pwm_ops; 444 pc->chip.ops = &ehrpwm_pwm_ops;
445 pc->chip.of_xlate = of_pwm_xlate_with_flags;
446 pc->chip.of_pwm_n_cells = 3;
422 pc->chip.base = -1; 447 pc->chip.base = -1;
423 pc->chip.npwm = NUM_PWM_CHANNEL; 448 pc->chip.npwm = NUM_PWM_CHANNEL;
424 449
@@ -432,6 +457,13 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
432 if (!pc->mmio_base) 457 if (!pc->mmio_base)
433 return -EADDRNOTAVAIL; 458 return -EADDRNOTAVAIL;
434 459
460 /* Acquire tbclk for Time Base EHRPWM submodule */
461 pc->tbclk = devm_clk_get(&pdev->dev, "tbclk");
462 if (IS_ERR(pc->tbclk)) {
463 dev_err(&pdev->dev, "Failed to get tbclk\n");
464 return PTR_ERR(pc->tbclk);
465 }
466
435 ret = pwmchip_add(&pc->chip); 467 ret = pwmchip_add(&pc->chip);
436 if (ret < 0) { 468 if (ret < 0) {
437 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 469 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
@@ -439,14 +471,40 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
439 } 471 }
440 472
441 pm_runtime_enable(&pdev->dev); 473 pm_runtime_enable(&pdev->dev);
474 pm_runtime_get_sync(&pdev->dev);
475
476 status = pwmss_submodule_state_change(pdev->dev.parent,
477 PWMSS_EPWMCLK_EN);
478 if (!(status & PWMSS_EPWMCLK_EN_ACK)) {
479 dev_err(&pdev->dev, "PWMSS config space clock enable failed\n");
480 ret = -EINVAL;
481 goto pwmss_clk_failure;
482 }
483
484 pm_runtime_put_sync(&pdev->dev);
485
442 platform_set_drvdata(pdev, pc); 486 platform_set_drvdata(pdev, pc);
443 return 0; 487 return 0;
488
489pwmss_clk_failure:
490 pm_runtime_put_sync(&pdev->dev);
491 pm_runtime_disable(&pdev->dev);
492 pwmchip_remove(&pc->chip);
493 return ret;
444} 494}
445 495
446static int ehrpwm_pwm_remove(struct platform_device *pdev) 496static int ehrpwm_pwm_remove(struct platform_device *pdev)
447{ 497{
448 struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); 498 struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
449 499
500 pm_runtime_get_sync(&pdev->dev);
501 /*
502 * Due to hardware misbehaviour, acknowledge of the stop_req
503 * is missing. Hence checking of the status bit skipped.
504 */
505 pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EPWMCLK_STOP_REQ);
506 pm_runtime_put_sync(&pdev->dev);
507
450 pm_runtime_put_sync(&pdev->dev); 508 pm_runtime_put_sync(&pdev->dev);
451 pm_runtime_disable(&pdev->dev); 509 pm_runtime_disable(&pdev->dev);
452 return pwmchip_remove(&pc->chip); 510 return pwmchip_remove(&pc->chip);
@@ -454,7 +512,9 @@ static int ehrpwm_pwm_remove(struct platform_device *pdev)
454 512
455static struct platform_driver ehrpwm_pwm_driver = { 513static struct platform_driver ehrpwm_pwm_driver = {
456 .driver = { 514 .driver = {
457 .name = "ehrpwm", 515 .name = "ehrpwm",
516 .owner = THIS_MODULE,
517 .of_match_table = ehrpwm_of_match,
458 }, 518 },
459 .probe = ehrpwm_pwm_probe, 519 .probe = ehrpwm_pwm_probe,
460 .remove = ehrpwm_pwm_remove, 520 .remove = ehrpwm_pwm_remove,