This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 5be057f0618b35acd8f5c4c19acafab639be17e3
Author: raiden00pl <[email protected]>
AuthorDate: Sat Oct 24 13:25:29 2026 +0200

    arch/arm/src/common/stm32: add STM32L4 compatible LPTIM API
    
    Add the timer operations of the STM32L4 LPTIM API to the common driver:
    setmode, setclock, setchannel, setclocksource, setpolarity, setcountmode
    and getperiod.  init() resets the timer and fails for an instance in use,
    start() takes stm32_lptim_mode_t.
    
    Signed-off-by: raiden00pl <[email protected]>
    Assisted-by: Claude Code
---
 arch/arm/src/common/stm32/stm32_lptim.c | 982 +++++++++++++++++++++++---------
 arch/arm/src/common/stm32/stm32_lptim.h |  96 +++-
 2 files changed, 784 insertions(+), 294 deletions(-)

diff --git a/arch/arm/src/common/stm32/stm32_lptim.c 
b/arch/arm/src/common/stm32/stm32_lptim.c
index fcdf86a6a18..ac880b92deb 100644
--- a/arch/arm/src/common/stm32/stm32_lptim.c
+++ b/arch/arm/src/common/stm32/stm32_lptim.c
@@ -28,218 +28,651 @@
 #include <nuttx/arch.h>
 #include <nuttx/irq.h>
 
-#include <sys/types.h>
-#include <stdint.h>
+#include <sys/param.h>
+
 #include <stdbool.h>
+#include <stdint.h>
 #include <assert.h>
 #include <errno.h>
-#include <nuttx/debug.h>
 
 #include <arch/board/board.h>
 
-#include "chip.h"
 #include "arm_internal.h"
-#include "stm32_rcc.h"
+#include "chip.h"
+#include "stm32.h"
 #include "stm32_lptim.h"
 #include "stm32_lptim_clk.h"
 
-#if defined(CONFIG_STM32_LPTIM1)  || defined(CONFIG_STM32_LPTIM2)  || \
-    defined(CONFIG_STM32_LPTIM3)  || defined(CONFIG_STM32_LPTIM4)  || \
-    defined(CONFIG_STM32_LPTIM5)
+#if defined(CONFIG_STM32_LPTIM1) || \
+    defined(CONFIG_STM32_LPTIM2) || \
+    defined(CONFIG_STM32_LPTIM3) || \
+    defined(CONFIG_STM32_LPTIM4) || \
+    defined(CONFIG_STM32_LPTIM5) || \
+    defined(CONFIG_STM32_LPTIM6)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* LPTIM kernel clock frequency, optionally provided by board.h.  It is
+ * needed only by setclock().
+ */
+
+#ifdef STM32_LPTIM1_CLKIN
+#  define LPTIM1_CLKIN STM32_LPTIM1_CLKIN
+#else
+#  define LPTIM1_CLKIN 0
+#endif
+#ifdef STM32_LPTIM2_CLKIN
+#  define LPTIM2_CLKIN STM32_LPTIM2_CLKIN
+#else
+#  define LPTIM2_CLKIN 0
+#endif
+#ifdef STM32_LPTIM3_CLKIN
+#  define LPTIM3_CLKIN STM32_LPTIM3_CLKIN
+#else
+#  define LPTIM3_CLKIN 0
+#endif
+#ifdef STM32_LPTIM4_CLKIN
+#  define LPTIM4_CLKIN STM32_LPTIM4_CLKIN
+#else
+#  define LPTIM4_CLKIN 0
+#endif
+#ifdef STM32_LPTIM5_CLKIN
+#  define LPTIM5_CLKIN STM32_LPTIM5_CLKIN
+#else
+#  define LPTIM5_CLKIN 0
+#endif
+#ifdef STM32_LPTIM6_CLKIN
+#  define LPTIM6_CLKIN STM32_LPTIM6_CLKIN
+#else
+#  define LPTIM6_CLKIN 0
+#endif
+
+/* Output channel pins, GPIO_LPTIMn_CHmOUT from board.h (0: none) */
+
+#define LPTIM_NCHANNELS 4
+
+#ifdef GPIO_LPTIM1_CH1OUT
+#  define LPTIM1_CH1OUT GPIO_LPTIM1_CH1OUT
+#else
+#  define LPTIM1_CH1OUT 0
+#endif
+#ifdef GPIO_LPTIM1_CH2OUT
+#  define LPTIM1_CH2OUT GPIO_LPTIM1_CH2OUT
+#else
+#  define LPTIM1_CH2OUT 0
+#endif
+#ifdef GPIO_LPTIM1_CH3OUT
+#  define LPTIM1_CH3OUT GPIO_LPTIM1_CH3OUT
+#else
+#  define LPTIM1_CH3OUT 0
+#endif
+#ifdef GPIO_LPTIM1_CH4OUT
+#  define LPTIM1_CH4OUT GPIO_LPTIM1_CH4OUT
+#else
+#  define LPTIM1_CH4OUT 0
+#endif
+#ifdef GPIO_LPTIM2_CH1OUT
+#  define LPTIM2_CH1OUT GPIO_LPTIM2_CH1OUT
+#else
+#  define LPTIM2_CH1OUT 0
+#endif
+#ifdef GPIO_LPTIM2_CH2OUT
+#  define LPTIM2_CH2OUT GPIO_LPTIM2_CH2OUT
+#else
+#  define LPTIM2_CH2OUT 0
+#endif
+#ifdef GPIO_LPTIM2_CH3OUT
+#  define LPTIM2_CH3OUT GPIO_LPTIM2_CH3OUT
+#else
+#  define LPTIM2_CH3OUT 0
+#endif
+#ifdef GPIO_LPTIM2_CH4OUT
+#  define LPTIM2_CH4OUT GPIO_LPTIM2_CH4OUT
+#else
+#  define LPTIM2_CH4OUT 0
+#endif
+#ifdef GPIO_LPTIM3_CH1OUT
+#  define LPTIM3_CH1OUT GPIO_LPTIM3_CH1OUT
+#else
+#  define LPTIM3_CH1OUT 0
+#endif
+#ifdef GPIO_LPTIM3_CH2OUT
+#  define LPTIM3_CH2OUT GPIO_LPTIM3_CH2OUT
+#else
+#  define LPTIM3_CH2OUT 0
+#endif
+#ifdef GPIO_LPTIM3_CH3OUT
+#  define LPTIM3_CH3OUT GPIO_LPTIM3_CH3OUT
+#else
+#  define LPTIM3_CH3OUT 0
+#endif
+#ifdef GPIO_LPTIM3_CH4OUT
+#  define LPTIM3_CH4OUT GPIO_LPTIM3_CH4OUT
+#else
+#  define LPTIM3_CH4OUT 0
+#endif
+#ifdef GPIO_LPTIM4_CH1OUT
+#  define LPTIM4_CH1OUT GPIO_LPTIM4_CH1OUT
+#else
+#  define LPTIM4_CH1OUT 0
+#endif
+#ifdef GPIO_LPTIM4_CH2OUT
+#  define LPTIM4_CH2OUT GPIO_LPTIM4_CH2OUT
+#else
+#  define LPTIM4_CH2OUT 0
+#endif
+#ifdef GPIO_LPTIM4_CH3OUT
+#  define LPTIM4_CH3OUT GPIO_LPTIM4_CH3OUT
+#else
+#  define LPTIM4_CH3OUT 0
+#endif
+#ifdef GPIO_LPTIM4_CH4OUT
+#  define LPTIM4_CH4OUT GPIO_LPTIM4_CH4OUT
+#else
+#  define LPTIM4_CH4OUT 0
+#endif
+#ifdef GPIO_LPTIM5_CH1OUT
+#  define LPTIM5_CH1OUT GPIO_LPTIM5_CH1OUT
+#else
+#  define LPTIM5_CH1OUT 0
+#endif
+#ifdef GPIO_LPTIM5_CH2OUT
+#  define LPTIM5_CH2OUT GPIO_LPTIM5_CH2OUT
+#else
+#  define LPTIM5_CH2OUT 0
+#endif
+#ifdef GPIO_LPTIM5_CH3OUT
+#  define LPTIM5_CH3OUT GPIO_LPTIM5_CH3OUT
+#else
+#  define LPTIM5_CH3OUT 0
+#endif
+#ifdef GPIO_LPTIM5_CH4OUT
+#  define LPTIM5_CH4OUT GPIO_LPTIM5_CH4OUT
+#else
+#  define LPTIM5_CH4OUT 0
+#endif
+#ifdef GPIO_LPTIM6_CH1OUT
+#  define LPTIM6_CH1OUT GPIO_LPTIM6_CH1OUT
+#else
+#  define LPTIM6_CH1OUT 0
+#endif
+#ifdef GPIO_LPTIM6_CH2OUT
+#  define LPTIM6_CH2OUT GPIO_LPTIM6_CH2OUT
+#else
+#  define LPTIM6_CH2OUT 0
+#endif
+#ifdef GPIO_LPTIM6_CH3OUT
+#  define LPTIM6_CH3OUT GPIO_LPTIM6_CH3OUT
+#else
+#  define LPTIM6_CH3OUT 0
+#endif
+#ifdef GPIO_LPTIM6_CH4OUT
+#  define LPTIM6_CH4OUT GPIO_LPTIM6_CH4OUT
+#else
+#  define LPTIM6_CH4OUT 0
+#endif
+
+/* Largest PRESC field value (division by 128) */
+
+#define LPTIM_PRESC_MAX 7
 
 /****************************************************************************
- * Private Function prototypes
+ * Private Types
  ****************************************************************************/
 
