[PATCH 6/7] pwm: move existing pwm driver to drivers/pwm

Eric Miao eric.y.miao at gmail.com
Tue Sep 28 04:02:28 EDT 2010


On Tue, Sep 28, 2010 at 3:40 PM, Arun Murthy <arun.murthy at stericsson.com> wrote:
> As of now only ab8500 and twl6030 are moved.
>

You can use 'git format-patch -M' to reduce the patch size when renaming
is involved.

> Signed-off-by: Arun Murthy <arun.murthy at stericsson.com>
> Acked-by: Linus Walleij <linus.walleij at stericsson.com>
> ---
>  drivers/mfd/Kconfig       |    9 --
>  drivers/mfd/Makefile      |    1 -
>  drivers/mfd/twl6030-pwm.c |  196 ---------------------------------------------
>  drivers/misc/Kconfig      |    9 --
>  drivers/misc/Makefile     |    1 -
>  drivers/misc/ab8500-pwm.c |  157 ------------------------------------
>  drivers/pwm/Kconfig       |   18 ++++
>  drivers/pwm/Makefile      |    3 +
>  drivers/pwm/pwm-ab8500.c  |  157 ++++++++++++++++++++++++++++++++++++
>  drivers/pwm/pwm-twl6040.c |  196 +++++++++++++++++++++++++++++++++++++++++++++
>  10 files changed, 374 insertions(+), 373 deletions(-)
>  delete mode 100644 drivers/mfd/twl6030-pwm.c
>  delete mode 100644 drivers/misc/ab8500-pwm.c
>  create mode 100644 drivers/pwm/pwm-ab8500.c
>  create mode 100644 drivers/pwm/pwm-twl6040.c
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 256fabd..ab1d376 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -186,15 +186,6 @@ config TWL4030_CODEC
>        select MFD_CORE
>        default n
>
> -config TWL6030_PWM
> -       tristate "TWL6030 PWM (Pulse Width Modulator) Support"
> -       depends on TWL4030_CORE
> -       select HAVE_PWM
> -       default n
> -       help
> -         Say yes here if you want support for TWL6030 PWM.
> -         This is used to control charging LED brightness.
> -
>  config MFD_STMPE
>        bool "Support STMicroelectronics STMPE"
>        depends on I2C=y && GENERIC_HARDIRQS
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index d5968cd..1a89dbf 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -37,7 +37,6 @@ obj-$(CONFIG_MENELAUS)                += menelaus.o
>  obj-$(CONFIG_TWL4030_CORE)     += twl-core.o twl4030-irq.o twl6030-irq.o
>  obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
>  obj-$(CONFIG_TWL4030_CODEC)    += twl4030-codec.o
> -obj-$(CONFIG_TWL6030_PWM)      += twl6030-pwm.o
>
>  obj-$(CONFIG_MFD_MC13783)      += mc13783-core.o
>
> diff --git a/drivers/mfd/twl6030-pwm.c b/drivers/mfd/twl6030-pwm.c
> deleted file mode 100644
> index b78324b..0000000
> --- a/drivers/mfd/twl6030-pwm.c
> +++ /dev/null
> @@ -1,196 +0,0 @@
> -/*
> - * twl6030_pwm.c
> - * Driver for PHOENIX (TWL6030) Pulse Width Modulator
> - *
> - * Copyright (C) 2010 Texas Instruments
> - * Author: Hemanth V <hemanthv at 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/slab.h>
> -#include <linux/pwm.h>
> -#include <linux/err.h>
> -#include <linux/i2c/twl.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
> -
> -int twl6030_pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
> -{
> -       u8 duty_cycle;
> -       int ret = 0;
> -
> -       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;
> -}
> -
> -int twl6030_pwm_enable(struct pwm_device *pwm)
> -{
> -       u8 val;
> -       int ret = 0;
> -
> -       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;
> -}
> -
> -int twl6030_pwm_disable(struct pwm_device *pwm)
> -{
> -       u8 val;
> -       int ret = 0;
> -
> -       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 ret;
> -       }
> -
> -       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 ret;
> -}
> -
> -static int __devinit twl6030_pwm_probe(struct platform_device *pdev)
> -{
> -       struct pwm_device *pwm;
> -       struct pwm_ops *pops;
> -       int ret;
> -       u8 val;
> -
> -       pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
> -       if (pwm == NULL) {
> -               dev_err(&pdev->dev, "failed to allocate memory\n");
> -               return -ENOMEM;
> -       }
> -       pops = kzalloc(sizeof(struct pwm_ops), GFP_KERNEL);
> -       if (pops == NULL) {
> -               dev_err(&pdev->dev, "failed to allocate memory\n");
> -               kfree(pwm);
> -               return -ENOMEM;
> -       }
> -
> -       pops->pwm_config = twl6030_pwm_config;
> -       pops->pwm_enable = twl6030_pwm_enable;
> -       pops->pwm_disable = twl6030_pwm_disable;
> -       pops->name = &pdev->name;
> -       pwm->dev = &pdev->dev;
> -       pwm->pwm_id = pdev->id;
> -       pwm->pops = pops;
> -       ret = pwm_device_register(pwm);
> -       if (ret < 0) {
> -               dev_err(&pdev->dev, "failed to register pwm device\n");
> -               kfree(pwm);
> -               kfree(pops);
> -               return ret;
> -       }
> -       platform_set_drvdata(pdev, pwm);
> -       /* 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(&pdev->dev, "Failed to configure PWM, Error %d\n", ret);
> -               return ret;
> -       }
> -       dev_dbg(&pdev->dev, "pwm probe successful\n");
> -       return ret;
> -}
> -
> -static int __devexit twl6030_pwm_remove(struct platform_device *pdev)
> -{
> -       struct pwm_device *pwm = platform_get_drvdata(pdev);
> -
> -       pwm_device_unregister(pwm);
> -       kfree(pwm->pops);
> -       kfree(pwm);
> -       dev_dbg(&pdev->dev, "pwm driver removed\n");
> -       return 0;
> -}
> -
> -static struct platform_driver twl6030_pwm_driver = {
> -       .driver = {
> -               .name = "twl6030_pwm",
> -               .owner = THIS_MODULE,
> -       },
> -       .probe = twl6030_pwm_probe,
> -       .remove = __devexit_p(twl6030_pwm_remove),
> -};
> -
> -static int __init twl6030_pwm_init(void)
> -{
> -       return platform_driver_register(&twl6030_pwm_driver);
> -}
> -
> -static void __exit twl6030_pwm_deinit(void)
> -{
> -       platform_driver_unregister(&twl6030_pwm_driver);
> -}
> -
> -subsys_initcall(twl6030_pwm_init);
> -module_exit(twl6030_pwm_deinit);
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index ff8ea55..2c38d4e 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -62,15 +62,6 @@ config ATMEL_PWM
>          purposes including software controlled power-efficient backlights
>          on LCD displays, motor control, and waveform generation.
>
> -config AB8500_PWM
> -       bool "AB8500 PWM support"
> -       depends on AB8500_CORE
> -       select HAVE_PWM
> -       help
> -         This driver exports functions to enable/disble/config/free Pulse
> -         Width Modulation in the Analog Baseband Chip AB8500.
> -         It is used by led and backlight driver to control the intensity.
> -
>  config ATMEL_TCLIB
>        bool "Atmel AT32/AT91 Timer/Counter Library"
>        depends on (AVR32 || ARCH_AT91)
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index 5da82965..21b4761 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -35,5 +35,4 @@ obj-y                         += eeprom/
>  obj-y                          += cb710/
>  obj-$(CONFIG_VMWARE_BALLOON)   += vmware_balloon.o
>  obj-$(CONFIG_ARM_CHARLCD)      += arm-charlcd.o
> -obj-$(CONFIG_AB8500_PWM)       += ab8500-pwm.o
>  obj-$(CONFIG_PCH_PHUB)         += pch_phub.o
> diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c
> deleted file mode 100644
> index d2b23b6..0000000
> --- a/drivers/misc/ab8500-pwm.c
> +++ /dev/null
> @@ -1,157 +0,0 @@
> -/*
> - * Copyright (C) ST-Ericsson SA 2010
> - *
> - * Author: Arun R Murthy <arun.murthy at stericsson.com>
> - * License terms: GNU General Public License (GPL) version 2
> - */
> -#include <linux/err.h>
> -#include <linux/platform_device.h>
> -#include <linux/slab.h>
> -#include <linux/pwm.h>
> -#include <linux/mfd/ab8500.h>
> -#include <linux/mfd/abx500.h>
> -
> -/*
> - * PWM Out generators
> - * Bank: 0x10
> - */
> -#define AB8500_PWM_OUT_CTRL1_REG       0x60
> -#define AB8500_PWM_OUT_CTRL2_REG       0x61
> -#define AB8500_PWM_OUT_CTRL7_REG       0x66
> -
> -/* backlight driver constants */
> -#define ENABLE_PWM                     1
> -#define DISABLE_PWM                    0
> -
> -static LIST_HEAD(pwm_list);
> -
> -int ab8500_pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
> -{
> -       int ret = 0;
> -       unsigned int higher_val, lower_val;
> -       u8 reg;
> -
> -       /*
> -        * get the first 8 bits that are be written to
> -        * AB8500_PWM_OUT_CTRL1_REG[0:7]
> -        */
> -       lower_val = duty_ns & 0x00FF;
> -       /*
> -        * get bits [9:10] that are to be written to
> -        * AB8500_PWM_OUT_CTRL2_REG[0:1]
> -        */
> -       higher_val = ((duty_ns & 0x0300) >> 8);
> -
> -       reg = AB8500_PWM_OUT_CTRL1_REG + ((pwm->pwm_id - 1) * 2);
> -
> -       ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC,
> -                       reg, (u8)lower_val);
> -       if (ret < 0)
> -               return ret;
> -       ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC,
> -                       (reg + 1), (u8)higher_val);
> -
> -       return ret;
> -}
> -
> -int ab8500_pwm_enable(struct pwm_device *pwm)
> -{
> -       int ret;
> -
> -       ret = abx500_mask_and_set_register_interruptible(pwm->dev,
> -                               AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
> -                               1 << (pwm->pwm_id-1), 1 << (pwm->pwm_id-1));
> -       if (ret < 0)
> -               dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n",
> -                                                       pwm->label, ret);
> -       return ret;
> -}
> -
> -int ab8500_pwm_disable(struct pwm_device *pwm)
> -{
> -       int ret;
> -
> -       ret = abx500_mask_and_set_register_interruptible(pwm->dev,
> -                               AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
> -                               1 << (pwm->pwm_id-1), DISABLE_PWM);
> -       if (ret < 0)
> -               dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n",
> -                                                       pwm->label, ret);
> -       return ret;
> -}
> -
> -static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
> -{
> -       int ret = 0;
> -       struct pwm_ops *pops;
> -       struct pwm_device *pwm_dev;
> -       /*
> -        * Nothing to be done in probe, this is required to get the
> -        * device which is required for ab8500 read and write
> -        */
> -       pops = kzalloc(sizeof(struct pwm_ops), GFP_KERNEL);
> -       if (pops == NULL) {
> -               dev_err(&pdev->dev, "failed to allocate memory\n");
> -               return -ENOMEM;
> -       }
> -       pwm_dev = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
> -       if (pwm_dev == NULL) {
> -               dev_err(&pdev->dev, "failed to allocate memory\n");
> -               kfree(pops);
> -               return -ENOMEM;
> -       }
> -       pops->pwm_config = ab8500_pwm_config;
> -       pops->pwm_enable = ab8500_pwm_enable;
> -       pops->pwm_disable = ab8500_pwm_disable;
> -       pops->name = "ab8500";
> -       pwm_dev->dev = &pdev->dev;
> -       pwm_dev->pwm_id = pdev->id;
> -       pwm_dev->pops = pops;
> -       ret = pwm_device_register(pwm_dev);
> -       if (ret < 0) {
> -               dev_err(&pdev->dev, "failed to register pwm device\n");
> -               kfree(pwm_dev);
> -               kfree(pops);
> -               return ret;
> -       }
> -       platform_set_drvdata(pdev, pwm_dev);
> -       dev_dbg(&pdev->dev, "pwm probe successful\n");
> -       return ret;
> -}
> -
> -static int __devexit ab8500_pwm_remove(struct platform_device *pdev)
> -{
> -       struct pwm_device *pwm_dev = platform_get_drvdata(pdev);
> -
> -       pwm_device_unregister(pwm_dev);
> -       dev_dbg(&pdev->dev, "pwm driver removed\n");
> -       kfree(pwm_dev->pops);
> -       kfree(pwm_dev);
> -       return 0;
> -}
> -
> -static struct platform_driver ab8500_pwm_driver = {
> -       .driver = {
> -               .name = "ab8500-pwm",
> -               .owner = THIS_MODULE,
> -       },
> -       .probe = ab8500_pwm_probe,
> -       .remove = __devexit_p(ab8500_pwm_remove),
> -};
> -
> -static int __init ab8500_pwm_init(void)
> -{
> -       return platform_driver_register(&ab8500_pwm_driver);
> -}
> -
> -static void __exit ab8500_pwm_exit(void)
> -{
> -       platform_driver_unregister(&ab8500_pwm_driver);
> -}
> -
> -subsys_initcall(ab8500_pwm_init);
> -module_exit(ab8500_pwm_exit);
> -MODULE_AUTHOR("Arun MURTHY <arun.murthy at stericsson.com>");
> -MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver");
> -MODULE_ALIAS("AB8500 PWM driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index a88640c..e347365 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -14,4 +14,22 @@ menuconfig PWM_DEVICES
>
>  if PWM_DEVICES
>
> +config AB8500_PWM
> +       bool "AB8500 PWM support"
> +       depends on AB8500_CORE
> +       select HAVE_PWM
> +       help
> +         This driver exports functions to enable/disble/config/free Pulse
> +         Width Modulation in the Analog Baseband Chip AB8500.
> +         It is used by led and backlight driver to control the intensity.
> +
> +config TWL6030_PWM
> +       tristate "TWL6030 PWM (Pulse Width Modulator) Support"
> +       depends on TWL4030_CORE
> +       select HAVE_PWM
> +       default n
> +       help
> +         Say yes here if you want support for TWL6030 PWM.
> +         This is used to control charging LED brightness.
> +
>  endif # PWM_DEVICES
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index 552f969..f35afb4 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -1 +1,4 @@
>  obj-$(CONFIG_PWM_DEVICES)      += pwm-core.o
> +
> +obj-$(CONFIG_AB8500_PWM)       += pwm-ab8500.o
> +obj-$(CONFIG_TWL6030_PWM)      += pwm-twl6030.o
> diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
> new file mode 100644
> index 0000000..d2b23b6
> --- /dev/null
> +++ b/drivers/pwm/pwm-ab8500.c
> @@ -0,0 +1,157 @@
> +/*
> + * Copyright (C) ST-Ericsson SA 2010
> + *
> + * Author: Arun R Murthy <arun.murthy at stericsson.com>
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/pwm.h>
> +#include <linux/mfd/ab8500.h>
> +#include <linux/mfd/abx500.h>
> +
> +/*
> + * PWM Out generators
> + * Bank: 0x10
> + */
> +#define AB8500_PWM_OUT_CTRL1_REG       0x60
> +#define AB8500_PWM_OUT_CTRL2_REG       0x61
> +#define AB8500_PWM_OUT_CTRL7_REG       0x66
> +
> +/* backlight driver constants */
> +#define ENABLE_PWM                     1
> +#define DISABLE_PWM                    0
> +
> +static LIST_HEAD(pwm_list);
> +
> +int ab8500_pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
> +{
> +       int ret = 0;
> +       unsigned int higher_val, lower_val;
> +       u8 reg;
> +
> +       /*
> +        * get the first 8 bits that are be written to
> +        * AB8500_PWM_OUT_CTRL1_REG[0:7]
> +        */
> +       lower_val = duty_ns & 0x00FF;
> +       /*
> +        * get bits [9:10] that are to be written to
> +        * AB8500_PWM_OUT_CTRL2_REG[0:1]
> +        */
> +       higher_val = ((duty_ns & 0x0300) >> 8);
> +
> +       reg = AB8500_PWM_OUT_CTRL1_REG + ((pwm->pwm_id - 1) * 2);
> +
> +       ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC,
> +                       reg, (u8)lower_val);
> +       if (ret < 0)
> +               return ret;
> +       ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC,
> +                       (reg + 1), (u8)higher_val);
> +
> +       return ret;
> +}
> +
> +int ab8500_pwm_enable(struct pwm_device *pwm)
> +{
> +       int ret;
> +
> +       ret = abx500_mask_and_set_register_interruptible(pwm->dev,
> +                               AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
> +                               1 << (pwm->pwm_id-1), 1 << (pwm->pwm_id-1));
> +       if (ret < 0)
> +               dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n",
> +                                                       pwm->label, ret);
> +       return ret;
> +}
> +
> +int ab8500_pwm_disable(struct pwm_device *pwm)
> +{
> +       int ret;
> +
> +       ret = abx500_mask_and_set_register_interruptible(pwm->dev,
> +                               AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
> +                               1 << (pwm->pwm_id-1), DISABLE_PWM);
> +       if (ret < 0)
> +               dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n",
> +                                                       pwm->label, ret);
> +       return ret;
> +}
> +
> +static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
> +{
> +       int ret = 0;
> +       struct pwm_ops *pops;
> +       struct pwm_device *pwm_dev;
> +       /*
> +        * Nothing to be done in probe, this is required to get the
> +        * device which is required for ab8500 read and write
> +        */
> +       pops = kzalloc(sizeof(struct pwm_ops), GFP_KERNEL);
> +       if (pops == NULL) {
> +               dev_err(&pdev->dev, "failed to allocate memory\n");
> +               return -ENOMEM;
> +       }
> +       pwm_dev = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
> +       if (pwm_dev == NULL) {
> +               dev_err(&pdev->dev, "failed to allocate memory\n");
> +               kfree(pops);
> +               return -ENOMEM;
> +       }
> +       pops->pwm_config = ab8500_pwm_config;
> +       pops->pwm_enable = ab8500_pwm_enable;
> +       pops->pwm_disable = ab8500_pwm_disable;
> +       pops->name = "ab8500";
> +       pwm_dev->dev = &pdev->dev;
> +       pwm_dev->pwm_id = pdev->id;
> +       pwm_dev->pops = pops;
> +       ret = pwm_device_register(pwm_dev);
> +       if (ret < 0) {
> +               dev_err(&pdev->dev, "failed to register pwm device\n");
> +               kfree(pwm_dev);
> +               kfree(pops);
> +               return ret;
> +       }
> +       platform_set_drvdata(pdev, pwm_dev);
> +       dev_dbg(&pdev->dev, "pwm probe successful\n");
> +       return ret;
> +}
> +
> +static int __devexit ab8500_pwm_remove(struct platform_device *pdev)
> +{
> +       struct pwm_device *pwm_dev = platform_get_drvdata(pdev);
> +
> +       pwm_device_unregister(pwm_dev);
> +       dev_dbg(&pdev->dev, "pwm driver removed\n");
> +       kfree(pwm_dev->pops);
> +       kfree(pwm_dev);
> +       return 0;
> +}
> +
> +static struct platform_driver ab8500_pwm_driver = {
> +       .driver = {
> +               .name = "ab8500-pwm",
> +               .owner = THIS_MODULE,
> +       },
> +       .probe = ab8500_pwm_probe,
> +       .remove = __devexit_p(ab8500_pwm_remove),
> +};
> +
> +static int __init ab8500_pwm_init(void)
> +{
> +       return platform_driver_register(&ab8500_pwm_driver);
> +}
> +
> +static void __exit ab8500_pwm_exit(void)
> +{
> +       platform_driver_unregister(&ab8500_pwm_driver);
> +}
> +
> +subsys_initcall(ab8500_pwm_init);
> +module_exit(ab8500_pwm_exit);
> +MODULE_AUTHOR("Arun MURTHY <arun.murthy at stericsson.com>");
> +MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver");
> +MODULE_ALIAS("AB8500 PWM driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/pwm/pwm-twl6040.c b/drivers/pwm/pwm-twl6040.c
> new file mode 100644
> index 0000000..b78324b
> --- /dev/null
> +++ b/drivers/pwm/pwm-twl6040.c
> @@ -0,0 +1,196 @@
> +/*
> + * twl6030_pwm.c
> + * Driver for PHOENIX (TWL6030) Pulse Width Modulator
> + *
> + * Copyright (C) 2010 Texas Instruments
> + * Author: Hemanth V <hemanthv at 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/slab.h>
> +#include <linux/pwm.h>
> +#include <linux/err.h>
> +#include <linux/i2c/twl.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
> +
> +int twl6030_pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
> +{
> +       u8 duty_cycle;
> +       int ret = 0;
> +
> +       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;
> +}
> +
> +int twl6030_pwm_enable(struct pwm_device *pwm)
> +{
> +       u8 val;
> +       int ret = 0;
> +
> +       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;
> +}
> +
> +int twl6030_pwm_disable(struct pwm_device *pwm)
> +{
> +       u8 val;
> +       int ret = 0;
> +
> +       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 ret;
> +       }
> +
> +       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 ret;
> +}
> +
> +static int __devinit twl6030_pwm_probe(struct platform_device *pdev)
> +{
> +       struct pwm_device *pwm;
> +       struct pwm_ops *pops;
> +       int ret;
> +       u8 val;
> +
> +       pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
> +       if (pwm == NULL) {
> +               dev_err(&pdev->dev, "failed to allocate memory\n");
> +               return -ENOMEM;
> +       }
> +       pops = kzalloc(sizeof(struct pwm_ops), GFP_KERNEL);
> +       if (pops == NULL) {
> +               dev_err(&pdev->dev, "failed to allocate memory\n");
> +               kfree(pwm);
> +               return -ENOMEM;
> +       }
> +
> +       pops->pwm_config = twl6030_pwm_config;
> +       pops->pwm_enable = twl6030_pwm_enable;
> +       pops->pwm_disable = twl6030_pwm_disable;
> +       pops->name = &pdev->name;
> +       pwm->dev = &pdev->dev;
> +       pwm->pwm_id = pdev->id;
> +       pwm->pops = pops;
> +       ret = pwm_device_register(pwm);
> +       if (ret < 0) {
> +               dev_err(&pdev->dev, "failed to register pwm device\n");
> +               kfree(pwm);
> +               kfree(pops);
> +               return ret;
> +       }
> +       platform_set_drvdata(pdev, pwm);
> +       /* 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(&pdev->dev, "Failed to configure PWM, Error %d\n", ret);
> +               return ret;
> +       }
> +       dev_dbg(&pdev->dev, "pwm probe successful\n");
> +       return ret;
> +}
> +
> +static int __devexit twl6030_pwm_remove(struct platform_device *pdev)
> +{
> +       struct pwm_device *pwm = platform_get_drvdata(pdev);
> +
> +       pwm_device_unregister(pwm);
> +       kfree(pwm->pops);
> +       kfree(pwm);
> +       dev_dbg(&pdev->dev, "pwm driver removed\n");
> +       return 0;
> +}
> +
> +static struct platform_driver twl6030_pwm_driver = {
> +       .driver = {
> +               .name = "twl6030_pwm",
> +               .owner = THIS_MODULE,
> +       },
> +       .probe = twl6030_pwm_probe,
> +       .remove = __devexit_p(twl6030_pwm_remove),
> +};
> +
> +static int __init twl6030_pwm_init(void)
> +{
> +       return platform_driver_register(&twl6030_pwm_driver);
> +}
> +
> +static void __exit twl6030_pwm_deinit(void)
> +{
> +       platform_driver_unregister(&twl6030_pwm_driver);
> +}
> +
> +subsys_initcall(twl6030_pwm_init);
> +module_exit(twl6030_pwm_deinit);
> --
> 1.7.2.dirty
>
>



More information about the linux-arm-kernel mailing list