From: Hemanth V
Date: Fri, 26 Aug 2011 10:49:29 +0530
Subject: [PATCH] Add PWM1 and PWM2 support to twl6030-pwm driver
This patch adds support for PWM1/PWM2. TWL6030 PWM driver also
supports Indicator LED PWM. Function pointers are defined for
for init, enable, disable and configuration for both Indicator LED
PWM (led_pwm) and PWM1/PWM2 (std_pwm)
Tested-by: Tomi Valkeinen
Signed-off-by: Hemanth V
---
drivers/mfd/twl6030-pwm.c | 324 ++--
1 files changed, 309 insertions(+), 15 deletions(-)
diff --git a/drivers/mfd/twl6030-pwm.c b/drivers/mfd/twl6030-pwm.c
index e8fee14..8d9c3f5 100644
--- a/drivers/mfd/twl6030-pwm.c
+++ b/drivers/mfd/twl6030-pwm.c
@@ -5,6 +5,9 @@
* Copyright (C) 2010 Texas Instruments
* Author: Hemanth V
*
+ * Added support for PWM1, PWM2
+ * Hemanth V
+ *
* 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.
@@ -36,7 +39,9 @@
#define PWM_CTRL2_CURR_02 (2 << 4)
/* LED supply source */
+#define PWM_CTRL2_SRC_VBUS (0 << 2)
#define PWM_CTRL2_SRC_VAC (1 << 2)
+#define PWM_CTRL2_SRC_EXT (2 << 2)
/* LED modes */
#define PWM_CTRL2_MODE_HW (0 << 0)
@@ -45,12 +50,53 @@
#define PWM_CTRL2_MODE_MASK0x3
+/* PWMs supported by driver */
+#define PWM_ID_LED 1
+#define PWM_ID_PWM12
+#define PWM_ID_PWM23
+
+#define LED_PWM1ON 0x00
+#define LED_PWM1OFF0x01
+#define LED_PWM2ON 0x03
+#define LED_PWM2OFF0x04
+#define TWL6030_TOGGLE30x92
+#define PWMSTATUS2 0x94
+
+/* Defines for TOGGLE3 register */
+#define PWM2EN (1 << 5)
+#define PWM2S (1 << 4)
+#define PWM2R (1 << 3)
+#define PWM1EN (1 << 2)
+#define PWM1S (1 << 1)
+#define PWM1R (1 << 0)
+
+/* Defines for PWMSTATUS2 register */
+#define PWM1_CLK_EN(1 << 1)
+#define PWM2_CLK_EN(1 << 3)
+#defineTRUE1
+#defineFALSE 0
+
+static DEFINE_MUTEX(pwm_lock);
+static LIST_HEAD(pwm_list);
+
+struct pwm_device;
+
+struct pwm_ops {
+ int (*config)(struct pwm_device *, int, int);
+ int (*enable)(struct pwm_device *);
+ void(*disable)(struct pwm_device *);
+ int (*init)(struct pwm_device *);
+};
+
struct pwm_device {
- const char *label;
- unsigned int pwm_id;
+ struct list_headnode;
+ const char *label;
+ unsigned intpwm_id;
+ unsigned intuse_count;
+ struct pwm_ops *ops;
};
-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+int led_pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
{
u8 duty_cycle;
int ret;
@@ -69,9 +115,8 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int
period_ns)
}
return 0;
}
-EXPORT_SYMBOL(pwm_config);
-int pwm_enable(struct pwm_device *pwm)
+int led_pwm_enable(struct pwm_device *pwm)
{
u8 val;
int ret;
@@ -95,9 +140,8 @@ int pwm_enable(struct pwm_device *pwm)
twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
return 0;
}
-EXPORT_SYMBOL(pwm_enable);
-void pwm_disable(struct pwm_device *pwm)
+void led_pwm_disable(struct pwm_device *pwm)
{
u8 val;
int ret;
@@ -120,37 +164,284 @@ void pwm_disable(struct pwm_device *pwm)
}
return;
}
-EXPORT_SYMBOL(pwm_disable);
-struct pwm_device *pwm_request(int pwm_id, const char *label)
+int led_pwm_init(struct pwm_device *pwm)
{
u8 val;
int ret;
+
+ val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VBUS |
+ PWM_CTRL2_MODE_HW;
+
+ ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
+
+ return ret;
+}
+
+static struct pwm_ops pwm_led = {
+ .config = led_pwm_config,
+ .enable = led_pwm_enable,
+ .disable = led_pwm_disable,
+ .init = led_pwm_init,
+};
+
+int std_pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+ int ret = 0, level, pwm_id, reg;
+
+ level = (duty_ns * PWM_CTRL1_MAX) / period_ns;
+ pwm_id = pwm->pwm_id;
+
+ if (pwm_id == PWM_ID_PWM1)
+ reg = LED_PWM1ON;
+ else
+ reg = LED_PWM2ON;
+
+ if (level > 1) {
+ if (level == 255)
+ level = 0x7F;
+ else
+ level = (~(level/2)) & 0x7F;
+
+ ret = twl_i2c_write_u8(TWL_MODULE_PWM, level, reg);
+ }
+
+ return ret;
+}
+
+void std_pwm_disable(struct pwm_device *pwm)
+{
+
+ int ret, pwm_id;
+ bool pwm1_enabled = FALSE;
+ bool pwm2_enabled = FALSE;
+ u8 reg_val, reset_val, dis_val = 0;
+
+