-/* Low-power timer methods */
+struct stm32_lptim_priv_s
+{
+  const struct stm32_lptim_ops_s *ops;
+  bool     inuse;                  /* Returned by stm32_lptim_init() */
+  uint32_t base;                   /* LPTIMn base address */
+  int      irq;                    /* LPTIMn interrupt */
+  uint32_t freq;                   /* LPTIMn kernel clock frequency */
+  uint32_t enreg;                  /* RCC clock enable register */
+  uint32_t enbit;                  /* RCC clock enable bit */
+  uint32_t rstreg;                 /* RCC reset register */
+  uint32_t rstbit;                 /* RCC reset bit */
+  uint32_t pins[LPTIM_NCHANNELS];  /* Output channel pin configurations */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
 
+static int stm32_lptim_setmode(struct stm32_lptim_dev_s *dev,
+                               stm32_lptim_mode_t mode);
+static int stm32_lptim_setclock(struct stm32_lptim_dev_s *dev,
+                                uint32_t freq);
+static int stm32_lptim_setchannel(struct stm32_lptim_dev_s *dev,
+                                  stm32_lptim_channel_t channel,
+                                  int enable);
+static int stm32_lptim_setclocksource(struct stm32_lptim_dev_s *dev,
+                                      stm32_lptim_clksrc_t clksrc);
+static int stm32_lptim_setpolarity(struct stm32_lptim_dev_s *dev,
+                                   stm32_lptim_clkpol_t polarity);
+static uint32_t stm32_lptim_getcounter(struct stm32_lptim_dev_s *dev);
+static int stm32_lptim_setcountmode(struct stm32_lptim_dev_s *dev,
+                                    stm32_lptim_cntmode_t cntmode);
+static void stm32_lptim_setperiod(struct stm32_lptim_dev_s *dev,
+                                  uint32_t period);
+static uint32_t stm32_lptim_getperiod(struct stm32_lptim_dev_s *dev);
 static void stm32_lptim_setcfgr(struct stm32_lptim_dev_s *dev,
                                 uint32_t regval);
-static void stm32_lptim_setperiod(struct stm32_lptim_dev_s *dev,
-                                uint32_t period);
 static void stm32_lptim_setcompare(struct stm32_lptim_dev_s *dev,
-                                uint32_t cmp);
-static uint32_t stm32_lptim_getcounter(struct stm32_lptim_dev_s *dev);
-static int  stm32_lptim_setinput(struct stm32_lptim_dev_s *dev,
+                                   uint32_t cmp);
+static int stm32_lptim_setinput(struct stm32_lptim_dev_s *dev,
                                 uint32_t input, uint32_t mux);
 static void stm32_lptim_enable(struct stm32_lptim_dev_s *dev, bool on);
 static void stm32_lptim_start(struct stm32_lptim_dev_s *dev,
-                                 stm32_lptim_start_mode_t mode);
+                              stm32_lptim_mode_t mode);
 static void stm32_lptim_resetcounter(struct stm32_lptim_dev_s *dev);
