.. | .. |
---|
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); |
---|