diff options
Diffstat (limited to '')
-rw-r--r-- | drivers/pwm/pwm-twl6030.c (renamed from drivers/mfd/twl6030-pwm.c) | 119 |
1 files changed, 69 insertions, 50 deletions
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"); |