aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHemanth V <hemanthv@ti.com>2010-07-14 06:04:56 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2010-08-12 05:27:59 -0400
commit31fc03df5df364100a41134783c02490fbd25745 (patch)
tree761c424eebb03314ca98b49e6c3b05e4c9ad8cda
parent9accdc1bf239ef20c0fe12ceff2a7532374fd7cd (diff)
mfd: Add support for TWL6030 PWM
TWL6030 supports PWM (Pulse Width Modulator) which is used to control charging LED. PWM allows for controlling brightness. This patch implements the APIs required by leds-pwm driver. Signed-off-by: Hemanth V <hemanthv@ti.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/Kconfig9
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/twl6030-pwm.c163
3 files changed, 173 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index d59334f34bf6..23a891f396e4 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -186,6 +186,15 @@ config TWL4030_CODEC
186 select MFD_CORE 186 select MFD_CORE
187 default n 187 default n
188 188
189config TWL6030_PWM
190 tristate "TWL6030 PWM (Pulse Width Modulator) Support"
191 depends on TWL4030_CORE
192 select HAVE_PWM
193 default n
194 help
195 Say yes here if you want support for TWL6030 PWM.
196 This is used to control charging LED brightness.
197
189config MFD_STMPE 198config MFD_STMPE
190 bool "Support STMicroelectronics STMPE" 199 bool "Support STMicroelectronics STMPE"
191 depends on I2C=y && GENERIC_HARDIRQS 200 depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 1f7077966994..cc7cce0976f3 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_MENELAUS) += menelaus.o
37obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o 37obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
38obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o 38obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
39obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o 39obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o
40obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
40 41
41obj-$(CONFIG_MFD_MC13783) += mc13783-core.o 42obj-$(CONFIG_MFD_MC13783) += mc13783-core.o
42 43
diff --git a/drivers/mfd/twl6030-pwm.c b/drivers/mfd/twl6030-pwm.c
new file mode 100644
index 000000000000..5d25bdc78424
--- /dev/null
+++ b/drivers/mfd/twl6030-pwm.c
@@ -0,0 +1,163 @@
1/*
2 * twl6030_pwm.c
3 * Driver for PHOENIX (TWL6030) Pulse Width Modulator
4 *
5 * Copyright (C) 2010 Texas Instruments
6 * Author: Hemanth V <hemanthv@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <linux/module.h>
22#include <linux/platform_device.h>
23#include <linux/i2c/twl.h>
24#include <linux/slab.h>
25
26#define LED_PWM_CTRL1 0xF4
27#define LED_PWM_CTRL2 0xF5
28
29/* Max value for CTRL1 register */
30#define PWM_CTRL1_MAX 255
31
32/* Pull down disable */
33#define PWM_CTRL2_DIS_PD (1 << 6)
34
35/* Current control 2.5 milli Amps */
36#define PWM_CTRL2_CURR_02 (2 << 4)
37
38/* LED supply source */
39#define PWM_CTRL2_SRC_VAC (1 << 2)
40
41/* LED modes */
42#define PWM_CTRL2_MODE_HW (0 << 0)
43#define PWM_CTRL2_MODE_SW (1 << 0)
44#define PWM_CTRL2_MODE_DIS (2 << 0)
45
46#define PWM_CTRL2_MODE_MASK 0x3
47
48struct pwm_device {
49 const char *label;
50 unsigned int pwm_id;
51};
52
53int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
54{
55 u8 duty_cycle;
56 int ret;
57
58 if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
59 return -EINVAL;
60
61 duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns;
62
63 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1);
64
65 if (ret < 0) {
66 pr_err("%s: Failed to configure PWM, Error %d\n",
67 pwm->label, ret);
68 return ret;
69 }
70 return 0;
71}
72EXPORT_SYMBOL(pwm_config);
73
74int pwm_enable(struct pwm_device *pwm)
75{
76 u8 val;
77 int ret;
78
79 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
80 if (ret < 0) {
81 pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret);
82 return ret;
83 }
84
85 /* Change mode to software control */
86 val &= ~PWM_CTRL2_MODE_MASK;
87 val |= PWM_CTRL2_MODE_SW;
88
89 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
90 if (ret < 0) {
91 pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret);
92 return ret;
93 }
94
95 twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
96 return 0;
97}
98EXPORT_SYMBOL(pwm_enable);
99
100void pwm_disable(struct pwm_device *pwm)
101{
102 u8 val;
103 int ret;
104
105 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
106 if (ret < 0) {
107 pr_err("%s: Failed to disable PWM, Error %d\n",
108 pwm->label, ret);
109 return;
110 }
111
112 val &= ~PWM_CTRL2_MODE_MASK;
113 val |= PWM_CTRL2_MODE_HW;
114
115 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
116 if (ret < 0) {
117 pr_err("%s: Failed to disable PWM, Error %d\n",
118 pwm->label, ret);
119 return;
120 }
121 return;
122}
123EXPORT_SYMBOL(pwm_disable);
124
125struct pwm_device *pwm_request(int pwm_id, const char *label)
126{
127 u8 val;
128 int ret;
129 struct pwm_device *pwm;
130
131 pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
132 if (pwm == NULL) {
133 pr_err("%s: failed to allocate memory\n", label);
134 return NULL;
135 }
136
137 pwm->label = label;
138 pwm->pwm_id = pwm_id;
139
140 /* Configure PWM */
141 val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
142 PWM_CTRL2_MODE_HW;
143
144 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
145
146 if (ret < 0) {
147 pr_err("%s: Failed to configure PWM, Error %d\n",
148 pwm->label, ret);
149
150 kfree(pwm);
151 return NULL;
152 }
153
154 return pwm;
155}
156EXPORT_SYMBOL(pwm_request);
157
158void pwm_free(struct pwm_device *pwm)
159{
160 pwm_disable(pwm);
161 kfree(pwm);
162}
163EXPORT_SYMBOL(pwm_free);