-static void stm32_lptim_enablerar(struct stm32_lptim_dev_s *dev,
-                                  bool on);
-
-static int  stm32_lptim_setisr(struct stm32_lptim_dev_s *dev,
-                               xcpt_t handler, void *arg, int source);
+static void stm32_lptim_enablerar(struct stm32_lptim_dev_s *dev, bool on);
+static int stm32_lptim_setisr(struct stm32_lptim_dev_s *dev,
+                              xcpt_t handler, void *arg, int source);
 static void stm32_lptim_enableint(struct stm32_lptim_dev_s *dev,
                                   int source);
 static void stm32_lptim_disableint(struct stm32_lptim_dev_s *dev,
-                                 int source);
-static void stm32_lptim_ackint(struct stm32_lptim_dev_s *dev,
-                               int source);
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
+                                   int source);
+static void stm32_lptim_ackint(struct stm32_lptim_dev_s *dev, int source);
 
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
-static const struct stm32_lptim_ops_s stm32_lptim_ops =
-{
-  .setcfgr         = &stm32_lptim_setcfgr,
-  .setperiod       = &stm32_lptim_setperiod,
-  .setcompare      = &stm32_lptim_setcompare,
-  .getcounter      = &stm32_lptim_getcounter,
-  .setinput        = &stm32_lptim_setinput,
-  .enable          = &stm32_lptim_enable,
-  .start           = &stm32_lptim_start,
-  .resetcounter    = &stm32_lptim_resetcounter,
-  .enablerar       = &stm32_lptim_enablerar,
-  .setisr          = &stm32_lptim_setisr,
-  .enableint       = &stm32_lptim_enableint,
-  .disableint      = &stm32_lptim_disableint,
-  .ackint          = &stm32_lptim_ackint
+static const struct stm32_lptim_ops_s g_lptim_ops =
+{
+  .setmode        = stm32_lptim_setmode,
+  .setclock       = stm32_lptim_setclock,
+  .setchannel     = stm32_lptim_setchannel,
+  .setclocksource = stm32_lptim_setclocksource,
+  .setpolarity    = stm32_lptim_setpolarity,
+  .getcounter     = stm32_lptim_getcounter,
+  .setcountmode   = stm32_lptim_setcountmode,
+  .setperiod      = stm32_lptim_setperiod,
+  .getperiod      = stm32_lptim_getperiod,
+  .setcfgr        = stm32_lptim_setcfgr,
+  .setcompare     = stm32_lptim_setcompare,
+  .setinput       = stm32_lptim_setinput,
+  .enable         = stm32_lptim_enable,
+  .start          = stm32_lptim_start,
+  .resetcounter   = stm32_lptim_resetcounter,
+  .enablerar      = stm32_lptim_enablerar,
+  .setisr         = stm32_lptim_setisr,
+  .enableint      = stm32_lptim_enableint,
+  .disableint     = stm32_lptim_disableint,
+  .ackint         = stm32_lptim_ackint,
 };
 
 #ifdef CONFIG_STM32_LPTIM1
-struct stm32_lptim_dev_s stm32_lptim1_priv =
+static struct stm32_lptim_priv_s g_lptim1 =
 {
-  .ops        = &stm32_lptim_ops,
+  .ops        = &g_lptim_ops,
   .base       = STM32_LPTIM1_BASE,
+  .irq        = STM32_IRQ_LPTIM1,
+  .freq       = LPTIM1_CLKIN,
+  .enreg      = STM32_RCC_LPTIM1_EN_REG,
+  .enbit      = STM32_RCC_LPTIM1_EN,
+  .rstreg     = STM32_RCC_LPTIM1_RST_REG,
+  .rstbit     = STM32_RCC_LPTIM1_RST,
+  .pins       =
+  {
+    LPTIM1_CH1OUT, LPTIM1_CH2OUT, LPTIM1_CH3OUT, LPTIM1_CH4OUT
+  },
 };
 #endif
+
 #ifdef CONFIG_STM32_LPTIM2
-struct stm32_lptim_dev_s stm32_lptim2_priv =
+static struct stm32_lptim_priv_s g_lptim2 =
 {
-  .ops        = &stm32_lptim_ops,
+  .ops        = &g_lptim_ops,
   .base       = STM32_LPTIM2_BASE,
+  .irq        = STM32_IRQ_LPTIM2,
+  .freq       = LPTIM2_CLKIN,
+  .enreg      = STM32_RCC_LPTIM2_EN_REG,
+  .enbit      = STM32_RCC_LPTIM2_EN,
+  .rstreg     = STM32_RCC_LPTIM2_RST_REG,
+  .rstbit     = STM32_RCC_LPTIM2_RST,
+  .pins       =
+  {
+    LPTIM2_CH1OUT, LPTIM2_CH2OUT, LPTIM2_CH3OUT, LPTIM2_CH4OUT
+  },
 };
 #endif
+
 #ifdef CONFIG_STM32_LPTIM3
-struct stm32_lptim_dev_s stm32_lptim3_priv =
+static struct stm32_lptim_priv_s g_lptim3 =
 {
-  .ops        = &stm32_lptim_ops,
+  .ops        = &g_lptim_ops,
   .base       = STM32_LPTIM3_BASE,
+  .irq        = STM32_IRQ_LPTIM3,
+  .freq       = LPTIM3_CLKIN,
+  .enreg      = STM32_RCC_LPTIM3_EN_REG,
+  .enbit      = STM32_RCC_LPTIM3_EN,
+  .rstreg     = STM32_RCC_LPTIM3_RST_REG,
+  .rstbit     = STM32_RCC_LPTIM3_RST,
+  .pins       =
+  {
+    LPTIM3_CH1OUT, LPTIM3_CH2OUT, LPTIM3_CH3OUT, LPTIM3_CH4OUT
+  },
 };
 #endif
+
 #ifdef CONFIG_STM32_LPTIM4
-struct stm32_lptim_dev_s stm32_lptim4_priv =
+static struct stm32_lptim_priv_s g_lptim4 =
 {
-  .ops        = &stm32_lptim_ops,
+  .ops        = &g_lptim_ops,
   .base       = STM32_LPTIM4_BASE,
+  .irq        = STM32_IRQ_LPTIM4,
+  .freq       = LPTIM4_CLKIN,
+  .enreg      = STM32_RCC_LPTIM4_EN_REG,
+  .enbit      = STM32_RCC_LPTIM4_EN,
+  .rstreg     = STM32_RCC_LPTIM4_RST_REG,
+  .rstbit     = STM32_RCC_LPTIM4_RST,
+  .pins       =
+  {
+    LPTIM4_CH1OUT, LPTIM4_CH2OUT, LPTIM4_CH3OUT, LPTIM4_CH4OUT
+  },
 };
 #endif
+
 #ifdef CONFIG_STM32_LPTIM5
-struct stm32_lptim_dev_s stm32_lptim5_priv =
+static struct stm32_lptim_priv_s g_lptim5 =
 {
-  .ops        = &stm32_lptim_ops,
+  .ops        = &g_lptim_ops,
   .base       = STM32_LPTIM5_BASE,
+  .irq        = STM32_IRQ_LPTIM5,
+  .freq       = LPTIM5_CLKIN,
+  .enreg      = STM32_RCC_LPTIM5_EN_REG,
+  .enbit      = STM32_RCC_LPTIM5_EN,
+  .rstreg     = STM32_RCC_LPTIM5_RST_REG,
+  .rstbit     = STM32_RCC_LPTIM5_RST,
+  .pins       =
+  {
+    LPTIM5_CH1OUT, LPTIM5_CH2OUT, LPTIM5_CH3OUT, LPTIM5_CH4OUT
+  },
+};
+#endif
+
+#ifdef CONFIG_STM32_LPTIM6
+static struct stm32_lptim_priv_s g_lptim6 =
+{
+  .ops        = &g_lptim_ops,
+  .base       = STM32_LPTIM6_BASE,
+  .irq        = STM32_IRQ_LPTIM6,
+  .freq       = LPTIM6_CLKIN,
+  .enreg      = STM32_RCC_LPTIM6_EN_REG,
+  .enbit      = STM32_RCC_LPTIM6_EN,
+  .rstreg     = STM32_RCC_LPTIM6_RST_REG,
+  .rstbit     = STM32_RCC_LPTIM6_RST,
+  .pins       =
+  {
+    LPTIM6_CH1OUT, LPTIM6_CH2OUT, LPTIM6_CH3OUT, LPTIM6_CH4OUT
+  },
 };
 #endif
 
+/* Instances indexed by LPTIM number - 1 */
+
+static struct stm32_lptim_priv_s * const g_lptim[] =
+{
+#ifdef CONFIG_STM32_LPTIM1
+  [0] = &g_lptim1,
+#endif
+#ifdef CONFIG_STM32_LPTIM2
+  [1] = &g_lptim2,
+#endif
+#ifdef CONFIG_STM32_LPTIM3
+  [2] = &g_lptim3,
+#endif
+#ifdef CONFIG_STM32_LPTIM4
+  [3] = &g_lptim4,
+#endif
+#ifdef CONFIG_STM32_LPTIM5
+  [4] = &g_lptim5,
+#endif
+#ifdef CONFIG_STM32_LPTIM6
+  [5] = &g_lptim6,
+#endif
+};
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
-/* Get a 32-bit register value by offset.
- */
+/****************************************************************************
+ * Name: stm32_getreg32 / stm32_putreg32 / stm32_modifyreg32
+ ****************************************************************************/
 
 static inline uint32_t stm32_getreg32(struct stm32_lptim_dev_s *dev,
                                       uint8_t offset)
 {
-  return getreg32(dev->base + offset);
+  return getreg32(((struct stm32_lptim_priv_s *)dev)->base + offset);
 }
 
-/* Put a 32-bit register value by offset.
- */
-
 static inline void stm32_putreg32(struct stm32_lptim_dev_s *dev,
                                   uint8_t offset, uint32_t value)
 {
-  putreg32(value, dev->base + offset);
+  putreg32(value, ((struct stm32_lptim_priv_s *)dev)->base + offset);
 }
 
-static void stm32_lptim_setcfgr(struct stm32_lptim_dev_s *dev,
-                                uint32_t regval)
+static inline void stm32_modifyreg32(struct stm32_lptim_dev_s *dev,
+                                     uint8_t offset, uint32_t clearbits,
+                                     uint32_t setbits)
 {
-  stm32_putreg32(dev, STM32_LPTIM_CFGR_OFFSET, regval);
+  modifyreg32(((struct stm32_lptim_priv_s *)dev)->base + offset,
+              clearbits, setbits);
 }
 
-static void stm32_lptim_setperiod(struct stm32_lptim_dev_s *dev,
-                                  uint32_t period)
-{
 #ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2
-  uint32_t timeout;
+/****************************************************************************
+ * Name: stm32_lptim_writesync
+ *
+ * Description:
+ *   Write ARR or CMP and, when the timer is enabled, wait until the write
+ *   to the register in the LPTIM kernel clock domain is complete.
+ *
+ ****************************************************************************/
 
-  /* For STM32H5: Clear ARROK flag BEFORE writing ARR when timer is enabled
-   * This ensures we wait for the new value to be loaded
-   */
+static void stm32_lptim_writesync(struct stm32_lptim_dev_s *dev,
+                                  uint8_t offset, uint32_t value,
+                                  uint32_t okflag)
+{
+  bool enabled = (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) &
+                  LPTIM_CR_ENABLE) != 0;
+  uint32_t timeout;
 
-  if (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) & LPTIM_CR_ENABLE)
+  if (enabled)
     {
-      stm32_putreg32(dev, STM32_LPTIM_ICR_OFFSET, LPTIM_ISR_ARROK);
+      stm32_putreg32(dev, STM32_LPTIM_ICR_OFFSET, okflag);
     }
-#endif
 
-  stm32_putreg32(dev, STM32_LPTIM_ARR_OFFSET, period);
-
-#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2
-  /* Wait for ARROK flag when timer is enabled */
+  stm32_putreg32(dev, offset, value);
 
-  if (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) & LPTIM_CR_ENABLE)
+  if (enabled)
     {
       timeout = 10000;
-      while (!(stm32_getreg32(dev, STM32_LPTIM_ISR_OFFSET) & LPTIM_ISR_ARROK)
-             && timeout > 0)
+      while (!(stm32_getreg32(dev, STM32_LPTIM_ISR_OFFSET) & okflag) &&
+             timeout > 0)
         {
           timeout--;
         }
     }
