diff options
| author | Philip, Avinash <avinashphilip@ti.com> | 2012-11-27 03:48:13 -0500 |
|---|---|---|
| committer | Thierry Reding <thierry.reding@avionic-design.de> | 2012-11-28 09:16:17 -0500 |
| commit | 53ad9e8d37031397ee141f9bf701c0fba4257b0f (patch) | |
| tree | 41dda85d04ca64360a42874e6ea62a0299942de5 | |
| parent | d91861dafda44d808272f55758ca91d962feda6e (diff) | |
pwm: tiehrpwm: Add device-tree binding
This patch
1. Add support for device-tree binding for EHRWPM driver.
2. Set size of pwm-cells set to 3 to support PWM channel number, PWM
period & polarity configuration from device tree.
3. Add enable/disable clock gating in PWM subsystem common config space.
4. When here set .owner member in platform_driver structure to
THIS_MODULE.
Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
| -rw-r--r-- | Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt | 23 | ||||
| -rw-r--r-- | drivers/pwm/pwm-tiehrpwm.c | 42 |
2 files changed, 64 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt new file mode 100644 index 000000000000..4fc7079d822e --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | TI SOC EHRPWM based PWM controller | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : Must be "ti,am33xx-ehrpwm" | ||
| 5 | - #pwm-cells: Should be 3. Number of cells being used to specify PWM property. | ||
| 6 | First cell specifies the per-chip index of the PWM to use, the second | ||
| 7 | cell is the period in nanoseconds and bit 0 in the third cell is used to | ||
| 8 | encode the polarity of PWM output. Set bit 0 of the third in PWM specifier | ||
| 9 | to 1 for inverse polarity & set to 0 for normal polarity. | ||
| 10 | - reg: physical base address and size of the registers map. | ||
| 11 | |||
| 12 | Optional properties: | ||
| 13 | - ti,hwmods: Name of the hwmod associated to the EHRPWM: | ||
| 14 | "ehrpwm<x>", <x> being the 0-based instance number from the HW spec | ||
| 15 | |||
| 16 | Example: | ||
| 17 | |||
| 18 | ehrpwm0: ehrpwm@0 { | ||
| 19 | compatible = "ti,am33xx-ehrpwm"; | ||
| 20 | #pwm-cells = <3>; | ||
| 21 | reg = <0x48300200 0x100>; | ||
| 22 | ti,hwmods = "ehrpwm0"; | ||
| 23 | }; | ||
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 565f96ad2787..ee7a8b3dbed9 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c | |||
| @@ -25,6 +25,9 @@ | |||
| 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 | |||
| 30 | #include "pwm-tipwmss.h" | ||
| 28 | 31 | ||
| 29 | /* EHRPWM registers and bits definitions */ | 32 | /* EHRPWM registers and bits definitions */ |
| 30 | 33 | ||
| @@ -399,12 +402,19 @@ static const struct pwm_ops ehrpwm_pwm_ops = { | |||
| 399 | .owner = THIS_MODULE, | 402 | .owner = THIS_MODULE, |
| 400 | }; | 403 | }; |
| 401 | 404 | ||
| 405 | static const struct of_device_id ehrpwm_of_match[] = { | ||
| 406 | { .compatible = "ti,am33xx-ehrpwm" }, | ||
| 407 | {}, | ||
| 408 | }; | ||
| 409 | MODULE_DEVICE_TABLE(of, ehrpwm_of_match); | ||
| 410 | |||
| 402 | static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev) | 411 | static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev) |
| 403 | { | 412 | { |
| 404 | int ret; | 413 | int ret; |
| 405 | struct resource *r; | 414 | struct resource *r; |
| 406 | struct clk *clk; | 415 | struct clk *clk; |
| 407 | struct ehrpwm_pwm_chip *pc; | 416 | struct ehrpwm_pwm_chip *pc; |
| 417 | u16 status; | ||
| 408 | 418 | ||
| 409 | pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); | 419 | pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); |
| 410 | if (!pc) { | 420 | if (!pc) { |
| @@ -426,6 +436,8 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev) | |||
| 426 | 436 | ||
| 427 | pc->chip.dev = &pdev->dev; | 437 | pc->chip.dev = &pdev->dev; |
| 428 | pc->chip.ops = &ehrpwm_pwm_ops; | 438 | pc->chip.ops = &ehrpwm_pwm_ops; |
| 439 | pc->chip.of_xlate = of_pwm_xlate_with_flags; | ||
| 440 | pc->chip.of_pwm_n_cells = 3; | ||
| 429 | pc->chip.base = -1; | 441 | pc->chip.base = -1; |
| 430 | pc->chip.npwm = NUM_PWM_CHANNEL; | 442 | pc->chip.npwm = NUM_PWM_CHANNEL; |
| 431 | 443 | ||
| @@ -453,14 +465,40 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev) | |||
| 453 | } | 465 | } |
| 454 | 466 | ||
| 455 | pm_runtime_enable(&pdev->dev); | 467 | pm_runtime_enable(&pdev->dev); |
| 468 | pm_runtime_get_sync(&pdev->dev); | ||
| 469 | |||
| 470 | status = pwmss_submodule_state_change(pdev->dev.parent, | ||
| 471 | PWMSS_EPWMCLK_EN); | ||
| 472 | if (!(status & PWMSS_EPWMCLK_EN_ACK)) { | ||
| 473 | dev_err(&pdev->dev, "PWMSS config space clock enable failed\n"); | ||
| 474 | ret = -EINVAL; | ||
| 475 | goto pwmss_clk_failure; | ||
| 476 | } | ||
| 477 | |||
| 478 | pm_runtime_put_sync(&pdev->dev); | ||
| 479 | |||
| 456 | platform_set_drvdata(pdev, pc); | 480 | platform_set_drvdata(pdev, pc); |
| 457 | return 0; | 481 | return 0; |
| 482 | |||
| 483 | pwmss_clk_failure: | ||
| 484 | pm_runtime_put_sync(&pdev->dev); | ||
| 485 | pm_runtime_disable(&pdev->dev); | ||
| 486 | pwmchip_remove(&pc->chip); | ||
| 487 | return ret; | ||
| 458 | } | 488 | } |
| 459 | 489 | ||
| 460 | static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev) | 490 | static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev) |
| 461 | { | 491 | { |
| 462 | struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); | 492 | struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); |
| 463 | 493 | ||
| 494 | pm_runtime_get_sync(&pdev->dev); | ||
| 495 | /* | ||
| 496 | * Due to hardware misbehaviour, acknowledge of the stop_req | ||
| 497 | * is missing. Hence checking of the status bit skipped. | ||
| 498 | */ | ||
| 499 | pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EPWMCLK_STOP_REQ); | ||
| 500 | pm_runtime_put_sync(&pdev->dev); | ||
| 501 | |||
| 464 | pm_runtime_put_sync(&pdev->dev); | 502 | pm_runtime_put_sync(&pdev->dev); |
| 465 | pm_runtime_disable(&pdev->dev); | 503 | pm_runtime_disable(&pdev->dev); |
| 466 | return pwmchip_remove(&pc->chip); | 504 | return pwmchip_remove(&pc->chip); |
| @@ -468,7 +506,9 @@ static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev) | |||
| 468 | 506 | ||
| 469 | static struct platform_driver ehrpwm_pwm_driver = { | 507 | static struct platform_driver ehrpwm_pwm_driver = { |
| 470 | .driver = { | 508 | .driver = { |
| 471 | .name = "ehrpwm", | 509 | .name = "ehrpwm", |
| 510 | .owner = THIS_MODULE, | ||
| 511 | .of_match_table = ehrpwm_of_match, | ||
| 472 | }, | 512 | }, |
| 473 | .probe = ehrpwm_pwm_probe, | 513 | .probe = ehrpwm_pwm_probe, |
| 474 | .remove = __devexit_p(ehrpwm_pwm_remove), | 514 | .remove = __devexit_p(ehrpwm_pwm_remove), |
