aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorThierry Reding <thierry.reding@avionic-design.de>2012-09-18 04:29:51 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-09-19 06:04:25 -0400
commit48a364b758f861b21747a5148f26aedc504edb7f (patch)
treee76941d9155ecd0dc5534ef840a5c0d6ddc107f0 /drivers
parentf78959cfa335196ba36d8c4651078f14dc07f2a8 (diff)
pwm: Move TWL6030 PWM driver to PWM framework
This commit moves the driver to drivers/pwm and converts it to the new PWM framework. In order for this to work properly, register the PWM as child of the multi-function TWL6030 device. Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/Kconfig10
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/twl-core.c7
-rw-r--r--drivers/pwm/Kconfig9
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/pwm-twl6030.c (renamed from drivers/mfd/twl6030-pwm.c)119
6 files changed, 86 insertions, 61 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b0d7d9b5b7d4..2143fd283a74 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -298,16 +298,6 @@ config MFD_TWL4030_AUDIO
298 select MFD_CORE 298 select MFD_CORE
299 default n 299 default n
300 300
301config TWL6030_PWM
302 tristate "TWL6030 PWM (Pulse Width Modulator) Support"
303 depends on TWL4030_CORE
304 select HAVE_PWM
305 depends on !PWM
306 default n
307 help
308 Say yes here if you want support for TWL6030 PWM.
309 This is used to control charging LED brightness.
310
311config TWL6040_CORE 301config TWL6040_CORE
312 bool "Support for TWL6040 audio codec" 302 bool "Support for TWL6040 audio codec"
313 depends on I2C=y && GENERIC_HARDIRQS 303 depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b88cdb876e15..95dfa14ad174 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -63,7 +63,6 @@ obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
63obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o 63obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
64obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o 64obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
65obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o 65obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o
66obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
67obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o 66obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o
68 67
69obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o 68obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e208d88d2180..3d700129cf3e 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -670,6 +670,13 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
670 return PTR_ERR(child); 670 return PTR_ERR(child);
671 } 671 }
672 672
673 if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) {
674 child = add_child(TWL6030_MODULE_ID1, "twl6030-pwm", NULL, 0,
675 false, 0, 0);
676 if (IS_ERR(child))
677 return PTR_ERR(child);
678 }
679
673 if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb && 680 if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
674 twl_class_is_4030()) { 681 twl_class_is_4030()) {
675 682
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 8fc3808d7a3e..c7500dcdc65e 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -96,6 +96,15 @@ config PWM_TIEHRPWM
96 To compile this driver as a module, choose M here: the module 96 To compile this driver as a module, choose M here: the module
97 will be called pwm-tiehrpwm. 97 will be called pwm-tiehrpwm.
98 98
99config PWM_TWL6030
100 tristate "TWL6030 PWM support"
101 depends on TWL4030_CORE
102 help
103 Generic PWM framework driver for TWL6030.
104
105 To compile this driver as a module, choose M here: the module
106 will be called pwm-twl6030.
107
99config PWM_VT8500 108config PWM_VT8500
100 tristate "vt8500 pwm support" 109 tristate "vt8500 pwm support"
101 depends on ARCH_VT8500 110 depends on ARCH_VT8500
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index e4b2c898964d..78f123dca30d 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
8obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o 8obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
9obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o 9obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
10obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o 10obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o
11obj-$(CONFIG_PWM_TWL6030) += pwm-twl6030.o
11obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o 12obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o
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 @@
20 20
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/pwm.h>
23#include <linux/i2c/twl.h> 24#include <linux/i2c/twl.h>
24#include <linux/slab.h> 25#include <linux/slab.h>
25 26
@@ -45,40 +46,54 @@
45 46
46#define PWM_CTRL2_MODE_MASK 0x3 47#define PWM_CTRL2_MODE_MASK 0x3
47 48
48struct pwm_device { 49struct twl6030_pwm_chip {
49 const char *label; 50 struct pwm_chip chip;
50 unsigned int pwm_id;
51}; 51};
52 52
53int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) 53static int twl6030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
54{ 54{
55 u8 duty_cycle;
56 int ret; 55 int ret;
56 u8 val;
57 57
58 if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) 58 /* Configure PWM */
59 return -EINVAL; 59 val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
60 PWM_CTRL2_MODE_HW;
60 61
61 duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns; 62 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
63 if (ret < 0) {
64 dev_err(chip->dev, "%s: Failed to configure PWM, Error %d\n",
65 pwm->label, ret);
66 return ret;
67 }
62 68
63 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1); 69 return 0;
70}
64 71
72static int twl6030_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
73 int duty_ns, int period_ns)
74{
75 u8 duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns;
76 int ret;
77
78 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1);
65 if (ret < 0) { 79 if (ret < 0) {
66 pr_err("%s: Failed to configure PWM, Error %d\n", 80 pr_err("%s: Failed to configure PWM, Error %d\n",
67 pwm->label, ret); 81 pwm->label, ret);
68 return ret; 82 return ret;
69 } 83 }
84
70 return 0; 85 return 0;
71} 86}
72EXPORT_SYMBOL(pwm_config);
73 87
74int pwm_enable(struct pwm_device *pwm) 88static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
75{ 89{
76 u8 val;
77 int ret; 90 int ret;
91 u8 val;
78 92
79 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); 93 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
80 if (ret < 0) { 94 if (ret < 0) {
81 pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); 95 dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
96 pwm->label, ret);
82 return ret; 97 return ret;
83 } 98 }
84 99
@@ -88,23 +103,23 @@ int pwm_enable(struct pwm_device *pwm)
88 103
89 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); 104 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
90 if (ret < 0) { 105 if (ret < 0) {
91 pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); 106 dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
107 pwm->label, ret);
92 return ret; 108 return ret;
93 } 109 }
94 110
95 twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); 111 twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
96 return 0; 112 return 0;
97} 113}
98EXPORT_SYMBOL(pwm_enable);
99 114
100void pwm_disable(struct pwm_device *pwm) 115static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
101{ 116{
102 u8 val;
103 int ret; 117 int ret;
118 u8 val;
104 119
105 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); 120 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
106 if (ret < 0) { 121 if (ret < 0) {
107 pr_err("%s: Failed to disable PWM, Error %d\n", 122 dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
108 pwm->label, ret); 123 pwm->label, ret);
109 return; 124 return;
110 } 125 }
@@ -114,52 +129,56 @@ void pwm_disable(struct pwm_device *pwm)
114 129
115 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); 130 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
116 if (ret < 0) { 131 if (ret < 0) {
117 pr_err("%s: Failed to disable PWM, Error %d\n", 132 dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
118 pwm->label, ret); 133 pwm->label, ret);
119 return;
120 } 134 }
121 return;
122} 135}
123EXPORT_SYMBOL(pwm_disable);
124 136
125struct pwm_device *pwm_request(int pwm_id, const char *label) 137static const struct pwm_ops twl6030_pwm_ops = {
138 .request = twl6030_pwm_request,
139 .config = twl6030_pwm_config,
140 .enable = twl6030_pwm_enable,
141 .disable = twl6030_pwm_disable,
142};
143
144static int twl6030_pwm_probe(struct platform_device *pdev)
126{ 145{
127 u8 val; 146 struct twl6030_pwm_chip *twl6030;
128 int ret; 147 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 148
137 pwm->label = label; 149 twl6030 = devm_kzalloc(&pdev->dev, sizeof(*twl6030), GFP_KERNEL);
138 pwm->pwm_id = pwm_id; 150 if (!twl6030)
139 151 return -ENOMEM;
140 /* Configure PWM */
141 val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
142 PWM_CTRL2_MODE_HW;
143 152
144 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); 153 twl6030->chip.dev = &pdev->dev;
154 twl6030->chip.ops = &twl6030_pwm_ops;
155 twl6030->chip.base = -1;
156 twl6030->chip.npwm = 1;
145 157
146 if (ret < 0) { 158 ret = pwmchip_add(&twl6030->chip);
147 pr_err("%s: Failed to configure PWM, Error %d\n", 159 if (ret < 0)
148 pwm->label, ret); 160 return ret;
149 161
150 kfree(pwm); 162 platform_set_drvdata(pdev, twl6030);
151 return NULL;
152 }
153 163
154 return pwm; 164 return 0;
155} 165}
156EXPORT_SYMBOL(pwm_request);
157 166
158void pwm_free(struct pwm_device *pwm) 167static int twl6030_pwm_remove(struct platform_device *pdev)
159{ 168{
160 pwm_disable(pwm); 169 struct twl6030_pwm_chip *twl6030 = platform_get_drvdata(pdev);
161 kfree(pwm); 170
171 return pwmchip_remove(&twl6030->chip);
162} 172}
163EXPORT_SYMBOL(pwm_free);
164 173
174static struct platform_driver twl6030_pwm_driver = {
175 .driver = {
176 .name = "twl6030-pwm",
177 },
178 .probe = twl6030_pwm_probe,
179 .remove = __devexit_p(twl6030_pwm_remove),
180};
181module_platform_driver(twl6030_pwm_driver);
182
183MODULE_ALIAS("platform:twl6030-pwm");
165MODULE_LICENSE("GPL"); 184MODULE_LICENSE("GPL");