+}
 #endif
+
+/****************************************************************************
+ * Name: stm32_lptim_setmode
+ *
+ * Description:
+ *   Disable the timer, or enable it and start counting once or
+ *   continuously.
+ *
+ ****************************************************************************/
+
+static int stm32_lptim_setmode(struct stm32_lptim_dev_s *dev,
+                               stm32_lptim_mode_t mode)
+{
+  DEBUGASSERT(dev != NULL);
+
+  mode &= STM32_LPTIM_MODE_MASK;
+  if (mode == STM32_LPTIM_MODE_DISABLED)
+    {
+      stm32_lptim_enable(dev, false);
+    }
+  else if (mode == STM32_LPTIM_MODE_SINGLE ||
+           mode == STM32_LPTIM_MODE_CONTINUOUS)
+    {
+      stm32_lptim_enable(dev, true);
+      stm32_lptim_start(dev, mode);
+    }
+  else
+    {
+      return -EINVAL;
+    }
+
+  return OK;
 }
 
-static void stm32_lptim_setcompare(struct stm32_lptim_dev_s *dev,
-                                   uint32_t cmp)
+/****************************************************************************
+ * Name: stm32_lptim_setclock
+ *
+ * Description:
+ *   Set the counter clock to the kernel clock divided by the largest power
+ *   of two (up to 128) whose result is not above freq, and return the
+ *   resulting frequency.  freq == 0 stops the LPTIM clock.  Requires
+ *   STM32_LPTIMn_CLKIN in board.h.
+ *
+ ****************************************************************************/
+
+static int stm32_lptim_setclock(struct stm32_lptim_dev_s *dev,
+                                uint32_t freq)
 {
-#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2
-  uint32_t timeout;
+  struct stm32_lptim_priv_s *priv = (struct stm32_lptim_priv_s *)dev;
+  uint32_t presc;
 
-  /* For STM32H5: Clear CMPOK flag BEFORE writing CMP when timer is enabled */
+  DEBUGASSERT(dev != NULL);
 
-  if (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) & LPTIM_CR_ENABLE)
+  if (freq == 0)
     {
-      stm32_putreg32(dev, STM32_LPTIM_ICR_OFFSET, LPTIM_ISR_CMPOK);
+      modifyreg32(priv->enreg, priv->enbit, 0);
+      return 0;
     }
-#endif
 
-  stm32_putreg32(dev, STM32_LPTIM_CMP_OFFSET, cmp);
+  if (priv->freq == 0)
+    {
+      return -EINVAL;
+    }
 
