diff options
author | Thierry Reding <thierry.reding@avionic-design.de> | 2012-09-18 10:29:51 +0200 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-09-19 12:04:25 +0200 |
commit | 48a364b758f861b21747a5148f26aedc504edb7f (patch) | |
tree | e76941d9155ecd0dc5534ef840a5c0d6ddc107f0 /drivers/pwm | |
parent | mfd: twl: Replace twl_has_*() macros by IS_ENABLED() (diff) | |
download | linux-48a364b758f861b21747a5148f26aedc504edb7f.tar.xz linux-48a364b758f861b21747a5148f26aedc504edb7f.zip |
pwm: Move TWL6030 PWM driver to PWM framework
This commit moves the driver to drivers/pwm and converts it to the new
PWM framework. In order for this to work properly, register the PWM as
child of the multi-function TWL6030 device.
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to '')
-rw-r--r-- | drivers/pwm/Kconfig | 9 | ||||
-rw-r--r-- | drivers/pwm/Makefile | 1 | ||||
-rw-r--r-- | drivers/pwm/pwm-twl6030.c (renamed from drivers/mfd/twl6030-pwm.c) | 119 |
3 files changed, 79 insertions, 50 deletions
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 8fc3808d7a3e..c7500dcdc65e 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -96,6 +96,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 e4b2c898964d..78f123dca30d 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -8,4 +8,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/mfd/twl6030-pwm.c b/drivers/pwm/pwm-twl6030.c index e8fee147678d..8e6387864ca2 100644 --- a/drivers/mfd/twl6030-pwm.c +++ b/drivers/pwm/pwm-twl6030.c @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/pwm.h> #include <linux/i2c/twl.h> #include <linux/slab.h> @@ -45,40 +46,54 @@ #define PWM_CTRL2_MODE_MASK 0x3 -struct pwm_device { - const char *label; - unsigned int pwm_id; +struct twl6030_pwm_chip { + struct pwm_chip chip; }; -int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +static int twl6030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { - u8 duty_cycle; int ret; + u8 val; - if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) - return -EINVAL; + /* Configure PWM */ + val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC | + PWM_CTRL2_MODE_HW; - duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns; + 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; + } - ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1); + 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; } -EXPORT_SYMBOL(pwm_config); -int pwm_enable(struct pwm_device *pwm) +static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { - u8 val; int ret; + u8 val; 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); + dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n", + pwm->label, ret); return ret; } @@ -88,23 +103,23 @@ int pwm_enable(struct pwm_device *pwm) 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); + 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; } -EXPORT_SYMBOL(pwm_enable); -void pwm_disable(struct pwm_device *pwm) +static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { - u8 val; int ret; + u8 val; 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", + dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n", pwm->label, ret); return; } @@ -114,52 +129,56 @@ void pwm_disable(struct pwm_device *pwm) 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", + dev_err(chip->dev, "%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) +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) { - u8 val; + struct twl6030_pwm_chip *twl6030; 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; + twl6030 = devm_kzalloc(&pdev->dev, sizeof(*twl6030), GFP_KERNEL); + if (!twl6030) + return -ENOMEM; - ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); + twl6030->chip.dev = &pdev->dev; + twl6030->chip.ops = &twl6030_pwm_ops; + twl6030->chip.base = -1; + twl6030->chip.npwm = 1; - if (ret < 0) { - pr_err("%s: Failed to configure PWM, Error %d\n", - pwm->label, ret); + ret = pwmchip_add(&twl6030->chip); + if (ret < 0) + return ret; - kfree(pwm); - return NULL; - } + platform_set_drvdata(pdev, twl6030); - return pwm; + return 0; } -EXPORT_SYMBOL(pwm_request); -void pwm_free(struct pwm_device *pwm) +static int twl6030_pwm_remove(struct platform_device *pdev) { - pwm_disable(pwm); - kfree(pwm); + struct twl6030_pwm_chip *twl6030 = platform_get_drvdata(pdev); + + return pwmchip_remove(&twl6030->chip); } -EXPORT_SYMBOL(pwm_free); +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"); |