aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMilo Kim <milo.kim@ti.com>2013-12-05 21:18:43 -0500
committerLee Jones <lee.jones@linaro.org>2014-01-21 03:28:00 -0500
commitaf66b3c0934e350059646651958306565313e145 (patch)
tree5441be801d1a2950c465e8ba7dd879dec7393652 /drivers
parent470eca47bded10f2e1a425b44d6f2b1418271a9f (diff)
pwm: Add LP3943 PWM driver
This is the other of the LP3943 MFD driver. LP3943 can be used as a PWM generator, up to 2 channels. * Two PWM generators supported * Supported PWM operations request, free, config, enable and disable * Pin assignment A driver data, 'pin_used' is checked when a PWM is requested. If the output pin is already assigned, then returns as failure. If the pin is available, 'pin_used' is set. When the PWM is not used anymore, then it is cleared. It is defined as unsigned long type for atomic bit operation APIs, but only LSB 16bits are used because LP3943 has 16 outputs. Signed-off-by: Milo Kim <milo.kim@ti.com> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pwm/Kconfig10
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/pwm-lp3943.c314
3 files changed, 325 insertions, 0 deletions
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index eece329d7872..7acab93d5a47 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -90,6 +90,16 @@ config PWM_JZ4740
90 To compile this driver as a module, choose M here: the module 90 To compile this driver as a module, choose M here: the module
91 will be called pwm-jz4740. 91 will be called pwm-jz4740.
92 92
93config PWM_LP3943
94 tristate "TI/National Semiconductor LP3943 PWM support"
95 depends on MFD_LP3943
96 help
97 Generic PWM framework driver for LP3943 which supports two PWM
98 channels.
99
100 To compile this driver as a module, choose M here: the module
101 will be called pwm-lp3943.
102
93config PWM_LPC32XX 103config PWM_LPC32XX
94 tristate "LPC32XX PWM support" 104 tristate "LPC32XX PWM support"
95 depends on ARCH_LPC32XX 105 depends on ARCH_LPC32XX
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 8b754e4dba4a..4abf337dcd02 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
6obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o 6obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
7obj-$(CONFIG_PWM_IMX) += pwm-imx.o 7obj-$(CONFIG_PWM_IMX) += pwm-imx.o
8obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o 8obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
9obj-$(CONFIG_PWM_LP3943) += pwm-lp3943.o
9obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o 10obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
10obj-$(CONFIG_PWM_MXS) += pwm-mxs.o 11obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
11obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o 12obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c
new file mode 100644
index 000000000000..8a843a04c224
--- /dev/null
+++ b/drivers/pwm/pwm-lp3943.c
@@ -0,0 +1,314 @@
1/*
2 * TI/National Semiconductor LP3943 PWM driver
3 *
4 * Copyright 2013 Texas Instruments
5 *
6 * Author: Milo Kim <milo.kim@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.
11 */
12
13#include <linux/err.h>
14#include <linux/i2c.h>
15#include <linux/mfd/lp3943.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/pwm.h>
19#include <linux/slab.h>
20
21#define LP3943_MAX_DUTY 255
22#define LP3943_MIN_PERIOD 6250
23#define LP3943_MAX_PERIOD 1600000
24
25struct lp3943_pwm {
26 struct pwm_chip chip;
27 struct lp3943 *lp3943;
28 struct lp3943_platform_data *pdata;
29};
30
31static inline struct lp3943_pwm *to_lp3943_pwm(struct pwm_chip *_chip)
32{
33 return container_of(_chip, struct lp3943_pwm, chip);
34}
35
36static struct lp3943_pwm_map *
37lp3943_pwm_request_map(struct lp3943_pwm *lp3943_pwm, int hwpwm)
38{
39 struct lp3943_platform_data *pdata = lp3943_pwm->pdata;
40 struct lp3943 *lp3943 = lp3943_pwm->lp3943;
41 struct lp3943_pwm_map *pwm_map;
42 int i, offset;
43
44 pwm_map = kzalloc(sizeof(*pwm_map), GFP_KERNEL);
45 if (!pwm_map)
46 return ERR_PTR(-ENOMEM);
47
48 pwm_map->output = pdata->pwms[hwpwm]->output;
49 pwm_map->num_outputs = pdata->pwms[hwpwm]->num_outputs;
50
51 for (i = 0; i < pwm_map->num_outputs; i++) {
52 offset = pwm_map->output[i];
53
54 /* Return an error if the pin is already assigned */
55 if (test_and_set_bit(offset, &lp3943->pin_used))
56 return ERR_PTR(-EBUSY);
57 }
58
59 return pwm_map;
60}
61
62static int lp3943_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
63{
64 struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
65 struct lp3943_pwm_map *pwm_map;
66
67 pwm_map = lp3943_pwm_request_map(lp3943_pwm, pwm->hwpwm);
68 if (IS_ERR(pwm_map))
69 return PTR_ERR(pwm_map);
70
71 return pwm_set_chip_data(pwm, pwm_map);
72}
73
74static void lp3943_pwm_free_map(struct lp3943_pwm *lp3943_pwm,
75 struct lp3943_pwm_map *pwm_map)
76{
77 struct lp3943 *lp3943 = lp3943_pwm->lp3943;
78 int i, offset;
79
80 for (i = 0; i < pwm_map->num_outputs; i++) {
81 offset = pwm_map->output[i];
82 clear_bit(offset, &lp3943->pin_used);
83 }
84
85 kfree(pwm_map);
86}
87
88static void lp3943_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
89{
90 struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
91 struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
92
93 lp3943_pwm_free_map(lp3943_pwm, pwm_map);
94}
95
96static int lp3943_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
97 int duty_ns, int period_ns)
98{
99 struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
100 struct lp3943 *lp3943 = lp3943_pwm->lp3943;
101 u8 val, reg_duty, reg_prescale;
102 int err;
103
104 /*
105 * How to configure the LP3943 PWMs
106 *
107 * 1) Period = 6250 ~ 1600000
108 * 2) Prescale = period / 6250 -1
109 * 3) Duty = input duty
110 *
111 * Prescale and duty are register values
112 */
113
114 if (pwm->hwpwm == 0) {
115 reg_prescale = LP3943_REG_PRESCALE0;
116 reg_duty = LP3943_REG_PWM0;
117 } else {
118 reg_prescale = LP3943_REG_PRESCALE1;
119 reg_duty = LP3943_REG_PWM1;
120 }
121
122 period_ns = clamp(period_ns, LP3943_MIN_PERIOD, LP3943_MAX_PERIOD);
123 val = (u8)(period_ns / LP3943_MIN_PERIOD - 1);
124
125 err = lp3943_write_byte(lp3943, reg_prescale, val);
126 if (err)
127 return err;
128
129 val = (u8)(duty_ns * LP3943_MAX_DUTY / period_ns);
130
131 return lp3943_write_byte(lp3943, reg_duty, val);
132}
133
134static int lp3943_pwm_set_mode(struct lp3943_pwm *lp3943_pwm,
135 struct lp3943_pwm_map *pwm_map,
136 u8 val)
137{
138 struct lp3943 *lp3943 = lp3943_pwm->lp3943;
139 const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
140 int i, index, err;
141
142 for (i = 0; i < pwm_map->num_outputs; i++) {
143 index = pwm_map->output[i];
144 err = lp3943_update_bits(lp3943, mux[index].reg,
145 mux[index].mask,
146 val << mux[index].shift);
147 if (err)
148 return err;
149 }
150
151 return 0;
152}
153
154static int lp3943_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
155{
156 struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
157 struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
158 u8 val;
159
160 if (pwm->hwpwm == 0)
161 val = LP3943_DIM_PWM0;
162 else
163 val = LP3943_DIM_PWM1;
164
165 /*
166 * Each PWM generator is set to control any of outputs of LP3943.
167 * To enable/disable the PWM, these output pins should be configured.
168 */
169
170 return lp3943_pwm_set_mode(lp3943_pwm, pwm_map, val);
171}
172
173static void lp3943_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
174{
175 struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
176 struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
177
178 /*
179 * LP3943 outputs are open-drain, so the pin should be configured
180 * when the PWM is disabled.
181 */
182
183 lp3943_pwm_set_mode(lp3943_pwm, pwm_map, LP3943_GPIO_OUT_HIGH);
184}
185
186static const struct pwm_ops lp3943_pwm_ops = {
187 .request = lp3943_pwm_request,
188 .free = lp3943_pwm_free,
189 .config = lp3943_pwm_config,
190 .enable = lp3943_pwm_enable,
191 .disable = lp3943_pwm_disable,
192 .owner = THIS_MODULE,
193};
194
195static int lp3943_pwm_parse_dt(struct device *dev,
196 struct lp3943_pwm *lp3943_pwm)
197{
198 static const char * const name[] = { "ti,pwm0", "ti,pwm1", };
199 struct device_node *node = dev->of_node;
200 struct lp3943_platform_data *pdata;
201 struct lp3943_pwm_map *pwm_map;
202 enum lp3943_pwm_output *output;
203 int i, err, proplen, count = 0;
204 u32 num_outputs;
205
206 if (!node)
207 return -EINVAL;
208
209 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
210 if (!pdata)
211 return -ENOMEM;
212
213 /*
214 * Read the output map configuration from the device tree.
215 * Each of the two PWM generators can drive zero or more outputs.
216 */
217
218 for (i = 0; i < LP3943_NUM_PWMS; i++) {
219 if (!of_get_property(node, name[i], &proplen))
220 continue;
221
222 num_outputs = proplen / sizeof(u32);
223 if (num_outputs == 0)
224 continue;
225
226 output = devm_kzalloc(dev, sizeof(*output) * num_outputs,
227 GFP_KERNEL);
228 if (!output)
229 return -ENOMEM;
230
231 err = of_property_read_u32_array(node, name[i], output,
232 num_outputs);
233 if (err)
234 return err;
235
236 pwm_map = devm_kzalloc(dev, sizeof(*pwm_map), GFP_KERNEL);
237 if (!pwm_map)
238 return -ENOMEM;
239
240 pwm_map->output = output;
241 pwm_map->num_outputs = num_outputs;
242 pdata->pwms[i] = pwm_map;
243
244 count++;
245 }
246
247 if (count == 0)
248 return -ENODATA;
249
250 lp3943_pwm->pdata = pdata;
251 return 0;
252}
253
254static int lp3943_pwm_probe(struct platform_device *pdev)
255{
256 struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
257 struct lp3943_pwm *lp3943_pwm;
258 int ret;
259
260 lp3943_pwm = devm_kzalloc(&pdev->dev, sizeof(*lp3943_pwm), GFP_KERNEL);
261 if (!lp3943_pwm)
262 return -ENOMEM;
263
264 lp3943_pwm->pdata = lp3943->pdata;
265 if (!lp3943_pwm->pdata) {
266 if (IS_ENABLED(CONFIG_OF))
267 ret = lp3943_pwm_parse_dt(&pdev->dev, lp3943_pwm);
268 else
269 ret = -ENODEV;
270
271 if (ret)
272 return ret;
273 }
274
275 lp3943_pwm->lp3943 = lp3943;
276 lp3943_pwm->chip.dev = &pdev->dev;
277 lp3943_pwm->chip.ops = &lp3943_pwm_ops;
278 lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
279
280 platform_set_drvdata(pdev, lp3943_pwm);
281
282 return pwmchip_add(&lp3943_pwm->chip);
283}
284
285static int lp3943_pwm_remove(struct platform_device *pdev)
286{
287 struct lp3943_pwm *lp3943_pwm = platform_get_drvdata(pdev);
288
289 return pwmchip_remove(&lp3943_pwm->chip);
290}
291
292#ifdef CONFIG_OF
293static const struct of_device_id lp3943_pwm_of_match[] = {
294 { .compatible = "ti,lp3943-pwm", },
295 { }
296};
297MODULE_DEVICE_TABLE(of, lp3943_pwm_of_match);
298#endif
299
300static struct platform_driver lp3943_pwm_driver = {
301 .probe = lp3943_pwm_probe,
302 .remove = lp3943_pwm_remove,
303 .driver = {
304 .name = "lp3943-pwm",
305 .owner = THIS_MODULE,
306 .of_match_table = of_match_ptr(lp3943_pwm_of_match),
307 },
308};
309module_platform_driver(lp3943_pwm_driver);
310
311MODULE_DESCRIPTION("LP3943 PWM driver");
312MODULE_ALIAS("platform:lp3943-pwm");
313MODULE_AUTHOR("Milo Kim");
314MODULE_LICENSE("GPL");