-#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2
-  /* Wait for CMPOK flag when timer is enabled */
+  presc = 0;
+  while (presc < LPTIM_PRESC_MAX && (priv->freq >> presc) > freq)
+    {
+      presc++;
+    }
+
+  modifyreg32(priv->enreg, 0, priv->enbit);
+  stm32_modifyreg32(dev, STM32_LPTIM_CFGR_OFFSET, LPTIM_CFGR_PRESC_MASK,
+                    presc << LPTIM_CFGR_PRESC_SHIFT);
 
-  if (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) & LPTIM_CR_ENABLE)
+  return priv->freq >> presc;
+}
+
+/****************************************************************************
+ * Name: stm32_lptim_setchannel
+ *
+ * Description:
+ *   Configure (enable != 0) or release the pin of an output channel.
+ *
+ ****************************************************************************/
+
+static int stm32_lptim_setchannel(struct stm32_lptim_dev_s *dev,
+                                  stm32_lptim_channel_t channel,
+                                  int enable)
+{
+  struct stm32_lptim_priv_s *priv = (struct stm32_lptim_priv_s *)dev;
+  uint32_t pin;
+
+  DEBUGASSERT(dev != NULL);
+
+  channel &= STM32_LPTIM_CH_MASK;
+  if (channel < 1 || channel > LPTIM_NCHANNELS)
     {
-      timeout = 10000;
-      while (!(stm32_getreg32(dev, STM32_LPTIM_ISR_OFFSET) & LPTIM_ISR_CMPOK)
-             && timeout > 0)
-        {
-          timeout--;
-        }
+      return -EINVAL;
     }
-#endif
+
+  pin = priv->pins[channel - 1];
+  if (pin == 0)
+    {
+      return -EINVAL;
+    }
+
+  if (enable)
+    {
+      stm32_configgpio(pin);
+    }
+  else
+    {
+      stm32_unconfiggpio(pin);
+    }
+
+  return OK;
 }
 
-static uint32_t stm32_lptim_getcounter(struct stm32_lptim_dev_s *dev)
+/****************************************************************************
+ * Name: stm32_lptim_setclocksource
+ *
+ * Description:
+ *   Count the external clock on input 1 (STM32_LPTIM_CLK_EXT) or the
+ *   kernel clock selected in RCC (any other value).
+ *
+ ****************************************************************************/
+
+static int stm32_lptim_setclocksource(struct stm32_lptim_dev_s *dev,
+                                      stm32_lptim_clksrc_t clksrc)
 {
-  /* For a reliable LPTIM_CNT register read access, two consecutive
-   *  read accesses must be performed and compared
-   */
+  DEBUGASSERT(dev != NULL);
+
+  stm32_modifyreg32(dev, STM32_LPTIM_CFGR_OFFSET, LPTIM_CFGR_CKSEL,
+                    clksrc == STM32_LPTIM_CLK_EXT ? LPTIM_CFGR_CKSEL : 0);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_lptim_setpolarity
+ ****************************************************************************/
+
+static int stm32_lptim_setpolarity(struct stm32_lptim_dev_s *dev,
+                                   stm32_lptim_clkpol_t polarity)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (polarity > STM32_LPTIM_CLKPOL_BOTH)
+    {
+      return -EINVAL;
+    }
+
+  /* The enumeration values are the CKPOL field values */
 
+  stm32_modifyreg32(dev, STM32_LPTIM_CFGR_OFFSET, LPTIM_CFGR_CKPOL_MASK,
+                    (uint32_t)polarity << LPTIM_CFGR_CKPOL_SHIFT);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_lptim_getcounter
+ ****************************************************************************/
+
+static uint32_t stm32_lptim_getcounter(struct stm32_lptim_dev_s *dev)
+{
   uint32_t cnt1;
   uint32_t cnt2;
 
+  DEBUGASSERT(dev != NULL);
+
+  /* For a reliable LPTIM_CNT register read access, two consecutive
+   * read accesses must be performed and compared
+   */
+
   cnt2 = stm32_getreg32(dev, STM32_LPTIM_CNT_OFFSET);
 
   do
@@ -252,174 +685,218 @@ static uint32_t stm32_lptim_getcounter(struct 
stm32_lptim_dev_s *dev)
   return cnt1;
 }
 
+/****************************************************************************
+ * Name: stm32_lptim_setcountmode
+ *
+ * Description:
+ *   Increment the counter on each counter clock pulse or on each valid
+ *   pulse on input 1.
+ *
+ ****************************************************************************/
+
+static int stm32_lptim_setcountmode(struct stm32_lptim_dev_s *dev,
+                                    stm32_lptim_cntmode_t cntmode)
+{
+  DEBUGASSERT(dev != NULL);
+
+  if (cntmode != STM32_LPTIM_COUNT_CLOCK &&
+      cntmode != STM32_LPTIM_COUNT_EXTTRIG)
+    {
+      return -EINVAL;
+    }
+
+  stm32_modifyreg32(dev, STM32_LPTIM_CFGR_OFFSET, LPTIM_CFGR_COUNTMODE,
+                    cntmode == STM32_LPTIM_COUNT_EXTTRIG ?
+                    LPTIM_CFGR_COUNTMODE : 0);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_lptim_setperiod / stm32_lptim_getperiod
+ ****************************************************************************/
+
+static void stm32_lptim_setperiod(struct stm32_lptim_dev_s *dev,
+                                  uint32_t period)
+{
+  DEBUGASSERT(dev != NULL);
+
+#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2
+  stm32_lptim_writesync(dev, STM32_LPTIM_ARR_OFFSET, period,
+                        LPTIM_ISR_ARROK);
+#else
+  stm32_putreg32(dev, STM32_LPTIM_ARR_OFFSET, period);
+#endif
+}
+
+static uint32_t stm32_lptim_getperiod(struct stm32_lptim_dev_s *dev)
+{
+  DEBUGASSERT(dev != NULL);
+
+  return stm32_getreg32(dev, STM32_LPTIM_ARR_OFFSET);
+}
+
+/****************************************************************************
+ * Name: stm32_lptim_setcfgr
+ ****************************************************************************/
+
+static void stm32_lptim_setcfgr(struct stm32_lptim_dev_s *dev,
+                                uint32_t regval)
+{
+  stm32_putreg32(dev, STM32_LPTIM_CFGR_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: stm32_lptim_setcompare
+ ****************************************************************************/
+
+static void stm32_lptim_setcompare(struct stm32_lptim_dev_s *dev,
+                                   uint32_t cmp)
+{
+#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2
+  stm32_lptim_writesync(dev, STM32_LPTIM_CMP_OFFSET, cmp, LPTIM_ISR_CMPOK);
+#else
+  stm32_putreg32(dev, STM32_LPTIM_CMP_OFFSET, cmp);
+#endif
+}
+
+/****************************************************************************
+ * Name: stm32_lptim_setinput
+ *
+ * Description:
+ *   Select the input 1 (input == 0) or input 2 (input != 0) multiplexer
+ *   setting in CFGR2.  The valid settings are instance specific.
+ *
+ ****************************************************************************/
+
 static int stm32_lptim_setinput(struct stm32_lptim_dev_s *dev,
                                 uint32_t input, uint32_t mux)
 {
-  switch (dev->base)
+  if (input == 0)
     {
-#ifdef CONFIG_STM32_LPTIM1
-      case STM32_LPTIM1_BASE:
-#endif
-#ifdef CONFIG_STM32_LPTIM2
-      case STM32_LPTIM2_BASE:
-#endif
-#if defined(CONFIG_STM32_LPTIM1) || defined(CONFIG_STM32_LPTIM2)
-        if (input == 0)
-          {
-            modifyreg32(dev->base + STM32_LPTIM_CFGR2_OFFSET,
-                        LPTIM_CFGR2_IN1SEL_MASK, mux);
-          }
-        else
-          {
-            modifyreg32(dev->base + STM32_LPTIM_CFGR2_OFFSET,
+      stm32_modifyreg32(dev, STM32_LPTIM_CFGR2_OFFSET,
+                        LPTIM_CFGR2_IN1SEL_MASK,
+                        mux << LPTIM_CFGR2_IN1SEL_SHIFT);
+    }
+  else
+    {
+      stm32_modifyreg32(dev, STM32_LPTIM_CFGR2_OFFSET,
                         LPTIM_CFGR2_IN2SEL_MASK,
                         mux << LPTIM_CFGR2_IN2SEL_SHIFT);
-          }
-        break;
-#endif
-#ifdef CONFIG_STM32_LPTIM3
-      case STM32_LPTIM3_BASE:
-        modifyreg32(dev->base + STM32_LPTIM_CFGR2_OFFSET,
-                    LPTIM_CFGR2_IN1SEL_MASK, mux);
-        break;
-#endif
-      default:
-        return -EINVAL;
     }
 
   return OK;
 }
 
+/****************************************************************************
+ * Name: stm32_lptim_enable
+ ****************************************************************************/
+
 static void stm32_lptim_enable(struct stm32_lptim_dev_s *dev, bool on)
 {
-  uint32_t val = stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET);
-
   if (on)
     {
-      val |= LPTIM_CR_ENABLE;
+      stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_ENABLE);
     }
   else
     {
-      val &= ~LPTIM_CR_ENABLE;
+      stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, LPTIM_CR_ENABLE, 0);
     }
-
-  stm32_putreg32(dev, STM32_LPTIM_CR_OFFSET, val);
 }
 
+/****************************************************************************
+ * Name: stm32_lptim_start
+ ****************************************************************************/
+
 static void stm32_lptim_start(struct stm32_lptim_dev_s *dev,
-                              stm32_lptim_start_mode_t mode)
+                              stm32_lptim_mode_t mode)
 {
-  uint32_t val = stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET);
-
-  switch (mode)
+  switch (mode & STM32_LPTIM_MODE_MASK)
     {
       case STM32_LPTIM_MODE_CONTINUOUS:
-        val |= LPTIM_CR_CNTSTRT;
+        stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_CNTSTRT);
         break;
+
       case STM32_LPTIM_MODE_SINGLE:
-        val |= LPTIM_CR_SNGSTRT;
+        stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_SNGSTRT);
         break;
