| .. | .. |
|---|
| 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 | +#endif |
|---|
| 591 | + state->enabled == pwm->state.enabled) |
|---|
| 477 | 592 | return 0; |
|---|
| 478 | 593 | |
|---|
| 479 | | - if (pwm->chip->ops->apply) { |
|---|
| 480 | | - err = pwm->chip->ops->apply(pwm->chip, pwm, state); |
|---|
| 594 | + if (chip->ops->apply) { |
|---|
| 595 | + err = chip->ops->apply(chip, pwm, state); |
|---|
| 481 | 596 | if (err) |
|---|
| 482 | 597 | return err; |
|---|
| 483 | 598 | |
|---|
| 599 | + trace_pwm_apply(pwm, state); |
|---|
| 600 | + |
|---|
| 484 | 601 | pwm->state = *state; |
|---|
| 602 | + |
|---|
| 603 | + /* |
|---|
| 604 | + * only do this after pwm->state was applied as some |
|---|
| 605 | + * implementations of .get_state depend on this |
|---|
| 606 | + */ |
|---|
| 607 | + pwm_apply_state_debug(pwm, state); |
|---|
| 485 | 608 | } else { |
|---|
| 486 | 609 | /* |
|---|
| 487 | 610 | * FIXME: restore the initial state in case of error. |
|---|
| 488 | 611 | */ |
|---|
| 489 | 612 | if (state->polarity != pwm->state.polarity) { |
|---|
| 490 | | - if (!pwm->chip->ops->set_polarity) |
|---|
| 613 | + if (!chip->ops->set_polarity) |
|---|
| 491 | 614 | return -ENOTSUPP; |
|---|
| 492 | 615 | |
|---|
| 493 | 616 | /* |
|---|
| .. | .. |
|---|
| 496 | 619 | * ->apply(). |
|---|
| 497 | 620 | */ |
|---|
| 498 | 621 | if (pwm->state.enabled) { |
|---|
| 499 | | - pwm->chip->ops->disable(pwm->chip, pwm); |
|---|
| 622 | + chip->ops->disable(chip, pwm); |
|---|
| 500 | 623 | pwm->state.enabled = false; |
|---|
| 501 | 624 | } |
|---|
| 502 | 625 | |
|---|
| 503 | | - err = pwm->chip->ops->set_polarity(pwm->chip, pwm, |
|---|
| 504 | | - state->polarity); |
|---|
| 626 | + err = chip->ops->set_polarity(chip, pwm, |
|---|
| 627 | + state->polarity); |
|---|
| 505 | 628 | if (err) |
|---|
| 506 | 629 | return err; |
|---|
| 507 | 630 | |
|---|
| 508 | 631 | pwm->state.polarity = state->polarity; |
|---|
| 509 | 632 | } |
|---|
| 510 | 633 | |
|---|
| 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 | 634 | if (state->period != pwm->state.period || |
|---|
| 537 | 635 | 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, |
|---|
| 636 | + err = chip->ops->config(pwm->chip, pwm, |
|---|
| 548 | 637 | state->duty_cycle, |
|---|
| 549 | 638 | state->period); |
|---|
| 550 | | - } |
|---|
| 551 | 639 | if (err) |
|---|
| 552 | 640 | return err; |
|---|
| 553 | 641 | |
|---|
| .. | .. |
|---|
| 557 | 645 | |
|---|
| 558 | 646 | if (state->enabled != pwm->state.enabled) { |
|---|
| 559 | 647 | if (state->enabled) { |
|---|
| 560 | | - err = pwm->chip->ops->enable(pwm->chip, pwm); |
|---|
| 648 | + err = chip->ops->enable(chip, pwm); |
|---|
| 561 | 649 | if (err) |
|---|
| 562 | 650 | return err; |
|---|
| 563 | 651 | } else { |
|---|
| 564 | | - pwm->chip->ops->disable(pwm->chip, pwm); |
|---|
| 652 | + chip->ops->disable(chip, pwm); |
|---|
| 565 | 653 | } |
|---|
| 566 | 654 | |
|---|
| 567 | 655 | pwm->state.enabled = state->enabled; |
|---|
| .. | .. |
|---|
| 672 | 760 | return ERR_PTR(-EPROBE_DEFER); |
|---|
| 673 | 761 | } |
|---|
| 674 | 762 | |
|---|
| 763 | +static struct device_link *pwm_device_link_add(struct device *dev, |
|---|
| 764 | + struct pwm_device *pwm) |
|---|
| 765 | +{ |
|---|
| 766 | + struct device_link *dl; |
|---|
| 767 | + |
|---|
| 768 | + if (!dev) { |
|---|
| 769 | + /* |
|---|
| 770 | + * No device for the PWM consumer has been provided. It may |
|---|
| 771 | + * impact the PM sequence ordering: the PWM supplier may get |
|---|
| 772 | + * suspended before the consumer. |
|---|
| 773 | + */ |
|---|
| 774 | + dev_warn(pwm->chip->dev, |
|---|
| 775 | + "No consumer device specified to create a link to\n"); |
|---|
| 776 | + return NULL; |
|---|
| 777 | + } |
|---|
| 778 | + |
|---|
| 779 | + dl = device_link_add(dev, pwm->chip->dev, DL_FLAG_AUTOREMOVE_CONSUMER); |
|---|
| 780 | + if (!dl) { |
|---|
| 781 | + dev_err(dev, "failed to create device link to %s\n", |
|---|
| 782 | + dev_name(pwm->chip->dev)); |
|---|
| 783 | + return ERR_PTR(-EINVAL); |
|---|
| 784 | + } |
|---|
| 785 | + |
|---|
| 786 | + return dl; |
|---|
| 787 | +} |
|---|
| 788 | + |
|---|
| 675 | 789 | /** |
|---|
| 676 | 790 | * of_pwm_get() - request a PWM via the PWM framework |
|---|
| 791 | + * @dev: device for PWM consumer |
|---|
| 677 | 792 | * @np: device node to get the PWM from |
|---|
| 678 | 793 | * @con_id: consumer name |
|---|
| 679 | 794 | * |
|---|
| .. | .. |
|---|
| 691 | 806 | * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded |
|---|
| 692 | 807 | * error code on failure. |
|---|
| 693 | 808 | */ |
|---|
| 694 | | -struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id) |
|---|
| 809 | +struct pwm_device *of_pwm_get(struct device *dev, struct device_node *np, |
|---|
| 810 | + const char *con_id) |
|---|
| 695 | 811 | { |
|---|
| 696 | 812 | struct pwm_device *pwm = NULL; |
|---|
| 697 | 813 | struct of_phandle_args args; |
|---|
| 814 | + struct device_link *dl; |
|---|
| 698 | 815 | struct pwm_chip *pc; |
|---|
| 699 | 816 | int index = 0; |
|---|
| 700 | 817 | int err; |
|---|
| .. | .. |
|---|
| 725 | 842 | if (IS_ERR(pwm)) |
|---|
| 726 | 843 | goto put; |
|---|
| 727 | 844 | |
|---|
| 845 | + dl = pwm_device_link_add(dev, pwm); |
|---|
| 846 | + if (IS_ERR(dl)) { |
|---|
| 847 | + /* of_xlate ended up calling pwm_request_from_chip() */ |
|---|
| 848 | + pwm_free(pwm); |
|---|
| 849 | + pwm = ERR_CAST(dl); |
|---|
| 850 | + goto put; |
|---|
| 851 | + } |
|---|
| 852 | + |
|---|
| 728 | 853 | /* |
|---|
| 729 | 854 | * If a consumer name was not given, try to look it up from the |
|---|
| 730 | 855 | * "pwm-names" property if it exists. Otherwise use the name of |
|---|
| .. | .. |
|---|
| 745 | 870 | return pwm; |
|---|
| 746 | 871 | } |
|---|
| 747 | 872 | EXPORT_SYMBOL_GPL(of_pwm_get); |
|---|
| 873 | + |
|---|
| 874 | +#if IS_ENABLED(CONFIG_ACPI) |
|---|
| 875 | +static struct pwm_chip *device_to_pwmchip(struct device *dev) |
|---|
| 876 | +{ |
|---|
| 877 | + struct pwm_chip *chip; |
|---|
| 878 | + |
|---|
| 879 | + mutex_lock(&pwm_lock); |
|---|
| 880 | + |
|---|
| 881 | + list_for_each_entry(chip, &pwm_chips, list) { |
|---|
| 882 | + struct acpi_device *adev = ACPI_COMPANION(chip->dev); |
|---|
| 883 | + |
|---|
| 884 | + if ((chip->dev == dev) || (adev && &adev->dev == dev)) { |
|---|
| 885 | + mutex_unlock(&pwm_lock); |
|---|
| 886 | + return chip; |
|---|
| 887 | + } |
|---|
| 888 | + } |
|---|
| 889 | + |
|---|
| 890 | + mutex_unlock(&pwm_lock); |
|---|
| 891 | + |
|---|
| 892 | + return ERR_PTR(-EPROBE_DEFER); |
|---|
| 893 | +} |
|---|
| 894 | +#endif |
|---|
| 895 | + |
|---|
| 896 | +/** |
|---|
| 897 | + * acpi_pwm_get() - request a PWM via parsing "pwms" property in ACPI |
|---|
| 898 | + * @fwnode: firmware node to get the "pwm" property from |
|---|
| 899 | + * |
|---|
| 900 | + * Returns the PWM device parsed from the fwnode and index specified in the |
|---|
| 901 | + * "pwms" property or a negative error-code on failure. |
|---|
| 902 | + * Values parsed from the device tree are stored in the returned PWM device |
|---|
| 903 | + * object. |
|---|
| 904 | + * |
|---|
| 905 | + * This is analogous to of_pwm_get() except con_id is not yet supported. |
|---|
| 906 | + * ACPI entries must look like |
|---|
| 907 | + * Package () {"pwms", Package () |
|---|
| 908 | + * { <PWM device reference>, <PWM index>, <PWM period> [, <PWM flags>]}} |
|---|
| 909 | + * |
|---|
| 910 | + * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded |
|---|
| 911 | + * error code on failure. |
|---|
| 912 | + */ |
|---|
| 913 | +static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode) |
|---|
| 914 | +{ |
|---|
| 915 | + struct pwm_device *pwm = ERR_PTR(-ENODEV); |
|---|
| 916 | +#if IS_ENABLED(CONFIG_ACPI) |
|---|
| 917 | + struct fwnode_reference_args args; |
|---|
| 918 | + struct acpi_device *acpi; |
|---|
| 919 | + struct pwm_chip *chip; |
|---|
| 920 | + int ret; |
|---|
| 921 | + |
|---|
| 922 | + memset(&args, 0, sizeof(args)); |
|---|
| 923 | + |
|---|
| 924 | + ret = __acpi_node_get_property_reference(fwnode, "pwms", 0, 3, &args); |
|---|
| 925 | + if (ret < 0) |
|---|
| 926 | + return ERR_PTR(ret); |
|---|
| 927 | + |
|---|
| 928 | + acpi = to_acpi_device_node(args.fwnode); |
|---|
| 929 | + if (!acpi) |
|---|
| 930 | + return ERR_PTR(-EINVAL); |
|---|
| 931 | + |
|---|
| 932 | + if (args.nargs < 2) |
|---|
| 933 | + return ERR_PTR(-EPROTO); |
|---|
| 934 | + |
|---|
| 935 | + chip = device_to_pwmchip(&acpi->dev); |
|---|
| 936 | + if (IS_ERR(chip)) |
|---|
| 937 | + return ERR_CAST(chip); |
|---|
| 938 | + |
|---|
| 939 | + pwm = pwm_request_from_chip(chip, args.args[0], NULL); |
|---|
| 940 | + if (IS_ERR(pwm)) |
|---|
| 941 | + return pwm; |
|---|
| 942 | + |
|---|
| 943 | + pwm->args.period = args.args[1]; |
|---|
| 944 | + pwm->args.polarity = PWM_POLARITY_NORMAL; |
|---|
| 945 | + |
|---|
| 946 | + if (args.nargs > 2 && args.args[2] & PWM_POLARITY_INVERTED) |
|---|
| 947 | + pwm->args.polarity = PWM_POLARITY_INVERSED; |
|---|
| 948 | +#endif |
|---|
| 949 | + |
|---|
| 950 | + return pwm; |
|---|
| 951 | +} |
|---|
| 748 | 952 | |
|---|
| 749 | 953 | /** |
|---|
| 750 | 954 | * pwm_add_table() - register PWM device consumers |
|---|
| .. | .. |
|---|
| 800 | 1004 | const char *dev_id = dev ? dev_name(dev) : NULL; |
|---|
| 801 | 1005 | struct pwm_device *pwm; |
|---|
| 802 | 1006 | struct pwm_chip *chip; |
|---|
| 1007 | + struct device_link *dl; |
|---|
| 803 | 1008 | unsigned int best = 0; |
|---|
| 804 | 1009 | struct pwm_lookup *p, *chosen = NULL; |
|---|
| 805 | 1010 | unsigned int match; |
|---|
| .. | .. |
|---|
| 807 | 1012 | |
|---|
| 808 | 1013 | /* look up via DT first */ |
|---|
| 809 | 1014 | if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) |
|---|
| 810 | | - return of_pwm_get(dev->of_node, con_id); |
|---|
| 1015 | + return of_pwm_get(dev, dev->of_node, con_id); |
|---|
| 1016 | + |
|---|
| 1017 | + /* then lookup via ACPI */ |
|---|
| 1018 | + if (dev && is_acpi_node(dev->fwnode)) { |
|---|
| 1019 | + pwm = acpi_pwm_get(dev->fwnode); |
|---|
| 1020 | + if (!IS_ERR(pwm) || PTR_ERR(pwm) != -ENOENT) |
|---|
| 1021 | + return pwm; |
|---|
| 1022 | + } |
|---|
| 811 | 1023 | |
|---|
| 812 | 1024 | /* |
|---|
| 813 | 1025 | * We look up the provider in the static table typically provided by |
|---|
| .. | .. |
|---|
| 883 | 1095 | pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id); |
|---|
| 884 | 1096 | if (IS_ERR(pwm)) |
|---|
| 885 | 1097 | return pwm; |
|---|
| 1098 | + |
|---|
| 1099 | + dl = pwm_device_link_add(dev, pwm); |
|---|
| 1100 | + if (IS_ERR(dl)) { |
|---|
| 1101 | + pwm_free(pwm); |
|---|
| 1102 | + return ERR_CAST(dl); |
|---|
| 1103 | + } |
|---|
| 886 | 1104 | |
|---|
| 887 | 1105 | pwm->args.period = chosen->period; |
|---|
| 888 | 1106 | pwm->args.polarity = chosen->polarity; |
|---|
| .. | .. |
|---|
| 976 | 1194 | if (!ptr) |
|---|
| 977 | 1195 | return ERR_PTR(-ENOMEM); |
|---|
| 978 | 1196 | |
|---|
| 979 | | - pwm = of_pwm_get(np, con_id); |
|---|
| 1197 | + pwm = of_pwm_get(dev, np, con_id); |
|---|
| 980 | 1198 | if (!IS_ERR(pwm)) { |
|---|
| 981 | 1199 | *ptr = pwm; |
|---|
| 982 | 1200 | devres_add(dev, ptr); |
|---|
| .. | .. |
|---|
| 987 | 1205 | return pwm; |
|---|
| 988 | 1206 | } |
|---|
| 989 | 1207 | EXPORT_SYMBOL_GPL(devm_of_pwm_get); |
|---|
| 1208 | + |
|---|
| 1209 | +/** |
|---|
| 1210 | + * devm_fwnode_pwm_get() - request a resource managed PWM from firmware node |
|---|
| 1211 | + * @dev: device for PWM consumer |
|---|
| 1212 | + * @fwnode: firmware node to get the PWM from |
|---|
| 1213 | + * @con_id: consumer name |
|---|
| 1214 | + * |
|---|
| 1215 | + * Returns the PWM device parsed from the firmware node. See of_pwm_get() and |
|---|
| 1216 | + * acpi_pwm_get() for a detailed description. |
|---|
| 1217 | + * |
|---|
| 1218 | + * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded |
|---|
| 1219 | + * error code on failure. |
|---|
| 1220 | + */ |
|---|
| 1221 | +struct pwm_device *devm_fwnode_pwm_get(struct device *dev, |
|---|
| 1222 | + struct fwnode_handle *fwnode, |
|---|
| 1223 | + const char *con_id) |
|---|
| 1224 | +{ |
|---|
| 1225 | + struct pwm_device **ptr, *pwm = ERR_PTR(-ENODEV); |
|---|
| 1226 | + |
|---|
| 1227 | + ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); |
|---|
| 1228 | + if (!ptr) |
|---|
| 1229 | + return ERR_PTR(-ENOMEM); |
|---|
| 1230 | + |
|---|
| 1231 | + if (is_of_node(fwnode)) |
|---|
| 1232 | + pwm = of_pwm_get(dev, to_of_node(fwnode), con_id); |
|---|
| 1233 | + else if (is_acpi_node(fwnode)) |
|---|
| 1234 | + pwm = acpi_pwm_get(fwnode); |
|---|
| 1235 | + |
|---|
| 1236 | + if (!IS_ERR(pwm)) { |
|---|
| 1237 | + *ptr = pwm; |
|---|
| 1238 | + devres_add(dev, ptr); |
|---|
| 1239 | + } else { |
|---|
| 1240 | + devres_free(ptr); |
|---|
| 1241 | + } |
|---|
| 1242 | + |
|---|
| 1243 | + return pwm; |
|---|
| 1244 | +} |
|---|
| 1245 | +EXPORT_SYMBOL_GPL(devm_fwnode_pwm_get); |
|---|
| 990 | 1246 | |
|---|
| 991 | 1247 | static int devm_pwm_match(struct device *dev, void *res, void *data) |
|---|
| 992 | 1248 | { |
|---|
| .. | .. |
|---|
| 1070 | 1326 | dev_name(chip->dev), chip->npwm, |
|---|
| 1071 | 1327 | (chip->npwm != 1) ? "s" : ""); |
|---|
| 1072 | 1328 | |
|---|
| 1073 | | - if (chip->ops->dbg_show) |
|---|
| 1074 | | - chip->ops->dbg_show(chip, s); |
|---|
| 1075 | | - else |
|---|
| 1076 | | - pwm_dbg_show(chip, s); |
|---|
| 1329 | + pwm_dbg_show(chip, s); |
|---|
| 1077 | 1330 | |
|---|
| 1078 | 1331 | return 0; |
|---|
| 1079 | 1332 | } |
|---|
| 1080 | 1333 | |
|---|
| 1081 | | -static const struct seq_operations pwm_seq_ops = { |
|---|
| 1334 | +static const struct seq_operations pwm_debugfs_sops = { |
|---|
| 1082 | 1335 | .start = pwm_seq_start, |
|---|
| 1083 | 1336 | .next = pwm_seq_next, |
|---|
| 1084 | 1337 | .stop = pwm_seq_stop, |
|---|
| 1085 | 1338 | .show = pwm_seq_show, |
|---|
| 1086 | 1339 | }; |
|---|
| 1087 | 1340 | |
|---|
| 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 | | -}; |
|---|
| 1341 | +DEFINE_SEQ_ATTRIBUTE(pwm_debugfs); |
|---|
| 1100 | 1342 | |
|---|
| 1101 | 1343 | static int __init pwm_debugfs_init(void) |
|---|
| 1102 | 1344 | { |
|---|
| 1103 | 1345 | debugfs_create_file("pwm", S_IFREG | S_IRUGO, NULL, NULL, |
|---|
| 1104 | | - &pwm_debugfs_ops); |
|---|
| 1346 | + &pwm_debugfs_fops); |
|---|
| 1105 | 1347 | |
|---|
| 1106 | 1348 | return 0; |
|---|
| 1107 | 1349 | } |
|---|
| 1108 | | -#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT |
|---|
| 1109 | | -postcore_initcall(pwm_debugfs_init); |
|---|
| 1110 | | -#else |
|---|
| 1111 | 1350 | subsys_initcall(pwm_debugfs_init); |
|---|
| 1112 | | -#endif |
|---|
| 1113 | 1351 | #endif /* CONFIG_DEBUG_FS */ |
|---|