diff options
Diffstat (limited to 'drivers/pwm/pwm-lp3943.c')
-rw-r--r-- | drivers/pwm/pwm-lp3943.c | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c new file mode 100644 index 000000000000..a40b9c34e9ff --- /dev/null +++ b/drivers/pwm/pwm-lp3943.c | |||
@@ -0,0 +1,316 @@ | |||
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 | |||
25 | struct lp3943_pwm { | ||
26 | struct pwm_chip chip; | ||
27 | struct lp3943 *lp3943; | ||
28 | struct lp3943_platform_data *pdata; | ||
29 | }; | ||
30 | |||
31 | static inline struct lp3943_pwm *to_lp3943_pwm(struct pwm_chip *_chip) | ||
32 | { | ||
33 | return container_of(_chip, struct lp3943_pwm, chip); | ||
34 | } | ||
35 | |||
36 | static struct lp3943_pwm_map * | ||
37 | lp3943_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 | kfree(pwm_map); | ||
57 | return ERR_PTR(-EBUSY); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | return pwm_map; | ||
62 | } | ||
63 | |||
64 | static int lp3943_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) | ||
65 | { | ||
66 | struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); | ||
67 | struct lp3943_pwm_map *pwm_map; | ||
68 | |||
69 | pwm_map = lp3943_pwm_request_map(lp3943_pwm, pwm->hwpwm); | ||
70 | if (IS_ERR(pwm_map)) | ||
71 | return PTR_ERR(pwm_map); | ||
72 | |||
73 | return pwm_set_chip_data(pwm, pwm_map); | ||
74 | } | ||
75 | |||
76 | static void lp3943_pwm_free_map(struct lp3943_pwm *lp3943_pwm, | ||
77 | struct lp3943_pwm_map *pwm_map) | ||
78 | { | ||
79 | struct lp3943 *lp3943 = lp3943_pwm->lp3943; | ||
80 | int i, offset; | ||
81 | |||
82 | for (i = 0; i < pwm_map->num_outputs; i++) { | ||
83 | offset = pwm_map->output[i]; | ||
84 | clear_bit(offset, &lp3943->pin_used); | ||
85 | } | ||
86 | |||
87 | kfree(pwm_map); | ||
88 | } | ||
89 | |||
90 | static void lp3943_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | ||
91 | { | ||
92 | struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); | ||
93 | struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm); | ||
94 | |||
95 | lp3943_pwm_free_map(lp3943_pwm, pwm_map); | ||
96 | } | ||
97 | |||
98 | static int lp3943_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | ||
99 | int duty_ns, int period_ns) | ||
100 | { | ||
101 | struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); | ||
102 | struct lp3943 *lp3943 = lp3943_pwm->lp3943; | ||
103 | u8 val, reg_duty, reg_prescale; | ||
104 | int err; | ||
105 | |||
106 | /* | ||
107 | * How to configure the LP3943 PWMs | ||
108 | * | ||
109 | * 1) Period = 6250 ~ 1600000 | ||
110 | * 2) Prescale = period / 6250 -1 | ||
111 | * 3) Duty = input duty | ||
112 | * | ||
113 | * Prescale and duty are register values | ||
114 | */ | ||
115 | |||
116 | if (pwm->hwpwm == 0) { | ||
117 | reg_prescale = LP3943_REG_PRESCALE0; | ||
118 | reg_duty = LP3943_REG_PWM0; | ||
119 | } else { | ||
120 | reg_prescale = LP3943_REG_PRESCALE1; | ||
121 | reg_duty = LP3943_REG_PWM1; | ||
122 | } | ||
123 | |||
124 | period_ns = clamp(period_ns, LP3943_MIN_PERIOD, LP3943_MAX_PERIOD); | ||
125 | val = (u8)(period_ns / LP3943_MIN_PERIOD - 1); | ||
126 | |||
127 | err = lp3943_write_byte(lp3943, reg_prescale, val); | ||
128 | if (err) | ||
129 | return err; | ||
130 | |||
131 | val = (u8)(duty_ns * LP3943_MAX_DUTY / period_ns); | ||
132 | |||
133 | return lp3943_write_byte(lp3943, reg_duty, val); | ||
134 | } | ||
135 | |||
136 | static int lp3943_pwm_set_mode(struct lp3943_pwm *lp3943_pwm, | ||
137 | struct lp3943_pwm_map *pwm_map, | ||
138 | u8 val) | ||
139 | { | ||
140 | struct lp3943 *lp3943 = lp3943_pwm->lp3943; | ||
141 | const struct lp3943_reg_cfg *mux = lp3943->mux_cfg; | ||
142 | int i, index, err; | ||
143 | |||
144 | for (i = 0; i < pwm_map->num_outputs; i++) { | ||
145 | index = pwm_map->output[i]; | ||
146 | err = lp3943_update_bits(lp3943, mux[index].reg, | ||
147 | mux[index].mask, | ||
148 | val << mux[index].shift); | ||
149 | if (err) | ||
150 | return err; | ||
151 | } | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int lp3943_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
157 | { | ||
158 | struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); | ||
159 | struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm); | ||
160 | u8 val; | ||
161 | |||
162 | if (pwm->hwpwm == 0) | ||
163 | val = LP3943_DIM_PWM0; | ||
164 | else | ||
165 | val = LP3943_DIM_PWM1; | ||
166 | |||
167 | /* | ||
168 | * Each PWM generator is set to control any of outputs of LP3943. | ||
169 | * To enable/disable the PWM, these output pins should be configured. | ||
170 | */ | ||
171 | |||
172 | return lp3943_pwm_set_mode(lp3943_pwm, pwm_map, val); | ||
173 | } | ||
174 | |||
175 | static void lp3943_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
176 | { | ||
177 | struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); | ||
178 | struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm); | ||
179 | |||
180 | /* | ||
181 | * LP3943 outputs are open-drain, so the pin should be configured | ||
182 | * when the PWM is disabled. | ||
183 | */ | ||
184 | |||
185 | lp3943_pwm_set_mode(lp3943_pwm, pwm_map, LP3943_GPIO_OUT_HIGH); | ||
186 | } | ||
187 | |||
188 | static const struct pwm_ops lp3943_pwm_ops = { | ||
189 | .request = lp3943_pwm_request, | ||
190 | .free = lp3943_pwm_free, | ||
191 | .config = lp3943_pwm_config, | ||
192 | .enable = lp3943_pwm_enable, | ||
193 | .disable = lp3943_pwm_disable, | ||
194 | .owner = THIS_MODULE, | ||
195 | }; | ||
196 | |||
197 | static int lp3943_pwm_parse_dt(struct device *dev, | ||
198 | struct lp3943_pwm *lp3943_pwm) | ||
199 | { | ||
200 | static const char * const name[] = { "ti,pwm0", "ti,pwm1", }; | ||
201 | struct device_node *node = dev->of_node; | ||
202 | struct lp3943_platform_data *pdata; | ||
203 | struct lp3943_pwm_map *pwm_map; | ||
204 | enum lp3943_pwm_output *output; | ||
205 | int i, err, proplen, count = 0; | ||
206 | u32 num_outputs; | ||
207 | |||
208 | if (!node) | ||
209 | return -EINVAL; | ||
210 | |||
211 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
212 | if (!pdata) | ||
213 | return -ENOMEM; | ||
214 | |||
215 | /* | ||
216 | * Read the output map configuration from the device tree. | ||
217 | * Each of the two PWM generators can drive zero or more outputs. | ||
218 | */ | ||
219 | |||
220 | for (i = 0; i < LP3943_NUM_PWMS; i++) { | ||
221 | if (!of_get_property(node, name[i], &proplen)) | ||
222 | continue; | ||
223 | |||
224 | num_outputs = proplen / sizeof(u32); | ||
225 | if (num_outputs == 0) | ||
226 | continue; | ||
227 | |||
228 | output = devm_kzalloc(dev, sizeof(*output) * num_outputs, | ||
229 | GFP_KERNEL); | ||
230 | if (!output) | ||
231 | return -ENOMEM; | ||
232 | |||
233 | err = of_property_read_u32_array(node, name[i], output, | ||
234 | num_outputs); | ||
235 | if (err) | ||
236 | return err; | ||
237 | |||
238 | pwm_map = devm_kzalloc(dev, sizeof(*pwm_map), GFP_KERNEL); | ||
239 | if (!pwm_map) | ||
240 | return -ENOMEM; | ||
241 | |||
242 | pwm_map->output = output; | ||
243 | pwm_map->num_outputs = num_outputs; | ||
244 | pdata->pwms[i] = pwm_map; | ||
245 | |||
246 | count++; | ||
247 | } | ||
248 | |||
249 | if (count == 0) | ||
250 | return -ENODATA; | ||
251 | |||
252 | lp3943_pwm->pdata = pdata; | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static int lp3943_pwm_probe(struct platform_device *pdev) | ||
257 | { | ||
258 | struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent); | ||
259 | struct lp3943_pwm *lp3943_pwm; | ||
260 | int ret; | ||
261 | |||
262 | lp3943_pwm = devm_kzalloc(&pdev->dev, sizeof(*lp3943_pwm), GFP_KERNEL); | ||
263 | if (!lp3943_pwm) | ||
264 | return -ENOMEM; | ||
265 | |||
266 | lp3943_pwm->pdata = lp3943->pdata; | ||
267 | if (!lp3943_pwm->pdata) { | ||
268 | if (IS_ENABLED(CONFIG_OF)) | ||
269 | ret = lp3943_pwm_parse_dt(&pdev->dev, lp3943_pwm); | ||
270 | else | ||
271 | ret = -ENODEV; | ||
272 | |||
273 | if (ret) | ||
274 | return ret; | ||
275 | } | ||
276 | |||
277 | lp3943_pwm->lp3943 = lp3943; | ||
278 | lp3943_pwm->chip.dev = &pdev->dev; | ||
279 | lp3943_pwm->chip.ops = &lp3943_pwm_ops; | ||
280 | lp3943_pwm->chip.npwm = LP3943_NUM_PWMS; | ||
281 | |||
282 | platform_set_drvdata(pdev, lp3943_pwm); | ||
283 | |||
284 | return pwmchip_add(&lp3943_pwm->chip); | ||
285 | } | ||
286 | |||
287 | static int lp3943_pwm_remove(struct platform_device *pdev) | ||
288 | { | ||
289 | struct lp3943_pwm *lp3943_pwm = platform_get_drvdata(pdev); | ||
290 | |||
291 | return pwmchip_remove(&lp3943_pwm->chip); | ||
292 | } | ||
293 | |||
294 | #ifdef CONFIG_OF | ||
295 | static const struct of_device_id lp3943_pwm_of_match[] = { | ||
296 | { .compatible = "ti,lp3943-pwm", }, | ||
297 | { } | ||
298 | }; | ||
299 | MODULE_DEVICE_TABLE(of, lp3943_pwm_of_match); | ||
300 | #endif | ||
301 | |||
302 | static struct platform_driver lp3943_pwm_driver = { | ||
303 | .probe = lp3943_pwm_probe, | ||
304 | .remove = lp3943_pwm_remove, | ||
305 | .driver = { | ||
306 | .name = "lp3943-pwm", | ||
307 | .owner = THIS_MODULE, | ||
308 | .of_match_table = of_match_ptr(lp3943_pwm_of_match), | ||
309 | }, | ||
310 | }; | ||
311 | module_platform_driver(lp3943_pwm_driver); | ||
312 | |||
313 | MODULE_DESCRIPTION("LP3943 PWM driver"); | ||
314 | MODULE_ALIAS("platform:lp3943-pwm"); | ||
315 | MODULE_AUTHOR("Milo Kim"); | ||
316 | MODULE_LICENSE("GPL"); | ||