-    }
 
-  stm32_putreg32(dev, STM32_LPTIM_CR_OFFSET, val);
+      default:
+        break;
+    }
 }
 
+/****************************************************************************
+ * Name: stm32_lptim_resetcounter
+ ****************************************************************************/
+
 static void stm32_lptim_resetcounter(struct stm32_lptim_dev_s *dev)
 {
-  uint32_t val = stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET);
-
-  val |= LPTIM_CR_COUNTRST;
-  stm32_putreg32(dev, STM32_LPTIM_CR_OFFSET, val);
+  stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_COUNTRST);
 }
 
+/****************************************************************************
+ * Name: stm32_lptim_enablerar
+ ****************************************************************************/
+
 static void stm32_lptim_enablerar(struct stm32_lptim_dev_s *dev, bool on)
 {
-  uint32_t val = stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET);
-
   if (on)
     {
-      val |= LPTIM_CR_RSTARE;
+      stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_RSTARE);
     }
   else
     {
-      val &= ~LPTIM_CR_RSTARE;
+      stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, LPTIM_CR_RSTARE, 0);
     }
-
-  stm32_putreg32(dev, STM32_LPTIM_CR_OFFSET, val);
 }
 
+/****************************************************************************
+ * Name: stm32_lptim_setisr
+ ****************************************************************************/
+
 static int stm32_lptim_setisr(struct stm32_lptim_dev_s *dev,
                               xcpt_t handler, void *arg, int source)
 {
-  int vectorno;
+  int irq;
 
   DEBUGASSERT(dev != NULL);
   DEBUGASSERT(source == 0);
 
-  switch (dev->base)
-    {
-#ifdef CONFIG_STM32_LPTIM1
-      case STM32_LPTIM1_BASE:
-        vectorno = STM32_IRQ_LPTIM1;
-        break;
-#endif
-#ifdef CONFIG_STM32_LPTIM2
-      case STM32_LPTIM2_BASE:
-        vectorno = STM32_IRQ_LPTIM2;
-        break;
-#endif
-#ifdef CONFIG_STM32_LPTIM3
-      case STM32_LPTIM3_BASE:
-        vectorno = STM32_IRQ_LPTIM3;
-        break;
-#endif
-#ifdef CONFIG_STM32_LPTIM4
-      case STM32_LPTIM4_BASE:
-        vectorno = STM32_IRQ_LPTIM4;
-        break;
-#endif
-#ifdef CONFIG_STM32_LPTIM5
-      case STM32_LPTIM5_BASE:
-        vectorno = STM32_IRQ_LPTIM5;
-        break;
-#endif
-
-      default:
-        return -EINVAL;
-    }
+  irq = ((struct stm32_lptim_priv_s *)dev)->irq;
 
   /* Disable interrupt when callback is removed */
 
   if (!handler)
     {
-      up_disable_irq(vectorno);
-      irq_detach(vectorno);
+      up_disable_irq(irq);
+      irq_detach(irq);
       return OK;
     }
 
   /* Otherwise set callback and enable interrupt */
 
-  irq_attach(vectorno, handler, arg);
-  up_enable_irq(vectorno);
+  irq_attach(irq, handler, arg);
+  up_enable_irq(irq);
 
 #ifdef CONFIG_ARCH_IRQPRIO
   /* Set the interrupt priority */
 
-  up_prioritize_irq(vectorno, NVIC_SYSH_PRIORITY_DEFAULT);
+  up_prioritize_irq(irq, NVIC_SYSH_PRIORITY_DEFAULT);
 #endif
 
   return OK;
 }
 
