Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

pwm: stm32: add support for stm32mp25

Add support for STM32MP25 SoC. Use newly introduced compatible to handle
new features along with registers and bits diversity.
The MFD part of the driver fills in ipidr, so it is used to check the
hardware configuration register, when available to gather the number
of PWM channels and complementary outputs.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
Link: https://lore.kernel.org/r/20250110091922.980627-5-fabrice.gasnier@foss.st.com
Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>

authored by

Fabrice Gasnier and committed by
Uwe Kleine-König
fd0b0697 076a2f3d

+35 -7
+35 -7
drivers/pwm/pwm-stm32.c
··· 19 19 #define CCMR_CHANNEL_SHIFT 8 20 20 #define CCMR_CHANNEL_MASK 0xFF 21 21 #define MAX_BREAKINPUT 2 22 + #define STM32_MAX_PWM_OUTPUT 4 22 23 23 24 struct stm32_breakinput { 24 25 u32 index; ··· 769 768 return stm32_pwm_apply_breakinputs(priv); 770 769 } 771 770 772 - static void stm32_pwm_detect_complementary(struct stm32_pwm *priv) 771 + static void stm32_pwm_detect_complementary(struct stm32_pwm *priv, struct stm32_timers *ddata) 773 772 { 774 773 u32 ccer; 774 + 775 + if (ddata->ipidr) { 776 + u32 val; 777 + 778 + /* Simply read from HWCFGR the number of complementary outputs (MP25). */ 779 + regmap_read(priv->regmap, TIM_HWCFGR1, &val); 780 + priv->have_complementary_output = !!FIELD_GET(TIM_HWCFGR1_NB_OF_DT, val); 781 + return; 782 + } 775 783 776 784 /* 777 785 * If complementary bit doesn't exist writing 1 will have no ··· 793 783 priv->have_complementary_output = (ccer != 0); 794 784 } 795 785 796 - static unsigned int stm32_pwm_detect_channels(struct regmap *regmap, 786 + static unsigned int stm32_pwm_detect_channels(struct stm32_timers *ddata, 797 787 unsigned int *num_enabled) 798 788 { 789 + struct regmap *regmap = ddata->regmap; 799 790 u32 ccer, ccer_backup; 791 + 792 + regmap_read(regmap, TIM_CCER, &ccer_backup); 793 + *num_enabled = hweight32(ccer_backup & TIM_CCER_CCXE); 794 + 795 + if (ddata->ipidr) { 796 + u32 hwcfgr; 797 + unsigned int npwm; 798 + 799 + /* Deduce from HWCFGR the number of outputs (MP25). */ 800 + regmap_read(regmap, TIM_HWCFGR1, &hwcfgr); 801 + 802 + /* 803 + * Timers may have more capture/compare channels than the 804 + * actual number of PWM channel outputs (e.g. TIM_CH[1..4]). 805 + */ 806 + npwm = FIELD_GET(TIM_HWCFGR1_NB_OF_CC, hwcfgr); 807 + 808 + return npwm < STM32_MAX_PWM_OUTPUT ? npwm : STM32_MAX_PWM_OUTPUT; 809 + } 800 810 801 811 /* 802 812 * If channels enable bits don't exist writing 1 will have no 803 813 * effect so we can detect and count them. 804 814 */ 805 - regmap_read(regmap, TIM_CCER, &ccer_backup); 806 815 regmap_set_bits(regmap, TIM_CCER, TIM_CCER_CCXE); 807 816 regmap_read(regmap, TIM_CCER, &ccer); 808 817 regmap_write(regmap, TIM_CCER, ccer_backup); 809 - 810 - *num_enabled = hweight32(ccer_backup & TIM_CCER_CCXE); 811 818 812 819 return hweight32(ccer & TIM_CCER_CCXE); 813 820 } ··· 840 813 unsigned int i; 841 814 int ret; 842 815 843 - npwm = stm32_pwm_detect_channels(ddata->regmap, &num_enabled); 816 + npwm = stm32_pwm_detect_channels(ddata, &num_enabled); 844 817 845 818 chip = devm_pwmchip_alloc(dev, npwm, sizeof(*priv)); 846 819 if (IS_ERR(chip)) ··· 861 834 return dev_err_probe(dev, ret, 862 835 "Failed to configure breakinputs\n"); 863 836 864 - stm32_pwm_detect_complementary(priv); 837 + stm32_pwm_detect_complementary(priv, ddata); 865 838 866 839 ret = devm_clk_rate_exclusive_get(dev, priv->clk); 867 840 if (ret) ··· 934 907 935 908 static const struct of_device_id stm32_pwm_of_match[] = { 936 909 { .compatible = "st,stm32-pwm", }, 910 + { .compatible = "st,stm32mp25-pwm", }, 937 911 { /* end node */ }, 938 912 }; 939 913 MODULE_DEVICE_TABLE(of, stm32_pwm_of_match);