Thread (1 message) 1 message, 1 author, 2010-09-28
STALE5790d

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

From: Eric Miao <hidden>
Date: 2010-09-28 08:02:28

On Tue, Sep 28, 2010 at 3:40 PM, Arun Murthy [off-list ref] 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.
quoted hunk
Signed-off-by: Arun Murthy <redacted>
Acked-by: Linus Walleij <redacted>
---
?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@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@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@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@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@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@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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help