+/****************************************************************************
+ * Name: stm32_lptim_enableint / stm32_lptim_disableint / stm32_lptim_ackint
+ ****************************************************************************/
+
 static void stm32_lptim_enableint(struct stm32_lptim_dev_s *dev,
                                   int source)
 {
   DEBUGASSERT(dev != NULL);
 
-  uint32_t val = stm32_getreg32(dev, STM32_LPTIM_IER_OFFSET);
-
-  val |= source;
-  stm32_putreg32(dev, STM32_LPTIM_IER_OFFSET, val);
+  stm32_modifyreg32(dev, STM32_LPTIM_IER_OFFSET, 0, source);
 }
 
 static void stm32_lptim_disableint(struct stm32_lptim_dev_s *dev,
@@ -427,10 +904,7 @@ static void stm32_lptim_disableint(struct 
stm32_lptim_dev_s *dev,
 {
   DEBUGASSERT(dev != NULL);
 
-  uint32_t val = stm32_getreg32(dev, STM32_LPTIM_IER_OFFSET);
-
-  val &= ~source;
-  stm32_putreg32(dev, STM32_LPTIM_IER_OFFSET, val);
+  stm32_modifyreg32(dev, STM32_LPTIM_IER_OFFSET, source, 0);
 }
 
 static void stm32_lptim_ackint(struct stm32_lptim_dev_s *dev, int source)
@@ -442,100 +916,46 @@ static void stm32_lptim_ackint(struct stm32_lptim_dev_s 
*dev, int source)
  * Public Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: stm32_lptim_init
+ ****************************************************************************/
+
 struct stm32_lptim_dev_s *stm32_lptim_init(int lptimer)
 {
-  struct stm32_lptim_dev_s *dev = NULL;
+  struct stm32_lptim_priv_s *priv;
 
-  /* Get structure and enable power */
+  if (lptimer < 1 || lptimer > (int)nitems(g_lptim))
+    {
+      return NULL;
+    }
 
-  switch (lptimer)
+  priv = g_lptim[lptimer - 1];
+  if (priv == NULL || priv->inuse)
     {
-#if defined(CONFIG_STM32_LPTIM1) && defined(STM32_RCC_LPTIM1_EN_REG)
-      case 1:
-        dev = &stm32_lptim1_priv;
-        modifyreg32(STM32_RCC_LPTIM1_EN_REG, 0, STM32_RCC_LPTIM1_EN);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM2) && defined(STM32_RCC_LPTIM2_EN_REG)
-      case 2:
-        dev = &stm32_lptim2_priv;
-        modifyreg32(STM32_RCC_LPTIM2_EN_REG, 0, STM32_RCC_LPTIM2_EN);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM3) && defined(STM32_RCC_LPTIM3_EN_REG)
-      case 3:
-        dev = &stm32_lptim3_priv;
-        modifyreg32(STM32_RCC_LPTIM3_EN_REG, 0, STM32_RCC_LPTIM3_EN);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM4) && defined(STM32_RCC_LPTIM4_EN_REG)
-      case 4:
-        dev = &stm32_lptim4_priv;
-        modifyreg32(STM32_RCC_LPTIM4_EN_REG, 0, STM32_RCC_LPTIM4_EN);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM5) && defined(STM32_RCC_LPTIM5_EN_REG)
-      case 5:
-        dev = &stm32_lptim5_priv;
-        modifyreg32(STM32_RCC_LPTIM5_EN_REG, 0, STM32_RCC_LPTIM5_EN);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM6) && defined(STM32_RCC_LPTIM6_EN_REG)
-      case 6:
-        dev = &stm32_lptim6_priv;
-        modifyreg32(STM32_RCC_LPTIM6_EN_REG, 0, STM32_RCC_LPTIM6_EN);
-        break;
-#endif
-      default:
-        return NULL;
+      return NULL;
     }
 
-  return dev;
+  modifyreg32(priv->enreg, 0, priv->enbit);
+  modifyreg32(priv->rstreg, 0, priv->rstbit);
+  modifyreg32(priv->rstreg, priv->rstbit, 0);
+
+  priv->inuse = true;
+  return (struct stm32_lptim_dev_s *)priv;
 }
 
-int stm32_lptim_deinit(struct stm32_lptim_dev_s * dev)
-{
-  DEBUGASSERT(dev != NULL);
+/****************************************************************************
+ * Name: stm32_lptim_deinit
+ ****************************************************************************/
 
-  /* Disable power */
+int stm32_lptim_deinit(struct stm32_lptim_dev_s *dev)
+{
+  struct stm32_lptim_priv_s *priv = (struct stm32_lptim_priv_s *)dev;
 
-  switch (dev->base)
-    {
-#if defined(CONFIG_STM32_LPTIM1) && defined(STM32_RCC_LPTIM1_EN_REG)
-      case STM32_LPTIM1_BASE:
-        modifyreg32(STM32_RCC_LPTIM1_EN_REG, STM32_RCC_LPTIM1_EN, 0);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM2) && defined(STM32_RCC_LPTIM2_EN_REG)
-      case STM32_LPTIM2_BASE:
-        modifyreg32(STM32_RCC_LPTIM2_EN_REG, STM32_RCC_LPTIM2_EN, 0);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM3) && defined(STM32_RCC_LPTIM3_EN_REG)
-      case STM32_LPTIM3_BASE:
-        modifyreg32(STM32_RCC_LPTIM3_EN_REG, STM32_RCC_LPTIM3_EN, 0);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM4) && defined(STM32_RCC_LPTIM4_EN_REG)
-      case STM32_LPTIM4_BASE:
-        modifyreg32(STM32_RCC_LPTIM4_EN_REG, STM32_RCC_LPTIM4_EN, 0);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM5) && defined(STM32_RCC_LPTIM5_EN_REG)
-      case STM32_LPTIM5_BASE:
-        modifyreg32(STM32_RCC_LPTIM5_EN_REG, STM32_RCC_LPTIM5_EN, 0);
-        break;
-#endif
-#if defined(CONFIG_STM32_LPTIM6) && defined(STM32_RCC_LPTIM6_EN_REG)
-      case STM32_LPTIM6_BASE:
-        modifyreg32(STM32_RCC_LPTIM6_EN_REG, STM32_RCC_LPTIM6_EN, 0);
-        break;
-#endif
-      default:
-        return -EINVAL;
-    }
+  DEBUGASSERT(dev != NULL);
 
+  modifyreg32(priv->enreg, priv->enbit, 0);
+  priv->inuse = false;
   return OK;
 }
 
-#endif /* defined(CONFIG_STM32_LPTIM1 || ... || CONFIG_STM32_LPTIM5) */
+#endif /* CONFIG_STM32_LPTIM1 || ... || CONFIG_STM32_LPTIM6 */
diff --git a/arch/arm/src/common/stm32/stm32_lptim.h 
b/arch/arm/src/common/stm32/stm32_lptim.h
index 3ed2a3b736a..1afe37be7f6 100644
--- a/arch/arm/src/common/stm32/stm32_lptim.h
+++ b/arch/arm/src/common/stm32/stm32_lptim.h
@@ -28,6 +28,10 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <nuttx/irq.h>
+
+#include <stdbool.h>
+#include <stdint.h>
 
 #include "chip.h"
 #include "hardware/stm32_lptim.h"
