mfd: stm32-lptimer: Add support for stm32mp25
authorFabrice Gasnier <fabrice.gasnier@foss.st.com>
Tue, 29 Apr 2025 12:51:28 +0000 (14:51 +0200)
committerLee Jones <lee@kernel.org>
Tue, 13 May 2025 10:12:52 +0000 (11:12 +0100)
Add support for STM32MP25 SoC.
A new hardware configuration register (HWCFGR2) has been added, to gather
number of capture/compare channels, autonomous mode and input capture
capability. The full feature set is implemented in LPTIM1/2/3/4. LPTIM5
supports a smaller set of features. This can now be read from HWCFGR
registers.

Add new registers to the stm32-lptimer.h: CCMR1, CCR2, HWCFGR1/2 and VERR.
Update the stm32_lptimer data struct so signal the number of
capture/compare channels to the child devices.
Also Remove some unused bit masks (CMPOK_ARROK / CMPOKCF_ARROKCF).

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
Link: https://lore.kernel.org/r/20250429125133.1574167-3-fabrice.gasnier@foss.st.com
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/mfd/stm32-lptimer.c
include/linux/mfd/stm32-lptimer.h

index b2704a9..09073db 100644 (file)
@@ -6,6 +6,7 @@
  * Inspired by Benjamin Gaignard's stm32-timers driver
  */
 
+#include <linux/bitfield.h>
 #include <linux/mfd/stm32-lptimer.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
@@ -49,6 +50,36 @@ static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata)
        return 0;
 }
 
+static int stm32_lptimer_detect_hwcfgr(struct stm32_lptimer *ddata)
+{
+       u32 val;
+       int ret;
+
+       ret = regmap_read(ddata->regmap, STM32_LPTIM_VERR, &ddata->version);
+       if (ret)
+               return ret;
+
+       /* Try to guess parameters from HWCFGR: e.g. encoder mode (STM32MP15) */
+       ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR1, &val);
+       if (ret)
+               return ret;
+
+       /* Fallback to legacy init if HWCFGR isn't present */
+       if (!val)
+               return stm32_lptimer_detect_encoder(ddata);
+
+       ddata->has_encoder = FIELD_GET(STM32_LPTIM_HWCFGR1_ENCODER, val);
+
+       ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR2, &val);
+       if (ret)
+               return ret;
+
+       /* Number of capture/compare channels */
+       ddata->num_cc_chans = FIELD_GET(STM32_LPTIM_HWCFGR2_CHAN_NUM, val);
+
+       return 0;
+}
+
 static int stm32_lptimer_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -73,7 +104,7 @@ static int stm32_lptimer_probe(struct platform_device *pdev)
        if (IS_ERR(ddata->clk))
                return PTR_ERR(ddata->clk);
 
-       ret = stm32_lptimer_detect_encoder(ddata);
+       ret = stm32_lptimer_detect_hwcfgr(ddata);
        if (ret)
                return ret;
 
index 06d3f11..a592c8d 100644 (file)
 #define STM32_LPTIM_IER                0x08    /* Interrupt Enable Reg      */
 #define STM32_LPTIM_CFGR       0x0C    /* Configuration Reg         */
 #define STM32_LPTIM_CR         0x10    /* Control Reg               */
-#define STM32_LPTIM_CMP                0x14    /* Compare Reg               */
+#define STM32_LPTIM_CMP                0x14    /* Compare Reg (MP25 CCR1)   */
 #define STM32_LPTIM_ARR                0x18    /* Autoreload Reg            */
 #define STM32_LPTIM_CNT                0x1C    /* Counter Reg               */
+#define STM32_LPTIM_CCMR1      0x2C    /* Capture/Compare Mode MP25 */
+#define STM32_LPTIM_CCR2       0x34    /* Compare Reg2 MP25         */
+
+#define STM32_LPTIM_HWCFGR2    0x3EC   /* Hardware configuration register 2 - MP25 */
+#define STM32_LPTIM_HWCFGR1    0x3F0   /* Hardware configuration register 1 - MP15 */
+#define STM32_LPTIM_VERR       0x3F4   /* Version identification register - MP15 */
 
 /* STM32_LPTIM_ISR - bit fields */
+#define STM32_LPTIM_DIEROK_ARROK       (BIT(24) | BIT(4)) /* MP25 */
+#define STM32_LPTIM_CMP2_ARROK         (BIT(19) | BIT(4))
 #define STM32_LPTIM_CMPOK_ARROK                GENMASK(4, 3)
 #define STM32_LPTIM_ARROK              BIT(4)
 #define STM32_LPTIM_CMPOK              BIT(3)
 
 /* STM32_LPTIM_ICR - bit fields */
-#define STM32_LPTIM_ARRMCF             BIT(1)
+#define STM32_LPTIM_DIEROKCF_ARROKCF   (BIT(24) | BIT(4)) /* MP25 */
+#define STM32_LPTIM_CMP2OKCF_ARROKCF   (BIT(19) | BIT(4))
 #define STM32_LPTIM_CMPOKCF_ARROKCF    GENMASK(4, 3)
+#define STM32_LPTIM_ARRMCF             BIT(1)
 
-/* STM32_LPTIM_IER - bit flieds */
+/* STM32_LPTIM_IER - bit fields */
 #define STM32_LPTIM_ARRMIE     BIT(1)
 
 /* STM32_LPTIM_CR - bit fields */
 /* STM32_LPTIM_ARR */
 #define STM32_LPTIM_MAX_ARR    0xFFFF
 
+/* STM32_LPTIM_CCMR1 */
+#define STM32_LPTIM_CC2P       GENMASK(19, 18)
+#define STM32_LPTIM_CC2E       BIT(17)
+#define STM32_LPTIM_CC2SEL     BIT(16)
+#define STM32_LPTIM_CC1P       GENMASK(3, 2)
+#define STM32_LPTIM_CC1E       BIT(1)
+#define STM32_LPTIM_CC1SEL     BIT(0)
+
+/* STM32_LPTIM_HWCFGR1 */
+#define STM32_LPTIM_HWCFGR1_ENCODER    BIT(16)
+
+/* STM32_LPTIM_HWCFGR2 */
+#define STM32_LPTIM_HWCFGR2_CHAN_NUM   GENMASK(3, 0)
+
+/* STM32_LPTIM_VERR */
+#define STM32_LPTIM_VERR_23    0x23    /* STM32MP25 */
+
 /**
  * struct stm32_lptimer - STM32 Low-Power Timer data assigned by parent device
  * @clk: clock reference for this instance
  * @regmap: register map reference for this instance
  * @has_encoder: indicates this Low-Power Timer supports encoder mode
+ * @num_cc_chans: indicates the number of capture/compare channels
+ * @version: indicates the major and minor revision of the controller
  */
 struct stm32_lptimer {
        struct clk *clk;
        struct regmap *regmap;
        bool has_encoder;
+       unsigned int num_cc_chans;
+       u32 version;
 };
 
 #endif