| .. | .. |
|---|
| 12 | 12 | #include <linux/mfd/stm32-timers.h> |
|---|
| 13 | 13 | #include <linux/module.h> |
|---|
| 14 | 14 | #include <linux/of.h> |
|---|
| 15 | +#include <linux/pinctrl/consumer.h> |
|---|
| 15 | 16 | #include <linux/platform_device.h> |
|---|
| 16 | 17 | #include <linux/pwm.h> |
|---|
| 17 | 18 | |
|---|
| 18 | 19 | #define CCMR_CHANNEL_SHIFT 8 |
|---|
| 19 | 20 | #define CCMR_CHANNEL_MASK 0xFF |
|---|
| 20 | 21 | #define MAX_BREAKINPUT 2 |
|---|
| 22 | + |
|---|
| 23 | +struct stm32_breakinput { |
|---|
| 24 | + u32 index; |
|---|
| 25 | + u32 level; |
|---|
| 26 | + u32 filter; |
|---|
| 27 | +}; |
|---|
| 21 | 28 | |
|---|
| 22 | 29 | struct stm32_pwm { |
|---|
| 23 | 30 | struct pwm_chip chip; |
|---|
| .. | .. |
|---|
| 26 | 33 | struct regmap *regmap; |
|---|
| 27 | 34 | u32 max_arr; |
|---|
| 28 | 35 | bool have_complementary_output; |
|---|
| 36 | + struct stm32_breakinput breakinputs[MAX_BREAKINPUT]; |
|---|
| 37 | + unsigned int num_breakinputs; |
|---|
| 29 | 38 | u32 capture[4] ____cacheline_aligned; /* DMA'able buffer */ |
|---|
| 30 | | -}; |
|---|
| 31 | | - |
|---|
| 32 | | -struct stm32_breakinput { |
|---|
| 33 | | - u32 index; |
|---|
| 34 | | - u32 level; |
|---|
| 35 | | - u32 filter; |
|---|
| 36 | 39 | }; |
|---|
| 37 | 40 | |
|---|
| 38 | 41 | static inline struct stm32_pwm *to_stm32_pwm_dev(struct pwm_chip *chip) |
|---|
| .. | .. |
|---|
| 374 | 377 | else |
|---|
| 375 | 378 | regmap_update_bits(priv->regmap, TIM_CCMR2, mask, ccmr); |
|---|
| 376 | 379 | |
|---|
| 377 | | - regmap_update_bits(priv->regmap, TIM_BDTR, |
|---|
| 378 | | - TIM_BDTR_MOE | TIM_BDTR_AOE, |
|---|
| 379 | | - TIM_BDTR_MOE | TIM_BDTR_AOE); |
|---|
| 380 | + regmap_update_bits(priv->regmap, TIM_BDTR, TIM_BDTR_MOE, TIM_BDTR_MOE); |
|---|
| 380 | 381 | |
|---|
| 381 | 382 | return 0; |
|---|
| 382 | 383 | } |
|---|
| .. | .. |
|---|
| 440 | 441 | } |
|---|
| 441 | 442 | |
|---|
| 442 | 443 | static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
|---|
| 443 | | - struct pwm_state *state) |
|---|
| 444 | + const struct pwm_state *state) |
|---|
| 444 | 445 | { |
|---|
| 445 | 446 | bool enabled; |
|---|
| 446 | 447 | struct stm32_pwm *priv = to_stm32_pwm_dev(chip); |
|---|
| .. | .. |
|---|
| 468 | 469 | } |
|---|
| 469 | 470 | |
|---|
| 470 | 471 | static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm, |
|---|
| 471 | | - struct pwm_state *state) |
|---|
| 472 | + const struct pwm_state *state) |
|---|
| 472 | 473 | { |
|---|
| 473 | 474 | struct stm32_pwm *priv = to_stm32_pwm_dev(chip); |
|---|
| 474 | 475 | int ret; |
|---|
| .. | .. |
|---|
| 488 | 489 | }; |
|---|
| 489 | 490 | |
|---|
| 490 | 491 | static int stm32_pwm_set_breakinput(struct stm32_pwm *priv, |
|---|
| 491 | | - int index, int level, int filter) |
|---|
| 492 | + const struct stm32_breakinput *bi) |
|---|
| 492 | 493 | { |
|---|
| 493 | | - u32 bke = (index == 0) ? TIM_BDTR_BKE : TIM_BDTR_BK2E; |
|---|
| 494 | | - int shift = (index == 0) ? TIM_BDTR_BKF_SHIFT : TIM_BDTR_BK2F_SHIFT; |
|---|
| 495 | | - u32 mask = (index == 0) ? TIM_BDTR_BKE | TIM_BDTR_BKP | TIM_BDTR_BKF |
|---|
| 496 | | - : TIM_BDTR_BK2E | TIM_BDTR_BK2P | TIM_BDTR_BK2F; |
|---|
| 497 | | - u32 bdtr = bke; |
|---|
| 494 | + u32 shift = TIM_BDTR_BKF_SHIFT(bi->index); |
|---|
| 495 | + u32 bke = TIM_BDTR_BKE(bi->index); |
|---|
| 496 | + u32 bkp = TIM_BDTR_BKP(bi->index); |
|---|
| 497 | + u32 bkf = TIM_BDTR_BKF(bi->index); |
|---|
| 498 | + u32 mask = bkf | bkp | bke; |
|---|
| 499 | + u32 bdtr; |
|---|
| 498 | 500 | |
|---|
| 499 | | - /* |
|---|
| 500 | | - * The both bits could be set since only one will be wrote |
|---|
| 501 | | - * due to mask value. |
|---|
| 502 | | - */ |
|---|
| 503 | | - if (level) |
|---|
| 504 | | - bdtr |= TIM_BDTR_BKP | TIM_BDTR_BK2P; |
|---|
| 501 | + bdtr = (bi->filter & TIM_BDTR_BKF_MASK) << shift | bke; |
|---|
| 505 | 502 | |
|---|
| 506 | | - bdtr |= (filter & TIM_BDTR_BKF_MASK) << shift; |
|---|
| 503 | + if (bi->level) |
|---|
| 504 | + bdtr |= bkp; |
|---|
| 507 | 505 | |
|---|
| 508 | 506 | regmap_update_bits(priv->regmap, TIM_BDTR, mask, bdtr); |
|---|
| 509 | 507 | |
|---|
| .. | .. |
|---|
| 512 | 510 | return (bdtr & bke) ? 0 : -EINVAL; |
|---|
| 513 | 511 | } |
|---|
| 514 | 512 | |
|---|
| 515 | | -static int stm32_pwm_apply_breakinputs(struct stm32_pwm *priv, |
|---|
| 513 | +static int stm32_pwm_apply_breakinputs(struct stm32_pwm *priv) |
|---|
| 514 | +{ |
|---|
| 515 | + unsigned int i; |
|---|
| 516 | + int ret; |
|---|
| 517 | + |
|---|
| 518 | + for (i = 0; i < priv->num_breakinputs; i++) { |
|---|
| 519 | + ret = stm32_pwm_set_breakinput(priv, &priv->breakinputs[i]); |
|---|
| 520 | + if (ret < 0) |
|---|
| 521 | + return ret; |
|---|
| 522 | + } |
|---|
| 523 | + |
|---|
| 524 | + return 0; |
|---|
| 525 | +} |
|---|
| 526 | + |
|---|
| 527 | +static int stm32_pwm_probe_breakinputs(struct stm32_pwm *priv, |
|---|
| 516 | 528 | struct device_node *np) |
|---|
| 517 | 529 | { |
|---|
| 518 | | - struct stm32_breakinput breakinput[MAX_BREAKINPUT]; |
|---|
| 519 | | - int nb, ret, i, array_size; |
|---|
| 530 | + int nb, ret, array_size; |
|---|
| 531 | + unsigned int i; |
|---|
| 520 | 532 | |
|---|
| 521 | 533 | nb = of_property_count_elems_of_size(np, "st,breakinput", |
|---|
| 522 | 534 | sizeof(struct stm32_breakinput)); |
|---|
| .. | .. |
|---|
| 531 | 543 | if (nb > MAX_BREAKINPUT) |
|---|
| 532 | 544 | return -EINVAL; |
|---|
| 533 | 545 | |
|---|
| 546 | + priv->num_breakinputs = nb; |
|---|
| 534 | 547 | array_size = nb * sizeof(struct stm32_breakinput) / sizeof(u32); |
|---|
| 535 | 548 | ret = of_property_read_u32_array(np, "st,breakinput", |
|---|
| 536 | | - (u32 *)breakinput, array_size); |
|---|
| 549 | + (u32 *)priv->breakinputs, array_size); |
|---|
| 537 | 550 | if (ret) |
|---|
| 538 | 551 | return ret; |
|---|
| 539 | 552 | |
|---|
| 540 | | - for (i = 0; i < nb && !ret; i++) { |
|---|
| 541 | | - ret = stm32_pwm_set_breakinput(priv, |
|---|
| 542 | | - breakinput[i].index, |
|---|
| 543 | | - breakinput[i].level, |
|---|
| 544 | | - breakinput[i].filter); |
|---|
| 553 | + for (i = 0; i < priv->num_breakinputs; i++) { |
|---|
| 554 | + if (priv->breakinputs[i].index > 1 || |
|---|
| 555 | + priv->breakinputs[i].level > 1 || |
|---|
| 556 | + priv->breakinputs[i].filter > 15) |
|---|
| 557 | + return -EINVAL; |
|---|
| 545 | 558 | } |
|---|
| 546 | 559 | |
|---|
| 547 | | - return ret; |
|---|
| 560 | + return stm32_pwm_apply_breakinputs(priv); |
|---|
| 548 | 561 | } |
|---|
| 549 | 562 | |
|---|
| 550 | 563 | static void stm32_pwm_detect_complementary(struct stm32_pwm *priv) |
|---|
| .. | .. |
|---|
| 608 | 621 | priv->regmap = ddata->regmap; |
|---|
| 609 | 622 | priv->clk = ddata->clk; |
|---|
| 610 | 623 | priv->max_arr = ddata->max_arr; |
|---|
| 624 | + priv->chip.of_xlate = of_pwm_xlate_with_flags; |
|---|
| 625 | + priv->chip.of_pwm_n_cells = 3; |
|---|
| 611 | 626 | |
|---|
| 612 | 627 | if (!priv->regmap || !priv->clk) |
|---|
| 613 | 628 | return -EINVAL; |
|---|
| 614 | 629 | |
|---|
| 615 | | - ret = stm32_pwm_apply_breakinputs(priv, np); |
|---|
| 630 | + ret = stm32_pwm_probe_breakinputs(priv, np); |
|---|
| 616 | 631 | if (ret) |
|---|
| 617 | 632 | return ret; |
|---|
| 618 | 633 | |
|---|
| .. | .. |
|---|
| 645 | 660 | return 0; |
|---|
| 646 | 661 | } |
|---|
| 647 | 662 | |
|---|
| 663 | +static int __maybe_unused stm32_pwm_suspend(struct device *dev) |
|---|
| 664 | +{ |
|---|
| 665 | + struct stm32_pwm *priv = dev_get_drvdata(dev); |
|---|
| 666 | + unsigned int i; |
|---|
| 667 | + u32 ccer, mask; |
|---|
| 668 | + |
|---|
| 669 | + /* Look for active channels */ |
|---|
| 670 | + ccer = active_channels(priv); |
|---|
| 671 | + |
|---|
| 672 | + for (i = 0; i < priv->chip.npwm; i++) { |
|---|
| 673 | + mask = TIM_CCER_CC1E << (i * 4); |
|---|
| 674 | + if (ccer & mask) { |
|---|
| 675 | + dev_err(dev, "PWM %u still in use by consumer %s\n", |
|---|
| 676 | + i, priv->chip.pwms[i].label); |
|---|
| 677 | + return -EBUSY; |
|---|
| 678 | + } |
|---|
| 679 | + } |
|---|
| 680 | + |
|---|
| 681 | + return pinctrl_pm_select_sleep_state(dev); |
|---|
| 682 | +} |
|---|
| 683 | + |
|---|
| 684 | +static int __maybe_unused stm32_pwm_resume(struct device *dev) |
|---|
| 685 | +{ |
|---|
| 686 | + struct stm32_pwm *priv = dev_get_drvdata(dev); |
|---|
| 687 | + int ret; |
|---|
| 688 | + |
|---|
| 689 | + ret = pinctrl_pm_select_default_state(dev); |
|---|
| 690 | + if (ret) |
|---|
| 691 | + return ret; |
|---|
| 692 | + |
|---|
| 693 | + /* restore breakinput registers that may have been lost in low power */ |
|---|
| 694 | + return stm32_pwm_apply_breakinputs(priv); |
|---|
| 695 | +} |
|---|
| 696 | + |
|---|
| 697 | +static SIMPLE_DEV_PM_OPS(stm32_pwm_pm_ops, stm32_pwm_suspend, stm32_pwm_resume); |
|---|
| 698 | + |
|---|
| 648 | 699 | static const struct of_device_id stm32_pwm_of_match[] = { |
|---|
| 649 | 700 | { .compatible = "st,stm32-pwm", }, |
|---|
| 650 | 701 | { /* end node */ }, |
|---|
| .. | .. |
|---|
| 657 | 708 | .driver = { |
|---|
| 658 | 709 | .name = "stm32-pwm", |
|---|
| 659 | 710 | .of_match_table = stm32_pwm_of_match, |
|---|
| 711 | + .pm = &stm32_pwm_pm_ops, |
|---|
| 660 | 712 | }, |
|---|
| 661 | 713 | }; |
|---|
| 662 | 714 | module_platform_driver(stm32_pwm_driver); |
|---|