.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Generic pwmlib implementation |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de> |
---|
5 | 6 | * Copyright (C) 2011-2012 Avionic Design GmbH |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License as published by |
---|
9 | | - * the Free Software Foundation; either version 2, or (at your option) |
---|
10 | | - * any later version. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, |
---|
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | | - * |
---|
17 | | - * You should have received a copy of the GNU General Public License |
---|
18 | | - * along with this program; see the file COPYING. If not, write to |
---|
19 | | - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
20 | 7 | */ |
---|
21 | 8 | |
---|
| 9 | +#include <linux/acpi.h> |
---|
22 | 10 | #include <linux/module.h> |
---|
23 | 11 | #include <linux/pwm.h> |
---|
24 | 12 | #include <linux/radix-tree.h> |
---|
.. | .. |
---|
31 | 19 | #include <linux/seq_file.h> |
---|
32 | 20 | |
---|
33 | 21 | #include <dt-bindings/pwm/pwm.h> |
---|
| 22 | + |
---|
| 23 | +#define CREATE_TRACE_POINTS |
---|
| 24 | +#include <trace/events/pwm.h> |
---|
34 | 25 | |
---|
35 | 26 | #define MAX_PWMS 1024 |
---|
36 | 27 | |
---|
.. | .. |
---|
124 | 115 | module_put(pwm->chip->ops->owner); |
---|
125 | 116 | return err; |
---|
126 | 117 | } |
---|
| 118 | + } |
---|
| 119 | + |
---|
| 120 | + if (pwm->chip->ops->get_state) { |
---|
| 121 | + pwm->chip->ops->get_state(pwm->chip, pwm, &pwm->state); |
---|
| 122 | + trace_pwm_get(pwm, &pwm->state); |
---|
| 123 | + |
---|
| 124 | + if (IS_ENABLED(CONFIG_PWM_DEBUG)) |
---|
| 125 | + pwm->last = pwm->state; |
---|
127 | 126 | } |
---|
128 | 127 | |
---|
129 | 128 | set_bit(PWMF_REQUESTED, &pwm->flags); |
---|
.. | .. |
---|
236 | 235 | } |
---|
237 | 236 | EXPORT_SYMBOL_GPL(pwm_get_chip_data); |
---|
238 | 237 | |
---|
239 | | -static bool pwm_ops_check(const struct pwm_ops *ops) |
---|
| 238 | +static bool pwm_ops_check(const struct pwm_chip *chip) |
---|
240 | 239 | { |
---|
| 240 | + |
---|
| 241 | + const struct pwm_ops *ops = chip->ops; |
---|
| 242 | + |
---|
241 | 243 | /* driver supports legacy, non-atomic operation */ |
---|
242 | | - if (ops->config && ops->enable && ops->disable) |
---|
243 | | - return true; |
---|
| 244 | + if (ops->config && ops->enable && ops->disable) { |
---|
| 245 | + if (IS_ENABLED(CONFIG_PWM_DEBUG)) |
---|
| 246 | + dev_warn(chip->dev, |
---|
| 247 | + "Driver needs updating to atomic API\n"); |
---|
244 | 248 | |
---|
245 | | - /* driver supports atomic operation */ |
---|
246 | | - if (ops->apply) |
---|
247 | 249 | return true; |
---|
| 250 | + } |
---|
248 | 251 | |
---|
249 | | - return false; |
---|
| 252 | + if (!ops->apply) |
---|
| 253 | + return false; |
---|
| 254 | + |
---|
| 255 | + if (IS_ENABLED(CONFIG_PWM_DEBUG) && !ops->get_state) |
---|
| 256 | + dev_warn(chip->dev, |
---|
| 257 | + "Please implement the .get_state() callback\n"); |
---|
| 258 | + |
---|
| 259 | + return true; |
---|
250 | 260 | } |
---|
251 | 261 | |
---|
252 | 262 | /** |
---|
.. | .. |
---|
270 | 280 | if (!chip || !chip->dev || !chip->ops || !chip->npwm) |
---|
271 | 281 | return -EINVAL; |
---|
272 | 282 | |
---|
273 | | - if (!pwm_ops_check(chip->ops)) |
---|
| 283 | + if (!pwm_ops_check(chip)) |
---|
274 | 284 | return -EINVAL; |
---|
275 | 285 | |
---|
276 | 286 | mutex_lock(&pwm_lock); |
---|
.. | .. |
---|
295 | 305 | pwm->hwpwm = i; |
---|
296 | 306 | pwm->state.polarity = polarity; |
---|
297 | 307 | pwm->state.output_type = PWM_OUTPUT_FIXED; |
---|
298 | | - |
---|
299 | | - if (chip->ops->get_state) |
---|
300 | | - chip->ops->get_state(chip, pwm, &pwm->state); |
---|
301 | 308 | |
---|
302 | 309 | radix_tree_insert(&pwm_tree, pwm->pwm, pwm); |
---|
303 | 310 | } |
---|
.. | .. |
---|
458 | 465 | } |
---|
459 | 466 | EXPORT_SYMBOL_GPL(pwm_free); |
---|
460 | 467 | |
---|
| 468 | +static void pwm_apply_state_debug(struct pwm_device *pwm, |
---|
| 469 | + const struct pwm_state *state) |
---|
| 470 | +{ |
---|
| 471 | + struct pwm_state *last = &pwm->last; |
---|
| 472 | + struct pwm_chip *chip = pwm->chip; |
---|
| 473 | + struct pwm_state s1, s2; |
---|
| 474 | + int err; |
---|
| 475 | + |
---|
| 476 | + if (!IS_ENABLED(CONFIG_PWM_DEBUG)) |
---|
| 477 | + return; |
---|
| 478 | + |
---|
| 479 | + /* No reasonable diagnosis possible without .get_state() */ |
---|
| 480 | + if (!chip->ops->get_state) |
---|
| 481 | + return; |
---|
| 482 | + |
---|
| 483 | + /* |
---|
| 484 | + * *state was just applied. Read out the hardware state and do some |
---|
| 485 | + * checks. |
---|
| 486 | + */ |
---|
| 487 | + |
---|
| 488 | + chip->ops->get_state(chip, pwm, &s1); |
---|
| 489 | + trace_pwm_get(pwm, &s1); |
---|
| 490 | + |
---|
| 491 | + /* |
---|
| 492 | + * The lowlevel driver either ignored .polarity (which is a bug) or as |
---|
| 493 | + * best effort inverted .polarity and fixed .duty_cycle respectively. |
---|
| 494 | + * Undo this inversion and fixup for further tests. |
---|
| 495 | + */ |
---|
| 496 | + if (s1.enabled && s1.polarity != state->polarity) { |
---|
| 497 | + s2.polarity = state->polarity; |
---|
| 498 | + s2.duty_cycle = s1.period - s1.duty_cycle; |
---|
| 499 | + s2.period = s1.period; |
---|
| 500 | + s2.enabled = s1.enabled; |
---|
| 501 | + } else { |
---|
| 502 | + s2 = s1; |
---|
| 503 | + } |
---|
| 504 | + |
---|
| 505 | + if (s2.polarity != state->polarity && |
---|
| 506 | + state->duty_cycle < state->period) |
---|
| 507 | + dev_warn(chip->dev, ".apply ignored .polarity\n"); |
---|
| 508 | + |
---|
| 509 | + if (state->enabled && |
---|
| 510 | + last->polarity == state->polarity && |
---|
| 511 | + last->period > s2.period && |
---|
| 512 | + last->period <= state->period) |
---|
| 513 | + dev_warn(chip->dev, |
---|
| 514 | + ".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n", |
---|
| 515 | + state->period, s2.period, last->period); |
---|
| 516 | + |
---|
| 517 | + if (state->enabled && state->period < s2.period) |
---|
| 518 | + dev_warn(chip->dev, |
---|
| 519 | + ".apply is supposed to round down period (requested: %llu, applied: %llu)\n", |
---|
| 520 | + state->period, s2.period); |
---|
| 521 | + |
---|
| 522 | + if (state->enabled && |
---|
| 523 | + last->polarity == state->polarity && |
---|
| 524 | + last->period == s2.period && |
---|
| 525 | + last->duty_cycle > s2.duty_cycle && |
---|
| 526 | + last->duty_cycle <= state->duty_cycle) |
---|
| 527 | + dev_warn(chip->dev, |
---|
| 528 | + ".apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n", |
---|
| 529 | + state->duty_cycle, state->period, |
---|
| 530 | + s2.duty_cycle, s2.period, |
---|
| 531 | + last->duty_cycle, last->period); |
---|
| 532 | + |
---|
| 533 | + if (state->enabled && state->duty_cycle < s2.duty_cycle) |
---|
| 534 | + dev_warn(chip->dev, |
---|
| 535 | + ".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n", |
---|
| 536 | + state->duty_cycle, state->period, |
---|
| 537 | + s2.duty_cycle, s2.period); |
---|
| 538 | + |
---|
| 539 | + if (!state->enabled && s2.enabled && s2.duty_cycle > 0) |
---|
| 540 | + dev_warn(chip->dev, |
---|
| 541 | + "requested disabled, but yielded enabled with duty > 0\n"); |
---|
| 542 | + |
---|
| 543 | + /* reapply the state that the driver reported being configured. */ |
---|
| 544 | + err = chip->ops->apply(chip, pwm, &s1); |
---|
| 545 | + if (err) { |
---|
| 546 | + *last = s1; |
---|
| 547 | + dev_err(chip->dev, "failed to reapply current setting\n"); |
---|
| 548 | + return; |
---|
| 549 | + } |
---|
| 550 | + |
---|
| 551 | + trace_pwm_apply(pwm, &s1); |
---|
| 552 | + |
---|
| 553 | + chip->ops->get_state(chip, pwm, last); |
---|
| 554 | + trace_pwm_get(pwm, last); |
---|
| 555 | + |
---|
| 556 | + /* reapplication of the current state should give an exact match */ |
---|
| 557 | + if (s1.enabled != last->enabled || |
---|
| 558 | + s1.polarity != last->polarity || |
---|
| 559 | + (s1.enabled && s1.period != last->period) || |
---|
| 560 | + (s1.enabled && s1.duty_cycle != last->duty_cycle)) { |
---|
| 561 | + dev_err(chip->dev, |
---|
| 562 | + ".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n", |
---|
| 563 | + s1.enabled, s1.polarity, s1.duty_cycle, s1.period, |
---|
| 564 | + last->enabled, last->polarity, last->duty_cycle, |
---|
| 565 | + last->period); |
---|
| 566 | + } |
---|
| 567 | +} |
---|
| 568 | + |
---|
461 | 569 | /** |
---|
462 | 570 | * pwm_apply_state() - atomically apply a new state to a PWM device |
---|
463 | 571 | * @pwm: PWM device |
---|
464 | | - * @state: new state to apply. This can be adjusted by the PWM driver |
---|
465 | | - * if the requested config is not achievable, for example, |
---|
466 | | - * ->duty_cycle and ->period might be approximated. |
---|
| 572 | + * @state: new state to apply |
---|
467 | 573 | */ |
---|
468 | | -int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state) |
---|
| 574 | +int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) |
---|
469 | 575 | { |
---|
| 576 | + struct pwm_chip *chip; |
---|
470 | 577 | int err; |
---|
471 | 578 | |
---|
472 | 579 | if (!pwm || !state || !state->period || |
---|
473 | 580 | state->duty_cycle > state->period) |
---|
474 | 581 | return -EINVAL; |
---|
475 | 582 | |
---|
476 | | - if (!memcmp(state, &pwm->state, sizeof(*state))) |
---|
| 583 | + chip = pwm->chip; |
---|
| 584 | + |
---|
| 585 | + if (state->period == pwm->state.period && |
---|
| 586 | + state->duty_cycle == pwm->state.duty_cycle && |
---|
| 587 | + state->polarity == pwm->state.polarity && |
---|
| 588 | +#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT |
---|
| 589 | + state->oneshot_count == pwm->state.oneshot_count && |
---|
| 590 | + state->oneshot_repeat == pwm->state.oneshot_repeat && |
---|
| 591 | + state->duty_offset == pwm->state.duty_offset && |
---|
| 592 | +#endif |
---|
| 593 | + state->enabled == pwm->state.enabled) |
---|
477 | 594 | return 0; |
---|
478 | 595 | |
---|
479 | | - if (pwm->chip->ops->apply) { |
---|
480 | | - err = pwm->chip->ops->apply(pwm->chip, pwm, state); |
---|
| 596 | + if (chip->ops->apply) { |
---|
| 597 | + err = chip->ops->apply(chip, pwm, state); |
---|
481 | 598 | if (err) |
---|
482 | 599 | return err; |
---|
483 | 600 | |
---|
| 601 | + trace_pwm_apply(pwm, state); |
---|
| 602 | + |
---|
484 | 603 | pwm->state = *state; |
---|
| 604 | + |
---|
| 605 | + /* |
---|
| 606 | + * only do this after pwm->state was applied as some |
---|
| 607 | + * implementations of .get_state depend on this |
---|
| 608 | + */ |
---|
| 609 | + pwm_apply_state_debug(pwm, state); |
---|
485 | 610 | } else { |
---|
486 | 611 | /* |
---|
487 | 612 | * FIXME: restore the initial state in case of error. |
---|
488 | 613 | */ |
---|
489 | 614 | if (state->polarity != pwm->state.polarity) { |
---|
490 | | - if (!pwm->chip->ops->set_polarity) |
---|
| 615 | + if (!chip->ops->set_polarity) |
---|
491 | 616 | return -ENOTSUPP; |
---|
492 | 617 | |
---|
493 | 618 | /* |
---|
.. | .. |
---|
496 | 621 | * ->apply(). |
---|
497 | 622 | */ |
---|
498 | 623 | if (pwm->state.enabled) { |
---|
499 | | - pwm->chip->ops->disable(pwm->chip, pwm); |
---|
| 624 | + chip->ops->disable(chip, pwm); |
---|
500 | 625 | pwm->state.enabled = false; |
---|
501 | 626 | } |
---|
502 | 627 | |
---|
503 | | - err = pwm->chip->ops->set_polarity(pwm->chip, pwm, |
---|
504 | | - state->polarity); |
---|
| 628 | + err = chip->ops->set_polarity(chip, pwm, |
---|
| 629 | + state->polarity); |
---|
505 | 630 | if (err) |
---|
506 | 631 | return err; |
---|
507 | 632 | |
---|
508 | 633 | pwm->state.polarity = state->polarity; |
---|
509 | 634 | } |
---|
510 | 635 | |
---|
511 | | - if (state->output_type != pwm->state.output_type) { |
---|
512 | | - if (!pwm->chip->ops->set_output_type) |
---|
513 | | - return -ENOTSUPP; |
---|
514 | | - |
---|
515 | | - err = pwm->chip->ops->set_output_type(pwm->chip, pwm, |
---|
516 | | - state->output_type); |
---|
517 | | - if (err) |
---|
518 | | - return err; |
---|
519 | | - |
---|
520 | | - pwm->state.output_type = state->output_type; |
---|
521 | | - } |
---|
522 | | - |
---|
523 | | - if (state->output_pattern != pwm->state.output_pattern && |
---|
524 | | - state->output_pattern != NULL) { |
---|
525 | | - if (!pwm->chip->ops->set_output_pattern) |
---|
526 | | - return -ENOTSUPP; |
---|
527 | | - |
---|
528 | | - err = pwm->chip->ops->set_output_pattern(pwm->chip, |
---|
529 | | - pwm, state->output_pattern); |
---|
530 | | - if (err) |
---|
531 | | - return err; |
---|
532 | | - |
---|
533 | | - pwm->state.output_pattern = state->output_pattern; |
---|
534 | | - } |
---|
535 | | - |
---|
536 | 636 | if (state->period != pwm->state.period || |
---|
537 | 637 | state->duty_cycle != pwm->state.duty_cycle) { |
---|
538 | | - if (pwm->chip->ops->config_extend) { |
---|
539 | | - err = pwm->chip->ops->config_extend(pwm->chip, |
---|
540 | | - pwm, state->duty_cycle, |
---|
541 | | - state->period); |
---|
542 | | - } else { |
---|
543 | | - if (state->period > UINT_MAX) |
---|
544 | | - pr_warn("period %llu duty_cycle %llu will be truncated\n", |
---|
545 | | - state->period, |
---|
546 | | - state->duty_cycle); |
---|
547 | | - err = pwm->chip->ops->config(pwm->chip, pwm, |
---|
| 638 | + err = chip->ops->config(pwm->chip, pwm, |
---|
548 | 639 | state->duty_cycle, |
---|
549 | 640 | state->period); |
---|
550 | | - } |
---|
551 | 641 | if (err) |
---|
552 | 642 | return err; |
---|
553 | 643 | |
---|
.. | .. |
---|
557 | 647 | |
---|
558 | 648 | if (state->enabled != pwm->state.enabled) { |
---|
559 | 649 | if (state->enabled) { |
---|
560 | | - err = pwm->chip->ops->enable(pwm->chip, pwm); |
---|
| 650 | + err = chip->ops->enable(chip, pwm); |
---|
561 | 651 | if (err) |
---|
562 | 652 | return err; |
---|
563 | 653 | } else { |
---|
564 | | - pwm->chip->ops->disable(pwm->chip, pwm); |
---|
| 654 | + chip->ops->disable(chip, pwm); |
---|
565 | 655 | } |
---|
566 | 656 | |
---|
567 | 657 | pwm->state.enabled = state->enabled; |
---|
.. | .. |
---|
672 | 762 | return ERR_PTR(-EPROBE_DEFER); |
---|
673 | 763 | } |
---|
674 | 764 | |
---|
| 765 | +static struct device_link *pwm_device_link_add(struct device *dev, |
---|
| 766 | + struct pwm_device *pwm) |
---|
| 767 | +{ |
---|
| 768 | + struct device_link *dl; |
---|
| 769 | + |
---|
| 770 | + if (!dev) { |
---|
| 771 | + /* |
---|
| 772 | + * No device for the PWM consumer has been provided. It may |
---|
| 773 | + * impact the PM sequence ordering: the PWM supplier may get |
---|
| 774 | + * suspended before the consumer. |
---|
| 775 | + */ |
---|
| 776 | + dev_warn(pwm->chip->dev, |
---|
| 777 | + "No consumer device specified to create a link to\n"); |
---|
| 778 | + return NULL; |
---|
| 779 | + } |
---|
| 780 | + |
---|
| 781 | + dl = device_link_add(dev, pwm->chip->dev, DL_FLAG_AUTOREMOVE_CONSUMER); |
---|
| 782 | + if (!dl) { |
---|
| 783 | + dev_err(dev, "failed to create device link to %s\n", |
---|
| 784 | + dev_name(pwm->chip->dev)); |
---|
| 785 | + return ERR_PTR(-EINVAL); |
---|
| 786 | + } |
---|
| 787 | + |
---|
| 788 | + return dl; |
---|
| 789 | +} |
---|
| 790 | + |
---|
675 | 791 | /** |
---|
676 | 792 | * of_pwm_get() - request a PWM via the PWM framework |
---|
| 793 | + * @dev: device for PWM consumer |
---|
677 | 794 | * @np: device node to get the PWM from |
---|
678 | 795 | * @con_id: consumer name |
---|
679 | 796 | * |
---|
.. | .. |
---|
691 | 808 | * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded |
---|
692 | 809 | * error code on failure. |
---|
693 | 810 | */ |
---|
694 | | -struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id) |
---|
| 811 | +struct pwm_device *of_pwm_get(struct device *dev, struct device_node *np, |
---|
| 812 | + const char *con_id) |
---|
695 | 813 | { |
---|
696 | 814 | struct pwm_device *pwm = NULL; |
---|
697 | 815 | struct of_phandle_args args; |
---|
| 816 | + struct device_link *dl; |
---|
698 | 817 | struct pwm_chip *pc; |
---|
699 | 818 | int index = 0; |
---|
700 | 819 | int err; |
---|
.. | .. |
---|
725 | 844 | if (IS_ERR(pwm)) |
---|
726 | 845 | goto put; |
---|
727 | 846 | |
---|
| 847 | + dl = pwm_device_link_add(dev, pwm); |
---|
| 848 | + if (IS_ERR(dl)) { |
---|
| 849 | + /* of_xlate ended up calling pwm_request_from_chip() */ |
---|
| 850 | + pwm_free(pwm); |
---|
| 851 | + pwm = ERR_CAST(dl); |
---|
| 852 | + goto put; |
---|
| 853 | + } |
---|
| 854 | + |
---|
728 | 855 | /* |
---|
729 | 856 | * If a consumer name was not given, try to look it up from the |
---|
730 | 857 | * "pwm-names" property if it exists. Otherwise use the name of |
---|
.. | .. |
---|
745 | 872 | return pwm; |
---|
746 | 873 | } |
---|
747 | 874 | EXPORT_SYMBOL_GPL(of_pwm_get); |
---|
| 875 | + |
---|
| 876 | +#if IS_ENABLED(CONFIG_ACPI) |
---|
| 877 | +static struct pwm_chip *device_to_pwmchip(struct device *dev) |
---|
| 878 | +{ |
---|
| 879 | + struct pwm_chip *chip; |
---|
| 880 | + |
---|
| 881 | + mutex_lock(&pwm_lock); |
---|
| 882 | + |
---|
| 883 | + list_for_each_entry(chip, &pwm_chips, list) { |
---|
| 884 | + struct acpi_device *adev = ACPI_COMPANION(chip->dev); |
---|
| 885 | + |
---|
| 886 | + if ((chip->dev == dev) || (adev && &adev->dev == dev)) { |
---|
| 887 | + mutex_unlock(&pwm_lock); |
---|
| 888 | + return chip; |
---|
| 889 | + } |
---|
| 890 | + } |
---|
| 891 | + |
---|
| 892 | + mutex_unlock(&pwm_lock); |
---|
| 893 | + |
---|
| 894 | + return ERR_PTR(-EPROBE_DEFER); |
---|
| 895 | +} |
---|
| 896 | +#endif |
---|
| 897 | + |
---|
| 898 | +/** |
---|
| 899 | + * acpi_pwm_get() - request a PWM via parsing "pwms" property in ACPI |
---|
| 900 | + * @fwnode: firmware node to get the "pwm" property from |
---|
| 901 | + * |
---|
| 902 | + * Returns the PWM device parsed from the fwnode and index specified in the |
---|
| 903 | + * "pwms" property or a negative error-code on failure. |
---|
| 904 | + * Values parsed from the device tree are stored in the returned PWM device |
---|
| 905 | + * object. |
---|
| 906 | + * |
---|
| 907 | + * This is analogous to of_pwm_get() except con_id is not yet supported. |
---|
| 908 | + * ACPI entries must look like |
---|
| 909 | + * Package () {"pwms", Package () |
---|
| 910 | + * { <PWM device reference>, <PWM index>, <PWM period> [, <PWM flags>]}} |
---|
| 911 | + * |
---|
| 912 | + * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded |
---|
| 913 | + * error code on failure. |
---|
| 914 | + */ |
---|
| 915 | +static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode) |
---|
| 916 | +{ |
---|
| 917 | + struct pwm_device *pwm = ERR_PTR(-ENODEV); |
---|
| 918 | +#if IS_ENABLED(CONFIG_ACPI) |
---|
| 919 | + struct fwnode_reference_args args; |
---|
| 920 | + struct acpi_device *acpi; |
---|
| 921 | + struct pwm_chip *chip; |
---|
| 922 | + int ret; |
---|
| 923 | + |
---|
| 924 | + memset(&args, 0, sizeof(args)); |
---|
| 925 | + |
---|
| 926 | + ret = __acpi_node_get_property_reference(fwnode, "pwms", 0, 3, &args); |
---|
| 927 | + if (ret < 0) |
---|
| 928 | + return ERR_PTR(ret); |
---|
| 929 | + |
---|
| 930 | + acpi = to_acpi_device_node(args.fwnode); |
---|
| 931 | + if (!acpi) |
---|
| 932 | + return ERR_PTR(-EINVAL); |
---|
| 933 | + |
---|
| 934 | + if (args.nargs < 2) |
---|
| 935 | + return ERR_PTR(-EPROTO); |
---|
| 936 | + |
---|
| 937 | + chip = device_to_pwmchip(&acpi->dev); |
---|
| 938 | + if (IS_ERR(chip)) |
---|
| 939 | + return ERR_CAST(chip); |
---|
| 940 | + |
---|
| 941 | + pwm = pwm_request_from_chip(chip, args.args[0], NULL); |
---|
| 942 | + if (IS_ERR(pwm)) |
---|
| 943 | + return pwm; |
---|
| 944 | + |
---|
| 945 | + pwm->args.period = args.args[1]; |
---|
| 946 | + pwm->args.polarity = PWM_POLARITY_NORMAL; |
---|
| 947 | + |
---|
| 948 | + if (args.nargs > 2 && args.args[2] & PWM_POLARITY_INVERTED) |
---|
| 949 | + pwm->args.polarity = PWM_POLARITY_INVERSED; |
---|
| 950 | +#endif |
---|
| 951 | + |
---|
| 952 | + return pwm; |
---|
| 953 | +} |
---|
748 | 954 | |
---|
749 | 955 | /** |
---|
750 | 956 | * pwm_add_table() - register PWM device consumers |
---|
.. | .. |
---|
800 | 1006 | const char *dev_id = dev ? dev_name(dev) : NULL; |
---|
801 | 1007 | struct pwm_device *pwm; |
---|
802 | 1008 | struct pwm_chip *chip; |
---|
| 1009 | + struct device_link *dl; |
---|
803 | 1010 | unsigned int best = 0; |
---|
804 | 1011 | struct pwm_lookup *p, *chosen = NULL; |
---|
805 | 1012 | unsigned int match; |
---|
.. | .. |
---|
807 | 1014 | |
---|
808 | 1015 | /* look up via DT first */ |
---|
809 | 1016 | if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) |
---|
810 | | - return of_pwm_get(dev->of_node, con_id); |
---|
| 1017 | + return of_pwm_get(dev, dev->of_node, con_id); |
---|
| 1018 | + |
---|
| 1019 | + /* then lookup via ACPI */ |
---|
| 1020 | + if (dev && is_acpi_node(dev->fwnode)) { |
---|
| 1021 | + pwm = acpi_pwm_get(dev->fwnode); |
---|
| 1022 | + if (!IS_ERR(pwm) || PTR_ERR(pwm) != -ENOENT) |
---|
| 1023 | + return pwm; |
---|
| 1024 | + } |
---|
811 | 1025 | |
---|
812 | 1026 | /* |
---|
813 | 1027 | * We look up the provider in the static table typically provided by |
---|
.. | .. |
---|
883 | 1097 | pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id); |
---|
884 | 1098 | if (IS_ERR(pwm)) |
---|
885 | 1099 | return pwm; |
---|
| 1100 | + |
---|
| 1101 | + dl = pwm_device_link_add(dev, pwm); |
---|
| 1102 | + if (IS_ERR(dl)) { |
---|
| 1103 | + pwm_free(pwm); |
---|
| 1104 | + return ERR_CAST(dl); |
---|
| 1105 | + } |
---|
886 | 1106 | |
---|
887 | 1107 | pwm->args.period = chosen->period; |
---|
888 | 1108 | pwm->args.polarity = chosen->polarity; |
---|
.. | .. |
---|
976 | 1196 | if (!ptr) |
---|
977 | 1197 | return ERR_PTR(-ENOMEM); |
---|
978 | 1198 | |
---|
979 | | - pwm = of_pwm_get(np, con_id); |
---|
| 1199 | + pwm = of_pwm_get(dev, np, con_id); |
---|
980 | 1200 | if (!IS_ERR(pwm)) { |
---|
981 | 1201 | *ptr = pwm; |
---|
982 | 1202 | devres_add(dev, ptr); |
---|
.. | .. |
---|
987 | 1207 | return pwm; |
---|
988 | 1208 | } |
---|
989 | 1209 | EXPORT_SYMBOL_GPL(devm_of_pwm_get); |
---|
| 1210 | + |
---|
| 1211 | +/** |
---|
| 1212 | + * devm_fwnode_pwm_get() - request a resource managed PWM from firmware node |
---|
| 1213 | + * @dev: device for PWM consumer |
---|
| 1214 | + * @fwnode: firmware node to get the PWM from |
---|
| 1215 | + * @con_id: consumer name |
---|
| 1216 | + * |
---|
| 1217 | + * Returns the PWM device parsed from the firmware node. See of_pwm_get() and |
---|
| 1218 | + * acpi_pwm_get() for a detailed description. |
---|
| 1219 | + * |
---|
| 1220 | + * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded |
---|
| 1221 | + * error code on failure. |
---|
| 1222 | + */ |
---|
| 1223 | +struct pwm_device *devm_fwnode_pwm_get(struct device *dev, |
---|
| 1224 | + struct fwnode_handle *fwnode, |
---|
| 1225 | + const char *con_id) |
---|
| 1226 | +{ |
---|
| 1227 | + struct pwm_device **ptr, *pwm = ERR_PTR(-ENODEV); |
---|
| 1228 | + |
---|
| 1229 | + ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); |
---|
| 1230 | + if (!ptr) |
---|
| 1231 | + return ERR_PTR(-ENOMEM); |
---|
| 1232 | + |
---|
| 1233 | + if (is_of_node(fwnode)) |
---|
| 1234 | + pwm = of_pwm_get(dev, to_of_node(fwnode), con_id); |
---|
| 1235 | + else if (is_acpi_node(fwnode)) |
---|
| 1236 | + pwm = acpi_pwm_get(fwnode); |
---|
| 1237 | + |
---|
| 1238 | + if (!IS_ERR(pwm)) { |
---|
| 1239 | + *ptr = pwm; |
---|
| 1240 | + devres_add(dev, ptr); |
---|
| 1241 | + } else { |
---|
| 1242 | + devres_free(ptr); |
---|
| 1243 | + } |
---|
| 1244 | + |
---|
| 1245 | + return pwm; |
---|
| 1246 | +} |
---|
| 1247 | +EXPORT_SYMBOL_GPL(devm_fwnode_pwm_get); |
---|
990 | 1248 | |
---|
991 | 1249 | static int devm_pwm_match(struct device *dev, void *res, void *data) |
---|
992 | 1250 | { |
---|
.. | .. |
---|
1070 | 1328 | dev_name(chip->dev), chip->npwm, |
---|
1071 | 1329 | (chip->npwm != 1) ? "s" : ""); |
---|
1072 | 1330 | |
---|
1073 | | - if (chip->ops->dbg_show) |
---|
1074 | | - chip->ops->dbg_show(chip, s); |
---|
1075 | | - else |
---|
1076 | | - pwm_dbg_show(chip, s); |
---|
| 1331 | + pwm_dbg_show(chip, s); |
---|
1077 | 1332 | |
---|
1078 | 1333 | return 0; |
---|
1079 | 1334 | } |
---|
1080 | 1335 | |
---|
1081 | | -static const struct seq_operations pwm_seq_ops = { |
---|
| 1336 | +static const struct seq_operations pwm_debugfs_sops = { |
---|
1082 | 1337 | .start = pwm_seq_start, |
---|
1083 | 1338 | .next = pwm_seq_next, |
---|
1084 | 1339 | .stop = pwm_seq_stop, |
---|
1085 | 1340 | .show = pwm_seq_show, |
---|
1086 | 1341 | }; |
---|
1087 | 1342 | |
---|
1088 | | -static int pwm_seq_open(struct inode *inode, struct file *file) |
---|
1089 | | -{ |
---|
1090 | | - return seq_open(file, &pwm_seq_ops); |
---|
1091 | | -} |
---|
1092 | | - |
---|
1093 | | -static const struct file_operations pwm_debugfs_ops = { |
---|
1094 | | - .owner = THIS_MODULE, |
---|
1095 | | - .open = pwm_seq_open, |
---|
1096 | | - .read = seq_read, |
---|
1097 | | - .llseek = seq_lseek, |
---|
1098 | | - .release = seq_release, |
---|
1099 | | -}; |
---|
| 1343 | +DEFINE_SEQ_ATTRIBUTE(pwm_debugfs); |
---|
1100 | 1344 | |
---|
1101 | 1345 | static int __init pwm_debugfs_init(void) |
---|
1102 | 1346 | { |
---|
1103 | 1347 | debugfs_create_file("pwm", S_IFREG | S_IRUGO, NULL, NULL, |
---|
1104 | | - &pwm_debugfs_ops); |
---|
| 1348 | + &pwm_debugfs_fops); |
---|
1105 | 1349 | |
---|
1106 | 1350 | return 0; |
---|
1107 | 1351 | } |
---|
1108 | | -#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT |
---|
1109 | | -postcore_initcall(pwm_debugfs_init); |
---|
1110 | | -#else |
---|
1111 | 1352 | subsys_initcall(pwm_debugfs_init); |
---|
1112 | | -#endif |
---|
1113 | 1353 | #endif /* CONFIG_DEBUG_FS */ |
---|