All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
To: Thierry Reding <thierry.reding@avionic-design.de>
Cc: Samuel Ortiz <sameo@linux.intel.com>, NeilBrown <neilb@suse.de>,
	Benoit Cousson <b-cousson@ti.com>, Felipe Balbi <balbi@ti.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/2] pwm: Move TWL6030 PWM driver to PWM framework
Date: Mon, 03 Sep 2012 11:15:27 +0300	[thread overview]
Message-ID: <5044671F.2030303@ti.com> (raw)
In-Reply-To: <1346582458-7890-3-git-send-email-thierry.reding@avionic-design.de>

On 09/02/2012 01:40 PM, Thierry Reding wrote:
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index 5fbb2a6..1b1a789 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -638,6 +638,13 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
>  			return PTR_ERR(child);
>  	}
>  
> +	if (IS_ENABLED(CONFIG_PWM_TWL6030)) {

I think you should also check for the PMIC versions here before adding the child:
	if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) {

To avoid loading the twl6030-pwm driver for twl4030 class.

> +		child = add_child(TWL6030_MODULE_ID1, "twl6030-pwm", NULL, 0,
> +				  false, 0, 0);
> +		if (IS_ERR(child))
> +			return PTR_ERR(child);
> +	}
> +
>  	if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
>  	    twl_class_is_4030()) {
>  
> diff --git a/drivers/mfd/twl6030-pwm.c b/drivers/mfd/twl6030-pwm.c
> deleted file mode 100644
> index e8fee14..0000000
> --- a/drivers/mfd/twl6030-pwm.c
> +++ /dev/null
> @@ -1,165 +0,0 @@
> -/*
> - * twl6030_pwm.c
> - * Driver for PHOENIX (TWL6030) Pulse Width Modulator
> - *
> - * Copyright (C) 2010 Texas Instruments
> - * Author: Hemanth V <hemanthv@ti.com>
> - *
> - * This program is free software; you can redistribute it and/or modify it
> - * under the terms of the GNU General Public License version 2 as published by
> - * the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but WITHOUT
> - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> - * more details.
> - *
> - * You should have received a copy of the GNU General Public License along with
> - * this program.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <linux/module.h>
> -#include <linux/platform_device.h>
> -#include <linux/i2c/twl.h>
> -#include <linux/slab.h>
> -
> -#define LED_PWM_CTRL1	0xF4
> -#define LED_PWM_CTRL2	0xF5
> -
> -/* Max value for CTRL1 register */
> -#define PWM_CTRL1_MAX	255
> -
> -/* Pull down disable */
> -#define PWM_CTRL2_DIS_PD	(1 << 6)
> -
> -/* Current control 2.5 milli Amps */
> -#define PWM_CTRL2_CURR_02	(2 << 4)
> -
> -/* LED supply source */
> -#define PWM_CTRL2_SRC_VAC	(1 << 2)
> -
> -/* LED modes */
> -#define PWM_CTRL2_MODE_HW	(0 << 0)
> -#define PWM_CTRL2_MODE_SW	(1 << 0)
> -#define PWM_CTRL2_MODE_DIS	(2 << 0)
> -
> -#define PWM_CTRL2_MODE_MASK	0x3
> -
> -struct pwm_device {
> -	const char *label;
> -	unsigned int pwm_id;
> -};
> -
> -int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
> -{
> -	u8 duty_cycle;
> -	int ret;
> -
> -	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
> -		return -EINVAL;
> -
> -	duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns;
> -
> -	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1);
> -
> -	if (ret < 0) {
> -		pr_err("%s: Failed to configure PWM, Error %d\n",
> -			pwm->label, ret);
> -		return ret;
> -	}
> -	return 0;
> -}
> -EXPORT_SYMBOL(pwm_config);
> -
> -int pwm_enable(struct pwm_device *pwm)
> -{
> -	u8 val;
> -	int ret;
> -
> -	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
> -	if (ret < 0) {
> -		pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret);
> -		return ret;
> -	}
> -
> -	/* Change mode to software control */
> -	val &= ~PWM_CTRL2_MODE_MASK;
> -	val |= PWM_CTRL2_MODE_SW;
> -
> -	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
> -	if (ret < 0) {
> -		pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret);
> -		return ret;
> -	}
> -
> -	twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
> -	return 0;
> -}
> -EXPORT_SYMBOL(pwm_enable);
> -
> -void pwm_disable(struct pwm_device *pwm)
> -{
> -	u8 val;
> -	int ret;
> -
> -	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
> -	if (ret < 0) {
> -		pr_err("%s: Failed to disable PWM, Error %d\n",
> -			pwm->label, ret);
> -		return;
> -	}
> -
> -	val &= ~PWM_CTRL2_MODE_MASK;
> -	val |= PWM_CTRL2_MODE_HW;
> -
> -	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
> -	if (ret < 0) {
> -		pr_err("%s: Failed to disable PWM, Error %d\n",
> -			pwm->label, ret);
> -		return;
> -	}
> -	return;
> -}
> -EXPORT_SYMBOL(pwm_disable);
> -
> -struct pwm_device *pwm_request(int pwm_id, const char *label)
> -{
> -	u8 val;
> -	int ret;
> -	struct pwm_device *pwm;
> -
> -	pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
> -	if (pwm == NULL) {
> -		pr_err("%s: failed to allocate memory\n", label);
> -		return NULL;
> -	}
> -
> -	pwm->label = label;
> -	pwm->pwm_id = pwm_id;
> -
> -	/* Configure PWM */
> -	val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
> -		PWM_CTRL2_MODE_HW;
> -
> -	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
> -
> -	if (ret < 0) {
> -		pr_err("%s: Failed to configure PWM, Error %d\n",
> -			 pwm->label, ret);
> -
> -		kfree(pwm);
> -		return NULL;
> -	}
> -
> -	return pwm;
> -}
> -EXPORT_SYMBOL(pwm_request);
> -
> -void pwm_free(struct pwm_device *pwm)
> -{
> -	pwm_disable(pwm);
> -	kfree(pwm);
> -}
> -EXPORT_SYMBOL(pwm_free);
> -
> -MODULE_LICENSE("GPL");
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index e678005..ed81720 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -142,6 +142,15 @@ config  PWM_TIEHRPWM
>  	  To compile this driver as a module, choose M here: the module
>  	  will be called pwm-tiehrpwm.
>  
> +config PWM_TWL6030
> +	tristate "TWL6030 PWM support"
> +	depends on TWL4030_CORE
> +	help
> +	  Generic PWM framework driver for TWL6030.
> +
> +	  To compile this driver as a module, choose M here: the module
> +	  will be called pwm-twl6030.
> +
>  config PWM_VT8500
>  	tristate "vt8500 pwm support"
>  	depends on ARCH_VT8500
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index 29cf57e..acfe482 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -11,4 +11,5 @@ obj-$(CONFIG_PWM_SAMSUNG)	+= pwm-samsung.o
>  obj-$(CONFIG_PWM_TEGRA)		+= pwm-tegra.o
>  obj-$(CONFIG_PWM_TIECAP)	+= pwm-tiecap.o
>  obj-$(CONFIG_PWM_TIEHRPWM)	+= pwm-tiehrpwm.o
> +obj-$(CONFIG_PWM_TWL6030)	+= pwm-twl6030.o
>  obj-$(CONFIG_PWM_VT8500)	+= pwm-vt8500.o
> diff --git a/drivers/pwm/pwm-twl6030.c b/drivers/pwm/pwm-twl6030.c
> new file mode 100644
> index 0000000..8e63878
> --- /dev/null
> +++ b/drivers/pwm/pwm-twl6030.c
> @@ -0,0 +1,184 @@
> +/*
> + * twl6030_pwm.c
> + * Driver for PHOENIX (TWL6030) Pulse Width Modulator
> + *
> + * Copyright (C) 2010 Texas Instruments
> + * Author: Hemanth V <hemanthv@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +#include <linux/i2c/twl.h>
> +#include <linux/slab.h>
> +
> +#define LED_PWM_CTRL1	0xF4
> +#define LED_PWM_CTRL2	0xF5
> +
> +/* Max value for CTRL1 register */
> +#define PWM_CTRL1_MAX	255
> +
> +/* Pull down disable */
> +#define PWM_CTRL2_DIS_PD	(1 << 6)
> +
> +/* Current control 2.5 milli Amps */
> +#define PWM_CTRL2_CURR_02	(2 << 4)
> +
> +/* LED supply source */
> +#define PWM_CTRL2_SRC_VAC	(1 << 2)
> +
> +/* LED modes */
> +#define PWM_CTRL2_MODE_HW	(0 << 0)
> +#define PWM_CTRL2_MODE_SW	(1 << 0)
> +#define PWM_CTRL2_MODE_DIS	(2 << 0)
> +
> +#define PWM_CTRL2_MODE_MASK	0x3
> +
> +struct twl6030_pwm_chip {
> +	struct pwm_chip chip;
> +};
> +
> +static int twl6030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +	int ret;
> +	u8 val;
> +
> +	/* Configure PWM */
> +	val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
> +	      PWM_CTRL2_MODE_HW;
> +
> +	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
> +	if (ret < 0) {
> +		dev_err(chip->dev, "%s: Failed to configure PWM, Error %d\n",
> +			pwm->label, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int twl6030_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> +			      int duty_ns, int period_ns)
> +{
> +	u8 duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns;
> +	int ret;
> +
> +	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1);
> +	if (ret < 0) {
> +		pr_err("%s: Failed to configure PWM, Error %d\n",
> +			pwm->label, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +	int ret;
> +	u8 val;
> +
> +	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
> +	if (ret < 0) {
> +		dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
> +			pwm->label, ret);
> +		return ret;
> +	}
> +
> +	/* Change mode to software control */
> +	val &= ~PWM_CTRL2_MODE_MASK;
> +	val |= PWM_CTRL2_MODE_SW;
> +
> +	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
> +	if (ret < 0) {
> +		dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
> +			pwm->label, ret);
> +		return ret;
> +	}
> +
> +	twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
> +	return 0;
> +}
> +
> +static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +	int ret;
> +	u8 val;
> +
> +	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
> +	if (ret < 0) {
> +		dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
> +			pwm->label, ret);
> +		return;
> +	}
> +
> +	val &= ~PWM_CTRL2_MODE_MASK;
> +	val |= PWM_CTRL2_MODE_HW;
> +
> +	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
> +	if (ret < 0) {
> +		dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
> +			pwm->label, ret);
> +	}
> +}
> +
> +static const struct pwm_ops twl6030_pwm_ops = {
> +	.request = twl6030_pwm_request,
> +	.config = twl6030_pwm_config,
> +	.enable = twl6030_pwm_enable,
> +	.disable = twl6030_pwm_disable,
> +};
> +
> +static int twl6030_pwm_probe(struct platform_device *pdev)
> +{
> +	struct twl6030_pwm_chip *twl6030;
> +	int ret;
> +
> +	twl6030 = devm_kzalloc(&pdev->dev, sizeof(*twl6030), GFP_KERNEL);
> +	if (!twl6030)
> +		return -ENOMEM;
> +
> +	twl6030->chip.dev = &pdev->dev;
> +	twl6030->chip.ops = &twl6030_pwm_ops;
> +	twl6030->chip.base = -1;
> +	twl6030->chip.npwm = 1;
> +
> +	ret = pwmchip_add(&twl6030->chip);
> +	if (ret < 0)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, twl6030);
> +
> +	return 0;
> +}
> +
> +static int twl6030_pwm_remove(struct platform_device *pdev)
> +{
> +	struct twl6030_pwm_chip *twl6030 = platform_get_drvdata(pdev);
> +
> +	return pwmchip_remove(&twl6030->chip);
> +}
> +
> +static struct platform_driver twl6030_pwm_driver = {
> +	.driver = {
> +		.name = "twl6030-pwm",
> +	},
> +	.probe = twl6030_pwm_probe,
> +	.remove = __devexit_p(twl6030_pwm_remove),
> +};
> +module_platform_driver(twl6030_pwm_driver);
> +
> +MODULE_ALIAS("platform:twl6030-pwm");
> +MODULE_LICENSE("GPL");
> 


-- 
Péter

  reply	other threads:[~2012-09-03  8:15 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-02 10:40 [PATCH 0/2] mfd: twl: Move PWM driver to PWM framework Thierry Reding
2012-09-02 10:40 ` [PATCH 1/2] mfd: twl: Replace twl_has_*() macros by IS_ENABLED() Thierry Reding
2012-09-18  7:31   ` Peter Ujfalusi
2012-09-02 10:40 ` [PATCH 2/2] pwm: Move TWL6030 PWM driver to PWM framework Thierry Reding
2012-09-03  8:15   ` Peter Ujfalusi [this message]
2012-09-07 13:17     ` Thierry Reding
2012-09-03  8:11 ` [PATCH 0/2] mfd: twl: Move " Peter Ujfalusi
2012-09-07 13:19   ` Thierry Reding
2012-09-07 13:52     ` Peter Ujfalusi
2012-09-18  7:07       ` Thierry Reding
2012-09-18  7:32         ` Peter Ujfalusi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5044671F.2030303@ti.com \
    --to=peter.ujfalusi@ti.com \
    --cc=b-cousson@ti.com \
    --cc=balbi@ti.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=neilb@suse.de \
    --cc=sameo@linux.intel.com \
    --cc=thierry.reding@avionic-design.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.