diff options
Diffstat (limited to 'drivers/pwm/pwm-pxa.c')
| -rw-r--r-- | drivers/pwm/pwm-pxa.c | 59 | 
1 files changed, 55 insertions, 4 deletions
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c index a4d2164aaf5..0b312ec420b 100644 --- a/drivers/pwm/pwm-pxa.c +++ b/drivers/pwm/pwm-pxa.c @@ -8,7 +8,7 @@   * published by the Free Software Foundation.   *   * 2008-02-13	initial version - * 		eric miao <eric.miao@marvell.com> + *		eric miao <eric.miao@marvell.com>   */  #include <linux/module.h> @@ -19,6 +19,7 @@  #include <linux/clk.h>  #include <linux/io.h>  #include <linux/pwm.h> +#include <linux/of_device.h>  #include <asm/div64.h> @@ -124,6 +125,46 @@ static struct pwm_ops pxa_pwm_ops = {  	.owner = THIS_MODULE,  }; +#ifdef CONFIG_OF +/* + * Device tree users must create one device instance for each PWM channel. + * Hence we dispense with the HAS_SECONDARY_PWM and "tell" the original driver + * code that this is a single channel pxa25x-pwm.  Currently all devices are + * supported identically. + */ +static const struct of_device_id pwm_of_match[] = { +	{ .compatible = "marvell,pxa250-pwm", .data = &pwm_id_table[0]}, +	{ .compatible = "marvell,pxa270-pwm", .data = &pwm_id_table[0]}, +	{ .compatible = "marvell,pxa168-pwm", .data = &pwm_id_table[0]}, +	{ .compatible = "marvell,pxa910-pwm", .data = &pwm_id_table[0]}, +	{ } +}; +MODULE_DEVICE_TABLE(of, pwm_of_match); +#else +#define pwm_of_match NULL +#endif + +static const struct platform_device_id *pxa_pwm_get_id_dt(struct device *dev) +{ +	const struct of_device_id *id = of_match_device(pwm_of_match, dev); + +	return id ? id->data : NULL; +} + +static struct pwm_device * +pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) +{ +	struct pwm_device *pwm; + +	pwm = pwm_request_from_chip(pc, 0, NULL); +	if (IS_ERR(pwm)) +		return pwm; + +	pwm_set_period(pwm, args->args[0]); + +	return pwm; +} +  static int pwm_probe(struct platform_device *pdev)  {  	const struct platform_device_id *id = platform_get_device_id(pdev); @@ -131,11 +172,15 @@ static int pwm_probe(struct platform_device *pdev)  	struct resource *r;  	int ret = 0; +	if (IS_ENABLED(CONFIG_OF) && id == NULL) +		id = pxa_pwm_get_id_dt(&pdev->dev); + +	if (id == NULL) +		return -EINVAL; +  	pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); -	if (pwm == NULL) { -		dev_err(&pdev->dev, "failed to allocate memory\n"); +	if (pwm == NULL)  		return -ENOMEM; -	}  	pwm->clk = devm_clk_get(&pdev->dev, NULL);  	if (IS_ERR(pwm->clk)) @@ -146,6 +191,11 @@ static int pwm_probe(struct platform_device *pdev)  	pwm->chip.base = -1;  	pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1; +	if (IS_ENABLED(CONFIG_OF)) { +		pwm->chip.of_xlate = pxa_pwm_of_xlate; +		pwm->chip.of_pwm_n_cells = 1; +	} +  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r);  	if (IS_ERR(pwm->mmio_base)) @@ -176,6 +226,7 @@ static struct platform_driver pwm_driver = {  	.driver		= {  		.name	= "pxa25x-pwm",  		.owner	= THIS_MODULE, +		.of_match_table = pwm_of_match,  	},  	.probe		= pwm_probe,  	.remove		= pwm_remove,  | 
