diff options
author | Thierry Reding <thierry.reding@avionic-design.de> | 2012-09-18 04:29:51 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-09-19 06:04:25 -0400 |
commit | 48a364b758f861b21747a5148f26aedc504edb7f (patch) | |
tree | e76941d9155ecd0dc5534ef840a5c0d6ddc107f0 /drivers | |
parent | f78959cfa335196ba36d8c4651078f14dc07f2a8 (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/Kconfig | 10 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 1 | ||||
-rw-r--r-- | drivers/mfd/twl-core.c | 7 | ||||
-rw-r--r-- | drivers/pwm/Kconfig | 9 | ||||
-rw-r--r-- | drivers/pwm/Makefile | 1 | ||||
-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 | ||
301 | config 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 | |||
311 | config TWL6040_CORE | 301 | config 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 | |||
63 | obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o | 63 | obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o |
64 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o | 64 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o |
65 | obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o | 65 | obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o |
66 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o | ||
67 | obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o | 66 | obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o |
68 | 67 | ||
69 | obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o | 68 | obj-$(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 | ||
99 | config 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 | |||
99 | config PWM_VT8500 | 108 | config 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 | |||
8 | obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o | 8 | obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o |
9 | obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o | 9 | obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o |
10 | obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o | 10 | obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o |
11 | obj-$(CONFIG_PWM_TWL6030) += pwm-twl6030.o | ||
11 | obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o | 12 | obj-$(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 | ||
48 | struct pwm_device { | 49 | struct twl6030_pwm_chip { |
49 | const char *label; | 50 | struct pwm_chip chip; |
50 | unsigned int pwm_id; | ||
51 | }; | 51 | }; |
52 | 52 | ||
53 | int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | 53 | static 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 | ||
72 | static 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 | } |
72 | EXPORT_SYMBOL(pwm_config); | ||
73 | 87 | ||
74 | int pwm_enable(struct pwm_device *pwm) | 88 | static 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 | } |
98 | EXPORT_SYMBOL(pwm_enable); | ||
99 | 114 | ||
100 | void pwm_disable(struct pwm_device *pwm) | 115 | static 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 | } |
123 | EXPORT_SYMBOL(pwm_disable); | ||
124 | 136 | ||
125 | struct pwm_device *pwm_request(int pwm_id, const char *label) | 137 | static 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 | |||
144 | static 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 | } |
156 | EXPORT_SYMBOL(pwm_request); | ||
157 | 166 | ||
158 | void pwm_free(struct pwm_device *pwm) | 167 | static 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 | } |
163 | EXPORT_SYMBOL(pwm_free); | ||
164 | 173 | ||
174 | static 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 | }; | ||
181 | module_platform_driver(twl6030_pwm_driver); | ||
182 | |||
183 | MODULE_ALIAS("platform:twl6030-pwm"); | ||
165 | MODULE_LICENSE("GPL"); | 184 | MODULE_LICENSE("GPL"); |