diff options
author | Thierry Reding <thierry.reding@avionic-design.de> | 2011-12-14 05:10:32 -0500 |
---|---|---|
committer | Thierry Reding <thierry.reding@avionic-design.de> | 2012-06-15 06:56:57 -0400 |
commit | 7299ab70e68e20e70cb45fe4ab4b6029fe964acd (patch) | |
tree | b396b29f6170deb3769c0b884ccf0fd64211f6ee /drivers/pwm/core.c | |
parent | e05e5070f0ec2557d2d2ff3655ba03f29e297151 (diff) |
pwm: Add device tree support
This patch adds helpers to support device tree bindings for the generic
PWM API. Device tree binding documentation for PWM controllers is also
provided.
Acked-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'drivers/pwm/core.c')
-rw-r--r-- | drivers/pwm/core.c | 148 |
1 files changed, 146 insertions, 2 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index a2af599e61ae..dbab53005da8 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c | |||
@@ -129,6 +129,45 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label) | |||
129 | return 0; | 129 | return 0; |
130 | } | 130 | } |
131 | 131 | ||
132 | static struct pwm_device *of_pwm_simple_xlate(struct pwm_chip *pc, | ||
133 | const struct of_phandle_args *args) | ||
134 | { | ||
135 | struct pwm_device *pwm; | ||
136 | |||
137 | if (pc->of_pwm_n_cells < 2) | ||
138 | return ERR_PTR(-EINVAL); | ||
139 | |||
140 | if (args->args[0] >= pc->npwm) | ||
141 | return ERR_PTR(-EINVAL); | ||
142 | |||
143 | pwm = pwm_request_from_chip(pc, args->args[0], NULL); | ||
144 | if (IS_ERR(pwm)) | ||
145 | return pwm; | ||
146 | |||
147 | pwm_set_period(pwm, args->args[1]); | ||
148 | |||
149 | return pwm; | ||
150 | } | ||
151 | |||
152 | void of_pwmchip_add(struct pwm_chip *chip) | ||
153 | { | ||
154 | if (!chip->dev || !chip->dev->of_node) | ||
155 | return; | ||
156 | |||
157 | if (!chip->of_xlate) { | ||
158 | chip->of_xlate = of_pwm_simple_xlate; | ||
159 | chip->of_pwm_n_cells = 2; | ||
160 | } | ||
161 | |||
162 | of_node_get(chip->dev->of_node); | ||
163 | } | ||
164 | |||
165 | void of_pwmchip_remove(struct pwm_chip *chip) | ||
166 | { | ||
167 | if (chip->dev && chip->dev->of_node) | ||
168 | of_node_put(chip->dev->of_node); | ||
169 | } | ||
170 | |||
132 | /** | 171 | /** |
133 | * pwm_set_chip_data() - set private chip data for a PWM | 172 | * pwm_set_chip_data() - set private chip data for a PWM |
134 | * @pwm: PWM device | 173 | * @pwm: PWM device |
@@ -201,6 +240,9 @@ int pwmchip_add(struct pwm_chip *chip) | |||
201 | 240 | ||
202 | ret = 0; | 241 | ret = 0; |
203 | 242 | ||
243 | if (IS_ENABLED(CONFIG_OF)) | ||
244 | of_pwmchip_add(chip); | ||
245 | |||
204 | out: | 246 | out: |
205 | mutex_unlock(&pwm_lock); | 247 | mutex_unlock(&pwm_lock); |
206 | return ret; | 248 | return ret; |
@@ -231,6 +273,10 @@ int pwmchip_remove(struct pwm_chip *chip) | |||
231 | } | 273 | } |
232 | 274 | ||
233 | list_del_init(&chip->list); | 275 | list_del_init(&chip->list); |
276 | |||
277 | if (IS_ENABLED(CONFIG_OF)) | ||
278 | of_pwmchip_remove(chip); | ||
279 | |||
234 | free_pwms(chip); | 280 | free_pwms(chip); |
235 | 281 | ||
236 | out: | 282 | out: |
@@ -356,6 +402,99 @@ void pwm_disable(struct pwm_device *pwm) | |||
356 | } | 402 | } |
357 | EXPORT_SYMBOL_GPL(pwm_disable); | 403 | EXPORT_SYMBOL_GPL(pwm_disable); |
358 | 404 | ||
405 | static struct pwm_chip *of_node_to_pwmchip(struct device_node *np) | ||
406 | { | ||
407 | struct pwm_chip *chip; | ||
408 | |||
409 | mutex_lock(&pwm_lock); | ||
410 | |||
411 | list_for_each_entry(chip, &pwm_chips, list) | ||
412 | if (chip->dev && chip->dev->of_node == np) { | ||
413 | mutex_unlock(&pwm_lock); | ||
414 | return chip; | ||
415 | } | ||
416 | |||
417 | mutex_unlock(&pwm_lock); | ||
418 | |||
419 | return ERR_PTR(-EPROBE_DEFER); | ||
420 | } | ||
421 | |||
422 | /** | ||
423 | * of_pwm_request() - request a PWM via the PWM framework | ||
424 | * @np: device node to get the PWM from | ||
425 | * @con_id: consumer name | ||
426 | * | ||
427 | * Returns the PWM device parsed from the phandle and index specified in the | ||
428 | * "pwms" property of a device tree node or a negative error-code on failure. | ||
429 | * Values parsed from the device tree are stored in the returned PWM device | ||
430 | * object. | ||
431 | * | ||
432 | * If con_id is NULL, the first PWM device listed in the "pwms" property will | ||
433 | * be requested. Otherwise the "pwm-names" property is used to do a reverse | ||
434 | * lookup of the PWM index. This also means that the "pwm-names" property | ||
435 | * becomes mandatory for devices that look up the PWM device via the con_id | ||
436 | * parameter. | ||
437 | */ | ||
438 | static struct pwm_device *of_pwm_request(struct device_node *np, | ||
439 | const char *con_id) | ||
440 | { | ||
441 | struct pwm_device *pwm = NULL; | ||
442 | struct of_phandle_args args; | ||
443 | struct pwm_chip *pc; | ||
444 | int index = 0; | ||
445 | int err; | ||
446 | |||
447 | if (con_id) { | ||
448 | index = of_property_match_string(np, "pwm-names", con_id); | ||
449 | if (index < 0) | ||
450 | return ERR_PTR(index); | ||
451 | } | ||
452 | |||
453 | err = of_parse_phandle_with_args(np, "pwms", "#pwm-cells", index, | ||
454 | &args); | ||
455 | if (err) { | ||
456 | pr_debug("%s(): can't parse \"pwms\" property\n", __func__); | ||
457 | return ERR_PTR(err); | ||
458 | } | ||
459 | |||
460 | pc = of_node_to_pwmchip(args.np); | ||
461 | if (IS_ERR(pc)) { | ||
462 | pr_debug("%s(): PWM chip not found\n", __func__); | ||
463 | pwm = ERR_CAST(pc); | ||
464 | goto put; | ||
465 | } | ||
466 | |||
467 | if (args.args_count != pc->of_pwm_n_cells) { | ||
468 | pr_debug("%s: wrong #pwm-cells for %s\n", np->full_name, | ||
469 | args.np->full_name); | ||
470 | pwm = ERR_PTR(-EINVAL); | ||
471 | goto put; | ||
472 | } | ||
473 | |||
474 | pwm = pc->of_xlate(pc, &args); | ||
475 | if (IS_ERR(pwm)) | ||
476 | goto put; | ||
477 | |||
478 | /* | ||
479 | * If a consumer name was not given, try to look it up from the | ||
480 | * "pwm-names" property if it exists. Otherwise use the name of | ||
481 | * the user device node. | ||
482 | */ | ||
483 | if (!con_id) { | ||
484 | err = of_property_read_string_index(np, "pwm-names", index, | ||
485 | &con_id); | ||
486 | if (err < 0) | ||
487 | con_id = np->name; | ||
488 | } | ||
489 | |||
490 | pwm->label = con_id; | ||
491 | |||
492 | put: | ||
493 | of_node_put(args.np); | ||
494 | |||
495 | return pwm; | ||
496 | } | ||
497 | |||
359 | /** | 498 | /** |
360 | * pwm_add_table() - register PWM device consumers | 499 | * pwm_add_table() - register PWM device consumers |
361 | * @table: array of consumers to register | 500 | * @table: array of consumers to register |
@@ -378,8 +517,9 @@ void __init pwm_add_table(struct pwm_lookup *table, size_t num) | |||
378 | * @dev: device for PWM consumer | 517 | * @dev: device for PWM consumer |
379 | * @con_id: consumer name | 518 | * @con_id: consumer name |
380 | * | 519 | * |
381 | * Look up a PWM chip and a relative index via a table supplied by board setup | 520 | * Lookup is first attempted using DT. If the device was not instantiated from |
382 | * code (see pwm_add_table()). | 521 | * a device tree, a PWM chip and a relative index is looked up via a table |
522 | * supplied by board setup code (see pwm_add_table()). | ||
383 | * | 523 | * |
384 | * Once a PWM chip has been found the specified PWM device will be requested | 524 | * Once a PWM chip has been found the specified PWM device will be requested |
385 | * and is ready to be used. | 525 | * and is ready to be used. |
@@ -394,6 +534,10 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) | |||
394 | unsigned int index; | 534 | unsigned int index; |
395 | unsigned int match; | 535 | unsigned int match; |
396 | 536 | ||
537 | /* look up via DT first */ | ||
538 | if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) | ||
539 | return of_pwm_request(dev->of_node, con_id); | ||
540 | |||
397 | /* | 541 | /* |
398 | * We look up the provider in the static table typically provided by | 542 | * We look up the provider in the static table typically provided by |
399 | * board setup code. We first try to lookup the consumer device by | 543 | * board setup code. We first try to lookup the consumer device by |