@@ -36,6 +40,27 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+#define STM32_LPTIM_SETMODE(d,mode)     ((d)->ops->setmode(d,mode))
+#define STM32_LPTIM_SETCLOCK(d,freq)    ((d)->ops->setclock(d,freq))
+#define STM32_LPTIM_SETCHANNEL(d,ch,en) ((d)->ops->setchannel(d,ch,en))
+#define STM32_LPTIM_SETCLOCKSOURCE(d,s) ((d)->ops->setclocksource(d,s))
+#define STM32_LPTIM_SETPOLARITY(d,p)    ((d)->ops->setpolarity(d,p))
+#define STM32_LPTIM_GETCOUNTER(d)       ((d)->ops->getcounter(d))
+#define STM32_LPTIM_SETCOUNTMODE(d,m)   ((d)->ops->setcountmode(d,m))
+#define STM32_LPTIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period))
+#define STM32_LPTIM_GETPERIOD(d)        ((d)->ops->getperiod(d))
+#define STM32_LPTIM_SETCFGR(d,regval)   ((d)->ops->setcfgr(d,regval))
+#define STM32_LPTIM_SETCOMPARE(d,cmp)   ((d)->ops->setcompare(d,cmp))
+#define STM32_LPTIM_SETINPUT(d,in,mux)  ((d)->ops->setinput(d,in,mux))
+#define STM32_LPTIM_ENABLE(d,on)        ((d)->ops->enable(d,on))
+#define STM32_LPTIM_START(d,mode)       ((d)->ops->start(d,mode))
+#define STM32_LPTIM_RESETCOUNTER(d)     ((d)->ops->resetcounter(d))
+#define STM32_LPTIM_ENABLERAR(d,on)     ((d)->ops->enablerar(d,on))
+#define STM32_LPTIM_SETISR(d,hnd,arg,s) ((d)->ops->setisr(d,hnd,arg,s))
+#define STM32_LPTIM_ENABLEINT(d,s)      ((d)->ops->enableint(d,s))
+#define STM32_LPTIM_DISABLEINT(d,s)     ((d)->ops->disableint(d,s))
+#define STM32_LPTIM_ACKINT(d,s)         ((d)->ops->ackint(d,s))
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -49,31 +74,76 @@ extern "C"
 
 typedef enum
 {
-  STM32_LPTIM_MODE_CONTINUOUS       = 0x00,
-  STM32_LPTIM_MODE_SINGLE           = 0x01
-} stm32_lptim_start_mode_t;
+  STM32_LPTIM_MODE_UNUSED     = -1,
+  STM32_LPTIM_MODE_DISABLED   = 0,
+  STM32_LPTIM_MODE_SINGLE     = 1,
+  STM32_LPTIM_MODE_CONTINUOUS = 2,
+  STM32_LPTIM_MODE_MASK       = 15
+} stm32_lptim_mode_t;
+
+/* Counter clock: STM32_LPTIM_CLK_EXT is the LPTIM input 1, all other
+ * values select the kernel clock chosen in RCC.
+ */
+
+typedef enum
+{
+  STM32_LPTIM_CLK_PCLK = 0,
+  STM32_LPTIM_CLK_LSI  = 1,
+  STM32_LPTIM_CLK_HSI  = 2,
+  STM32_LPTIM_CLK_LSE  = 3,
+  STM32_LPTIM_CLK_EXT  = 4
+} stm32_lptim_clksrc_t;
 
-/* LPTIM Device Structure */
+typedef enum
+{
+  STM32_LPTIM_COUNT_CLOCK   = 0,
+  STM32_LPTIM_COUNT_EXTTRIG = 1
+} stm32_lptim_cntmode_t;
+
+typedef enum
+{
+  STM32_LPTIM_CLKPOL_RISING  = 0,
+  STM32_LPTIM_CLKPOL_FALLING = 1,
+  STM32_LPTIM_CLKPOL_BOTH    = 2
+} stm32_lptim_clkpol_t;
+
+typedef enum
+{
+  STM32_LPTIM_CH_DISABLED  = 0,
+  STM32_LPTIM_CH_CHINVALID = 0,
+  STM32_LPTIM_CH_CH1       = 1,
+  STM32_LPTIM_CH_CH2       = 2,
+  STM32_LPTIM_CH_CH3       = 3,
+  STM32_LPTIM_CH_MASK      = 15
+} stm32_lptim_channel_t;
 
 struct stm32_lptim_dev_s
 {
-  const  struct stm32_lptim_ops_s *ops;
-  uint32_t                 base;
+  const struct stm32_lptim_ops_s *ops;
 };
 
-/* LPTIM Operations */
-
 struct stm32_lptim_ops_s
 {
-  void (*setcfgr)(struct stm32_lptim_dev_s *dev, uint32_t regval);
+  int  (*setmode)(struct stm32_lptim_dev_s *dev,
+                  stm32_lptim_mode_t mode);
+  int  (*setclock)(struct stm32_lptim_dev_s *dev, uint32_t freq);
+  int  (*setchannel)(struct stm32_lptim_dev_s *dev,
+                     stm32_lptim_channel_t channel, int enable);
+  int  (*setclocksource)(struct stm32_lptim_dev_s *dev,
+                         stm32_lptim_clksrc_t clksrc);
+  int  (*setpolarity)(struct stm32_lptim_dev_s *dev,
+                      stm32_lptim_clkpol_t polarity);
+  uint32_t (*getcounter)(struct stm32_lptim_dev_s *dev);
+  int  (*setcountmode)(struct stm32_lptim_dev_s *dev,
+                       stm32_lptim_cntmode_t cntmode);
   void (*setperiod)(struct stm32_lptim_dev_s *dev, uint32_t period);
+  uint32_t (*getperiod)(struct stm32_lptim_dev_s *dev);
+  void (*setcfgr)(struct stm32_lptim_dev_s *dev, uint32_t regval);
   void (*setcompare)(struct stm32_lptim_dev_s *dev, uint32_t cmp);
-  uint32_t (*getcounter)(struct stm32_lptim_dev_s *dev);
   int  (*setinput)(struct stm32_lptim_dev_s *dev, uint32_t input,
                    uint32_t mux);
   void (*enable)(struct stm32_lptim_dev_s *dev, bool on);
-  void (*start)(struct stm32_lptim_dev_s *dev,
-                stm32_lptim_start_mode_t mode);
+  void (*start)(struct stm32_lptim_dev_s *dev, stm32_lptim_mode_t mode);
   void (*resetcounter)(struct stm32_lptim_dev_s *dev);
   void (*enablerar)(struct stm32_lptim_dev_s *dev, bool on);
 
@@ -90,7 +160,7 @@ struct stm32_lptim_ops_s
  * Public Function Prototypes
  ****************************************************************************/
 
-/* Power-up low power timer and get its structure */
+/* Power-up and reset low power timer and get its structure */
 
 struct stm32_lptim_dev_s *stm32_lptim_init(int lptimer);
 

Reply via email to