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 | |
| 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>
| -rw-r--r-- | Documentation/devicetree/bindings/pwm/pwm.txt | 57 | ||||
| -rw-r--r-- | drivers/pwm/core.c | 148 | ||||
| -rw-r--r-- | include/linux/pwm.h | 6 |
3 files changed, 209 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/pwm/pwm.txt b/Documentation/devicetree/bindings/pwm/pwm.txt new file mode 100644 index 000000000000..73ec962bfe8c --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm.txt | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | Specifying PWM information for devices | ||
| 2 | ====================================== | ||
| 3 | |||
| 4 | 1) PWM user nodes | ||
| 5 | ----------------- | ||
| 6 | |||
| 7 | PWM users should specify a list of PWM devices that they want to use | ||
| 8 | with a property containing a 'pwm-list': | ||
| 9 | |||
| 10 | pwm-list ::= <single-pwm> [pwm-list] | ||
| 11 | single-pwm ::= <pwm-phandle> <pwm-specifier> | ||
| 12 | pwm-phandle : phandle to PWM controller node | ||
| 13 | pwm-specifier : array of #pwm-cells specifying the given PWM | ||
| 14 | (controller specific) | ||
| 15 | |||
| 16 | PWM properties should be named "pwms". The exact meaning of each pwms | ||
| 17 | property must be documented in the device tree binding for each device. | ||
| 18 | An optional property "pwm-names" may contain a list of strings to label | ||
| 19 | each of the PWM devices listed in the "pwms" property. If no "pwm-names" | ||
| 20 | property is given, the name of the user node will be used as fallback. | ||
| 21 | |||
| 22 | Drivers for devices that use more than a single PWM device can use the | ||
| 23 | "pwm-names" property to map the name of the PWM device requested by the | ||
| 24 | pwm_get() call to an index into the list given by the "pwms" property. | ||
| 25 | |||
| 26 | The following example could be used to describe a PWM-based backlight | ||
| 27 | device: | ||
| 28 | |||
| 29 | pwm: pwm { | ||
| 30 | #pwm-cells = <2>; | ||
| 31 | }; | ||
| 32 | |||
| 33 | [...] | ||
| 34 | |||
| 35 | bl: backlight { | ||
| 36 | pwms = <&pwm 0 5000000>; | ||
| 37 | pwm-names = "backlight"; | ||
| 38 | }; | ||
| 39 | |||
| 40 | pwm-specifier typically encodes the chip-relative PWM number and the PWM | ||
| 41 | period in nanoseconds. Note that in the example above, specifying the | ||
| 42 | "pwm-names" is redundant because the name "backlight" would be used as | ||
| 43 | fallback anyway. | ||
| 44 | |||
| 45 | 2) PWM controller nodes | ||
| 46 | ----------------------- | ||
| 47 | |||
| 48 | PWM controller nodes must specify the number of cells used for the | ||
| 49 | specifier using the '#pwm-cells' property. | ||
| 50 | |||
| 51 | An example PWM controller might look like this: | ||
| 52 | |||
| 53 | pwm: pwm@7000a000 { | ||
| 54 | compatible = "nvidia,tegra20-pwm"; | ||
| 55 | reg = <0x7000a000 0x100>; | ||
| 56 | #pwm-cells = <2>; | ||
| 57 | }; | ||
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 |
diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 2947a4fea6ad..21d076c5089e 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #ifndef __LINUX_PWM_H | 1 | #ifndef __LINUX_PWM_H |
| 2 | #define __LINUX_PWM_H | 2 | #define __LINUX_PWM_H |
| 3 | 3 | ||
| 4 | #include <linux/of.h> | ||
| 5 | |||
| 4 | struct pwm_device; | 6 | struct pwm_device; |
| 5 | struct seq_file; | 7 | struct seq_file; |
| 6 | 8 | ||
| @@ -105,6 +107,10 @@ struct pwm_chip { | |||
| 105 | unsigned int npwm; | 107 | unsigned int npwm; |
| 106 | 108 | ||
| 107 | struct pwm_device *pwms; | 109 | struct pwm_device *pwms; |
| 110 | |||
| 111 | struct pwm_device * (*of_xlate)(struct pwm_chip *pc, | ||
| 112 | const struct of_phandle_args *args); | ||
| 113 | unsigned int of_pwm_n_cells; | ||
| 108 | }; | 114 | }; |
| 109 | 115 | ||
| 110 | int pwm_set_chip_data(struct pwm_device *pwm, void *data); | 116 | int pwm_set_chip_data(struct pwm_device *pwm, void *data); |
