diff options
Diffstat (limited to 'drivers/pwm/pwm-tiehrpwm.c')
| -rw-r--r-- | drivers/pwm/pwm-tiehrpwm.c | 42 | 
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 565f96ad278..ee7a8b3dbed 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -25,6 +25,9 @@  #include <linux/err.h>  #include <linux/clk.h>  #include <linux/pm_runtime.h> +#include <linux/of_device.h> + +#include "pwm-tipwmss.h"  /* EHRPWM registers and bits definitions */ @@ -399,12 +402,19 @@ static const struct pwm_ops ehrpwm_pwm_ops = {  	.owner		= THIS_MODULE,  }; +static const struct of_device_id ehrpwm_of_match[] = { +	{ .compatible	= "ti,am33xx-ehrpwm" }, +	{}, +}; +MODULE_DEVICE_TABLE(of, ehrpwm_of_match); +  static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)  {  	int ret;  	struct resource *r;  	struct clk *clk;  	struct ehrpwm_pwm_chip *pc; +	u16 status;  	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);  	if (!pc) { @@ -426,6 +436,8 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)  	pc->chip.dev = &pdev->dev;  	pc->chip.ops = &ehrpwm_pwm_ops; +	pc->chip.of_xlate = of_pwm_xlate_with_flags; +	pc->chip.of_pwm_n_cells = 3;  	pc->chip.base = -1;  	pc->chip.npwm = NUM_PWM_CHANNEL; @@ -453,14 +465,40 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)  	}  	pm_runtime_enable(&pdev->dev); +	pm_runtime_get_sync(&pdev->dev); + +	status = pwmss_submodule_state_change(pdev->dev.parent, +			PWMSS_EPWMCLK_EN); +	if (!(status & PWMSS_EPWMCLK_EN_ACK)) { +		dev_err(&pdev->dev, "PWMSS config space clock enable failed\n"); +		ret = -EINVAL; +		goto pwmss_clk_failure; +	} + +	pm_runtime_put_sync(&pdev->dev); +  	platform_set_drvdata(pdev, pc);  	return 0; + +pwmss_clk_failure: +	pm_runtime_put_sync(&pdev->dev); +	pm_runtime_disable(&pdev->dev); +	pwmchip_remove(&pc->chip); +	return ret;  }  static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev)  {  	struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); +	pm_runtime_get_sync(&pdev->dev); +	/* +	 * Due to hardware misbehaviour, acknowledge of the stop_req +	 * is missing. Hence checking of the status bit skipped. +	 */ +	pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EPWMCLK_STOP_REQ); +	pm_runtime_put_sync(&pdev->dev); +  	pm_runtime_put_sync(&pdev->dev);  	pm_runtime_disable(&pdev->dev);  	return pwmchip_remove(&pc->chip); @@ -468,7 +506,9 @@ static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev)  static struct platform_driver ehrpwm_pwm_driver = {  	.driver = { -		.name = "ehrpwm", +		.name	= "ehrpwm", +		.owner	= THIS_MODULE, +		.of_match_table = ehrpwm_of_match,  	},  	.probe = ehrpwm_pwm_probe,  	.remove = __devexit_p(ehrpwm_pwm_remove),  |