You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/09 04:37:57 UTC

[incubator-nuttx] 02/02: arch/arm/src/stm32f7: port PWM driver from arch/stm32

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

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

commit a05db5299ee5df57cd80c544ded7db68ae78896a
Author: raiden00pl <ra...@railab.me>
AuthorDate: Sat Aug 6 15:42:14 2022 +0200

    arch/arm/src/stm32f7: port PWM driver from arch/stm32
    
    This change adds support for the following features:
      1. PWM complementary outputs
      2. interface for low-level PWM operations
      3. support for all PWM channel modes
      4. support for internal PWM channels (TIM1/TIM8)
      5. support for PWM channel polarity and IDLE state
      6. support for TRGO and BREAK
---
 arch/arm/src/stm32f7/Kconfig     | 1899 ++++++++++++-----
 arch/arm/src/stm32f7/stm32_pwm.c | 4144 ++++++++++++++++++++++++++------------
 arch/arm/src/stm32f7/stm32_pwm.h | 1068 +++++-----
 3 files changed, 4775 insertions(+), 2336 deletions(-)

diff --git a/arch/arm/src/stm32f7/Kconfig b/arch/arm/src/stm32f7/Kconfig
index f06bf97fbc..388ef1d975 100644
--- a/arch/arm/src/stm32f7/Kconfig
+++ b/arch/arm/src/stm32f7/Kconfig
@@ -2696,6 +2696,12 @@ config STM32F7_TICKLESS_CHANNEL
 
 endif # SCHED_TICKLESS
 
+config STM32F7_PWM_LL_OPS
+	bool "PWM low-level operations"
+	default n
+	---help---
+		Enable low-level PWM ops.
+
 config STM32F7_TIM1_PWM
 	bool "TIM1 PWM"
 	default n
@@ -2718,6 +2724,27 @@ config STM32F7_TIM1_MODE
 	---help---
 		Specifies the timer mode.
 
+config STM32F7_TIM1_LOCK
+	int "TIM1 Lock Level Configuration"
+	default 0
+	range 0 3
+	---help---
+		Timer 1 lock level configuration
+
+config STM32F7_TIM1_TDTS
+	int "TIM1 t_DTS Division"
+	default 0
+	range 0 2
+	---help---
+		Timer 1 dead-time and sampling clock (t_DTS) division
+
+config STM32F7_TIM1_DEADTIME
+	int "TIM1 Initial Dead-time"
+	default 0
+	range 0 255
+	---help---
+		Timer 1 initial dead-time
+
 if STM32F7_PWM_MULTICHAN
 
 config STM32F7_TIM1_CHANNEL1
@@ -2730,10 +2757,10 @@ if STM32F7_TIM1_CHANNEL1
 
 config STM32F7_TIM1_CH1MODE
 	int "TIM1 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM1_CH1OUT
 	bool "TIM1 Channel 1 Output"
@@ -2741,6 +2768,12 @@ config STM32F7_TIM1_CH1OUT
 	---help---
 		Enables channel 1 output.
 
+config STM32F7_TIM1_CH1NOUT
+	bool "TIM1 Channel 1 Complementary Output"
+	default n
+	---help---
+		Enables channel 1 Complementary Output.
+
 endif # STM32F7_TIM1_CHANNEL1
 
 config STM32F7_TIM1_CHANNEL2
@@ -2753,10 +2786,10 @@ if STM32F7_TIM1_CHANNEL2
 
 config STM32F7_TIM1_CH2MODE
 	int "TIM1 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM1_CH2OUT
 	bool "TIM1 Channel 2 Output"
@@ -2764,6 +2797,12 @@ config STM32F7_TIM1_CH2OUT
 	---help---
 		Enables channel 2 output.
 
+config STM32F7_TIM1_CH2NOUT
+	bool "TIM1 Channel 2 Complementary Output"
+	default n
+	---help---
+		Enables channel 2 Complementary Output.
+
 endif # STM32F7_TIM1_CHANNEL2
 
 config STM32F7_TIM1_CHANNEL3
@@ -2776,10 +2815,10 @@ if STM32F7_TIM1_CHANNEL3
 
 config STM32F7_TIM1_CH3MODE
 	int "TIM1 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM1_CH3OUT
 	bool "TIM1 Channel 3 Output"
@@ -2787,6 +2826,12 @@ config STM32F7_TIM1_CH3OUT
 	---help---
 		Enables channel 3 output.
 
+config STM32F7_TIM1_CH3NOUT
+	bool "TIM1 Channel 3 Complementary Output"
+	default n
+	---help---
+		Enables channel 3 Complementary Output.
+
 endif # STM32F7_TIM1_CHANNEL3
 
 config STM32F7_TIM1_CHANNEL4
@@ -2799,10 +2844,10 @@ if STM32F7_TIM1_CHANNEL4
 
 config STM32F7_TIM1_CH4MODE
 	int "TIM1 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM1_CH4OUT
 	bool "TIM1 Channel 4 Output"
@@ -2812,6 +2857,52 @@ config STM32F7_TIM1_CH4OUT
 
 endif # STM32F7_TIM1_CHANNEL4
 
+config STM32F7_TIM1_CHANNEL5
+	bool "TIM1 Channel 5 (internal)"
+	default n
+	---help---
+		Enables channel 5 (not available externally)
+
+if STM32F7_TIM1_CHANNEL5
+
+config STM32F7_TIM1_CH5MODE
+	int "TIM1 Channel 5 Mode"
+	default 6
+	range 0 11
+	---help---
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
+
+config STM32F7_TIM1_CH5OUT
+	bool "TIM1 Channel 5 Output"
+	default n
+	---help---
+		Enables channel 5 output.
+
+endif # STM32F7_TIM1_CHANNEL5
+
+config STM32F7_TIM1_CHANNEL6
+	bool "TIM1 Channel 6 (internal)"
+	default n
+	---help---
+		Enables channel 6 (not available externally)
+
+if STM32F7_TIM1_CHANNEL6
+
+config STM32F7_TIM1_CH6MODE
+	int "TIM1 Channel 6 Mode"
+	default 6
+	range 0 11
+	---help---
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
+
+config STM32F7_TIM1_CH6OUT
+	bool "TIM1 Channel 6 Output"
+	default n
+	---help---
+		Enables channel 6 output.
+
+endif # STM32F7_TIM1_CHANNEL6
+
 endif # STM32F7_PWM_MULTICHAN
 
 if !STM32F7_PWM_MULTICHAN
@@ -2824,12 +2915,70 @@ config STM32F7_TIM1_CHANNEL
 		If TIM1 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32F7_TIM1_CHANNEL = 1
+
+config STM32F7_TIM1_CH1OUT
+	bool "TIM1 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+config STM32F7_TIM1_CH1NOUT
+	bool "TIM1 Channel 1 Complementary Output"
+	default n
+	---help---
+		Enables channel 1 Complementary Output.
+
+endif # STM32F7_TIM1_CHANNEL = 1
+
+if STM32F7_TIM1_CHANNEL = 2
+
+config STM32F7_TIM1_CH2OUT
+	bool "TIM1 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+config STM32F7_TIM1_CH2NOUT
+	bool "TIM1 Channel 2 Complementary Output"
+	default n
+	---help---
+		Enables channel 2 Complementary Output.
+
+endif # STM32F7_TIM1_CHANNEL = 2
+
+if STM32F7_TIM1_CHANNEL = 3
+
+config STM32F7_TIM1_CH3OUT
+	bool "TIM1 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+config STM32F7_TIM1_CH3NOUT
+	bool "TIM1 Channel 3 Complementary Output"
+	default n
+	---help---
+		Enables channel 3 Complementary Output.
+
+endif # STM32F7_TIM1_CHANNEL = 3
+
+if STM32F7_TIM1_CHANNEL = 4
+
+config STM32F7_TIM1_CH4OUT
+	bool "TIM1 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32F7_TIM1_CHANNEL = 4
+
 config STM32F7_TIM1_CHMODE
 	int "TIM1 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -2869,10 +3018,10 @@ if STM32F7_TIM2_CHANNEL1
 
 config STM32F7_TIM2_CH1MODE
 	int "TIM2 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM2_CH1OUT
 	bool "TIM2 Channel 1 Output"
@@ -2892,10 +3041,10 @@ if STM32F7_TIM2_CHANNEL2
 
 config STM32F7_TIM2_CH2MODE
 	int "TIM2 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM2_CH2OUT
 	bool "TIM2 Channel 2 Output"
@@ -2915,10 +3064,10 @@ if STM32F7_TIM2_CHANNEL3
 
 config STM32F7_TIM2_CH3MODE
 	int "TIM2 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM2_CH3OUT
 	bool "TIM2 Channel 3 Output"
@@ -2938,10 +3087,10 @@ if STM32F7_TIM2_CHANNEL4
 
 config STM32F7_TIM2_CH4MODE
 	int "TIM2 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM2_CH4OUT
 	bool "TIM2 Channel 4 Output"
@@ -2963,12 +3112,52 @@ config STM32F7_TIM2_CHANNEL
 		If TIM2 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32F7_TIM2_CHANNEL = 1
+
+config STM32F7_TIM2_CH1OUT
+	bool "TIM2 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32F7_TIM2_CHANNEL = 1
+
+if STM32F7_TIM2_CHANNEL = 2
+
+config STM32F7_TIM2_CH2OUT
+	bool "TIM2 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+endif # STM32F7_TIM2_CHANNEL = 2
+
+if STM32F7_TIM2_CHANNEL = 3
+
+config STM32F7_TIM2_CH3OUT
+	bool "TIM2 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+endif # STM32F7_TIM2_CHANNEL = 3
+
+if STM32F7_TIM2_CHANNEL = 4
+
+config STM32F7_TIM2_CH4OUT
+	bool "TIM2 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32F7_TIM2_CHANNEL = 4
+
 config STM32F7_TIM2_CHMODE
 	int "TIM2 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -3008,10 +3197,10 @@ if STM32F7_TIM3_CHANNEL1
 
 config STM32F7_TIM3_CH1MODE
 	int "TIM3 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM3_CH1OUT
 	bool "TIM3 Channel 1 Output"
@@ -3031,10 +3220,10 @@ if STM32F7_TIM3_CHANNEL2
 
 config STM32F7_TIM3_CH2MODE
 	int "TIM3 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM3_CH2OUT
 	bool "TIM3 Channel 2 Output"
@@ -3054,10 +3243,10 @@ if STM32F7_TIM3_CHANNEL3
 
 config STM32F7_TIM3_CH3MODE
 	int "TIM3 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM3_CH3OUT
 	bool "TIM3 Channel 3 Output"
@@ -3077,10 +3266,10 @@ if STM32F7_TIM3_CHANNEL4
 
 config STM32F7_TIM3_CH4MODE
 	int "TIM3 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM3_CH4OUT
 	bool "TIM3 Channel 4 Output"
@@ -3102,12 +3291,52 @@ config STM32F7_TIM3_CHANNEL
 		If TIM3 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32F7_TIM3_CHANNEL = 1
+
+config STM32F7_TIM3_CH1OUT
+	bool "TIM3 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32F7_TIM3_CHANNEL = 1
+
+if STM32F7_TIM3_CHANNEL = 2
+
+config STM32F7_TIM3_CH2OUT
+	bool "TIM3 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+endif # STM32F7_TIM3_CHANNEL = 2
+
+if STM32F7_TIM3_CHANNEL = 3
+
+config STM32F7_TIM3_CH3OUT
+	bool "TIM3 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+endif # STM32F7_TIM3_CHANNEL = 3
+
+if STM32F7_TIM3_CHANNEL = 4
+
+config STM32F7_TIM3_CH4OUT
+	bool "TIM3 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32F7_TIM3_CHANNEL = 4
+
 config STM32F7_TIM3_CHMODE
 	int "TIM3 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -3147,10 +3376,10 @@ if STM32F7_TIM4_CHANNEL1
 
 config STM32F7_TIM4_CH1MODE
 	int "TIM4 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM4_CH1OUT
 	bool "TIM4 Channel 1 Output"
@@ -3170,10 +3399,10 @@ if STM32F7_TIM4_CHANNEL2
 
 config STM32F7_TIM4_CH2MODE
 	int "TIM4 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM4_CH2OUT
 	bool "TIM4 Channel 2 Output"
@@ -3193,10 +3422,10 @@ if STM32F7_TIM4_CHANNEL3
 
 config STM32F7_TIM4_CH3MODE
 	int "TIM4 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM4_CH3OUT
 	bool "TIM4 Channel 3 Output"
@@ -3216,10 +3445,10 @@ if STM32F7_TIM4_CHANNEL4
 
 config STM32F7_TIM4_CH4MODE
 	int "TIM4 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM4_CH4OUT
 	bool "TIM4 Channel 4 Output"
@@ -3241,12 +3470,52 @@ config STM32F7_TIM4_CHANNEL
 		If TIM4 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32F7_TIM4_CHANNEL = 1
+
+config STM32F7_TIM4_CH1OUT
+	bool "TIM4 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32F7_TIM4_CHANNEL = 1
+
+if STM32F7_TIM4_CHANNEL = 2
+
+config STM32F7_TIM4_CH2OUT
+	bool "TIM4 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+endif # STM32F7_TIM4_CHANNEL = 2
+
+if STM32F7_TIM4_CHANNEL = 3
+
+config STM32F7_TIM4_CH3OUT
+	bool "TIM4 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+endif # STM32F7_TIM4_CHANNEL = 3
+
+if STM32F7_TIM4_CHANNEL = 4
+
+config STM32F7_TIM4_CH4OUT
+	bool "TIM4 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32F7_TIM4_CHANNEL = 4
+
 config STM32F7_TIM4_CHMODE
 	int "TIM4 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -3286,10 +3555,10 @@ if STM32F7_TIM5_CHANNEL1
 
 config STM32F7_TIM5_CH1MODE
 	int "TIM5 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM5_CH1OUT
 	bool "TIM5 Channel 1 Output"
@@ -3309,10 +3578,10 @@ if STM32F7_TIM5_CHANNEL2
 
 config STM32F7_TIM5_CH2MODE
 	int "TIM5 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM5_CH2OUT
 	bool "TIM5 Channel 2 Output"
@@ -3332,10 +3601,10 @@ if STM32F7_TIM5_CHANNEL3
 
 config STM32F7_TIM5_CH3MODE
 	int "TIM5 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM5_CH3OUT
 	bool "TIM5 Channel 3 Output"
@@ -3355,10 +3624,10 @@ if STM32F7_TIM5_CHANNEL4
 
 config STM32F7_TIM5_CH4MODE
 	int "TIM5 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM5_CH4OUT
 	bool "TIM5 Channel 4 Output"
@@ -3380,39 +3649,100 @@ config STM32F7_TIM5_CHANNEL
 		If TIM5 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
-config STM32F7_TIM5_CHMODE
-	int "TIM5 Channel Mode"
-	default 0
-	range 0 5
+if STM32F7_TIM5_CHANNEL = 1
+
+config STM32F7_TIM5_CH1OUT
+	bool "TIM5 Channel 1 Output"
+	default n
 	---help---
-		Specifies the channel mode.
+		Enables channel 1 output.
 
-endif # !STM32F7_PWM_MULTICHAN
+endif # STM32F7_TIM5_CHANNEL = 1
 
-endif # STM32F7_TIM5_PWM
+if STM32F7_TIM5_CHANNEL = 2
 
-config STM32F7_TIM8_PWM
-	bool "TIM8 PWM"
+config STM32F7_TIM5_CH2OUT
+	bool "TIM5 Channel 2 Output"
 	default n
-	depends on STM32F7_TIM8
-	select STM32F7_PWM
 	---help---
-		Reserve timer 8 for use by PWM
+		Enables channel 2 output.
 
-		Timer devices may be used for different purposes.  One special purpose is
-		to generate modulated outputs for such things as motor control.  If STM32F7_TIM8
-		is defined then THIS following may also be defined to indicate that
-		the timer is intended to be used for pulsed output modulation.
+endif # STM32F7_TIM5_CHANNEL = 2
 
-if STM32F7_TIM8_PWM
+if STM32F7_TIM5_CHANNEL = 3
 
-config STM32F7_TIM8_MODE
-	int "TIM8 Mode"
-	default 0
-	range 0 4
+config STM32F7_TIM5_CH3OUT
+	bool "TIM5 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+endif # STM32F7_TIM5_CHANNEL = 3
+
+if STM32F7_TIM5_CHANNEL = 4
+
+config STM32F7_TIM5_CH4OUT
+	bool "TIM5 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32F7_TIM5_CHANNEL = 4
+
+config STM32F7_TIM5_CHMODE
+	int "TIM5 Channel Mode"
+	default 6
+	range 0 11
+	---help---
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
+
+endif # !STM32F7_PWM_MULTICHAN
+
+endif # STM32F7_TIM5_PWM
+
+config STM32F7_TIM8_PWM
+	bool "TIM8 PWM"
+	default n
+	depends on STM32F7_TIM8
+	select STM32F7_PWM
+	---help---
+		Reserve timer 8 for use by PWM
+
+		Timer devices may be used for different purposes.  One special purpose is
+		to generate modulated outputs for such things as motor control.  If STM32F7_TIM8
+		is defined then THIS following may also be defined to indicate that
+		the timer is intended to be used for pulsed output modulation.
+
+if STM32F7_TIM8_PWM
+
+config STM32F7_TIM8_MODE
+	int "TIM8 Mode"
+	default 0
+	range 0 4
 	---help---
 		Specifies the timer mode.
 
+config STM32F7_TIM8_LOCK
+	int "TIM8 Lock Level Configuration"
+	default 0
+	range 0 3
+	---help---
+		Timer 8 lock level configuration
+
+config STM32F7_TIM8_DEADTIME
+	int "TIM8 Initial Dead-time"
+	default 0
+	range 0 255
+	---help---
+		Timer 8 initial dead-time
+
+config STM32F7_TIM8_TDTS
+	int "TIM8 t_DTS Division"
+	default 0
+	range 0 2
+	---help---
+		Timer 8 dead-time and sampling clock (t_DTS) division
+
 if STM32F7_PWM_MULTICHAN
 
 config STM32F7_TIM8_CHANNEL1
@@ -3425,10 +3755,10 @@ if STM32F7_TIM8_CHANNEL1
 
 config STM32F7_TIM8_CH1MODE
 	int "TIM8 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM8_CH1OUT
 	bool "TIM8 Channel 1 Output"
@@ -3436,6 +3766,12 @@ config STM32F7_TIM8_CH1OUT
 	---help---
 		Enables channel 1 output.
 
+config STM32F7_TIM8_CH1NOUT
+	bool "TIM8 Channel 1 Complementary Output"
+	default n
+	---help---
+		Enables channel 1 Complementary Output.
+
 endif # STM32F7_TIM8_CHANNEL1
 
 config STM32F7_TIM8_CHANNEL2
@@ -3448,10 +3784,10 @@ if STM32F7_TIM8_CHANNEL2
 
 config STM32F7_TIM8_CH2MODE
 	int "TIM8 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM8_CH2OUT
 	bool "TIM8 Channel 2 Output"
@@ -3459,6 +3795,12 @@ config STM32F7_TIM8_CH2OUT
 	---help---
 		Enables channel 2 output.
 
+config STM32F7_TIM8_CH2NOUT
+	bool "TIM8 Channel 2 Complementary Output"
+	default n
+	---help---
+		Enables channel 2 Complementary Output.
+
 endif # STM32F7_TIM8_CHANNEL2
 
 config STM32F7_TIM8_CHANNEL3
@@ -3471,10 +3813,10 @@ if STM32F7_TIM8_CHANNEL3
 
 config STM32F7_TIM8_CH3MODE
 	int "TIM8 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM8_CH3OUT
 	bool "TIM8 Channel 3 Output"
@@ -3482,6 +3824,12 @@ config STM32F7_TIM8_CH3OUT
 	---help---
 		Enables channel 3 output.
 
+config STM32F7_TIM8_CH3NOUT
+	bool "TIM8 Channel 3 Complementary Output"
+	default n
+	---help---
+		Enables channel 3 Complementary Output.
+
 endif # STM32F7_TIM8_CHANNEL3
 
 config STM32F7_TIM8_CHANNEL4
@@ -3494,10 +3842,10 @@ if STM32F7_TIM8_CHANNEL4
 
 config STM32F7_TIM8_CH4MODE
 	int "TIM8 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM8_CH4OUT
 	bool "TIM8 Channel 4 Output"
@@ -3507,6 +3855,52 @@ config STM32F7_TIM8_CH4OUT
 
 endif # STM32F7_TIM8_CHANNEL4
 
+config STM32F7_TIM8_CHANNEL5
+	bool "TIM8 Channel 5 (internal)"
+	default n
+	---help---
+		Enables channel 5 (not available externally)
+
+if STM32F7_TIM8_CHANNEL5
+
+config STM32F7_TIM8_CH5MODE
+	int "TIM8 Channel 5 Mode"
+	default 6
+	range 0 11
+	---help---
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
+
+config STM32F7_TIM8_CH5OUT
+	bool "TIM8 Channel 5 Output"
+	default n
+	---help---
+		Enables channel 5 output.
+
+endif # STM32F7_TIM8_CHANNEL5
+
+config STM32F7_TIM8_CHANNEL6
+	bool "TIM8 Channel 6 (internal)"
+	default n
+	---help---
+		Enables channel 6 (not available externally)
+
+if STM32F7_TIM8_CHANNEL6
+
+config STM32F7_TIM8_CH6MODE
+	int "TIM8 Channel 6 Mode"
+	default 6
+	range 0 11
+	---help---
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
+
+config STM32F7_TIM8_CH6OUT
+	bool "TIM8 Channel 6 Output"
+	default n
+	---help---
+		Enables channel 6 output.
+
+endif # STM32F7_TIM8_CHANNEL6
+
 endif # STM32F7_PWM_MULTICHAN
 
 if !STM32F7_PWM_MULTICHAN
@@ -3519,12 +3913,70 @@ config STM32F7_TIM8_CHANNEL
 		If TIM8 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32F7_TIM8_CHANNEL = 1
+
+config STM32F7_TIM8_CH1OUT
+	bool "TIM8 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+config STM32F7_TIM8_CH1NOUT
+	bool "TIM8 Channel 1 Complementary Output"
+	default n
+	---help---
+		Enables channel 1 Complementary Output.
+
+endif # STM32F7_TIM8_CHANNEL = 1
+
+if STM32F7_TIM8_CHANNEL = 2
+
+config STM32F7_TIM8_CH2OUT
+	bool "TIM8 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+config STM32F7_TIM8_CH2NOUT
+	bool "TIM8 Channel 2 Complementary Output"
+	default n
+	---help---
+		Enables channel 2 Complementary Output.
+
+endif # STM32F7_TIM8_CHANNEL = 2
+
+if STM32F7_TIM8_CHANNEL = 3
+
+config STM32F7_TIM8_CH3OUT
+	bool "TIM8 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+config STM32F7_TIM8_CH3NOUT
+	bool "TIM8 Channel 3 Complementary Output"
+	default n
+	---help---
+		Enables channel 3 Complementary Output.
+
+endif # STM32F7_TIM8_CHANNEL = 3
+
+if STM32F7_TIM8_CHANNEL = 4
+
+config STM32F7_TIM8_CH4OUT
+	bool "TIM8 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32F7_TIM8_CHANNEL = 4
+
 config STM32F7_TIM8_CHMODE
 	int "TIM8 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -3557,10 +4009,10 @@ if STM32F7_TIM9_CHANNEL1
 
 config STM32F7_TIM9_CH1MODE
 	int "TIM9 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 9
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM9_CH1OUT
 	bool "TIM9 Channel 1 Output"
@@ -3580,10 +4032,10 @@ if STM32F7_TIM9_CHANNEL2
 
 config STM32F7_TIM9_CH2MODE
 	int "TIM9 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 9
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM9_CH2OUT
 	bool "TIM9 Channel 2 Output"
@@ -3593,70 +4045,44 @@ config STM32F7_TIM9_CH2OUT
 
 endif # STM32F7_TIM9_CHANNEL2
 
-config STM32F7_TIM9_CHANNEL3
-	bool "TIM9 Channel 3"
-	default n
-	---help---
-		Enables channel 3.
-
-if STM32F7_TIM9_CHANNEL3
+endif # STM32F7_PWM_MULTICHAN
 
-config STM32F7_TIM9_CH3MODE
-	int "TIM9 Channel 3 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
+if !STM32F7_PWM_MULTICHAN
 
-config STM32F7_TIM9_CH3OUT
-	bool "TIM9 Channel 3 Output"
-	default n
+config STM32F7_TIM9_CHANNEL
+	int "TIM9 PWM Output Channel"
+	default 1
+	range 1 2
 	---help---
-		Enables channel 3 output.
+		If TIM9 is enabled for PWM usage, you also need specifies the timer output
+		channel {1,2}
 
-endif # STM32F7_TIM9_CHANNEL3
+if STM32F7_TIM9_CHANNEL = 1
 
-config STM32F7_TIM9_CHANNEL4
-	bool "TIM9 Channel 4"
+config STM32F7_TIM9_CH1OUT
+	bool "TIM9 Channel 1 Output"
 	default n
 	---help---
-		Enables channel 4.
+		Enables channel 1 output.
 
-if STM32F7_TIM9_CHANNEL4
+endif # STM32F7_TIM9_CHANNEL = 1
 
-config STM32F7_TIM9_CH4MODE
-	int "TIM9 Channel 4 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
+if STM32F7_TIM9_CHANNEL = 2
 
-config STM32F7_TIM9_CH4OUT
-	bool "TIM9 Channel 4 Output"
+config STM32F7_TIM9_CH2OUT
+	bool "TIM9 Channel 2 Output"
 	default n
 	---help---
-		Enables channel 4 output.
-
-endif # STM32F7_TIM9_CHANNEL4
-
-endif # STM32F7_PWM_MULTICHAN
-
-if !STM32F7_PWM_MULTICHAN
+		Enables channel 2 output.
 
-config STM32F7_TIM9_CHANNEL
-	int "TIM9 PWM Output Channel"
-	default 1
-	range 1 4
-	---help---
-		If TIM9 is enabled for PWM usage, you also need specifies the timer output
-		channel {1,..,4}
+endif # STM32F7_TIM9_CHANNEL = 2
 
 config STM32F7_TIM9_CHMODE
 	int "TIM9 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 9
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -3689,10 +4115,10 @@ if STM32F7_TIM10_CHANNEL1
 
 config STM32F7_TIM10_CH1MODE
 	int "TIM10 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM10_CH1OUT
 	bool "TIM10 Channel 1 Output"
@@ -3702,75 +4128,6 @@ config STM32F7_TIM10_CH1OUT
 
 endif # STM32F7_TIM10_CHANNEL1
 
-config STM32F7_TIM10_CHANNEL2
-	bool "TIM10 Channel 2"
-	default n
-	---help---
-		Enables channel 2.
-
-if STM32F7_TIM10_CHANNEL2
-
-config STM32F7_TIM10_CH2MODE
-	int "TIM10 Channel 2 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM10_CH2OUT
-	bool "TIM10 Channel 2 Output"
-	default n
-	---help---
-		Enables channel 2 output.
-
-endif # STM32F7_TIM10_CHANNEL2
-
-config STM32F7_TIM10_CHANNEL3
-	bool "TIM10 Channel 3"
-	default n
-	---help---
-		Enables channel 3.
-
-if STM32F7_TIM10_CHANNEL3
-
-config STM32F7_TIM10_CH3MODE
-	int "TIM10 Channel 3 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM10_CH3OUT
-	bool "TIM10 Channel 3 Output"
-	default n
-	---help---
-		Enables channel 3 output.
-
-endif # STM32F7_TIM10_CHANNEL3
-
-config STM32F7_TIM10_CHANNEL4
-	bool "TIM10 Channel 4"
-	default n
-	---help---
-		Enables channel 4.
-
-if STM32F7_TIM10_CHANNEL4
-
-config STM32F7_TIM10_CH4MODE
-	int "TIM10 Channel 4 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM10_CH4OUT
-	bool "TIM10 Channel 4 Output"
-	default n
-	---help---
-		Enables channel 4 output.
-
-endif # STM32F7_TIM10_CHANNEL4
-
 endif # STM32F7_PWM_MULTICHAN
 
 if !STM32F7_PWM_MULTICHAN
@@ -3778,17 +4135,27 @@ if !STM32F7_PWM_MULTICHAN
 config STM32F7_TIM10_CHANNEL
 	int "TIM10 PWM Output Channel"
 	default 1
-	range 1 4
+	range 1 1
 	---help---
 		If TIM10 is enabled for PWM usage, you also need specifies the timer output
-		channel {1,..,4}
+		channel {1}
+
+if STM32F7_TIM10_CHANNEL = 1
+
+config STM32F7_TIM10_CH1OUT
+	bool "TIM10 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32F7_TIM10_CHANNEL = 1
 
 config STM32F7_TIM10_CHMODE
 	int "TIM10 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -3821,10 +4188,10 @@ if STM32F7_TIM11_CHANNEL1
 
 config STM32F7_TIM11_CH1MODE
 	int "TIM11 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM11_CH1OUT
 	bool "TIM11 Channel 1 Output"
@@ -3834,93 +4201,34 @@ config STM32F7_TIM11_CH1OUT
 
 endif # STM32F7_TIM11_CHANNEL1
 
-config STM32F7_TIM11_CHANNEL2
-	bool "TIM11 Channel 2"
-	default n
-	---help---
-		Enables channel 2.
+endif # STM32F7_PWM_MULTICHAN
 
-if STM32F7_TIM11_CHANNEL2
+if !STM32F7_PWM_MULTICHAN
 
-config STM32F7_TIM11_CH2MODE
-	int "TIM11 Channel 2 Mode"
-	default 0
-	range 0 5
+config STM32F7_TIM11_CHANNEL
+	int "TIM11 PWM Output Channel"
+	default 1
+	range 1 1
 	---help---
-		Specifies the channel mode.
+		If TIM11 is enabled for PWM usage, you also need specifies the timer output
+		channel {1}
+
+if STM32F7_TIM11_CHANNEL = 1
 
-config STM32F7_TIM11_CH2OUT
-	bool "TIM11 Channel 2 Output"
+config STM32F7_TIM11_CH1OUT
+	bool "TIM11 Channel 1 Output"
 	default n
 	---help---
-		Enables channel 2 output.
+		Enables channel 1 output.
 
-endif # STM32F7_TIM11_CHANNEL2
+endif # STM32F7_TIM11_CHANNEL = 1
 
-config STM32F7_TIM11_CHANNEL3
-	bool "TIM11 Channel 3"
-	default n
+config STM32F7_TIM11_CHMODE
+	int "TIM11 Channel Mode"
+	default 6
+	range 0 7
 	---help---
-		Enables channel 3.
-
-if STM32F7_TIM11_CHANNEL3
-
-config STM32F7_TIM11_CH3MODE
-	int "TIM11 Channel 3 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM11_CH3OUT
-	bool "TIM11 Channel 3 Output"
-	default n
-	---help---
-		Enables channel 3 output.
-
-endif # STM32F7_TIM11_CHANNEL3
-
-config STM32F7_TIM11_CHANNEL4
-	bool "TIM11 Channel 4"
-	default n
-	---help---
-		Enables channel 4.
-
-if STM32F7_TIM11_CHANNEL4
-
-config STM32F7_TIM11_CH4MODE
-	int "TIM11 Channel 4 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM11_CH4OUT
-	bool "TIM11 Channel 4 Output"
-	default n
-	---help---
-		Enables channel 4 output.
-
-endif # STM32F7_TIM11_CHANNEL4
-
-endif # STM32F7_PWM_MULTICHAN
-
-if !STM32F7_PWM_MULTICHAN
-
-config STM32F7_TIM11_CHANNEL
-	int "TIM11 PWM Output Channel"
-	default 1
-	range 1 4
-	---help---
-		If TIM11 is enabled for PWM usage, you also need specifies the timer output
-		channel {1,..,4}
-
-config STM32F7_TIM11_CHMODE
-	int "TIM11 Channel Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -3953,10 +4261,10 @@ if STM32F7_TIM12_CHANNEL1
 
 config STM32F7_TIM12_CH1MODE
 	int "TIM12 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 9
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM12_CH1OUT
 	bool "TIM12 Channel 1 Output"
@@ -3976,10 +4284,10 @@ if STM32F7_TIM12_CHANNEL2
 
 config STM32F7_TIM12_CH2MODE
 	int "TIM12 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 9
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM12_CH2OUT
 	bool "TIM12 Channel 2 Output"
@@ -3989,70 +4297,44 @@ config STM32F7_TIM12_CH2OUT
 
 endif # STM32F7_TIM12_CHANNEL2
 
-config STM32F7_TIM12_CHANNEL3
-	bool "TIM12 Channel 3"
-	default n
-	---help---
-		Enables channel 3.
-
-if STM32F7_TIM12_CHANNEL3
+endif # STM32F7_PWM_MULTICHAN
 
-config STM32F7_TIM12_CH3MODE
-	int "TIM12 Channel 3 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
+if !STM32F7_PWM_MULTICHAN
 
-config STM32F7_TIM12_CH3OUT
-	bool "TIM12 Channel 3 Output"
-	default n
+config STM32F7_TIM12_CHANNEL
+	int "TIM12 PWM Output Channel"
+	default 1
+	range 1 2
 	---help---
-		Enables channel 3 output.
+		If TIM12 is enabled for PWM usage, you also need specifies the timer output
+		channel {1,2}
 
-endif # STM32F7_TIM12_CHANNEL3
+if STM32F7_TIM12_CHANNEL = 1
 
-config STM32F7_TIM12_CHANNEL4
-	bool "TIM12 Channel 4"
+config STM32F7_TIM12_CH1OUT
+	bool "TIM12 Channel 1 Output"
 	default n
 	---help---
-		Enables channel 4.
+		Enables channel 1 output.
 
-if STM32F7_TIM12_CHANNEL4
+endif # STM32F7_TIM12_CHANNEL = 1
 
-config STM32F7_TIM12_CH4MODE
-	int "TIM12 Channel 4 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
+if STM32F7_TIM12_CHANNEL = 2
 
-config STM32F7_TIM12_CH4OUT
-	bool "TIM12 Channel 4 Output"
+config STM32F7_TIM12_CH2OUT
+	bool "TIM12 Channel 2 Output"
 	default n
 	---help---
-		Enables channel 4 output.
-
-endif # STM32F7_TIM12_CHANNEL4
-
-endif # STM32F7_PWM_MULTICHAN
-
-if !STM32F7_PWM_MULTICHAN
+		Enables channel 2 output.
 
-config STM32F7_TIM12_CHANNEL
-	int "TIM12 PWM Output Channel"
-	default 1
-	range 1 4
-	---help---
-		If TIM12 is enabled for PWM usage, you also need specifies the timer output
-		channel {1,..,4}
+endif # STM32F7_TIM12_CHANNEL = 2
 
 config STM32F7_TIM12_CHMODE
 	int "TIM12 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 9
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -4085,10 +4367,10 @@ if STM32F7_TIM13_CHANNEL1
 
 config STM32F7_TIM13_CH1MODE
 	int "TIM13 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM13_CH1OUT
 	bool "TIM13 Channel 1 Output"
@@ -4098,75 +4380,6 @@ config STM32F7_TIM13_CH1OUT
 
 endif # STM32F7_TIM13_CHANNEL1
 
-config STM32F7_TIM13_CHANNEL2
-	bool "TIM13 Channel 2"
-	default n
-	---help---
-		Enables channel 2.
-
-if STM32F7_TIM13_CHANNEL2
-
-config STM32F7_TIM13_CH2MODE
-	int "TIM13 Channel 2 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM13_CH2OUT
-	bool "TIM13 Channel 2 Output"
-	default n
-	---help---
-		Enables channel 2 output.
-
-endif # STM32F7_TIM13_CHANNEL2
-
-config STM32F7_TIM13_CHANNEL3
-	bool "TIM13 Channel 3"
-	default n
-	---help---
-		Enables channel 3.
-
-if STM32F7_TIM13_CHANNEL3
-
-config STM32F7_TIM13_CH3MODE
-	int "TIM13 Channel 3 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM13_CH3OUT
-	bool "TIM13 Channel 3 Output"
-	default n
-	---help---
-		Enables channel 3 output.
-
-endif # STM32F7_TIM13_CHANNEL3
-
-config STM32F7_TIM13_CHANNEL4
-	bool "TIM13 Channel 4"
-	default n
-	---help---
-		Enables channel 4.
-
-if STM32F7_TIM13_CHANNEL4
-
-config STM32F7_TIM13_CH4MODE
-	int "TIM13 Channel 4 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM13_CH4OUT
-	bool "TIM13 Channel 4 Output"
-	default n
-	---help---
-		Enables channel 4 output.
-
-endif # STM32F7_TIM13_CHANNEL4
-
 endif # STM32F7_PWM_MULTICHAN
 
 if !STM32F7_PWM_MULTICHAN
@@ -4174,17 +4387,27 @@ if !STM32F7_PWM_MULTICHAN
 config STM32F7_TIM13_CHANNEL
 	int "TIM13 PWM Output Channel"
 	default 1
-	range 1 4
+	range 1 1
 	---help---
 		If TIM13 is enabled for PWM usage, you also need specifies the timer output
-		channel {1,..,4}
+		channel {1}
+
+if STM32F7_TIM13_CHANNEL = 1
+
+config STM32F7_TIM13_CH1OUT
+	bool "TIM13 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32F7_TIM13_CHANNEL = 1
 
 config STM32F7_TIM13_CHMODE
 	int "TIM13 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -4217,10 +4440,10 @@ if STM32F7_TIM14_CHANNEL1
 
 config STM32F7_TIM14_CH1MODE
 	int "TIM14 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 config STM32F7_TIM14_CH1OUT
 	bool "TIM14 Channel 1 Output"
@@ -4230,75 +4453,6 @@ config STM32F7_TIM14_CH1OUT
 
 endif # STM32F7_TIM14_CHANNEL1
 
-config STM32F7_TIM14_CHANNEL2
-	bool "TIM14 Channel 2"
-	default n
-	---help---
-		Enables channel 2.
-
-if STM32F7_TIM14_CHANNEL2
-
-config STM32F7_TIM14_CH2MODE
-	int "TIM14 Channel 2 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM14_CH2OUT
-	bool "TIM14 Channel 2 Output"
-	default n
-	---help---
-		Enables channel 2 output.
-
-endif # STM32F7_TIM14_CHANNEL2
-
-config STM32F7_TIM14_CHANNEL3
-	bool "TIM14 Channel 3"
-	default n
-	---help---
-		Enables channel 3.
-
-if STM32F7_TIM14_CHANNEL3
-
-config STM32F7_TIM14_CH3MODE
-	int "TIM14 Channel 3 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM14_CH3OUT
-	bool "TIM14 Channel 3 Output"
-	default n
-	---help---
-		Enables channel 3 output.
-
-endif # STM32F7_TIM14_CHANNEL3
-
-config STM32F7_TIM14_CHANNEL4
-	bool "TIM14 Channel 4"
-	default n
-	---help---
-		Enables channel 4.
-
-if STM32F7_TIM14_CHANNEL4
-
-config STM32F7_TIM14_CH4MODE
-	int "TIM14 Channel 4 Mode"
-	default 0
-	range 0 5
-	---help---
-		Specifies the channel mode.
-
-config STM32F7_TIM14_CH4OUT
-	bool "TIM14 Channel 4 Output"
-	default n
-	---help---
-		Enables channel 4 output.
-
-endif # STM32F7_TIM14_CHANNEL4
-
 endif # STM32F7_PWM_MULTICHAN
 
 if !STM32F7_PWM_MULTICHAN
@@ -4306,17 +4460,27 @@ if !STM32F7_PWM_MULTICHAN
 config STM32F7_TIM14_CHANNEL
 	int "TIM14 PWM Output Channel"
 	default 1
-	range 1 4
+	range 1 1
 	---help---
 		If TIM14 is enabled for PWM usage, you also need specifies the timer output
-		channel {1,..,4}
+		channel {1}
+
+if STM32F7_TIM14_CHANNEL = 1
+
+config STM32F7_TIM14_CH1OUT
+	bool "TIM14 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32F7_TIM14_CHANNEL = 1
 
 config STM32F7_TIM14_CHMODE
 	int "TIM14 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h.
 
 endif # !STM32F7_PWM_MULTICHAN
 
@@ -4331,6 +4495,13 @@ config STM32F7_PWM_MULTICHAN
 		Specifies that the PWM driver supports multiple output
 		channels per timer.
 
+config STM32F7_PWM_TRGO
+	bool "TIM PWM TRGO support"
+	default n
+	depends on STM32F7_PWM
+	---help---
+		Enable TRGO support for PWM driver
+
 config STM32F7_TIM1_ADC
 	bool "TIM1 ADC"
 	default n
@@ -5191,6 +5362,682 @@ config STM32F7_TIM14_CAP
 		Timer devices may be used for different purposes.  One special purpose is
 		to capture input.
 
+menu "STM32 TIMx Outputs Configuration"
+
+config STM32F7_TIM1_CH1POL
+	int "TIM1 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH1OUT
+	---help---
+		TIM1 Channel 1 output polarity
+
+config STM32F7_TIM1_CH1IDLE
+	int "TIM1 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH1OUT
+	---help---
+		TIM1 Channel 1 output IDLE
+
+config STM32F7_TIM1_CH1NPOL
+	int "TIM1 Channel 1 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH1NOUT
+	---help---
+		TIM1 Channel 1 Complementary Output polarity
+
+config STM32F7_TIM1_CH1NIDLE
+	int "TIM1 Channel 1 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH1NOUT
+	---help---
+		TIM1 Channel 1 Complementary Output IDLE
+
+config STM32F7_TIM1_CH2POL
+	int "TIM1 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH2OUT
+	---help---
+		TIM1 Channel 2 output polarity
+
+config STM32F7_TIM1_CH2IDLE
+	int "TIM1 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH2OUT
+	---help---
+		TIM1 Channel 2 output IDLE
+
+config STM32F7_TIM1_CH2NPOL
+	int "TIM1 Channel 2 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH2NOUT
+	---help---
+		TIM1 Channel 2 Complementary Output polarity
+
+config STM32F7_TIM1_CH2NIDLE
+	int "TIM1 Channel 2 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH2NOUT
+	---help---
+		TIM1 Channel 2 Complementary Output IDLE
+
+config STM32F7_TIM1_CH3POL
+	int "TIM1 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH3OUT
+	---help---
+		TIM1 Channel 3 output polarity
+
+config STM32F7_TIM1_CH3IDLE
+	int "TIM1 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH3OUT
+	---help---
+		TIM1 Channel 3 output IDLE
+
+config STM32F7_TIM1_CH3NPOL
+	int "TIM1 Channel 3 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH3NOUT
+	---help---
+		TIM1 Channel 3 Complementary Output polarity
+
+config STM32F7_TIM1_CH3NIDLE
+	int "TIM1 Channel 3 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH3NOUT
+	---help---
+		TIM1 Channel 3 Complementary Output IDLE
+
+config STM32F7_TIM1_CH4POL
+	int "TIM1 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH4OUT
+	---help---
+		TIM1 Channel 4 output polarity
+
+config STM32F7_TIM1_CH4IDLE
+	int "TIM1 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH4OUT
+	---help---
+		TIM1 Channel 4 output IDLE
+
+config STM32F7_TIM1_CH5POL
+	int "TIM1 Channel 5 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH5OUT
+	---help---
+		TIM1 Channel 5 output polarity
+
+config STM32F7_TIM1_CH5IDLE
+	int "TIM1 Channel 5 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH5OUT
+	---help---
+		TIM1 Channel 5 output IDLE
+
+config STM32F7_TIM1_CH6POL
+	int "TIM1 Channel 6 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH6OUT
+	---help---
+		TIM1 Channel 6 output polarity
+
+config STM32F7_TIM1_CH6IDLE
+	int "TIM1 Channel 6 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM1_CH6OUT
+	---help---
+		TIM1 Channel 6 output IDLE
+
+config STM32F7_TIM2_CH1POL
+	int "TIM2 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM2_CH1OUT
+	---help---
+		TIM2 Channel 1 output polarity
+
+config STM32F7_TIM2_CH1IDLE
+	int "TIM2 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM2_CH1OUT
+	---help---
+		TIM2 Channel 1 output IDLE
+
+config STM32F7_TIM2_CH2POL
+	int "TIM2 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM2_CH2OUT
+	---help---
+		TIM2 Channel 2 output polarity
+
+config STM32F7_TIM2_CH2IDLE
+	int "TIM2 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM2_CH2OUT
+	---help---
+		TIM2 Channel 2 output IDLE
+
+config STM32F7_TIM2_CH3POL
+	int "TIM2 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM2_CH3OUT
+	---help---
+		TIM2 Channel 3 output polarity
+
+config STM32F7_TIM2_CH3IDLE
+	int "TIM2 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM2_CH3OUT
+	---help---
+		TIM2 Channel 3 output IDLE
+
+config STM32F7_TIM2_CH4POL
+	int "TIM2 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM2_CH4OUT
+	---help---
+		TIM2 Channel 4 output polarity
+
+config STM32F7_TIM2_CH4IDLE
+	int "TIM2 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM2_CH4OUT
+	---help---
+		TIM2 Channel 4 output IDLE
+
+config STM32F7_TIM3_CH1POL
+	int "TIM3 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM3_CH1OUT
+	---help---
+		TIM3 Channel 1 output polarity
+
+config STM32F7_TIM3_CH1IDLE
+	int "TIM3 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM3_CH1OUT
+	---help---
+		TIM3 Channel 1 output IDLE
+
+config STM32F7_TIM3_CH2POL
+	int "TIM3 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM3_CH2OUT
+	---help---
+		TIM3 Channel 2 output polarity
+
+config STM32F7_TIM3_CH2IDLE
+	int "TIM3 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM3_CH2OUT
+	---help---
+		TIM3 Channel 2 output IDLE
+
+config STM32F7_TIM3_CH3POL
+	int "TIM3 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM3_CH3OUT
+	---help---
+		TIM3 Channel 3 output polarity
+
+config STM32F7_TIM3_CH3IDLE
+	int "TIM3 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM3_CH3OUT
+	---help---
+		TIM3 Channel 3 output IDLE
+
+config STM32F7_TIM3_CH4POL
+	int "TIM3 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM3_CH4OUT
+	---help---
+		TIM3 Channel 4 output polarity
+
+config STM32F7_TIM3_CH4IDLE
+	int "TIM3 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM3_CH4OUT
+	---help---
+		TIM3 Channel 4 output IDLE
+
+config STM32F7_TIM4_CH1POL
+	int "TIM4 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM4_CH1OUT
+	---help---
+		TIM4 Channel 1 output polarity
+
+config STM32F7_TIM4_CH1IDLE
+	int "TIM4 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM4_CH1OUT
+	---help---
+		TIM4 Channel 1 output IDLE
+
+config STM32F7_TIM4_CH2POL
+	int "TIM4 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM4_CH2OUT
+	---help---
+		TIM4 Channel 2 output polarity
+
+config STM32F7_TIM4_CH2IDLE
+	int "TIM4 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM4_CH2OUT
+	---help---
+		TIM4 Channel 2 output IDLE
+
+config STM32F7_TIM4_CH3POL
+	int "TIM4 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM4_CH3OUT
+	---help---
+		TIM4 Channel 3 output polarity
+
+config STM32F7_TIM4_CH3IDLE
+	int "TIM4 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM4_CH3OUT
+	---help---
+		TIM4 Channel 3 output IDLE
+
+config STM32F7_TIM4_CH4POL
+	int "TIM4 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM4_CH4OUT
+	---help---
+		TIM4 Channel 4 output polarity
+
+config STM32F7_TIM4_CH4IDLE
+	int "TIM4 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM4_CH4OUT
+	---help---
+		TIM4 Channel 4 output IDLE
+
+config STM32F7_TIM5_CH1POL
+	int "TIM5 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM5_CH1OUT
+	---help---
+		TIM5 Channel 1 output polarity
+
+config STM32F7_TIM5_CH1IDLE
+	int "TIM5 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM5_CH1OUT
+	---help---
+		TIM5 Channel 1 output IDLE
+
+config STM32F7_TIM5_CH2POL
+	int "TIM5 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM5_CH2OUT
+	---help---
+		TIM5 Channel 2 output polarity
+
+config STM32F7_TIM5_CH2IDLE
+	int "TIM5 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM5_CH2OUT
+	---help---
+		TIM5 Channel 2 output IDLE
+
+config STM32F7_TIM5_CH3POL
+	int "TIM5 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM5_CH3OUT
+	---help---
+		TIM5 Channel 3 output polarity
+
+config STM32F7_TIM5_CH3IDLE
+	int "TIM5 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM5_CH3OUT
+	---help---
+		TIM5 Channel 3 output IDLE
+
+config STM32F7_TIM5_CH4POL
+	int "TIM5 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM5_CH4OUT
+	---help---
+		TIM5 Channel 4 output polarity
+
+config STM32F7_TIM5_CH4IDLE
+	int "TIM5 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM5_CH4OUT
+	---help---
+		TIM5 Channel 4 output IDLE
+
+config STM32F7_TIM8_CH1POL
+	int "TIM8 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH1OUT
+	---help---
+		TIM8 Channel 1 output polarity
+
+config STM32F7_TIM8_CH1IDLE
+	int "TIM8 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH1OUT
+	---help---
+		TIM8 Channel 1 output IDLE
+
+config STM32F7_TIM8_CH1NPOL
+	int "TIM8 Channel 1 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH1NOUT
+	---help---
+		TIM8 Channel 1 Complementary Output polarity
+
+config STM32F7_TIM8_CH1NIDLE
+	int "TIM8 Channel 1 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH1NOUT
+	---help---
+		TIM8 Channel 1 Complementary Output IDLE
+
+config STM32F7_TIM8_CH2POL
+	int "TIM8 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH2OUT
+	---help---
+		TIM8 Channel 2 output polarity
+
+config STM32F7_TIM8_CH2IDLE
+	int "TIM8 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH2OUT
+	---help---
+		TIM8 Channel 2 output IDLE
+
+config STM32F7_TIM8_CH2NPOL
+	int "TIM8 Channel 2 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH2NOUT
+	---help---
+		TIM8 Channel 2 Complementary Output polarity
+
+config STM32F7_TIM8_CH2NIDLE
+	int "TIM8 Channel 2 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH2NOUT
+	---help---
+		TIM8 Channel 2 Complementary Output IDLE
+
+config STM32F7_TIM8_CH3POL
+	int "TIM8 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH3OUT
+	---help---
+		TIM8 Channel 3 output polarity
+
+config STM32F7_TIM8_CH3IDLE
+	int "TIM8 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH3OUT
+	---help---
+		TIM8 Channel 3 output IDLE
+
+config STM32F7_TIM8_CH3NPOL
+	int "TIM8 Channel 3 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH3NOUT
+	---help---
+		TIM8 Channel 3 Complementary Output polarity
+
+config STM32F7_TIM8_CH3NIDLE
+	int "TIM8 Channel 3 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH3NOUT
+	---help---
+		TIM8 Channel 3 Complementary Output IDLE
+
+config STM32F7_TIM8_CH4POL
+	int "TIM8 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH4OUT
+	---help---
+		TIM8 Channel 4 output polarity
+
+config STM32F7_TIM8_CH4IDLE
+	int "TIM8 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH4OUT
+	---help---
+		TIM8 Channel 4 output IDLE
+
+config STM32F7_TIM8_CH5POL
+	int "TIM8 Channel 5 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH5OUT
+	---help---
+		TIM8 Channel 5 output polarity
+
+config STM32F7_TIM8_CH5IDLE
+	int "TIM8 Channel 5 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH5OUT
+	---help---
+		TIM8 Channel 5 output IDLE
+
+config STM32F7_TIM8_CH6POL
+	int "TIM8 Channel 6 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH6OUT
+	---help---
+		TIM8 Channel 6 output polarity
+
+config STM32F7_TIM8_CH6IDLE
+	int "TIM8 Channel 6 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM8_CH6OUT
+	---help---
+		TIM8 Channel 6 output IDLE
+
+config STM32F7_TIM9_CH1POL
+	int "TIM9 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM9_CH1OUT
+	---help---
+		TIM9 Channel 1 output polarity
+
+config STM32F7_TIM9_CH1IDLE
+	int "TIM9 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM9_CH1OUT
+	---help---
+		TIM9 Channel 1 output IDLE
+
+config STM32F7_TIM9_CH2POL
+	int "TIM9 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM9_CH2OUT
+	---help---
+		TIM9 Channel 2 output polarity
+
+config STM32F7_TIM9_CH2IDLE
+	int "TIM9 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM9_CH2OUT
+	---help---
+		TIM9 Channel 2 output IDLE
+
+config STM32F7_TIM10_CH1POL
+	int "TIM10 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM10_CH1OUT
+	---help---
+		TIM10 Channel 1 output polarity
+
+config STM32F7_TIM10_CH1IDLE
+	int "TIM10 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM10_CH1OUT
+	---help---
+		TIM10 Channel 1 output IDLE
+
+config STM32F7_TIM11_CH1POL
+	int "TIM11 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM11_CH1OUT
+	---help---
+		TIM11 Channel 1 output polarity
+
+config STM32F7_TIM11_CH1IDLE
+	int "TIM11 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM11_CH1OUT
+	---help---
+		TIM11 Channel 1 output IDLE
+
+config STM32F7_TIM12_CH1POL
+	int "TIM12 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM12_CH1OUT
+	---help---
+		TIM12 Channel 1 output polarity
+
+config STM32F7_TIM12_CH1IDLE
+	int "TIM12 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM12_CH1OUT
+	---help---
+		TIM12 Channel 1 output IDLE
+
+config STM32F7_TIM12_CH2POL
+	int "TIM12 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM12_CH2OUT
+	---help---
+		TIM12 Channel 2 output polarity
+
+config STM32F7_TIM12_CH2IDLE
+	int "TIM12 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM12_CH2OUT
+	---help---
+		TIM12 Channel 2 output IDLE
+
+config STM32F7_TIM13_CH1POL
+	int "TIM13 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM13_CH1OUT
+	---help---
+		TIM13 Channel 1 output polarity
+
+config STM32F7_TIM13_CH1IDLE
+	int "TIM13 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM13_CH1OUT
+	---help---
+		TIM13 Channel 1 output IDLE
+
+config STM32F7_TIM14_CH1POL
+	int "TIM14 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM14_CH1OUT
+	---help---
+		TIM14 Channel 1 output polarity
+
+config STM32F7_TIM14_CH1IDLE
+	int "TIM14 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32F7_TIM14_CH1OUT
+	---help---
+		TIM14 Channel 1 output IDLE
+
+endmenu #STM32 TIMx Outputs Configuration
+
 endmenu # Timer Configuration
 
 menu "CAN driver configuration"
diff --git a/arch/arm/src/stm32f7/stm32_pwm.c b/arch/arm/src/stm32f7/stm32_pwm.c
index 24ebb213d3..fb88fcc9ae 100644
--- a/arch/arm/src/stm32f7/stm32_pwm.c
+++ b/arch/arm/src/stm32f7/stm32_pwm.c
@@ -24,6 +24,7 @@
 
 #include <nuttx/config.h>
 
+#include <inttypes.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <assert.h>
@@ -31,27 +32,15 @@
 #include <debug.h>
 
 #include <nuttx/arch.h>
-#include <nuttx/timers/pwm.h>
 #include <arch/board/board.h>
 
 #include "arm_internal.h"
-#include "stm32_rcc.h"
 #include "chip.h"
 #include "stm32_pwm.h"
+#include "stm32_rcc.h"
 #include "stm32_gpio.h"
 
-/* This module then only compiles if there is at least one enabled timer
- * intended for use with the PWM upper half driver.
- */
-
-#if defined(CONFIG_STM32F7_TIM1_PWM)  || defined(CONFIG_STM32F7_TIM2_PWM)  || \
-    defined(CONFIG_STM32F7_TIM3_PWM)  || defined(CONFIG_STM32F7_TIM4_PWM)  || \
-    defined(CONFIG_STM32F7_TIM5_PWM)  || defined(CONFIG_STM32F7_TIM8_PWM)  || \
-    defined(CONFIG_STM32F7_TIM9_PWM)  || defined(CONFIG_STM32F7_TIM10_PWM) || \
-    defined(CONFIG_STM32F7_TIM11_PWM) || defined(CONFIG_STM32F7_TIM12_PWM) || \
-    defined(CONFIG_STM32F7_TIM13_PWM) || defined(CONFIG_STM32F7_TIM14_PWM) || \
-    defined(CONFIG_STM32F7_TIM15_PWM) || defined(CONFIG_STM32F7_TIM16_PWM) || \
-    defined(CONFIG_STM32F7_TIM17_PWM)
+#ifdef CONFIG_STM32F7_PWM
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -61,11 +50,14 @@
 
 /* The following definitions are used to identify the various time types */
 
-#define TIMTYPE_BASIC      0  /* Basic timers: TIM6-7 */
-#define TIMTYPE_GENERAL16  1  /* General 16-bit timers: TIM3-4 */
-#define TIMTYPE_COUNTUP16  2  /* General 16-bit count-up timers: TIM9-14 */
-#define TIMTYPE_GENERAL32  3  /* General 32-bit timers: TIM2-5 */
-#define TIMTYPE_ADVANCED   4  /* Advanced timers:  TIM1-8 */
+#define TIMTYPE_BASIC        0  /* Basic timers (no outputs) */
+#define TIMTYPE_GENERAL16    1  /* General 16-bit timers (up, down, up/down)*/
+#define TIMTYPE_COUNTUP16    2  /* General 16-bit count-up timers */
+#define TIMTYPE_COUNTUP16_N  3  /* General 16-bit count-up timers with
+                                 * complementary outptus
+                                 */
+#define TIMTYPE_GENERAL32    4  /* General 32-bit timers (up, down, up/down)*/
+#define TIMTYPE_ADVANCED     5  /* Advanced timers */
 
 #define TIMTYPE_TIM1       TIMTYPE_ADVANCED
 #define TIMTYPE_TIM2       TIMTYPE_GENERAL32
@@ -82,6 +74,8 @@
 #define TIMTYPE_TIM13      TIMTYPE_COUNTUP16
 #define TIMTYPE_TIM14      TIMTYPE_COUNTUP16
 
+/* No TIM15-17 in STM32F7 devices (TIMTYPE_COUNTUP16_N) */
+
 /* Timer clock source, RCC EN offset, enable bit,
  * RCC RST offset, reset bit to use
  */
@@ -147,6 +141,42 @@
 #define TIMRCCRST_TIM14  STM32_RCC_APB1RSTR
 #define TIMRST_TIM14     RCC_APB1RSTR_TIM14RST
 
+/* Default GPIO pins state */
+
+#define PINCFG_DEFAULT (GPIO_INPUT | GPIO_FLOAT)
+
+/* Advanced Timer support */
+
+#if defined(CONFIG_STM32F7_TIM1_PWM) || defined(CONFIG_STM32F7_TIM8_PWM)
+#  define HAVE_ADVTIM
+#else
+#  undef HAVE_ADVTIM
+#endif
+
+/* Pulsecount support */
+
+#ifdef CONFIG_PWM_PULSECOUNT
+#  ifndef HAVE_ADVTIM
+#    error "PWM_PULSECOUNT requires HAVE_ADVTIM"
+#  endif
+#  if defined(CONFIG_STM32F7_TIM1_PWM) || defined(CONFIG_STM32F7_TIM8_PWM)
+#    define HAVE_PWM_INTERRUPT
+#  endif
+#endif
+
+/* TRGO/TRGO2 support */
+
+#ifdef CONFIG_STM32F7_PWM_TRGO
+#  define HAVE_TRGO
+#endif
+
+/* Break support */
+
+#if defined(CONFIG_STM32F7_TIM1_BREAK1) || defined(CONFIG_STM32F7_TIM1_BREAK2) || \
+    defined(CONFIG_STM32F7_TIM8_BREAK1) || defined(CONFIG_STM32F7_TIM8_BREAK2)
+#  defined HAVE_BREAK
+#endif
+
 /* Debug ********************************************************************/
 
 #ifdef CONFIG_DEBUG_PWM_INFO
@@ -159,54 +189,83 @@
  * Private Types
  ****************************************************************************/
 
-enum stm32_timmode_e
+/* PWM output configuration */
+
+struct stm32_pwm_out_s
 {
-  STM32_TIMMODE_COUNTUP   = 0,
-  STM32_TIMMODE_COUNTDOWN = 1,
-  STM32_TIMMODE_CENTER1   = 2,
-  STM32_TIMMODE_CENTER2   = 3,
-  STM32_TIMMODE_CENTER3   = 4,
+  uint8_t  in_use:1;                    /* Output in use */
+  uint8_t  pol:1;                       /* Polarity. Default: positive */
+  uint8_t  idle:1;                      /* Idle state. Default: inactive */
+  uint8_t  _res:5;                      /* Reserved */
+  uint32_t pincfg;                      /* Output pin configuration */
 };
 
-enum stm32_chanmode_e
+/* PWM break configuration */
+
+#ifdef HAVE_BREAK
+struct stm32_pwm_break_s
 {
-  STM32_CHANMODE_PWM1        = 0,
-  STM32_CHANMODE_PWM2        = 1,
-  STM32_CHANMODE_COMBINED1   = 2,
-  STM32_CHANMODE_COMBINED2   = 3,
-  STM32_CHANMODE_ASYMMETRIC1 = 4,
-  STM32_CHANMODE_ASYMMETRIC2 = 5,
+  uint8_t en1:1;                        /* Break 1 enable */
+  uint8_t pol1:1;                       /* Break 1 polarity */
+  uint8_t _res:6;                       /* Reserved */
+  uint8_t en2:1;                        /* Break 2 enable */
+  uint8_t pol2:1;                       /* Break 2 polarity */
+  uint8_t flt2:6;                       /* Break 2 filter */
 };
+#endif
+
+/* PWM channel configuration */
 
 struct stm32_pwmchan_s
 {
-  uint8_t channel;                     /* Timer output channel: {1,..4} */
-  uint32_t pincfg;                     /* Output pin configuration */
-  enum stm32_chanmode_e mode;
+  uint8_t                  channel:4;   /* Timer output channel: {1,..4} */
+  uint8_t                  mode:4;      /* PWM channel mode (see stm32_pwm_chanmode_e) */
+  struct stm32_pwm_out_s   out1;        /* PWM output configuration */
+#ifdef HAVE_BREAK
+  struct stm32_pwm_break_s brk;         /* PWM break configuration */
+#endif
+#ifdef HAVE_PWM_COMPLEMENTARY
+  struct stm32_pwm_out_s   out2;        /* PWM complementary output configuration */
+#endif
 };
 
 /* This structure represents the state of one PWM timer */
 
 struct stm32_pwmtimer_s
 {
-  const struct pwm_ops_s *ops; /* PWM operations */
-  uint8_t timid;               /* Timer ID {1,...,17} */
-  struct stm32_pwmchan_s channels[PWM_NCHANNELS];
-  uint8_t timtype;             /* See the TIMTYPE_* definitions */
-  enum stm32_timmode_e mode;
-#ifdef CONFIG_PWM_PULSECOUNT
-  uint8_t irq;                 /* Timer update IRQ */
-  uint8_t prev;                /* The previous value of the RCR (pre-loaded) */
-  uint8_t curr;                /* The current value of the RCR (pre-loaded) */
-  uint32_t count;              /* Remaining pulse count */
-#else
-  uint32_t frequency;          /* Current frequency setting */
+  const struct pwm_ops_s *ops;      /* PWM operations */
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  const struct stm32_pwm_ops_s *llops; /* Low-level PWM ops */
+#endif
+  struct stm32_pwmchan_s *channels; /* Channels configuration */
+  uint8_t  timid:5;                 /* Timer ID {1,...,17} */
+  uint8_t  chan_num:3;              /* Number of configured channels */
+  uint8_t  timtype:3;               /* See the TIMTYPE_* definitions */
+  uint8_t  mode:3;                  /* Timer mode (see stm32_pwm_tim_mode_e) */
+  uint8_t  lock:2;                  /* Lock configuration */
+  uint8_t  t_dts:3;                 /* Clock division for t_DTS */
+  uint8_t  _res:5;                  /* Reserved */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  uint8_t  deadtime;                /* Dead-time value */
+#endif
+#ifdef HAVE_TRGO
+  uint8_t  trgo;                    /* TRGO configuration:
+                                     * 4 LSB = TRGO, 4 MSB = TRGO2
+                                     */
 #endif
-  uint32_t base;               /* The base address of the timer */
-  uint32_t pclk;               /* The frequency of the peripheral clock
-                                * that drives the timer module. */
 #ifdef CONFIG_PWM_PULSECOUNT
-  void *handle;                /* Handle used for upper-half callback */
+  uint8_t  irq;                     /* Timer update IRQ */
+  uint8_t  prev;                    /* The previous value of the RCR (pre-loaded) */
+  uint8_t  curr;                    /* The current value of the RCR (pre-loaded) */
+  uint32_t count;                   /* Remaining pulse count */
+#endif
+  uint32_t frequency;               /* Current frequency setting */
+  uint32_t base;                    /* The base address of the timer */
+  uint32_t pclk;                    /* The frequency of the peripheral
+                                     * clock that drives the timer module
+                                     */
+#ifdef CONFIG_PWM_PULSECOUNT
+  void *handle;                     /* Handle used for upper-half callback */
 #endif
 };
 
@@ -216,29 +275,77 @@ struct stm32_pwmtimer_s
 
 /* Register access */
 
-static uint16_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset);
+static uint32_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset);
 static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset,
-                       uint16_t value);
+                       uint32_t value);
+static void pwm_modifyreg(struct stm32_pwmtimer_s *priv, uint32_t offset,
+                          uint32_t clearbits, uint32_t setbits);
 
 #ifdef CONFIG_DEBUG_PWM_INFO
-static void pwm_dumpregs(struct stm32_pwmtimer_s *priv, const char *msg);
+static void pwm_dumpregs(struct pwm_lowerhalf_s *dev,
+                         const char *msg);
 #else
 #  define pwm_dumpregs(priv,msg)
 #endif
 
 /* Timer management */
 
-static int pwm_timer(struct stm32_pwmtimer_s *priv,
-                     const struct pwm_info_s *info);
+static int pwm_frequency_update(struct pwm_lowerhalf_s *dev,
+                                uint32_t frequency);
+static int pwm_mode_configure(struct pwm_lowerhalf_s *dev,
+                              uint8_t channel, uint32_t mode);
+static int pwm_timer_configure(struct stm32_pwmtimer_s *priv);
+static int pwm_output_configure(struct stm32_pwmtimer_s *priv,
+                                struct stm32_pwmchan_s *chan);
+static int pwm_outputs_enable(struct pwm_lowerhalf_s *dev,
+                              uint16_t outputs, bool state);
+static int pwm_soft_update(struct pwm_lowerhalf_s *dev);
+static int pwm_soft_break(struct pwm_lowerhalf_s *dev, bool state);
+static int pwm_ccr_update(struct pwm_lowerhalf_s *dev, uint8_t index,
+                          uint32_t ccr);
+static int pwm_arr_update(struct pwm_lowerhalf_s *dev, uint32_t arr);
+static uint32_t pwm_arr_get(struct pwm_lowerhalf_s *dev);
+static int pwm_duty_update(struct pwm_lowerhalf_s *dev, uint8_t channel,
+                           ub16_t duty);
+static int pwm_timer_enable(struct pwm_lowerhalf_s *dev, bool state);
+
+#ifdef HAVE_ADVTIM
+static int pwm_break_dt_configure(struct stm32_pwmtimer_s *priv);
+#endif
+#ifdef HAVE_TRGO
+static int pwm_trgo_configure(struct pwm_lowerhalf_s *dev,
+                              uint8_t trgo);
+#endif
+#if defined(HAVE_PWM_COMPLEMENTARY) && defined(CONFIG_STM32F7_PWM_LL_OPS)
+static int pwm_deadtime_update(struct pwm_lowerhalf_s *dev, uint8_t dt);
+#endif
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+static uint32_t pwm_ccr_get(struct pwm_lowerhalf_s *dev, uint8_t index);
+static uint16_t pwm_rcr_get(struct pwm_lowerhalf_s *dev);
+#endif
+#ifdef HAVE_ADVTIM
+static int pwm_rcr_update(struct pwm_lowerhalf_s *dev, uint16_t rcr);
+#endif
 
-#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32F7_TIM1_PWM) || defined(CONFIG_STM32F7_TIM8_PWM))
-static int pwm_interrupt(struct stm32_pwmtimer_s *priv);
-#if defined(CONFIG_STM32F7_TIM1_PWM)
-static int pwm_tim1interrupt(int irq, void *context, void *arg);
+#ifdef CONFIG_PWM_PULSECOUNT
+static int pwm_pulsecount_configure(struct pwm_lowerhalf_s *dev);
+#else
+static int pwm_configure(struct pwm_lowerhalf_s *dev);
 #endif
-#if defined(CONFIG_STM32F7_TIM8_PWM)
-static int pwm_tim8interrupt(int irq, void *context, void *arg);
+#ifdef CONFIG_PWM_PULSECOUNT
+static int pwm_pulsecount_timer(struct pwm_lowerhalf_s *dev,
+                                const struct pwm_info_s *info);
 #endif
+static int pwm_timer(struct pwm_lowerhalf_s *dev,
+                     const struct pwm_info_s *info);
+#ifdef HAVE_PWM_INTERRUPT
+static int pwm_interrupt(struct pwm_lowerhalf_s *dev);
+#  ifdef CONFIG_STM32F7_TIM1_PWM
+static int pwm_tim1interrupt(int irq, void *context, void *arg);
+#  endif
+#  ifdef CONFIG_STM32F7_TIM8_PWM
+static int pwm_tim8interrupt(int irq, void *context, void *arg);
+#  endif
 static uint8_t pwm_pulsecount(uint32_t count);
 #endif
 
@@ -248,13 +355,12 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev);
 static int pwm_shutdown(struct pwm_lowerhalf_s *dev);
 
 #ifdef CONFIG_PWM_PULSECOUNT
-static int pwm_start(struct pwm_lowerhalf_s *dev,
-                     const struct pwm_info_s *info,
-                     void *handle);
-#else
+static int pwm_start_pulsecount(struct pwm_lowerhalf_s *dev,
+                                const struct pwm_info_s *info,
+                                void *handle);
+#endif
 static int pwm_start(struct pwm_lowerhalf_s *dev,
                      const struct pwm_info_s *info);
-#endif
 
 static int pwm_stop(struct pwm_lowerhalf_s *dev);
 static int pwm_ioctl(struct pwm_lowerhalf_s *dev,
@@ -272,677 +378,1195 @@ static const struct pwm_ops_s g_pwmops =
 {
   .setup       = pwm_setup,
   .shutdown    = pwm_shutdown,
+#ifdef CONFIG_PWM_PULSECOUNT
+  .start       = pwm_start_pulsecount,
+#else
   .start       = pwm_start,
+#endif
   .stop        = pwm_stop,
   .ioctl       = pwm_ioctl,
 };
 
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+static const struct stm32_pwm_ops_s g_llpwmops =
+{
+  .configure       = pwm_configure,
+  .soft_break      = pwm_soft_break,
+  .ccr_update      = pwm_ccr_update,
+  .mode_update     = pwm_mode_configure,
+  .ccr_get         = pwm_ccr_get,
+  .arr_update      = pwm_arr_update,
+  .arr_get         = pwm_arr_get,
+#ifdef HAVE_ADVTIM
+  .rcr_update      = pwm_rcr_update,
+#endif
+  .rcr_get         = pwm_rcr_get,
+#ifdef HAVE_TRGO
+  .trgo_set        = pwm_trgo_configure,
+#endif
+  .outputs_enable  = pwm_outputs_enable,
+  .soft_update     = pwm_soft_update,
+  .freq_update     = pwm_frequency_update,
+  .tim_enable      = pwm_timer_enable,
+#  ifdef CONFIG_DEBUG_PWM_INFO
+  .dump_regs       = pwm_dumpregs,
+#  endif
+#  ifdef HAVE_PWM_COMPLEMENTARY
+  .dt_update       = pwm_deadtime_update,
+#  endif
+};
+#endif
+
 #ifdef CONFIG_STM32F7_TIM1_PWM
-static struct stm32_pwmtimer_s g_pwm1dev =
+
+static struct stm32_pwmchan_s g_pwm1channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 1,
-  .channels    =
-  {
+  /* TIM1 has 4 channels, 4 complementary */
+
 #ifdef CONFIG_STM32F7_TIM1_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM1_CH1MODE,
+#ifdef HAVE_BREAK
+    .brk =
+    {
+#ifdef CONFIG_STM32F7_TIM1_BREAK1
+      .en1 = 1,
+      .pol1 = CONFIG_STM32F7_TIM1_BRK1POL,
+#endif
+#ifdef CONFIG_STM32F7_TIM1_BREAK2
+      .en2 = 1,
+      .pol2 = CONFIG_STM32F7_TIM1_BRK2POL,
+      .flt2 = CONFIG_STM32F7_TIM1_BRK2FLT,
+#endif
+    },
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CH1OUT
+    .out1 =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM1_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM1_CH1IDLE,
       .pincfg  = PWM_TIM1_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM1_CH1MODE,
     },
 #endif
+#ifdef CONFIG_STM32F7_TIM1_CH1NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM1_CH1NPOL,
+      .idle    = CONFIG_STM32F7_TIM1_CH1NIDLE,
+      .pincfg  = PWM_TIM1_CH1NCFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32F7_TIM1_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32F7_TIM1_CH2MODE,
+#ifdef CONFIG_STM32F7_TIM1_CH2OUT
+    .out1 =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM1_CH2POL,
+      .idle    = CONFIG_STM32F7_TIM1_CH2IDLE,
       .pincfg  = PWM_TIM1_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM1_CH2MODE,
     },
 #endif
+#ifdef CONFIG_STM32F7_TIM1_CH2NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM1_CH2NPOL,
+      .idle    = CONFIG_STM32F7_TIM1_CH2NIDLE,
+      .pincfg  = PWM_TIM1_CH2NCFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32F7_TIM1_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32F7_TIM1_CH3MODE,
+#ifdef CONFIG_STM32F7_TIM1_CH3OUT
+    .out1 =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM1_CH3POL,
+      .idle    = CONFIG_STM32F7_TIM1_CH3IDLE,
       .pincfg  = PWM_TIM1_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM1_CH3MODE,
     },
 #endif
+#ifdef CONFIG_STM32F7_TIM1_CH3NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM1_CH3NPOL,
+      .idle    = CONFIG_STM32F7_TIM1_CH3NIDLE,
+      .pincfg  = PWM_TIM1_CH3NCFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32F7_TIM1_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32F7_TIM1_CH4MODE,
+#ifdef CONFIG_STM32F7_TIM1_CH4OUT
+    .out1 =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM1_CH4POL,
+      .idle    = CONFIG_STM32F7_TIM1_CH4IDLE,
       .pincfg  = PWM_TIM1_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM1_CH4MODE,
-    },
+    }
+#endif
+  },
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CHANNEL5
+  {
+    .channel = 5,
+    .mode    = CONFIG_STM32F7_TIM1_CH5MODE,
+#ifdef CONFIG_STM32F7_TIM1_CH5OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM1_CH5POL,
+      .idle    = CONFIG_STM32F7_TIM1_CH5IDLE,
+      .pincfg  = 0,    /* Not available externally */
+    }
 #endif
   },
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CHANNEL6
+  {
+    .channel = 6,
+    .mode    = CONFIG_STM32F7_TIM1_CH6MODE,
+#ifdef CONFIG_STM32F7_TIM1_CH6OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM1_CH6POL,
+      .idle    = CONFIG_STM32F7_TIM1_CH6IDLE,
+      .pincfg  = 0,    /* Not available externally */
+    }
+#endif
+  }
+#endif
+};
+
+static struct stm32_pwmtimer_s g_pwm1dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 1,
+  .chan_num    = PWM_TIM1_NCHANNELS,
+  .channels    = g_pwm1channels,
   .timtype     = TIMTYPE_TIM1,
   .mode        = CONFIG_STM32F7_TIM1_MODE,
+  .lock        = CONFIG_STM32F7_TIM1_LOCK,
+  .t_dts       = CONFIG_STM32F7_TIM1_TDTS,
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = CONFIG_STM32F7_TIM1_DEADTIME,
+#endif
+#if defined(HAVE_TRGO) && defined(STM32_TIM1_TRGO)
+  .trgo        = STM32_TIM1_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM1UP,
 #endif
   .base        = STM32_TIM1_BASE,
   .pclk        = TIMCLK_TIM1,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM1_PWM */
 
 #ifdef CONFIG_STM32F7_TIM2_PWM
-static struct stm32_pwmtimer_s g_pwm2dev =
+
+static struct stm32_pwmchan_s g_pwm2channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 2,
-  .channels    =
-  {
+  /* TIM2 has 4 channels */
+
 #ifdef CONFIG_STM32F7_TIM2_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM2_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM2_CH1OUT
+    .out1 =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM2_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM2_CH1IDLE,
       .pincfg  = PWM_TIM2_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM2_CH1MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM2_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32F7_TIM2_CH2MODE,
+#ifdef CONFIG_STM32F7_TIM2_CH2OUT
+    .out1 =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM2_CH2POL,
+      .idle    = CONFIG_STM32F7_TIM2_CH2IDLE,
       .pincfg  = PWM_TIM2_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM2_CH2MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM2_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32F7_TIM2_CH3MODE,
+#ifdef CONFIG_STM32F7_TIM2_CH3OUT
+    .out1 =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM2_CH3POL,
+      .idle    = CONFIG_STM32F7_TIM2_CH3IDLE,
       .pincfg  = PWM_TIM2_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM2_CH3MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM2_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32F7_TIM2_CH4MODE,
+#ifdef CONFIG_STM32F7_TIM2_CH4OUT
+    .out1 =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM2_CH4POL,
+      .idle    = CONFIG_STM32F7_TIM2_CH4IDLE,
       .pincfg  = PWM_TIM2_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM2_CH4MODE,
-    },
+    }
 #endif
-  },
+    /* No complementary outputs */
+  }
+#endif
+};
+
+static struct stm32_pwmtimer_s g_pwm2dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 2,
+  .chan_num    = PWM_TIM2_NCHANNELS,
+  .channels    = g_pwm2channels,
   .timtype     = TIMTYPE_TIM2,
   .mode        = CONFIG_STM32F7_TIM2_MODE,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO) && defined(STM32_TIM2_TRGO)
+  .trgo        = STM32_TIM2_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM2,
 #endif
   .base        = STM32_TIM2_BASE,
   .pclk        = TIMCLK_TIM2,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM2_PWM */
 
 #ifdef CONFIG_STM32F7_TIM3_PWM
-static struct stm32_pwmtimer_s g_pwm3dev =
+
+static struct stm32_pwmchan_s g_pwm3channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 3,
-  .channels    =
-  {
+  /* TIM3 has 4 channels */
+
 #ifdef CONFIG_STM32F7_TIM3_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM3_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM3_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM3_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM3_CH1IDLE,
       .pincfg  = PWM_TIM3_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM3_CH1MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM3_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32F7_TIM3_CH2MODE,
+#ifdef CONFIG_STM32F7_TIM3_CH2OUT
+    .out1    =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM3_CH2POL,
+      .idle    = CONFIG_STM32F7_TIM3_CH2IDLE,
       .pincfg  = PWM_TIM3_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM3_CH2MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM3_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32F7_TIM3_CH3MODE,
+#ifdef CONFIG_STM32F7_TIM3_CH3OUT
+    .out1    =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM3_CH3POL,
+      .idle    = CONFIG_STM32F7_TIM3_CH3IDLE,
       .pincfg  = PWM_TIM3_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM3_CH3MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM3_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32F7_TIM3_CH4MODE,
+#ifdef CONFIG_STM32F7_TIM3_CH4OUT
+    .out1    =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM3_CH4POL,
+      .idle    = CONFIG_STM32F7_TIM3_CH4IDLE,
       .pincfg  = PWM_TIM3_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM3_CH4MODE,
-    },
+    }
 #endif
-  },
+    /* No complementary outputs */
+  }
+#endif
+};
+
+static struct stm32_pwmtimer_s g_pwm3dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 3,
+  .chan_num    = PWM_TIM3_NCHANNELS,
+  .channels    = g_pwm3channels,
   .timtype     = TIMTYPE_TIM3,
   .mode        = CONFIG_STM32F7_TIM3_MODE,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO) && defined(STM32_TIM3_TRGO)
+  .trgo        = STM32_TIM3_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM3,
 #endif
   .base        = STM32_TIM3_BASE,
   .pclk        = TIMCLK_TIM3,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM3_PWM */
 
 #ifdef CONFIG_STM32F7_TIM4_PWM
-static struct stm32_pwmtimer_s g_pwm4dev =
+
+static struct stm32_pwmchan_s g_pwm4channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 4,
-  .channels    =
-  {
+  /* TIM4 has 4 channels */
+
 #ifdef CONFIG_STM32F7_TIM4_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM4_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM4_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM4_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM4_CH1IDLE,
       .pincfg  = PWM_TIM4_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM4_CH1MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM4_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32F7_TIM4_CH2MODE,
+#ifdef CONFIG_STM32F7_TIM4_CH2OUT
+    .out1    =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM4_CH2POL,
+      .idle    = CONFIG_STM32F7_TIM4_CH2IDLE,
       .pincfg  = PWM_TIM4_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM4_CH2MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM4_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32F7_TIM4_CH3MODE,
+#ifdef CONFIG_STM32F7_TIM4_CH3OUT
+    .out1    =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM4_CH3POL,
+      .idle    = CONFIG_STM32F7_TIM4_CH3IDLE,
       .pincfg  = PWM_TIM4_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM4_CH3MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM4_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32F7_TIM4_CH4MODE,
+#ifdef CONFIG_STM32F7_TIM4_CH4OUT
+    .out1    =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM4_CH4POL,
+      .idle    = CONFIG_STM32F7_TIM4_CH4IDLE,
       .pincfg  = PWM_TIM4_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM4_CH4MODE,
-    },
+    }
 #endif
-  },
+    /* No complementary outputs */
+  }
+#endif
+};
+
+static struct stm32_pwmtimer_s g_pwm4dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 4,
+  .chan_num    = PWM_TIM4_NCHANNELS,
+  .channels    = g_pwm4channels,
   .timtype     = TIMTYPE_TIM4,
   .mode        = CONFIG_STM32F7_TIM4_MODE,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO) && defined(STM32_TIM4_TRGO)
+  .trgo        = STM32_TIM4_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM4,
 #endif
   .base        = STM32_TIM4_BASE,
   .pclk        = TIMCLK_TIM4,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM4_PWM */
 
 #ifdef CONFIG_STM32F7_TIM5_PWM
-static struct stm32_pwmtimer_s g_pwm5dev =
+
+static struct stm32_pwmchan_s g_pwm5channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 5,
-  .channels    =
-  {
+  /* TIM5 has 4 channels */
+
 #ifdef CONFIG_STM32F7_TIM5_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM5_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM5_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM5_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM5_CH1IDLE,
       .pincfg  = PWM_TIM5_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM5_CH1MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM5_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32F7_TIM5_CH2MODE,
+#ifdef CONFIG_STM32F7_TIM5_CH2OUT
+    .out1    =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM5_CH2POL,
+      .idle    = CONFIG_STM32F7_TIM5_CH2IDLE,
       .pincfg  = PWM_TIM5_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM5_CH2MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM5_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32F7_TIM5_CH3MODE,
+#ifdef CONFIG_STM32F7_TIM5_CH3OUT
+    .out1    =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM5_CH3POL,
+      .idle    = CONFIG_STM32F7_TIM5_CH3IDLE,
       .pincfg  = PWM_TIM5_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM5_CH3MODE,
-    },
+    }
+#endif
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM5_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32F7_TIM5_CH4MODE,
+#ifdef CONFIG_STM32F7_TIM5_CH4OUT
+    .out1    =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM5_CH4POL,
+      .idle    = CONFIG_STM32F7_TIM5_CH4IDLE,
       .pincfg  = PWM_TIM5_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM5_CH4MODE,
-    },
+    }
 #endif
   },
+#endif
+};
+
+static struct stm32_pwmtimer_s g_pwm5dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 5,
+  .chan_num    = PWM_TIM5_NCHANNELS,
+  .channels    = g_pwm5channels,
   .timtype     = TIMTYPE_TIM5,
   .mode        = CONFIG_STM32F7_TIM5_MODE,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO) && defined(STM32_TIM5_TRGO)
+  .trgo        = STM32_TIM5_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM5,
 #endif
   .base        = STM32_TIM5_BASE,
   .pclk        = TIMCLK_TIM5,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM5_PWM */
 
 #ifdef CONFIG_STM32F7_TIM8_PWM
-static struct stm32_pwmtimer_s g_pwm8dev =
+
+static struct stm32_pwmchan_s g_pwm8channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 8,
-  .channels    =
-  {
+  /* TIM8 has 4 channels, 4 complementary */
+
 #ifdef CONFIG_STM32F7_TIM8_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM8_CH1MODE,
+#ifdef HAVE_BREAK
+    .brk =
     {
-      .channel = 1,
+#ifdef CONFIG_STM32F7_TIM8_BREAK1
+      .en1 = 1,
+      .pol1 = CONFIG_STM32F7_TIM8_BRK1POL,
+#endif
+#ifdef CONFIG_STM32F7_TIM8_BREAK2
+      .en2 = 1,
+      .pol2 = CONFIG_STM32F7_TIM8_BRK2POL,
+      .flt2 = CONFIG_STM32F7_TIM8_BRK2FLT,
+#endif
+    },
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CH1OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM8_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM8_CH1IDLE,
       .pincfg  = PWM_TIM8_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM8_CH1MODE,
     },
 #endif
+#ifdef CONFIG_STM32F7_TIM8_CH1NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM8_CH1NPOL,
+      .idle    = CONFIG_STM32F7_TIM8_CH1NIDLE,
+      .pincfg  = PWM_TIM8_CH1NCFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32F7_TIM8_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32F7_TIM8_CH2MODE,
+#ifdef CONFIG_STM32F7_TIM8_CH2OUT
+    .out1 =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM8_CH2POL,
+      .idle    = CONFIG_STM32F7_TIM8_CH2IDLE,
       .pincfg  = PWM_TIM8_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM8_CH2MODE,
     },
 #endif
+#ifdef CONFIG_STM32F7_TIM8_CH2NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM8_CH2NPOL,
+      .idle    = CONFIG_STM32F7_TIM8_CH2NIDLE,
+      .pincfg  = PWM_TIM8_CH2NCFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32F7_TIM8_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32F7_TIM8_CH3MODE,
+#ifdef CONFIG_STM32F7_TIM8_CH3OUT
+    .out1 =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM8_CH3POL,
+      .idle    = CONFIG_STM32F7_TIM8_CH3IDLE,
       .pincfg  = PWM_TIM8_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM8_CH3MODE,
     },
 #endif
+#ifdef CONFIG_STM32F7_TIM8_CH3NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM8_CH3NPOL,
+      .idle    = CONFIG_STM32F7_TIM8_CH3NIDLE,
+      .pincfg  = PWM_TIM8_CH3NCFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32F7_TIM8_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32F7_TIM8_CH4MODE,
+#ifdef CONFIG_STM32F7_TIM8_CH4OUT
+    .out1 =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM8_CH4POL,
+      .idle    = CONFIG_STM32F7_TIM8_CH4IDLE,
       .pincfg  = PWM_TIM8_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM8_CH4MODE,
-    },
+    }
+#endif
+  },
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CHANNEL5
+  {
+    .channel = 5,
+    .mode    = CONFIG_STM32F7_TIM8_CH5MODE,
+#ifdef CONFIG_STM32F7_TIM8_CH5OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM8_CH5POL,
+      .idle    = CONFIG_STM32F7_TIM8_CH5IDLE,
+      .pincfg  = 0,    /* Not available externally */
+    }
 #endif
   },
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CHANNEL6
+  {
+    .channel = 6,
+    .mode    = CONFIG_STM32F7_TIM8_CH6MODE,
+#ifdef CONFIG_STM32F7_TIM8_CH6OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM8_CH6POL,
+      .idle    = CONFIG_STM32F7_TIM8_CH6IDLE,
+      .pincfg  = 0,    /* Not available externally */
+    }
+#endif
+  }
+#endif
+};
+
+static struct stm32_pwmtimer_s g_pwm8dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 8,
+  .chan_num    = PWM_TIM8_NCHANNELS,
+  .channels    = g_pwm8channels,
   .timtype     = TIMTYPE_TIM8,
   .mode        = CONFIG_STM32F7_TIM8_MODE,
+  .lock        = CONFIG_STM32F7_TIM8_LOCK,
+  .t_dts       = CONFIG_STM32F7_TIM8_TDTS,
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = CONFIG_STM32F7_TIM8_DEADTIME,
+#endif
+#if defined(HAVE_TRGO) && defined(STM32_TIM8_TRGO)
+  .trgo        = STM32_TIM8_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM8UP,
 #endif
   .base        = STM32_TIM8_BASE,
   .pclk        = TIMCLK_TIM8,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM8_PWM */
 
 #ifdef CONFIG_STM32F7_TIM9_PWM
-static struct stm32_pwmtimer_s g_pwm9dev =
+
+static struct stm32_pwmchan_s g_pwm9channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 9,
-  .channels    =
-  {
+  /* TIM9 has 2 channels */
+
 #ifdef CONFIG_STM32F7_TIM9_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM9_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM9_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM9_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM9_CH1IDLE,
       .pincfg  = PWM_TIM9_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM9_CH1MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM9_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32F7_TIM9_CH2MODE,
+#ifdef CONFIG_STM32F7_TIM9_CH2OUT
+    .out1    =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM9_CH2POL,
+      .idle    = CONFIG_STM32F7_TIM9_CH2IDLE,
       .pincfg  = PWM_TIM9_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM9_CH2MODE,
-    },
+    }
 #endif
-#ifdef CONFIG_STM32F7_TIM9_CHANNEL3
-    {
-      .channel = 3,
-      .pincfg  = PWM_TIM9_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM9_CH3MODE,
-    },
+    /* No complementary outputs */
+  }
 #endif
-#ifdef CONFIG_STM32F7_TIM9_CHANNEL4
-    {
-      .channel = 4,
-      .pincfg  = PWM_TIM9_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM9_CH4MODE,
-    },
+};
+
+static struct stm32_pwmtimer_s g_pwm9dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
 #endif
-  },
+  .timid       = 9,
+  .chan_num    = PWM_TIM9_NCHANNELS,
+  .channels    = g_pwm9channels,
   .timtype     = TIMTYPE_TIM9,
   .mode        = STM32_TIMMODE_COUNTUP,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for TIM9 */
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM9,
 #endif
   .base        = STM32_TIM9_BASE,
   .pclk        = TIMCLK_TIM9,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM9_PWM */
 
 #ifdef CONFIG_STM32F7_TIM10_PWM
-static struct stm32_pwmtimer_s g_pwm10dev =
+
+static struct stm32_pwmchan_s g_pwm10channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 10,
-  .channels    =
-  {
+  /* TIM10 has 1 channel */
+
 #ifdef CONFIG_STM32F7_TIM10_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM10_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM10_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM10_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM10_CH1IDLE,
       .pincfg  = PWM_TIM10_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM10_CH1MODE,
-    },
-#endif
-#ifdef CONFIG_STM32F7_TIM10_CHANNEL2
-    {
-      .channel = 2,
-      .pincfg  = PWM_TIM10_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM10_CH2MODE,
-    },
+    }
 #endif
-#ifdef CONFIG_STM32F7_TIM10_CHANNEL3
-    {
-      .channel = 3,
-      .pincfg  = PWM_TIM10_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM10_CH3MODE,
-    },
+    /* No complementary outputs */
+  }
 #endif
-#ifdef CONFIG_STM32F7_TIM10_CHANNEL4
-    {
-      .channel = 4,
-      .pincfg  = PWM_TIM10_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM10_CH4MODE,
-    },
+};
+
+static struct stm32_pwmtimer_s g_pwm10dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
 #endif
-  },
+  .timid       = 10,
+  .chan_num    = PWM_TIM10_NCHANNELS,
+  .channels    = g_pwm10channels,
   .timtype     = TIMTYPE_TIM10,
   .mode        = STM32_TIMMODE_COUNTUP,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for TIM10 */
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM10,
 #endif
   .base        = STM32_TIM10_BASE,
   .pclk        = TIMCLK_TIM10,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM10_PWM */
 
 #ifdef CONFIG_STM32F7_TIM11_PWM
-static struct stm32_pwmtimer_s g_pwm11dev =
+
+static struct stm32_pwmchan_s g_pwm11channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 11,
-  .channels    =
-  {
+  /* TIM11 has 1 channel */
+
 #ifdef CONFIG_STM32F7_TIM11_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM11_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM11_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM11_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM11_CH1IDLE,
       .pincfg  = PWM_TIM11_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM11_CH1MODE,
-    },
-#endif
-#ifdef CONFIG_STM32F7_TIM11_CHANNEL2
-    {
-      .channel = 2,
-      .pincfg  = PWM_TIM11_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM11_CH2MODE,
-    },
+    }
 #endif
-#ifdef CONFIG_STM32F7_TIM11_CHANNEL3
-    {
-      .channel = 3,
-      .pincfg  = PWM_TIM11_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM11_CH3MODE,
-    },
+    /* No complementary outputs */
+  }
 #endif
-#ifdef CONFIG_STM32F7_TIM11_CHANNEL4
-    {
-      .channel = 4,
-      .pincfg  = PWM_TIM11_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM11_CH4MODE,
-    },
+};
+
+static struct stm32_pwmtimer_s g_pwm11dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
 #endif
-  },
+  .timid       = 11,
+  .chan_num    = PWM_TIM11_NCHANNELS,
+  .channels    = g_pwm11channels,
   .timtype     = TIMTYPE_TIM11,
   .mode        = STM32_TIMMODE_COUNTUP,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for TIM11 */
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM11,
 #endif
   .base        = STM32_TIM11_BASE,
   .pclk        = TIMCLK_TIM11,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM11_PWM */
 
 #ifdef CONFIG_STM32F7_TIM12_PWM
-static struct stm32_pwmtimer_s g_pwm12dev =
+
+static struct stm32_pwmchan_s g_pwm12channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 12,
-  .channels    =
-  {
+  /* TIM12 has 2 channels */
+
 #ifdef CONFIG_STM32F7_TIM12_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM12_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM12_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM12_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM12_CH1IDLE,
       .pincfg  = PWM_TIM12_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM12_CH1MODE,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32F7_TIM12_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32F7_TIM12_CH2MODE,
+#ifdef CONFIG_STM32F7_TIM12_CH2OUT
+    .out1    =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM12_CH2POL,
+      .idle    = CONFIG_STM32F7_TIM12_CH2IDLE,
       .pincfg  = PWM_TIM12_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM12_CH2MODE,
-    },
+    }
 #endif
-#ifdef CONFIG_STM32F7_TIM12_CHANNEL3
-    {
-      .channel = 3,
-      .pincfg  = PWM_TIM12_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM12_CH3MODE,
-    },
+    /* No complementary outputs */
+  }
 #endif
-#ifdef CONFIG_STM32F7_TIM12_CHANNEL4
-    {
-      .channel = 4,
-      .pincfg  = PWM_TIM12_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM12_CH4MODE,
-    },
+};
+
+static struct stm32_pwmtimer_s g_pwm12dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
 #endif
-  },
+  .timid       = 12,
+  .chan_num    = PWM_TIM12_NCHANNELS,
+  .channels    = g_pwm12channels,
   .timtype     = TIMTYPE_TIM12,
   .mode        = STM32_TIMMODE_COUNTUP,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for TIM12 */
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM12,
 #endif
   .base        = STM32_TIM12_BASE,
   .pclk        = TIMCLK_TIM12,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM12_PWM */
 
 #ifdef CONFIG_STM32F7_TIM13_PWM
-static struct stm32_pwmtimer_s g_pwm13dev =
+
+static struct stm32_pwmchan_s g_pwm13channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 13,
-  .channels    =
-  {
+  /* TIM13 has 1 channel */
+
 #ifdef CONFIG_STM32F7_TIM13_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM13_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM13_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM13_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM13_CH1IDLE,
       .pincfg  = PWM_TIM13_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM13_CH1MODE,
-    },
-#endif
-#ifdef CONFIG_STM32F7_TIM13_CHANNEL2
-    {
-      .channel = 2,
-      .pincfg  = PWM_TIM13_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM13_CH2MODE,
-    },
+    }
 #endif
-#ifdef CONFIG_STM32F7_TIM13_CHANNEL3
-    {
-      .channel = 3,
-      .pincfg  = PWM_TIM13_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM13_CH3MODE,
-    },
+    /* No complementary outputs */
+  }
 #endif
-#ifdef CONFIG_STM32F7_TIM13_CHANNEL4
-    {
-      .channel = 4,
-      .pincfg  = PWM_TIM13_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM13_CH4MODE,
-    },
+};
+
+static struct stm32_pwmtimer_s g_pwm13dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
 #endif
-  },
+  .timid       = 13,
+  .chan_num    = PWM_TIM13_NCHANNELS,
+  .channels    = g_pwm13channels,
   .timtype     = TIMTYPE_TIM13,
   .mode        = STM32_TIMMODE_COUNTUP,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for TIM13 */
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32_IRQ_TIM13,
 #endif
   .base        = STM32_TIM13_BASE,
   .pclk        = TIMCLK_TIM13,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM13_PWM */
 
 #ifdef CONFIG_STM32F7_TIM14_PWM
-static struct stm32_pwmtimer_s g_pwm14dev =
-{
-  .ops         = &g_pwmops,
-  .timid       = 14,
-  .channels    =
-  {
-#ifdef CONFIG_STM32F7_TIM14_CHANNEL1
-    {
-      .channel = 1,
-      .pincfg  = PWM_TIM14_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM14_CH1MODE,
-    },
-#endif
-#ifdef CONFIG_STM32F7_TIM14_CHANNEL2
-    {
-      .channel = 2,
-      .pincfg  = PWM_TIM14_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM14_CH2MODE,
-    },
-#endif
-#ifdef CONFIG_STM32F7_TIM14_CHANNEL3
-    {
-      .channel = 3,
-      .pincfg  = PWM_TIM14_CH3CFG,
-      .mode    = CONFIG_STM32F7_TIM14_CH3MODE,
-    },
-#endif
-#ifdef CONFIG_STM32F7_TIM14_CHANNEL4
-    {
-      .channel = 4,
-      .pincfg  = PWM_TIM14_CH4CFG,
-      .mode    = CONFIG_STM32F7_TIM14_CH4MODE,
-    },
-#endif
-  },
-  .timtype     = TIMTYPE_TIM14,
-  .mode        = STM32_TIMMODE_COUNTUP,
-#ifdef CONFIG_PWM_PULSECOUNT
-  .irq         = STM32_IRQ_TIM14,
-#endif
-  .base        = STM32_TIM14_BASE,
-  .pclk        = TIMCLK_TIM14,
-};
-#endif
 
-#ifdef CONFIG_STM32F7_TIM15_PWM
-static struct stm32_pwmtimer_s g_pwm15dev =
+static struct stm32_pwmchan_s g_pwm14channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 15,
-  .channels    =
+  /* TIM14 has 1 channel */
+
+#ifdef CONFIG_STM32F7_TIM14_CHANNEL1
   {
-#ifdef CONFIG_STM32F7_TIM15_CHANNEL1
-    {
-      .channel = 1,
-      .pincfg  = PWM_TIM15_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM15_CH1MODE,
-    },
-#endif
-#ifdef CONFIG_STM32F7_TIM15_CHANNEL2
+    .channel = 1,
+    .mode    = CONFIG_STM32F7_TIM14_CH1MODE,
+#ifdef CONFIG_STM32F7_TIM14_CH1OUT
+    .out1    =
     {
-      .channel = 2,
-      .pincfg  = PWM_TIM15_CH2CFG,
-      .mode    = CONFIG_STM32F7_TIM15_CH2MODE,
-    },
+      .in_use  = 1,
+      .pol     = CONFIG_STM32F7_TIM14_CH1POL,
+      .idle    = CONFIG_STM32F7_TIM14_CH1IDLE,
+      .pincfg  = PWM_TIM14_CH1CFG,
+    }
 #endif
-  },
-  .timtype     = TIMTYPE_TIM15,
-  .mode        = STM32_TIMMODE_COUNTUP,
-#ifdef CONFIG_PWM_PULSECOUNT
-  .irq         = STM32_IRQ_TIM15,
+    /* No complementary outputs */
+  }
 #endif
-  .base        = STM32_TIM15_BASE,
-  .pclk        = TIMCLK_TIM15,
 };
-#endif
 
-#ifdef CONFIG_STM32F7_TIM16_PWM
-static struct stm32_pwmtimer_s g_pwm16dev =
+static struct stm32_pwmtimer_s g_pwm14dev =
 {
   .ops         = &g_pwmops,
-  .timid       = 16,
-  .channels    =
-  {
-#ifdef CONFIG_STM32F7_TIM16_CHANNEL1
-    {
-      .channel = 1,
-      .pincfg  = PWM_TIM16_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM16_CH1MODE,
-    },
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+  .llops       = &g_llpwmops,
 #endif
-  },
-  .timtype     = TIMTYPE_TIM16,
+  .timid       = 14,
+  .chan_num    = PWM_TIM14_NCHANNELS,
+  .channels    = g_pwm14channels,
+  .timtype     = TIMTYPE_TIM14,
   .mode        = STM32_TIMMODE_COUNTUP,
-#ifdef CONFIG_PWM_PULSECOUNT
-  .irq         = STM32_IRQ_TIM16,
-#endif
-  .base        = STM32_TIM16_BASE,
-  .pclk        = TIMCLK_TIM16,
-};
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
 #endif
-
-#ifdef CONFIG_STM32F7_TIM17_PWM
-static struct stm32_pwmtimer_s g_pwm17dev =
-{
-  .ops         = &g_pwmops,
-  .timid       = 17,
-  .channels    =
-  {
-#ifdef CONFIG_STM32F7_TIM17_CHANNEL1
-    {
-      .channel = 1,
-      .pincfg  = PWM_TIM17_CH1CFG,
-      .mode    = CONFIG_STM32F7_TIM17_CH1MODE,
-    },
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for TIM14 */
 #endif
-  },
-  .timtype     = TIMTYPE_TIM17,
-  .mode        = STM32_TIMMODE_COUNTUP,
 #ifdef CONFIG_PWM_PULSECOUNT
-  .irq         = STM32_IRQ_TIM17,
+  .irq         = STM32_IRQ_TIM14,
 #endif
-  .base        = STM32_TIM17_BASE,
-  .pclk        = TIMCLK_TIM17,
+  .base        = STM32_TIM14_BASE,
+  .pclk        = TIMCLK_TIM14,
 };
-#endif
+#endif /* CONFIG_STM32F7_TIM14_PWM */
 
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pwm_getreg
- *
- * Description:
- *   Read the value of an PWM timer register.
- *
- * Input Parameters:
- *   priv - A reference to the PWM block status
- *   offset - The offset to the register to read
- *
- * Returned Value:
- *   The current contents of the specified register
- *
+ * Name: pwm_reg_is_32bit
  ****************************************************************************/
 
-static uint16_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset)
+static bool pwm_reg_is_32bit(uint8_t timtype, uint32_t offset)
 {
-  return getreg16(priv->base + offset);
+  bool ret = false;
+
+  if (timtype == TIMTYPE_GENERAL32)
+    {
+      if (offset == STM32_GTIM_CNT_OFFSET ||
+          offset == STM32_GTIM_ARR_OFFSET ||
+          offset == STM32_GTIM_CCR1_OFFSET ||
+          offset == STM32_GTIM_CCR2_OFFSET ||
+          offset == STM32_GTIM_CCR3_OFFSET ||
+          offset == STM32_GTIM_CCR4_OFFSET)
+        {
+          ret = true;
+        }
+    }
+  else if (timtype == TIMTYPE_ADVANCED)
+    {
+      if (offset == STM32_ATIM_CR2_OFFSET ||
+          offset == STM32_ATIM_CCMR1_OFFSET ||
+          offset == STM32_ATIM_CCMR2_OFFSET ||
+          offset == STM32_ATIM_CCER_OFFSET ||
+          offset == STM32_ATIM_BDTR_OFFSET ||
+          offset == STM32_ATIM_CCMR3_OFFSET ||
+          offset == STM32_ATIM_CCR5_OFFSET)
+        {
+          ret = true;
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: pwm_getreg
+ *
+ * Description:
+ *   Read the value of an PWM timer register
+ *
+ * Input Parameters:
+ *   priv   - A reference to the PWM block status
+ *   offset - The offset to the register to read
+ *
+ * Returned Value:
+ *   The current contents of the specified register
+ *
+ ****************************************************************************/
+
+static uint32_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset)
+{
+  uint32_t retval = 0;
+
+  if (pwm_reg_is_32bit(priv->timtype, offset) == true)
+    {
+      /* 32-bit register */
+
+      retval = getreg32(priv->base + offset);
+    }
+  else
+    {
+      /* 16-bit register */
+
+      retval = getreg16(priv->base + offset);
+    }
+
+  /* Return 32-bit value */
+
+  return retval;
 }
 
 /****************************************************************************
  * Name: pwm_putreg
  *
  * Description:
- *   Read the value of an PWM timer register.
+ *   Read the value of an PWM timer register
  *
  * Input Parameters:
- *   priv - A reference to the PWM block status
+ *   priv   - A reference to the PWM block status
  *   offset - The offset to the register to read
  *
  * Returned Value:
@@ -951,27 +1575,54 @@ static uint16_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset)
  ****************************************************************************/
 
 static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset,
-                       uint16_t value)
-{
-  if (priv->timtype == TIMTYPE_GENERAL32 &&
-      (offset == STM32_GTIM_CNT_OFFSET ||
-       offset == STM32_GTIM_ARR_OFFSET ||
-       offset == STM32_GTIM_CCR1_OFFSET ||
-       offset == STM32_GTIM_CCR2_OFFSET ||
-       offset == STM32_GTIM_CCR3_OFFSET ||
-       offset == STM32_GTIM_CCR4_OFFSET))
-    {
-      /* a 32 bit access is required for a 32 bit register:
-       * if only a 16 bit write would be performed, then the
-       * upper 16 bits of the 32 bit register will be a copy of
-       * the lower 16 bits.
-       */
+                       uint32_t value)
+{
+  if (pwm_reg_is_32bit(priv->timtype, offset) == true)
+    {
+      /* 32-bit register */
 
       putreg32(value, priv->base + offset);
     }
   else
     {
-      putreg16(value, priv->base + offset);
+      /* 16-bit register */
+
+      putreg16((uint16_t)value, priv->base + offset);
+    }
+}
+
+/****************************************************************************
+ * Name: pwm_modifyreg
+ *
+ * Description:
+ *   Modify PWM register (32-bit or 16-bit)
+ *
+ * Input Parameters:
+ *   priv    - A reference to the PWM block status
+ *   offset  - The offset to the register to read
+ *   clrbits - The bits to clear
+ *   setbits - The bits to set
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void pwm_modifyreg(struct stm32_pwmtimer_s *priv, uint32_t offset,
+                            uint32_t clearbits, uint32_t setbits)
+{
+  if (pwm_reg_is_32bit(priv->timtype, offset) == true)
+    {
+      /* 32-bit register */
+
+      modifyreg32(priv->base + offset, clearbits, setbits);
+    }
+  else
+    {
+      /* 16-bit register */
+
+      modifyreg16(priv->base + offset, (uint16_t)clearbits,
+                  (uint16_t)setbits);
     }
 }
 
@@ -982,7 +1633,7 @@ static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset,
  *   Dump all timer registers.
  *
  * Input Parameters:
- *   priv - A reference to the PWM block status
+ *   dev - A reference to the lower half PWM driver state structure
  *
  * Returned Value:
  *   None
@@ -990,8 +1641,10 @@ static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset,
  ****************************************************************************/
 
 #ifdef CONFIG_DEBUG_PWM_INFO
-static void pwm_dumpregs(struct stm32_pwmtimer_s *priv, const char *msg)
+static void pwm_dumpregs(struct pwm_lowerhalf_s *dev, const char *msg)
 {
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+
   pwminfo("%s:\n", msg);
   if (priv->timid == 16 || priv->timid == 17)
     {
@@ -1009,21 +1662,11 @@ static void pwm_dumpregs(struct stm32_pwmtimer_s *priv, const char *msg)
               pwm_getreg(priv, STM32_GTIM_DIER_OFFSET));
     }
 
-  if (priv->timid >= 15 || priv->timid <= 17)
-    {
-      pwminfo("   SR: %04x EGR:  %04x CCMR1: %04x\n",
-              pwm_getreg(priv, STM32_GTIM_SR_OFFSET),
-              pwm_getreg(priv, STM32_GTIM_EGR_OFFSET),
-              pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET));
-    }
-  else
-    {
-      pwminfo("   SR: %04x EGR:  %04x CCMR1: %04x CCMR2: %04x\n",
-              pwm_getreg(priv, STM32_GTIM_SR_OFFSET),
-              pwm_getreg(priv, STM32_GTIM_EGR_OFFSET),
-              pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET),
-              pwm_getreg(priv, STM32_GTIM_CCMR2_OFFSET));
-    }
+  pwminfo("   SR: %04x EGR:  %04x CCMR1: %04x CCMR2: %04x\n",
+          pwm_getreg(priv, STM32_GTIM_SR_OFFSET),
+          pwm_getreg(priv, STM32_GTIM_EGR_OFFSET),
+          pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET),
+          pwm_getreg(priv, STM32_GTIM_CCMR2_OFFSET));
 
   /* REVISIT: CNT and ARR may be 32-bits wide */
 
@@ -1033,688 +1676,1690 @@ static void pwm_dumpregs(struct stm32_pwmtimer_s *priv, const char *msg)
           pwm_getreg(priv, STM32_GTIM_PSC_OFFSET),
           pwm_getreg(priv, STM32_GTIM_ARR_OFFSET));
 
-  if (priv->timid >= 15 || priv->timid <= 17)
+  if (priv->timid == 1 || priv->timid == 8)
     {
       pwminfo("  RCR: %04x BDTR: %04x\n",
           pwm_getreg(priv, STM32_ATIM_RCR_OFFSET),
           pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET));
     }
 
-  /* REVISIT: CCR1-CCR4 may be 32-bits wide */
-
-  if (priv->timid == 16 || priv->timid == 17)
-    {
-      pwminfo(" CCR1: %04x\n",
-              pwm_getreg(priv, STM32_GTIM_CCR1_OFFSET));
-    }
-  else
-    {
-      pwminfo(" CCR1: %04x CCR2: %04x CCR3:  %04x CCR4:  %04x\n",
-              pwm_getreg(priv, STM32_GTIM_CCR1_OFFSET),
-              pwm_getreg(priv, STM32_GTIM_CCR2_OFFSET),
-              pwm_getreg(priv, STM32_GTIM_CCR3_OFFSET),
-              pwm_getreg(priv, STM32_GTIM_CCR4_OFFSET));
-    }
+  pwminfo(" CCR1: %04x CCR2: %04x CCR3:  %04x CCR4:  %04x\n",
+          pwm_getreg(priv, STM32_GTIM_CCR1_OFFSET),
+          pwm_getreg(priv, STM32_GTIM_CCR2_OFFSET),
+          pwm_getreg(priv, STM32_GTIM_CCR3_OFFSET),
+          pwm_getreg(priv, STM32_GTIM_CCR4_OFFSET));
 
   pwminfo("  DCR: %04x DMAR: %04x\n",
       pwm_getreg(priv, STM32_GTIM_DCR_OFFSET),
       pwm_getreg(priv, STM32_GTIM_DMAR_OFFSET));
+
+  if (priv->timtype == TIMTYPE_ADVANCED)
+    {
+      pwminfo("  CCMR3: %04x CCR5: %04x CCR6: %04x\n",
+              pwm_getreg(priv, STM32_ATIM_CCMR3_OFFSET),
+              pwm_getreg(priv, STM32_ATIM_CCR5_OFFSET),
+              pwm_getreg(priv, STM32_ATIM_CCR6_OFFSET));
+    }
 }
 #endif
 
 /****************************************************************************
- * Name: pwm_timer
- *
- * Description:
- *   (Re-)initialize the timer resources and start the pulsed output
- *
- * Input Parameters:
- *   priv - A reference to the lower half PWM driver state structure
- *   info - A reference to the characteristics of the pulsed output
- *
- * Returned Value:
- *   Zero on success; a negated errno value on failure
- *
+ * Name: pwm_ccr_update
  ****************************************************************************/
 
-static int pwm_timer(struct stm32_pwmtimer_s *priv,
-                     const struct pwm_info_s *info)
+static int pwm_ccr_update(struct pwm_lowerhalf_s *dev, uint8_t index,
+                          uint32_t ccr)
 {
-#ifdef CONFIG_PWM_MULTICHAN
-  int      i;
-#endif
-
-  /* Calculated values */
-
-  uint32_t prescaler;
-  uint32_t timclk;
-  uint32_t reload;
-  uint32_t ccr;
-
-  /* Register contents */
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint32_t offset = 0;
 
-  uint16_t cr1;
-  uint16_t ccer;
-  uint16_t cr2;
-  uint16_t ccmr1;
-  uint16_t ccmr2;
+  /* Only ADV timers have CC5 and CC6 */
 
-  /* New timer register bit settings */
+  if (priv->timtype != TIMTYPE_ADVANCED && (index == 5 || index == 6))
+    {
+      pwmerr("ERROR: No such CCR: %u\n", index);
+      return -EINVAL;
+    }
 
-  uint16_t ccenable;
-  uint16_t ocmode1;
-  uint16_t ocmode2;
+  /* REVISIT: start index from 0? */
 
-  DEBUGASSERT(priv != NULL && info != NULL);
+  switch (index)
+    {
+      case STM32_PWM_CHAN1:
+        {
+          offset = STM32_GTIM_CCR1_OFFSET;
+          break;
+        }
 
-#if defined(CONFIG_PWM_MULTICHAN)
-  pwminfo("TIM%u frequency: %lu\n",
-          priv->timid, info->frequency);
-#elif defined(CONFIG_PWM_PULSECOUNT)
-  pwminfo("TIM%u channel: %u frequency: %u duty: %08x count: %u\n",
-          priv->timid, priv->channels[0].channel, info->frequency,
-          info->duty, info->count);
-#else
-  pwminfo("TIM%u channel: %u frequency: %u duty: %08x\n",
-          priv->timid, priv->channels[0].channel, info->frequency,
-          info->duty);
-#endif
+      case STM32_PWM_CHAN2:
+        {
+          offset = STM32_GTIM_CCR2_OFFSET;
+          break;
+        }
 
-  DEBUGASSERT(info->frequency > 0);
-#ifndef CONFIG_PWM_MULTICHAN
-  DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100));
-#endif
+      case STM32_PWM_CHAN3:
+        {
+          offset = STM32_GTIM_CCR3_OFFSET;
+          break;
+        }
 
-  /* Disable all interrupts and DMA requests, clear all pending status */
+      case STM32_PWM_CHAN4:
+        {
+          offset = STM32_GTIM_CCR4_OFFSET;
+          break;
+        }
 
-#ifdef CONFIG_PWM_PULSECOUNT
-  pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, 0);
-  pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
-#endif
+      case STM32_PWM_CHAN5:
+        {
+          offset = STM32_ATIM_CCR5_OFFSET;
+          break;
+        }
 
-  /* Calculate optimal values for the timer prescaler and for the timer
-   * reload register.  If 'frequency' is the desired frequency, then
-   *
-   *   reload = timclk / frequency
-   *   timclk = pclk / presc
-   *
-   * Or,
-   *
-   *   reload = pclk / presc / frequency
-   *
-   * There are many solutions to this, but the best solution will be the one
-   * that has the largest reload value and the smallest prescaler value.
-   * That is the solution that should give us the most accuracy in the timer
-   * control.  Subject to:
-   *
-   *   0 <= presc  <= 65536
-   *   1 <= reload <= 65535
-   *
-   * So presc = pclk / 65535 / frequency would be optimal.
-   *
-   * Example:
-   *
-   *  pclk      = 42 MHz
-   *  frequency = 100 Hz
-   *
-   *  prescaler = 42,000,000 / 65,535 / 100
-   *            = 6.4 (or 7 -- taking the ceiling always)
-   *  timclk    = 42,000,000 / 7
-   *            = 6,000,000
-   *  reload    = 6,000,000 / 100
-   *            = 60,000
-   */
+      case STM32_PWM_CHAN6:
+        {
+          offset = STM32_ATIM_CCR6_OFFSET;
+          break;
+        }
 
-  prescaler = (priv->pclk / info->frequency + 65534) / 65535;
-  if (prescaler < 1)
-    {
-      prescaler = 1;
-    }
-  else if (prescaler > 65536)
-    {
-      prescaler = 65536;
+      default:
+        {
+          pwmerr("ERROR: No such CCR: %u\n", index);
+          return -EINVAL;
+        }
     }
 
-  timclk = priv->pclk / prescaler;
+  /* Update CCR register */
 
-  reload = timclk / info->frequency;
-  if (reload < 2)
-    {
-      reload = 1;
-    }
-  else if (reload > 65535)
-    {
-      reload = 65535;
-    }
-  else
-    {
-      reload--;
-    }
+  pwm_putreg(priv, offset, ccr);
 
-  pwminfo("TIM%u PCLK: %lu frequency: %lu "
-          "TIMCLK: %lu prescaler: %lu reload: %lu\n",
-          priv->timid, priv->pclk, info->frequency,
-          timclk, prescaler, reload);
+  return OK;
+}
 
-  /* Set up the timer CR1 register:
-   *
-   * 1,8   CKD[1:0] ARPE CMS[1:0] DIR OPM URS UDIS CEN
-   * 2-5   CKD[1:0] ARPE CMS      DIR OPM URS UDIS CEN
-   * 6-7            ARPE              OPM URS UDIS CEN
-   * 9-14  CKD[1:0] ARPE                  URS UDIS CEN
-   * 15-17 CKD[1:0] ARPE              OPM URS UDIS CEN
-   */
+/****************************************************************************
+ * Name: pwm_ccr_get
+ ****************************************************************************/
 
-  cr1 = pwm_getreg(priv, STM32_GTIM_CR1_OFFSET);
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+static uint32_t pwm_ccr_get(struct pwm_lowerhalf_s *dev, uint8_t index)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint32_t offset = 0;
 
-  /* Disable the timer until we get it configured */
+  switch (index)
+    {
+      case STM32_PWM_CHAN1:
+        {
+          offset = STM32_GTIM_CCR1_OFFSET;
+          break;
+        }
 
-  cr1 &= ~GTIM_CR1_CEN;
+      case STM32_PWM_CHAN2:
+        {
+          offset = STM32_GTIM_CCR2_OFFSET;
+          break;
+        }
 
-  /* Set the counter mode for the advanced timers (1,8) and most general
-   * purpose timers (all 2-5, but not 9-17), i.e., all but TIMTYPE_COUNTUP16
-   * and TIMTYPE_BASIC
-   */
+      case STM32_PWM_CHAN3:
+        {
+          offset = STM32_GTIM_CCR3_OFFSET;
+          break;
+        }
 
-#if defined(CONFIG_STM32F7_TIM1_PWM) || defined(CONFIG_STM32F7_TIM2_PWM) || \
-    defined(CONFIG_STM32F7_TIM3_PWM) || defined(CONFIG_STM32F7_TIM4_PWM) || \
-    defined(CONFIG_STM32F7_TIM5_PWM) || defined(CONFIG_STM32F7_TIM8_PWM)
+      case STM32_PWM_CHAN4:
+        {
+          offset = STM32_GTIM_CCR4_OFFSET;
+          break;
+        }
 
-  if (priv->timtype != TIMTYPE_BASIC && priv->timtype != TIMTYPE_COUNTUP16)
-    {
-      /* Select the Counter Mode:
-       *
-       * GTIM_CR1_EDGE: The counter counts up or down depending on the
-       *   direction bit (DIR).
-       * GTIM_CR1_CENTER1, GTIM_CR1_CENTER2, GTIM_CR1_CENTER3: The counter
-       *   counts up then down.
-       * GTIM_CR1_DIR: 0: count up, 1: count down
-       */
+      case STM32_PWM_CHAN5:
+        {
+          offset = STM32_ATIM_CCR5_OFFSET;
+          break;
+        }
 
-      cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK);
+      case STM32_PWM_CHAN6:
+        {
+          offset = STM32_ATIM_CCR6_OFFSET;
+          break;
+        }
 
-      switch (priv->mode)
+      default:
         {
-          case STM32_TIMMODE_COUNTUP:
-            cr1 |= GTIM_CR1_EDGE;
-            break;
+          pwmerr("ERROR: No such CCR: %u\n", index);
+          return -EINVAL;
+        }
+    }
 
-          case STM32_TIMMODE_COUNTDOWN:
-            cr1 |= GTIM_CR1_EDGE | GTIM_CR1_DIR;
-            break;
+  /* Return CCR register */
 
-          case STM32_TIMMODE_CENTER1:
-            cr1 |= GTIM_CR1_CENTER1;
-            break;
+  return pwm_getreg(priv, offset);
+}
+#endif /* CONFIG_STM32F7_PWM_LL_OPS */
 
-          case STM32_TIMMODE_CENTER2:
-            cr1 |= GTIM_CR1_CENTER2;
-            break;
+/****************************************************************************
+ * Name: pwm_arr_update
+ ****************************************************************************/
+
+static int pwm_arr_update(struct pwm_lowerhalf_s *dev, uint32_t arr)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+
+  /* Update ARR register */
+
+  pwm_putreg(priv, STM32_GTIM_ARR_OFFSET, arr);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_arr_get
+ ****************************************************************************/
+
+static uint32_t pwm_arr_get(struct pwm_lowerhalf_s *dev)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+
+  return pwm_getreg(priv, STM32_GTIM_ARR_OFFSET);
+}
+
+#ifdef HAVE_ADVTIM
+/****************************************************************************
+ * Name: pwm_rcr_update
+ ****************************************************************************/
+
+static int pwm_rcr_update(struct pwm_lowerhalf_s *dev, uint16_t rcr)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+
+  /* Update RCR register */
+
+  pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, rcr);
+
+  return OK;
+}
+#endif
+
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+/****************************************************************************
+ * Name: pwm_rcr_get
+ ****************************************************************************/
+
+static uint16_t pwm_rcr_get(struct pwm_lowerhalf_s *dev)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+
+  return pwm_getreg(priv, STM32_ATIM_RCR_OFFSET);
+}
+#endif
+
+/****************************************************************************
+ * Name: pwm_duty_update
+ *
+ * Description:
+ *   Try to change only channel duty
+ *
+ * Input Parameters:
+ *   dev     - A reference to the lower half PWM driver state structure
+ *   channel - Channel to by updated
+ *   duty    - New duty
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_duty_update(struct pwm_lowerhalf_s *dev, uint8_t channel,
+                           ub16_t duty)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint32_t reload = 0;
+  uint32_t ccr    = 0;
+
+  /* We don't want compilation warnings if no DEBUGASSERT */
+
+  UNUSED(priv);
+
+  DEBUGASSERT(priv != NULL);
+
+  pwminfo("TIM%u channel: %u duty: %08" PRIx32 "\n",
+          priv->timid, channel, duty);
+
+#ifndef CONFIG_PWM_MULTICHAN
+  DEBUGASSERT(channel == priv->channels[0].channel);
+  DEBUGASSERT(duty >= 0 && duty < uitoub16(100));
+#endif
+
+  /* Get the reload values */
+
+  reload = pwm_arr_get(dev);
+
+  /* Duty cycle:
+   *
+   * duty cycle = ccr / reload (fractional value)
+   */
+
+  ccr = b16toi(duty * reload + b16HALF);
+
+  pwminfo("ccr: %" PRIu32 "\n", ccr);
+
+  /* Write corresponding CCR register */
+
+  pwm_ccr_update(dev, channel, ccr);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_timer_enable
+ ****************************************************************************/
+
+static int pwm_timer_enable(struct pwm_lowerhalf_s *dev, bool state)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+
+  if (state == true)
+    {
+      /* Enable timer counter */
+
+      pwm_modifyreg(priv, STM32_GTIM_CR1_OFFSET, 0, GTIM_CR1_CEN);
+    }
+  else
+    {
+      /* Disable timer counter */
+
+      pwm_modifyreg(priv, STM32_GTIM_CR1_OFFSET, GTIM_CR1_CEN, 0);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_frequency_update
+ *
+ * Description:
+ *   Update a PWM timer frequency
+ *
+ ****************************************************************************/
+
+static int pwm_frequency_update(struct pwm_lowerhalf_s *dev,
+                                uint32_t frequency)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint32_t reload    = 0;
+  uint32_t timclk    = 0;
+  uint32_t prescaler = 0;
+
+  /* Calculate optimal values for the timer prescaler and for the timer
+   * reload register. If 'frequency' is the desired frequency, then
+   *
+   *   reload = timclk / frequency
+   *   timclk = pclk / presc
+   *
+   * Or,
+   *
+   *   reload = pclk / presc / frequency
+   *
+   * There are many solutions to this, but the best solution will be the one
+   * that has the largest reload value and the smallest prescaler value.
+   * That is the solution that should give us the most accuracy in the timer
+   * control.  Subject to:
+   *
+   *   0 <= presc  <= 65536
+   *   1 <= reload <= 65535
+   *
+   * So presc = pclk / 65535 / frequency would be optimal.
+   *
+   * Example:
+   *
+   *  pclk      = 42 MHz
+   *  frequency = 100 Hz
+   *
+   *  prescaler = 42,000,000 / 65,535 / 100
+   *            = 6.4 (or 7 -- taking the ceiling always)
+   *  timclk    = 42,000,000 / 7
+   *            = 6,000,000
+   *  reload    = 6,000,000 / 100
+   *            = 60,000
+   */
+
+  prescaler = (priv->pclk / frequency + 65534) / 65535;
+  if (prescaler < 1)
+    {
+      prescaler = 1;
+    }
+  else if (prescaler > 65536)
+    {
+      prescaler = 65536;
+    }
+
+  timclk = priv->pclk / prescaler;
+
+  reload = timclk / frequency;
+  if (reload < 2)
+    {
+      reload = 1;
+    }
+  else if (reload > 65535)
+    {
+      reload = 65535;
+    }
+  else
+    {
+      reload--;
+    }
+
+  pwminfo("TIM%u PCLK: %" PRIu32" frequency: %" PRIu32
+          " TIMCLK: %" PRIu32 " "
+          "prescaler: %" PRIu32 " reload: %" PRIu32 "\n",
+          priv->timid, priv->pclk, frequency, timclk, prescaler, reload);
+
+  /* Set the reload and prescaler values */
+
+  pwm_arr_update(dev, reload);
+  pwm_putreg(priv, STM32_GTIM_PSC_OFFSET, (uint16_t)(prescaler - 1));
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_timer_configure
+ *
+ * Description:
+ *   Initial configuration for PWM timer
+ *
+ ****************************************************************************/
+
+static int pwm_timer_configure(struct stm32_pwmtimer_s *priv)
+{
+  uint16_t cr1 = 0;
+  int      ret = OK;
+
+  /* Set up the timer CR1 register:
+   *
+   * 1,8   CKD[1:0] ARPE CMS[1:0] DIR OPM URS UDIS CEN
+   * 2-5   CKD[1:0] ARPE CMS      DIR OPM URS UDIS CEN
+   * 6-7            ARPE              OPM URS UDIS CEN
+   * 9-14  CKD[1:0] ARPE                  URS UDIS CEN
+   * 15-17 CKD[1:0] ARPE              OPM URS UDIS CEN
+   */
+
+  cr1 = pwm_getreg(priv, STM32_GTIM_CR1_OFFSET);
+
+  /* Set the counter mode for the advanced timers (1,8) and most general
+   * purpose timers (all 2-5, but not 9-17), i.e., all but TIMTYPE_COUNTUP16
+   * and TIMTYPE_BASIC
+   */
+
+  if (priv->timtype != TIMTYPE_BASIC && priv->timtype != TIMTYPE_COUNTUP16)
+    {
+      /* Select the Counter Mode:
+       *
+       * GTIM_CR1_EDGE: The counter counts up or down depending on the
+       *   direction bit (DIR).
+       * GTIM_CR1_CENTER1, GTIM_CR1_CENTER2, GTIM_CR1_CENTER3: The counter
+       *   counts up then down.
+       * GTIM_CR1_DIR: 0: count up, 1: count down
+       */
+
+      cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK);
+
+      switch (priv->mode)
+        {
+          case STM32_TIMMODE_COUNTUP:
+            {
+              cr1 |= GTIM_CR1_EDGE;
+              break;
+            }
+
+          case STM32_TIMMODE_COUNTDOWN:
+            {
+              cr1 |= GTIM_CR1_EDGE | GTIM_CR1_DIR;
+              break;
+            }
+
+          case STM32_TIMMODE_CENTER1:
+            {
+              cr1 |= GTIM_CR1_CENTER1;
+              break;
+            }
+
+          case STM32_TIMMODE_CENTER2:
+            {
+              cr1 |= GTIM_CR1_CENTER2;
+              break;
+            }
 
           case STM32_TIMMODE_CENTER3:
-            cr1 |= GTIM_CR1_CENTER3;
-            break;
+            {
+              cr1 |= GTIM_CR1_CENTER3;
+              break;
+            }
+
+          default:
+            {
+              pwmerr("ERROR: No such timer mode: %u\n",
+                     (unsigned int)priv->mode);
+              ret = -EINVAL;
+              goto errout;
+            }
+        }
+    }
+
+  /* Enable ARR Preload
+   * TODO: this should be configurable
+   */
+
+  cr1 |= GTIM_CR1_ARPE;
+
+  /* Write CR1 */
+
+  pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: pwm_mode_configure
+ *
+ * Description:
+ *   Configure a PWM mode for given channel
+ *
+ ****************************************************************************/
+
+static int pwm_mode_configure(struct pwm_lowerhalf_s *dev,
+                              uint8_t channel, uint32_t mode)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint32_t chanmode = 0;
+  uint32_t ocmode   = 0;
+  uint32_t ccmr     = 0;
+  uint32_t offset   = 0;
+  int      ret      = OK;
+  bool     ocmbit   = false;
+
+  /* Only advanced timers have channels 5-6 */
+
+  if (channel > 4 && priv->timtype != TIMTYPE_ADVANCED)
+    {
+      pwmerr("ERROR: No such channel: %u\n", channel);
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  /* Get channel mode
+   * TODO: configurable preload for CCxR
+   */
+
+  switch (mode)
+    {
+      case STM32_CHANMODE_FRZN:
+        {
+          chanmode = GTIM_CCMR_MODE_FRZN;
+          break;
+        }
+
+      case STM32_CHANMODE_CHACT:
+        {
+          chanmode = GTIM_CCMR_MODE_CHACT;
+          break;
+        }
+
+      case STM32_CHANMODE_CHINACT:
+        {
+          chanmode = GTIM_CCMR_MODE_CHINACT;
+          break;
+        }
+
+      case STM32_CHANMODE_OCREFTOG:
+        {
+          chanmode = GTIM_CCMR_MODE_OCREFTOG;
+          break;
+        }
+
+      case STM32_CHANMODE_OCREFLO:
+        {
+          chanmode = GTIM_CCMR_MODE_OCREFLO;
+          break;
+        }
+
+      case STM32_CHANMODE_OCREFHI:
+        {
+          chanmode = GTIM_CCMR_MODE_OCREFHI;
+          break;
+        }
+
+      case STM32_CHANMODE_PWM1:
+        {
+          chanmode = GTIM_CCMR_MODE_PWM1;
+          break;
+        }
+
+      case STM32_CHANMODE_PWM2:
+        {
+          chanmode = GTIM_CCMR_MODE_PWM2;
+          break;
+        }
+
+      case STM32_CHANMODE_COMBINED1:
+        {
+          chanmode = ATIM_CCMR_MODE_COMBINED1;
+          ocmbit   = true;
+          break;
+        }
+
+      case STM32_CHANMODE_COMBINED2:
+        {
+          chanmode = ATIM_CCMR_MODE_COMBINED2;
+          ocmbit   = true;
+          break;
+        }
+
+      case STM32_CHANMODE_ASYMMETRIC1:
+        {
+          chanmode = ATIM_CCMR_MODE_ASYMMETRIC1;
+          ocmbit   = true;
+          break;
+        }
+
+      case STM32_CHANMODE_ASYMMETRIC2:
+        {
+          chanmode = ATIM_CCMR_MODE_ASYMMETRIC2;
+          ocmbit   = true;
+          break;
+        }
+
+      default:
+        {
+          pwmerr("ERROR: No such mode: %u\n", (unsigned int)mode);
+          ret = -EINVAL;
+          goto errout;
+        }
+    }
+
+  /* Get CCMR offset */
+
+  switch (channel)
+    {
+      case STM32_PWM_CHAN1:
+      case STM32_PWM_CHAN2:
+        {
+          offset = STM32_GTIM_CCMR1_OFFSET;
+          break;
+        }
+
+      case STM32_PWM_CHAN3:
+      case STM32_PWM_CHAN4:
+        {
+          offset = STM32_GTIM_CCMR2_OFFSET;
+          break;
+        }
+
+      case STM32_PWM_CHAN5:
+      case STM32_PWM_CHAN6:
+        {
+          offset = STM32_ATIM_CCMR3_OFFSET;
+          break;
+        }
+
+      default:
+        {
+          pwmerr("ERROR: No such channel: %u\n", channel);
+          ret = -EINVAL;
+          goto errout;
+        }
+    }
+
+  /* Get current registers */
+
+  ccmr = pwm_getreg(priv, offset);
+
+  /* PWM mode configuration.
+   * NOTE: The CCMRx registers are identical if the channels are outputs.
+   */
+
+  switch (channel)
+    {
+      /* Configure channel 1/3/5 */
+
+      case STM32_PWM_CHAN1:
+      case STM32_PWM_CHAN3:
+      case STM32_PWM_CHAN5:
+        {
+          /* Reset current channel 1/3/5 mode configuration */
+
+          ccmr &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK |
+                     ATIM_CCMR1_OC1PE);
+
+          /* Configure CC1/3/5 as output */
+
+          ocmode |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT);
+
+          /* Configure Compare 1/3/5 mode */
+
+          ocmode |= (chanmode << ATIM_CCMR1_OC1M_SHIFT);
+
+          /* Enable CCR1/3/5 preload */
+
+          ocmode |= ATIM_CCMR1_OC1PE;
+
+          /* Reset current OC bit */
+
+          ccmr &= ~(ATIM_CCMR1_OC1M);
+
+          /* Set an additional OC1/3/5M bit */
+
+          if (ocmbit)
+            {
+              ocmode |= ATIM_CCMR1_OC1M;
+            }
+          break;
+        }
 
-          default:
-            pwmerr("ERROR: No such timer mode: %u\n",
-                   (unsigned int)priv->mode);
-            return -EINVAL;
+      /* Configure channel 2/4/6 */
+
+      case STM32_PWM_CHAN2:
+      case STM32_PWM_CHAN4:
+      case STM32_PWM_CHAN6:
+        {
+          /* Reset current channel 2/4/6 mode configuration */
+
+          ccmr &= ~(ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK |
+                     ATIM_CCMR1_OC2PE);
+
+          /* Configure CC2/4/6 as output */
+
+          ocmode |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT);
+
+          /* Configure Compare 2/4/6 mode */
+
+          ocmode |= (chanmode << ATIM_CCMR1_OC2M_SHIFT);
+
+          /* Enable CCR2/4/6 preload */
+
+          ocmode |= ATIM_CCMR1_OC2PE;
+
+          /* Reset current OC bit */
+
+          ccmr &= ~(ATIM_CCMR1_OC2M);
+
+          /* Set an additioneal OC2/4/6M bit */
+
+          if (ocmbit)
+            {
+              ocmode |= ATIM_CCMR1_OC2M;
+            }
+          break;
+        }
+    }
+
+  /* Set the selected output compare mode */
+
+  ccmr |= ocmode;
+
+  /* Write CCMRx registers */
+
+  pwm_putreg(priv, offset, ccmr);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: pwm_output_configure
+ *
+ * Description:
+ *   Configure PWM output for given channel
+ *
+ ****************************************************************************/
+
+static int pwm_output_configure(struct stm32_pwmtimer_s *priv,
+                                struct stm32_pwmchan_s *chan)
+{
+  uint32_t cr2  = 0;
+  uint32_t ccer = 0;
+  uint8_t  channel = 0;
+
+  /* Get channel */
+
+  channel = chan->channel;
+
+  /* Get current registers state */
+
+  cr2  = pwm_getreg(priv, STM32_GTIM_CR2_OFFSET);
+  ccer = pwm_getreg(priv, STM32_GTIM_CCER_OFFSET);
+
+  /* | OISx/OISxN  | IDLE | for ADVANCED and COUNTUP16 | CR2 register
+   * | CCxP/CCxNP  | POL  | all PWM timers             | CCER register
+   */
+
+  /* Configure output polarity (all PWM timers) */
+
+  if (chan->out1.pol == STM32_POL_NEG)
+    {
+      ccer |= (GTIM_CCER_CC1P << ((channel - 1) * 4));
+    }
+  else
+    {
+      ccer &= ~(GTIM_CCER_CC1P << ((channel - 1) * 4));
+    }
+
+#ifdef HAVE_ADVTIM
+  if (priv->timtype == TIMTYPE_ADVANCED)
+    {
+      /* Configure output IDLE State */
+
+      if (chan->out1.idle == STM32_IDLE_ACTIVE)
+        {
+          cr2 |= (ATIM_CR2_OIS1 << ((channel - 1) * 2));
+        }
+      else
+        {
+          cr2 &= ~(ATIM_CR2_OIS1 << ((channel - 1) * 2));
+        }
+
+#ifdef HAVE_PWM_COMPLEMENTARY
+      /* Configure complementary output IDLE state */
+
+      if (chan->out2.idle == STM32_IDLE_ACTIVE)
+        {
+          cr2 |= (ATIM_CR2_OIS1N << ((channel - 1) * 2));
+        }
+      else
+        {
+          cr2 &= ~(ATIM_CR2_OIS1N << ((channel - 1) * 2));
+        }
+
+      /* Configure complementary output polarity */
+
+      if (chan->out2.pol == STM32_POL_NEG)
+        {
+          ccer |= (ATIM_CCER_CC1NP << ((channel - 1) * 4));
+        }
+      else
+        {
+          ccer &= ~(ATIM_CCER_CC1NP << ((channel - 1) * 4));
         }
+#endif /* HAVE_PWM_COMPLEMENTARY */
+
+      /* TODO: OIS5 and OIS6 */
+
+      cr2 &= ~(ATIM_CR2_OIS5 | ATIM_CR2_OIS6);
+
+      /* TODO: CC5P and CC6P */
+
+      ccer &= ~(ATIM_CCER_CC5P | ATIM_CCER_CC6P);
+    }
+  else
+#endif /* HAVE_ADVTIM */
+    {
+      /* CCxNP must be cleared if not ADVANCED timer.
+       *
+       * REVISIT: not all families have CCxNP bits for GTIM,
+       *          which causes an ugly condition above
+       */
+
+      ccer &= ~(GTIM_CCER_CC1NP << ((channel - 1) * 4));
+    }
+
+  /* Write registers */
+
+  pwm_modifyreg(priv, STM32_GTIM_CR2_OFFSET, 0, cr2);
+  pwm_modifyreg(priv, STM32_GTIM_CCER_OFFSET, 0, ccer);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_outputs_enable
+ *
+ * Description:
+ *   Enable/disable given timer PWM outputs.
+ *
+ *   NOTE: This is bulk operation - we can enable/disable many outputs
+ *   at one time
+ *
+ * Input Parameters:
+ *   dev     - A reference to the lower half PWM driver state structure
+ *   outputs - outputs to set (look at enum stm32_chan_e in stm32_pwm.h)
+ *   state   - Enable/disable operation
+ *
+ ****************************************************************************/
+
+static int pwm_outputs_enable(struct pwm_lowerhalf_s *dev,
+                              uint16_t outputs, bool state)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint32_t ccer   = 0;
+  uint32_t regval = 0;
+
+  /* Get curren register state */
+
+  ccer = pwm_getreg(priv, STM32_GTIM_CCER_OFFSET);
+
+  /* Get outputs configuration */
+
+  regval |= ((outputs & STM32_PWM_OUT1)  ? GTIM_CCER_CC1E  : 0);
+  regval |= ((outputs & STM32_PWM_OUT1N) ? ATIM_CCER_CC1NE : 0);
+  regval |= ((outputs & STM32_PWM_OUT2)  ? GTIM_CCER_CC2E  : 0);
+  regval |= ((outputs & STM32_PWM_OUT2N) ? ATIM_CCER_CC2NE : 0);
+  regval |= ((outputs & STM32_PWM_OUT3)  ? GTIM_CCER_CC3E  : 0);
+  regval |= ((outputs & STM32_PWM_OUT3N) ? ATIM_CCER_CC3NE : 0);
+  regval |= ((outputs & STM32_PWM_OUT4)  ? GTIM_CCER_CC4E  : 0);
+
+  /* NOTE: CC4N doesn't exist, but some docs show configuration bits for it */
+
+  regval |= ((outputs & STM32_PWM_OUT5)  ? ATIM_CCER_CC5E  : 0);
+  regval |= ((outputs & STM32_PWM_OUT6)  ? ATIM_CCER_CC6E  : 0);
+
+  if (state == true)
+    {
+      /* Enable outpus - set bits */
+
+      ccer |= regval;
+    }
+  else
+    {
+      /* Disable outputs - reset bits */
+
+      ccer &= ~regval;
+    }
+
+  /* Write register */
+
+  pwm_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
+
+  return OK;
+}
+
+#if defined(HAVE_PWM_COMPLEMENTARY) && defined(CONFIG_STM32F7_PWM_LL_OPS)
+
+/****************************************************************************
+ * Name: pwm_deadtime_update
+ ****************************************************************************/
+
+static int pwm_deadtime_update(struct pwm_lowerhalf_s *dev, uint8_t dt)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint32_t bdtr = 0;
+  int      ret  = OK;
+
+  /* Check if locked */
+
+  if (priv->lock > 0)
+    {
+      ret = -EACCES;
+      goto errout;
+    }
+
+  /* Get current register state */
+
+  bdtr = pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET);
+
+  /* TODO: check if BDTR not locked */
+
+  /* Update deadtime */
+
+  bdtr &= ~(ATIM_BDTR_DTG_MASK);
+  bdtr |= (dt << ATIM_BDTR_DTG_SHIFT);
+
+  /* Write BDTR register */
+
+  pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, bdtr);
+
+errout:
+  return ret;
+}
+#endif
+
+#ifdef HAVE_TRGO
+/****************************************************************************
+ * Name: pwm_trgo_configure
+ *
+ * Description:
+ *   Confiugre an output synchronisation event for PWM timer (TRGO/TRGO2)
+ *
+ ****************************************************************************/
+
+static int pwm_trgo_configure(struct pwm_lowerhalf_s *dev,
+                              uint8_t trgo)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint32_t cr2 = 0;
+
+  /* Configure TRGO (4 LSB in trgo) */
+
+  cr2 |= (((trgo >> 0) & 0x0f) << ATIM_CR2_MMS_SHIFT) & ATIM_CR2_MMS_MASK;
+
+  /* Configure TRGO2 (4 MSB in trgo) */
+
+  cr2 |= (((trgo >> 4) & 0x0f) << ATIM_CR2_MMS2_SHIFT) & ATIM_CR2_MMS2_MASK;
+
+  /* Write register */
+
+  pwm_modifyreg(priv, STM32_GTIM_CR2_OFFSET, 0, cr2);
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: pwm_soft_update
+ *
+ * Description:
+ *   Generate an software update event
+ *
+ ****************************************************************************/
+
+static int pwm_soft_update(struct pwm_lowerhalf_s *dev)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+
+  pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, GTIM_EGR_UG);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_soft_break
+ *
+ * Description:
+ *   Generate an software break event
+ *
+ *   Outputs are enabled if state is false.
+ *   Outputs are disabled if state is true.
+ *
+ *   NOTE: only timers with complementary outputs have BDTR register and
+ *         support software break.
+ *
+ ****************************************************************************/
+
+static int pwm_soft_break(struct pwm_lowerhalf_s *dev, bool state)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+
+  if (state == true)
+    {
+      /* Reset MOE bit */
+
+      pwm_modifyreg(priv, STM32_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE, 0);
+    }
+  else
+    {
+      /* Set MOE bit */
+
+      pwm_modifyreg(priv, STM32_ATIM_BDTR_OFFSET, 0, ATIM_BDTR_MOE);
     }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_outputs_from_channels
+ *
+ * Description:
+ *   Get enabled outputs configuration from the PWM timer state
+ *
+ ****************************************************************************/
+
+static uint16_t pwm_outputs_from_channels(struct stm32_pwmtimer_s *priv)
+{
+  uint16_t outputs = 0;
+  uint8_t  channel = 0;
+  uint8_t  i       = 0;
+
+  for (i = 0; i < priv->chan_num; i += 1)
+    {
+      /* Get channel */
+
+      channel = priv->channels[i].channel;
+
+      /* Set outputs if channel configured */
+
+      if (channel != 0)
+        {
+          /* Enable output if confiugred */
+
+          if (priv->channels[i].out1.in_use == 1)
+            {
+              outputs |= (STM32_PWM_OUT1 << ((channel - 1) * 2));
+            }
+
+#ifdef HAVE_PWM_COMPLEMENTARY
+          /* Enable complementary output if configured */
+
+          if (priv->channels[i].out2.in_use == 1)
+            {
+              outputs |= (STM32_PWM_OUT1N << ((channel - 1) * 2));
+            }
 #endif
+        }
+    }
+
+  return outputs;
+}
+
+#ifdef HAVE_ADVTIM
+
+/****************************************************************************
+ * Name: pwm_break_dt_configure
+ *
+ * Description:
+ *   Configure break and deadtime
+ *
+ * NOTE: we have to configure all BDTR registers at once due to possible
+ *       lock configuration
+ *
+ ****************************************************************************/
+
+static int pwm_break_dt_configure(struct stm32_pwmtimer_s *priv)
+{
+  uint32_t bdtr = 0;
 
   /* Set the clock division to zero for all (but the basic timers, but there
    * should be no basic timers in this context
    */
 
-  cr1 &= ~GTIM_CR1_CKD_MASK;
-  pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+  pwm_modifyreg(priv, STM32_GTIM_CR1_OFFSET, GTIM_CR1_CKD_MASK,
+                priv->t_dts << GTIM_CR1_CKD_SHIFT);
+
+#ifdef HAVE_PWM_COMPLEMENTARY
+  /* Initialize deadtime */
+
+  bdtr |= (priv->deadtime << ATIM_BDTR_DTG_SHIFT);
+#endif
+
+#ifdef HAVE_BREAK
+  /* Configure Break 1 */
+
+  if (priv->brk.en1 == 1)
+    {
+      /* Enable Break 1 */
+
+      bdtr |= ATIM_BDTR_BKE;
+
+      /* Set Break 1 polarity */
+
+      bdtr |= (priv->brk.pol1 == STM32_POL_NEG ? ATIM_BDTR_BKP : 0);
+    }
+
+  /* Configure Break 1 */
+
+  if (priv->brk.en2 == 1)
+    {
+      /* Enable Break 2 */
+
+      bdtr |= ATIM_BDTR_BK2E;
+
+      /* Set Break 2 polarity */
+
+      bdtr |= (priv->brk.pol2 == STM32_POL_NEG ? ATIM_BDTR_BK2P : 0);
+
+      /* Configure BRK2 filter */
+
+      bdtr |= (priv->brk.flt2 << ATIM_BDTR_BK2F_SHIFT);
+    }
+#endif /* HAVE_BREAK */
+
+  /* Clear the OSSI and OSSR bits in the BDTR register.
+   *
+   * REVISIT: this should be configurable
+   */
+
+  bdtr &= ~(ATIM_BDTR_OSSI | ATIM_BDTR_OSSR);
+
+  /* Configure lock */
 
-  /* Set the reload and prescaler values */
+  bdtr |= priv->lock << ATIM_BDTR_LOCK_SHIFT;
 
-  pwm_putreg(priv, STM32_GTIM_ARR_OFFSET, (uint16_t)reload);
-  pwm_putreg(priv, STM32_GTIM_PSC_OFFSET, (uint16_t)(prescaler - 1));
+  /* Write BDTR register at once */
 
-  /* Set the advanced timer's repetition counter */
+  pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, bdtr);
 
-#if defined(CONFIG_STM32F7_TIM1_PWM) || defined(CONFIG_STM32F7_TIM8_PWM)
-  if (priv->timtype == TIMTYPE_ADVANCED)
-    {
-      /* If a non-zero repetition count has been selected, then set the
-       * repetition counter to the count-1 (pwm_start() has already
-       * assured us that the count value is within range).
-       */
+  return OK;
+}
+#endif
 
 #ifdef CONFIG_PWM_PULSECOUNT
-      if (info->count > 0)
-        {
-          /* Save the remaining count and the number of counts that will have
-           * elapsed on the first interrupt.
-           */
 
-          /* If the first interrupt occurs at the end end of the first
-           * repetition count, then the count will be the same as the RCR
-           * value.
-           */
+/****************************************************************************
+ * Name: pwm_pulsecount_configure
+ *
+ * Description:
+ *   Configure PWM timer in PULSECOUNT mode
+ *
+ ****************************************************************************/
 
-          priv->prev  = pwm_pulsecount(info->count);
-          pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->prev - 1);
+static int pwm_pulsecount_configure(struct pwm_lowerhalf_s *dev)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint16_t outputs = 0;
+  uint8_t j        = 0;
+  int     ret      = OK;
 
-          /* Generate an update event to reload the prescaler.  This should
-           * preload the RCR into active repetition counter.
-           */
+  /* NOTE: leave timer counter disabled and all outputs disabled! */
 
-          pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+  /* Disable the timer until we get it configured */
 
-          /* Now set the value of the RCR that will be loaded on the next
-           * update event.
-           */
+  pwm_timer_enable(dev, false);
 
-          priv->count = info->count;
-          priv->curr  = pwm_pulsecount(info->count - priv->prev);
-          pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
-        }
+  /* Get configured outputs */
 
-      /* Otherwise, just clear the repetition counter */
+  outputs = pwm_outputs_from_channels(priv);
 
-      else
-#endif
-        {
-          /* Set the repetition counter to zero */
+  /* REVISIT: Disable outputs */
 
-          pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, 0);
+  ret = pwm_outputs_enable(dev, outputs, false);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-          /* Generate an update event to reload the prescaler */
+  /* Initial timer configuration */
 
-          pwm_putreg(priv, STM32_ATIM_EGR_OFFSET, ATIM_EGR_UG);
-        }
-    }
-  else
-#endif
+  ret = pwm_timer_configure(priv);
+  if (ret < 0)
     {
-      /* Generate an update event to reload the prescaler (all timers) */
+      goto errout;
+    }
+
+  /* Configure break and deadtime register */
 
-      pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, GTIM_EGR_UG);
+  ret = pwm_break_dt_configure(priv);
+  if (ret < 0)
+    {
+      goto errout;
     }
 
-  /* Handle channel specific setup */
+  /* Disable software break (enable outputs) */
 
-  ccenable = 0;
-  ocmode1  = 0;
-  ocmode2  = 0;
+  ret = pwm_soft_break(dev, false);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-#ifdef CONFIG_PWM_MULTICHAN
-  for (i = 0; i < CONFIG_PWM_NCHANNELS; i++)
-#endif
+#ifdef HAVE_TRGO
+  /* Configure TRGO/TRGO2 */
+
+  ret = pwm_trgo_configure(dev, priv->trgo);
+  if (ret < 0)
     {
-      ub16_t                duty;
-      uint16_t              chanmode;
-      uint8_t               channel;
-#ifdef CONFIG_PWM_MULTICHAN
-      int                   j;
+      goto errout;
+    }
 #endif
-      enum stm32_chanmode_e mode;
 
-#ifdef CONFIG_PWM_MULTICHAN
-      /* Break the loop if all following channels are not configured */
+  /* Configure timer channels */
 
-      if (info->channels[i].channel == -1)
+  for (j = 0; j < priv->chan_num; j++)
+    {
+      /* Skip channel if not in use */
+
+      if (priv->channels[j].channel != 0)
         {
-          break;
-        }
+          /* Update PWM mode */
 
-      duty = info->channels[i].duty;
-      channel = info->channels[i].channel;
+          pwm_mode_configure(dev, priv->channels[j].channel,
+                             priv->channels[j].mode);
 
-      /* A value of zero means to skip this channel */
+          /* PWM outputs configuration */
 
-      if (channel == 0)
-        {
-          continue;
+          pwm_output_configure(priv, &priv->channels[j]);
         }
+    }
 
-      /* Find the channel */
+errout:
+  return ret;
+}
 
-      for (j = 0; j < PWM_NCHANNELS; j++)
-        {
-          if (priv->channels[j].channel == channel)
-            {
-              mode = priv->channels[j].mode;
-              break;
-            }
-        }
+/****************************************************************************
+ * Name: pwm_pulsecount_timer
+ *
+ * Description:
+ *   (Re-)initialize the timer resources and start the pulsed output
+ *
+ * Input Parameters:
+ *   dev  - A reference to the lower half PWM driver state structure
+ *   info - A reference to the characteristics of the pulsed output
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ * TODO: PWM_PULSECOUNT should be configurable for each timer instance
+ * TODO: PULSECOUNT doesn't work with MULTICHAN at this moment
+ *
+ ****************************************************************************/
 
-      if (j >= PWM_NCHANNELS)
-        {
-          pwmerr("ERROR: No such channel: %u\n", channel);
-          return -EINVAL;
-        }
-#else
-      duty = info->duty;
-      channel = priv->channels[0].channel;
-      mode = priv->channels[0].mode;
-#endif
+static int pwm_pulsecount_timer(struct pwm_lowerhalf_s *dev,
+                                const struct pwm_info_s *info)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  ub16_t    duty    = 0;
+  uint8_t   channel = 0;
+  uint16_t  outputs = 0;
+  int       ret     = OK;
 
-      /* Duty cycle:
-       *
-       * duty cycle = ccr / reload (fractional value)
-       */
+  /* If we got here it means that timer instance support pulsecount mode! */
 
-      ccr = b16toi(duty * reload + b16HALF);
+  DEBUGASSERT(priv != NULL && info != NULL);
 
-      pwminfo("ccr: %lu\n", ccr);
+  pwminfo("TIM%u channel: %u frequency: %" PRIx32 " duty: %08" PRIx32
+          " count: %" PRIx32 "\n",
+          priv->timid, priv->channels[0].channel, info->frequency,
+          info->duty, info->count);
 
-      switch (mode)
-        {
-          case STM32_CHANMODE_PWM1:
-            chanmode = GTIM_CCMR_MODE_PWM1;
-            break;
+  DEBUGASSERT(info->frequency > 0);
 
-          case STM32_CHANMODE_PWM2:
-            chanmode = GTIM_CCMR_MODE_PWM2;
-            break;
+  /* Channel specific setup */
 
-          default:
-            pwmerr("ERROR: No such mode: %u\n", (unsigned int)mode);
-            return -EINVAL;
-        }
+  duty    = info->duty;
+  channel = priv->channels[0].channel;
 
-      switch (channel)
-        {
-          case 1:  /* PWM Mode configuration: Channel 1 */
-            {
-              /* Select the CCER enable bit for this channel */
+  /* Disable all interrupts and DMA requests, clear all pending status */
 
-              ccenable |= GTIM_CCER_CC1E;
+  pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, 0);
+  pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
 
-              /* Set the CCMR1 mode values (leave CCMR2 zero) */
+  /* Set timer frequency */
 
-              ocmode1  |= (GTIM_CCMR_CCS_CCOUT << GTIM_CCMR1_CC1S_SHIFT) |
-                          (chanmode << GTIM_CCMR1_OC1M_SHIFT) |
-                          GTIM_CCMR1_OC1PE;
+  ret = pwm_frequency_update(dev, info->frequency);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-              /* Set the duty cycle by writing to the CCR register for this
-               * channel
-               */
+  /* Update duty cycle */
 
-              pwm_putreg(priv, STM32_GTIM_CCR1_OFFSET, (uint16_t)ccr);
-            }
-            break;
+  ret = pwm_duty_update(dev, channel, duty);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-          case 2:  /* PWM Mode configuration: Channel 2 */
-            {
-              /* Select the CCER enable bit for this channel */
+  /* If a non-zero repetition count has been selected, then set the
+   * repetition counter to the count-1 (pwm_pulsecount_start() has already
+   * assured us that the count value is within range).
+   */
 
-              ccenable |= GTIM_CCER_CC2E;
+  if (info->count > 0)
+    {
+      /* Save the remaining count and the number of counts that will have
+       * elapsed on the first interrupt.
+       */
 
-              /* Set the CCMR1 mode values (leave CCMR2 zero) */
+      /* If the first interrupt occurs at the end end of the first
+       * repetition count, then the count will be the same as the RCR
+       * value.
+       */
 
-              ocmode1  |= (GTIM_CCMR_CCS_CCOUT << GTIM_CCMR1_CC2S_SHIFT) |
-                          (chanmode << GTIM_CCMR1_OC2M_SHIFT) |
-                          GTIM_CCMR1_OC2PE;
+      priv->prev  = pwm_pulsecount(info->count);
+      pwm_rcr_update(dev, priv->prev - 1);
 
-              /* Set the duty cycle by writing to the CCR register for this
-               * channel
-               */
+      /* Generate an update event to reload the prescaler.  This should
+       * preload the RCR into active repetition counter.
+       */
 
-              pwm_putreg(priv, STM32_GTIM_CCR2_OFFSET, (uint16_t)ccr);
-            }
-            break;
+      pwm_soft_update(dev);
 
-          case 3:  /* PWM Mode configuration: Channel 3 */
-            {
-              /* Select the CCER enable bit for this channel */
+      /* Now set the value of the RCR that will be loaded on the next
+       * update event.
+       */
 
-              ccenable |= GTIM_CCER_CC3E;
+      priv->count = info->count;
+      priv->curr  = pwm_pulsecount(info->count - priv->prev);
+      pwm_rcr_update(dev, priv->curr - 1);
+    }
 
-              /* Set the CCMR2 mode values (leave CCMR1 zero) */
+  /* Otherwise, just clear the repetition counter */
 
-              ocmode2  |= (GTIM_CCMR_CCS_CCOUT << GTIM_CCMR2_CC3S_SHIFT) |
-                          (chanmode << GTIM_CCMR2_OC3M_SHIFT) |
-                          GTIM_CCMR2_OC3PE;
+  else
+    {
+      /* Set the repetition counter to zero */
 
-              /* Set the duty cycle by writing to the CCR register for this
-               * channel
-               */
+      pwm_rcr_update(dev, 0);
 
-              pwm_putreg(priv, STM32_GTIM_CCR3_OFFSET, (uint16_t)ccr);
-            }
-            break;
+      /* Generate an update event to reload the prescaler */
 
-          case 4:  /* PWM Mode configuration: Channel 4 */
-            {
-              /* Select the CCER enable bit for this channel */
+      pwm_soft_update(dev);
+    }
 
-              ccenable |= GTIM_CCER_CC4E;
+  /* Get configured outputs */
 
-              /* Set the CCMR2 mode values (leave CCMR1 zero) */
+  outputs = pwm_outputs_from_channels(priv);
 
-              ocmode2  |= (GTIM_CCMR_CCS_CCOUT << GTIM_CCMR2_CC4S_SHIFT) |
-                          (chanmode << GTIM_CCMR2_OC4M_SHIFT) |
-                          GTIM_CCMR2_OC4PE;
+  /* Enable output */
 
-              /* Set the duty cycle by writing to the CCR register for this
-               * channel
-               */
+  ret = pwm_outputs_enable(dev, outputs, true);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-              pwm_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)ccr);
-            }
-            break;
+  /* Setup update interrupt.  If info->count is > 0, then we can be
+   * assured that pwm_pulsecount_start() has already verified: (1) that this
+   * is an advanced timer, and that (2) the repetition count is within range.
+   */
 
-          default:
-            pwmerr("ERROR: No such channel: %u\n", channel);
-            return -EINVAL;
-        }
-    }
+  if (info->count > 0)
+    {
+      /* Clear all pending interrupts and enable the update interrupt. */
 
-  /* Disable the Channel by resetting the CCxE Bit in the CCER register */
+      pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
+      pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, GTIM_DIER_UIE);
 
-  ccer = pwm_getreg(priv, STM32_GTIM_CCER_OFFSET);
-  ccer &= ~ccenable;
-  pwm_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
+      /* Enable the timer */
 
-  /* Fetch the CR2, CCMR1, and CCMR2 register (already have cr1 and ccer) */
+      pwm_timer_enable(dev, true);
 
-  cr2   = pwm_getreg(priv, STM32_GTIM_CR2_OFFSET);
-  ccmr1 = pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET);
-  ccmr2 = pwm_getreg(priv, STM32_GTIM_CCMR2_OFFSET);
+      /* And enable timer interrupts at the NVIC */
 
-  /* Reset the Output Compare Mode Bits and set the select output compare
-   * mode
-   */
+      up_enable_irq(priv->irq);
+    }
 
-  ccmr1 &= ~(GTIM_CCMR1_CC1S_MASK | GTIM_CCMR1_OC1M_MASK | GTIM_CCMR1_OC1PE |
-             GTIM_CCMR1_CC2S_MASK | GTIM_CCMR1_OC2M_MASK | GTIM_CCMR1_OC2PE);
-  ccmr2 &= ~(GTIM_CCMR2_CC3S_MASK | GTIM_CCMR2_OC3M_MASK | GTIM_CCMR2_OC3PE |
-             GTIM_CCMR2_CC4S_MASK | GTIM_CCMR2_OC4M_MASK | GTIM_CCMR2_OC4PE);
-  ccmr1 |= ocmode1;
-  ccmr2 |= ocmode2;
+  pwm_dumpregs(dev, "After starting");
 
-  /* Reset the output polarity level of all channels (selects high
-   * polarity)
-   */
+errout:
+  return ret;
+}
+
+#endif /* CONFIG_PWM_PULSECOUNT */
+
+/****************************************************************************
+ * Name: pwm_configure
+ *
+ * Description:
+ *   Configure PWM timer in normal mode (no PULSECOUNT)
+ *
+ ****************************************************************************/
 
-  ccer &= ~(GTIM_CCER_CC1P | GTIM_CCER_CC2P | GTIM_CCER_CC3P |
-            GTIM_CCER_CC4P);
+static int pwm_configure(struct pwm_lowerhalf_s *dev)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint16_t outputs = 0;
+  uint8_t j        = 0;
+  int     ret      = OK;
 
-  /* Enable the output state of the selected channels */
+  /* NOTE: leave timer counter disabled and all outputs disabled! */
 
-  ccer &= ~(GTIM_CCER_CC1E | GTIM_CCER_CC2E | GTIM_CCER_CC3E |
-            GTIM_CCER_CC4E);
-  ccer |= ccenable;
+  /* Get configured outputs */
 
-  /* Some special setup for advanced timers */
+  outputs = pwm_outputs_from_channels(priv);
 
-#if defined(CONFIG_STM32F7_TIM1_PWM) || defined(CONFIG_STM32F7_TIM8_PWM) || \
-    defined(CONFIG_STM32F7_TIM15_PWM) || defined(CONFIG_STM32F7_TIM16_PWM) || \
-    defined(CONFIG_STM32F7_TIM17_PWM)
-  if (priv->timtype == TIMTYPE_ADVANCED ||
-      priv->timtype == TIMTYPE_COUNTUP16)
+  /* Disable outputs */
+
+  ret = pwm_outputs_enable(dev, outputs, false);
+  if (ret < 0)
     {
-      uint16_t bdtr;
+      goto errout;
+    }
 
-      /* Reset output N polarity level, output N state, output compare state,
-       * output compare N idle state.
-       */
+  /* Disable the timer until we get it configured */
 
-      ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE |
-                ATIM_CCER_CC2NP | ATIM_CCER_CC3NE | ATIM_CCER_CC3NP |
-                ATIM_CCER_CC4NP);
+  pwm_timer_enable(dev, false);
 
-      /* Reset the output compare and output compare N IDLE State */
+  /* Initial timer configuration */
 
-      cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | ATIM_CR2_OIS2 |
-               ATIM_CR2_OIS2N | ATIM_CR2_OIS3 | ATIM_CR2_OIS3N |
-               ATIM_CR2_OIS4);
+  ret = pwm_timer_configure(priv);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-      /* Set the main output enable (MOE) bit and clear the OSSI and OSSR
-       * bits in the BDTR register.
-       */
+  /* Some special setup for advanced timers */
+
+#ifdef HAVE_ADVTIM
+  if (priv->timtype == TIMTYPE_ADVANCED)
+    {
+      /* Configure break and deadtime register */
+
+      ret = pwm_break_dt_configure(priv);
+      if (ret < 0)
+        {
+          goto errout;
+        }
 
-      bdtr  = pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET);
-      bdtr &= ~(ATIM_BDTR_OSSI | ATIM_BDTR_OSSR);
-      bdtr |= ATIM_BDTR_MOE;
-      pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, bdtr);
+#ifdef HAVE_TRGO
+      /* Configure TRGO/TRGO2 */
+
+      ret = pwm_trgo_configure(dev, priv->trgo);
+      if (ret < 0)
+        {
+          goto errout;
+        }
+#endif
     }
-  else
 #endif
+
+  /* Configure timer channels */
+
+  for (j = 0; j < priv->chan_num; j++)
     {
-      /* CCxNP must be cleared in any case */
+      /* Skip channel if not in use */
+
+      if (priv->channels[j].channel != 0)
+        {
+          /* Update PWM mode */
+
+          ret = pwm_mode_configure(dev, priv->channels[j].channel,
+                                   priv->channels[j].mode);
+          if (ret < 0)
+            {
+              goto errout;
+            }
 
-      ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP |
-                GTIM_CCER_CC4NP);
+          /* PWM outputs configuration */
+
+          ret = pwm_output_configure(priv, &priv->channels[j]);
+          if (ret < 0)
+            {
+              goto errout;
+            }
+        }
     }
 
-  /* Save the modified register values */
+  /* Disable software break at the end of the outputs configuration (enablei
+   * outputs).
+   *
+   * NOTE: Only timers with complementary outputs have BDTR register and
+   *       support software break.
+   */
 
-  pwm_putreg(priv, STM32_GTIM_CR2_OFFSET, cr2);
-  pwm_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
-  pwm_putreg(priv, STM32_GTIM_CCMR2_OFFSET, ccmr2);
-  pwm_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
+  if (priv->timtype == TIMTYPE_ADVANCED)
+    {
+      ret = pwm_soft_break(dev, false);
+      if (ret < 0)
+        {
+          goto errout;
+        }
+    }
 
-  /* Set the ARR Preload Bit */
+errout:
+  return ret;
+}
 
-  cr1 = pwm_getreg(priv, STM32_GTIM_CR1_OFFSET);
-  cr1 |= GTIM_CR1_ARPE;
-  pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+/****************************************************************************
+ * Name: pwm_duty_channels_update
+ *
+ * Description:
+ *   Update duty cycle for given channels
+ *
+ ****************************************************************************/
 
-  /* Setup update interrupt.  If info->count is > 0, then we can be
-   * assured that pwm_start() has already verified: (1) that this is an
-   * advanced timer, and that (2) the repetition count is within range.
-   */
+static int pwm_duty_channels_update(struct pwm_lowerhalf_s *dev,
+                                    const struct pwm_info_s *info)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint8_t   channel = 0;
+  ub16_t    duty    = 0;
+  int       ret     = OK;
+#ifdef CONFIG_PWM_MULTICHAN
+  int       i       = 0;
+  int       j       = 0;
+#endif
 
-#ifdef CONFIG_PWM_PULSECOUNT
-  if (info->count > 0)
+#ifdef CONFIG_PWM_MULTICHAN
+  for (i = 0; i < CONFIG_PWM_NCHANNELS; i++)
+#endif
     {
-      /* Clear all pending interrupts and enable the update interrupt. */
+#ifdef CONFIG_PWM_MULTICHAN
+      /* Break the loop if all following channels are not configured */
 
-      pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
-      pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, GTIM_DIER_UIE);
+      if (info->channels[i].channel == -1)
+        {
+          break;
+        }
 
-      /* Enable the timer */
+      duty    = info->channels[i].duty;
+      channel = info->channels[i].channel;
 
-      cr1 |= GTIM_CR1_CEN;
-      pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+      /* A value of zero means to skip this channel */
 
-      /* And enable timer interrupts at the NVIC */
+      if (channel != 0)
+        {
+          /* Find the channel */
 
-      up_enable_irq(priv->irq);
-    }
-  else
+          for (j = 0; j < priv->chan_num; j++)
+            {
+              if (priv->channels[j].channel == channel)
+                {
+                  break;
+                }
+            }
+
+          /* Check range */
+
+          if (j >= priv->chan_num)
+            {
+              pwmerr("ERROR: No such channel: %u\n", channel);
+              ret = -EINVAL;
+              goto errout;
+            }
+#else
+          duty = info->duty;
+          channel = priv->channels[0].channel;
 #endif
-    {
-      /* Just enable the timer, leaving all interrupts disabled */
 
-      cr1 |= GTIM_CR1_CEN;
-      pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1);
+          /* Update duty cycle */
+
+          ret = pwm_duty_update(dev, channel, duty);
+          if (ret < 0)
+            {
+              goto errout;
+            }
+#ifdef CONFIG_PWM_MULTICHAN
+        }
+#endif
     }
 
-  pwm_dumpregs(priv, "After starting");
+errout:
   return OK;
 }
 
-#ifndef CONFIG_PWM_PULSECOUNT
 /****************************************************************************
- * Name: pwm_update_duty
+ * Name: pwm_timer
  *
  * Description:
- *   Try to change only channel duty.
+ *   (Re-)initialize the timer resources and start the pulsed output
  *
  * Input Parameters:
- *   priv    - A reference to the lower half PWM driver state structure
- *   channel - Channel to by updated
- *   duty    - New duty.
+ *   dev  - A reference to the lower half PWM driver state structure
+ *   info - A reference to the characteristics of the pulsed output
  *
  * Returned Value:
  *   Zero on success; a negated errno value on failure
  *
  ****************************************************************************/
 
-static  int pwm_update_duty(struct stm32_pwmtimer_s *priv,
-                            uint8_t channel, ub16_t duty)
-{
-  /* Register offset */
+static int pwm_timer(struct pwm_lowerhalf_s *dev,
+                     const struct pwm_info_s *info)
+{
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  uint16_t outputs = 0;
+  int      ret     = OK;
+
+  DEBUGASSERT(priv != NULL && info != NULL);
+
+#if defined(CONFIG_PWM_MULTICHAN)
+  pwminfo("TIM%u frequency: %" PRIu32 "\n",
+          priv->timid, info->frequency);
+#else
+  pwminfo("TIM%u channel: %u frequency: %" PRIu32 " duty: %08" PRIx32 "\n",
+          priv->timid, priv->channels[0].channel,
+          info->frequency, info->duty);
+#endif
 
-  int ccr_offset;
+  DEBUGASSERT(info->frequency > 0);
+#ifndef CONFIG_PWM_MULTICHAN
+  DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100));
+#endif
 
-  /* Calculated values */
+  /* TODO: what if we have pwm running and we want disable some channels ? */
 
-  uint32_t reload;
-  uint32_t ccr;
+  /* Set timer frequency */
 
-  DEBUGASSERT(priv != NULL);
+  ret = pwm_frequency_update(dev, info->frequency);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-  pwminfo("TIM%u channel: %u duty: %08lx\n",
-          priv->timid, channel, duty);
+  /* Channel specific configuration */
 
-#ifndef CONFIG_PWM_MULTICHAN
-  DEBUGASSERT(channel == priv->channels[0].channel);
-  DEBUGASSERT(duty >= 0 && duty < uitoub16(100));
-#endif
+  ret = pwm_duty_channels_update(dev, info);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-  /* Get the reload values */
+  /* Set the advanced timer's repetition counter */
 
-  reload = pwm_getreg(priv, STM32_GTIM_ARR_OFFSET);
+#ifdef HAVE_ADVTIM
+  if (priv->timtype == TIMTYPE_ADVANCED)
+    {
+      /* If a non-zero repetition count has been selected, then set the
+       * repetition counter to the count-1 (pwm_start() has already
+       * assured us that the count value is within range).
+       */
 
-  /* Duty cycle:
-   *
-   * duty cycle = ccr / reload (fractional value)
-   */
+      /* Set the repetition counter to zero */
 
-  ccr = b16toi(duty * reload + b16HALF);
+      pwm_rcr_update(dev, 0);
 
-  pwminfo("ccr: %lu\n", ccr);
+      /* Generate an update event to reload the prescaler */
 
-  switch (channel)
+      pwm_soft_update(dev);
+    }
+  else
+#endif
     {
-      case 1:  /* Register offset for Channel 1 */
-        ccr_offset = STM32_GTIM_CCR1_OFFSET;
-        break;
+      /* Generate an update event to reload the prescaler (all timers) */
+
+      pwm_soft_update(dev);
+    }
 
-      case 2:  /* Register offset for Channel 2 */
-        ccr_offset = STM32_GTIM_CCR2_OFFSET;
-        break;
+  /* Get configured outputs */
 
-      case 3:  /* Register offset for Channel 3 */
-        ccr_offset = STM32_GTIM_CCR3_OFFSET;
-        break;
+  outputs = pwm_outputs_from_channels(priv);
 
-      case 4:  /* Register offset for Channel 4 */
-        ccr_offset = STM32_GTIM_CCR4_OFFSET;
-        break;
+  /* Enable outputs */
 
-      default:
-        pwmerr("ERROR: No such channel: %u\n", channel);
-        return -EINVAL;
+  ret = pwm_outputs_enable(dev, outputs, true);
+  if (ret < 0)
+    {
+      goto errout;
     }
 
-  /* Set the duty cycle by writing to the CCR register for this channel */
+  /* Just enable the timer, leaving all interrupts disabled */
 
-  pwm_putreg(priv, ccr_offset, (uint16_t)ccr);
+  pwm_timer_enable(dev, true);
 
-  return OK;
+  pwm_dumpregs(dev, "After starting");
+
+errout:
+  return ret;
 }
-#endif
+
+#ifdef HAVE_PWM_INTERRUPT
 
 /****************************************************************************
  * Name: pwm_interrupt
@@ -1723,16 +3368,16 @@ static  int pwm_update_duty(struct stm32_pwmtimer_s *priv,
  *   Handle timer interrupts.
  *
  * Input Parameters:
- *   priv - A reference to the lower half PWM driver state structure
+ *   dev - A reference to the lower half PWM driver state structure
  *
  * Returned Value:
  *   Zero on success; a negated errno value on failure
  *
  ****************************************************************************/
 
-#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32F7_TIM1_PWM) || defined(CONFIG_STM32F7_TIM8_PWM))
-static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
+static int pwm_interrupt(struct pwm_lowerhalf_s *dev)
 {
+  struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
   uint16_t regval;
 
   /* Verify that this is an update interrupt.  Nothing else is expected. */
@@ -1742,7 +3387,7 @@ static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
 
   /* Clear the UIF interrupt bit */
 
-  pwm_putreg(priv, STM32_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF);
+  pwm_putreg(priv, STM32_ATIM_SR_OFFSET, (regval & ~ATIM_SR_UIF));
 
   /* Calculate the new count by subtracting the number of pulses
    * since the last interrupt.
@@ -1750,17 +3395,15 @@ static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
 
   if (priv->count <= priv->prev)
     {
-      /* We are finished.  Turn off the mast output to stop the output as
+      /* We are finished.  Turn off the master output to stop the output as
        * quickly as possible.
        */
 
-      regval  = pwm_getreg(priv, STM32_ATIM_BDTR_OFFSET);
-      regval &= ~ATIM_BDTR_MOE;
-      pwm_putreg(priv, STM32_ATIM_BDTR_OFFSET, regval);
+      pwm_soft_break(dev, true);
 
       /* Disable first interrupts, stop and reset the timer */
 
-      pwm_stop((struct pwm_lowerhalf_s *)priv);
+      pwm_stop(dev);
 
       /* Then perform the callback into the upper half driver */
 
@@ -1787,19 +3430,18 @@ static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
 
       priv->prev = priv->curr;
       priv->curr = pwm_pulsecount(priv->count - priv->prev);
-      pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
+      pwm_rcr_update(dev, priv->curr - 1);
     }
 
   /* Now all of the time critical stuff is done so we can do some debug
-   * output
+   * output.
    */
 
-  pwminfo("Update interrupt SR: %04x prev: %u curr: %u count: %u\n",
+  pwminfo("Update interrupt SR: %04x prev: %u curr: %u count: %" PRIx32 "\n",
           regval, priv->prev, priv->curr, priv->count);
 
   return OK;
 }
-#endif
 
 /****************************************************************************
  * Name: pwm_tim1/8interrupt
@@ -1815,19 +3457,19 @@ static int pwm_interrupt(struct stm32_pwmtimer_s *priv)
  *
  ****************************************************************************/
 
-#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32F7_TIM1_PWM)
+#ifdef CONFIG_STM32F7_TIM1_PWM
 static int pwm_tim1interrupt(int irq, void *context, void *arg)
 {
-  return pwm_interrupt(&g_pwm1dev);
+  return pwm_interrupt((struct pwm_lowerhalf_s *)&g_pwm1dev);
 }
-#endif
+#endif /* CONFIG_STM32F7_TIM1_PWM */
 
-#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32F7_TIM8_PWM)
+#ifdef CONFIG_STM32F7_TIM8_PWM
 static int pwm_tim8interrupt(int irq, void *context, void *arg)
 {
-  return pwm_interrupt(&g_pwm8dev);
+  return pwm_interrupt((struct pwm_lowerhalf_s *)&g_pwm8dev);
 }
-#endif
+#endif /* CONFIG_STM32F7_TIM8_PWM */
 
 /****************************************************************************
  * Name: pwm_pulsecount
@@ -1843,16 +3485,17 @@ static int pwm_tim8interrupt(int irq, void *context, void *arg)
  *
  ****************************************************************************/
 
-#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32F7_TIM1_PWM) || defined(CONFIG_STM32F7_TIM8_PWM))
 static uint8_t pwm_pulsecount(uint32_t count)
 {
+  /* REVISIT: RCR_REP_MAX for GTIM or ATIM ? */
+
   /* The the remaining pulse count is less than or equal to the maximum, the
    * just return the count.
    */
 
   if (count <= ATIM_RCR_REP_MAX)
     {
-      return count;
+      return (uint8_t)count;
     }
 
   /* Otherwise, we have to be careful.  We do not want a small number of
@@ -1864,17 +3507,17 @@ static uint8_t pwm_pulsecount(uint32_t count)
 
   else if (count < (3 * ATIM_RCR_REP_MAX / 2))
     {
-      return (ATIM_RCR_REP_MAX + 1) >> 1;
+      return (uint8_t)((ATIM_RCR_REP_MAX + 1) >> 1);
     }
 
   /* Otherwise, return the maximum.  The final count will be 64 or more */
 
   else
     {
-      return ATIM_RCR_REP_MAX;
+      return (uint8_t)ATIM_RCR_REP_MAX;
     }
 }
-#endif
+#endif /* HAVE_PWM_INTERRUPT */
 
 /****************************************************************************
  * Name: pwm_set_apb_clock
@@ -1883,15 +3526,16 @@ static uint8_t pwm_pulsecount(uint32_t count)
  *   Enable or disable APB clock for the timer peripheral
  *
  * Input Parameters:
- *   dev - A reference to the lower half PWM driver state structure
- *   on  - Enable clock if 'on' is 'true' and disable if 'false'
+ *   priv - A reference to the PWM block status
+ *   on   - Enable clock if 'on' is 'true' and disable if 'false'
  *
  ****************************************************************************/
 
-static void pwm_set_apb_clock(struct stm32_pwmtimer_s *priv, bool on)
+static int pwm_set_apb_clock(struct stm32_pwmtimer_s *priv, bool on)
 {
-  uint32_t en_bit;
-  uint32_t regaddr;
+  uint32_t en_bit  = 0;
+  uint32_t regaddr = 0;
+  int      ret     = OK;
 
   pwminfo("timer %d clock enable: %d\n", priv->timid, on ? 1 : 0);
 
@@ -1901,102 +3545,124 @@ static void pwm_set_apb_clock(struct stm32_pwmtimer_s *priv, bool on)
     {
 #ifdef CONFIG_STM32F7_TIM1_PWM
       case 1:
-        regaddr  = TIMRCCEN_TIM1;
-        en_bit   = TIMEN_TIM1;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM1;
+          en_bit  = TIMEN_TIM1;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM2_PWM
       case 2:
-        regaddr  = TIMRCCEN_TIM2;
-        en_bit   = TIMEN_TIM2;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM2;
+          en_bit  = TIMEN_TIM2;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM3_PWM
       case 3:
-        regaddr  = TIMRCCEN_TIM3;
-        en_bit   = TIMEN_TIM3;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM3;
+          en_bit  = TIMEN_TIM3;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM4_PWM
       case 4:
-        regaddr  = TIMRCCEN_TIM4;
-        en_bit   = TIMEN_TIM4;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM4;
+          en_bit  = TIMEN_TIM4;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM5_PWM
       case 5:
-        regaddr  = TIMRCCEN_TIM5;
-        en_bit   = TIMEN_TIM5;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM5;
+          en_bit  = TIMEN_TIM5;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM8_PWM
       case 8:
-        regaddr  = TIMRCCEN_TIM8;
-        en_bit   = TIMEN_TIM8;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM8;
+          en_bit  = TIMEN_TIM8;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM9_PWM
       case 9:
-        regaddr  = TIMRCCEN_TIM9;
-        en_bit   = TIMEN_TIM9;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM9;
+          en_bit  = TIMEN_TIM9;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM10_PWM
       case 10:
-        regaddr  = TIMRCCEN_TIM10;
-        en_bit   = TIMEN_TIM10;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM10;
+          en_bit  = TIMEN_TIM10;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM11_PWM
       case 11:
-        regaddr  = TIMRCCEN_TIM11;
-        en_bit   = TIMEN_TIM11;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM11;
+          en_bit  = TIMEN_TIM11;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM12_PWM
       case 12:
-        regaddr  = TIMRCCEN_TIM12;
-        en_bit   = TIMEN_TIM12;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM12;
+          en_bit  = TIMEN_TIM12;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM13_PWM
       case 13:
-        regaddr  = TIMRCCEN_TIM13;
-        en_bit   = TIMEN_TIM13;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM13;
+          en_bit  = TIMEN_TIM13;
+          break;
+        }
 #endif
+
 #ifdef CONFIG_STM32F7_TIM14_PWM
       case 14:
-        regaddr  = TIMRCCEN_TIM14;
-        en_bit   = TIMEN_TIM14;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM15_PWM
-      case 15:
-        regaddr  = TIMRCCEN_TIM15;
-        en_bit   = TIMEN_TIM15;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM16_PWM
-      case 16:
-        regaddr  = TIMRCCEN_TIM16;
-        en_bit   = TIMEN_TIM16;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM17_PWM
-      case 17:
-        regaddr  = TIMRCCEN_TIM17;
-        en_bit   = TIMEN_TIM17;
-        break;
+        {
+          regaddr = TIMRCCEN_TIM14;
+          en_bit  = TIMEN_TIM14;
+          break;
+        }
 #endif
+
       default:
-        return;
+        {
+          pwmerr("ERROR: No such timer configured %d\n", priv->timid);
+          ret = -EINVAL;
+          goto errout;
+        }
     }
 
   /* Enable/disable APB 1/2 clock for timer */
 
-  pwminfo("RCC_APBxENR base: %08lx bits: %04lx\n",
-            regaddr, en_bit);
+  pwminfo("RCC_APBxENR base: %08" PRIx32 "  bits: %04" PRIx32 "\n",
+          regaddr, en_bit);
 
   if (on)
     {
@@ -2006,6 +3672,9 @@ static void pwm_set_apb_clock(struct stm32_pwmtimer_s *priv, bool on)
     {
       modifyreg32(regaddr, en_bit, 0);
     }
+
+errout:
+  return ret;
 }
 
 /****************************************************************************
@@ -2031,34 +3700,90 @@ static void pwm_set_apb_clock(struct stm32_pwmtimer_s *priv, bool on)
 static int pwm_setup(struct pwm_lowerhalf_s *dev)
 {
   struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
-  uint32_t pincfg;
-  int i;
+  uint32_t pincfg = 0;
+  int      ret    = OK;
+  int      i      = 0;
 
   pwminfo("TIM%u\n", priv->timid);
 
   /* Enable APB1/2 clocking for timer. */
 
-  pwm_set_apb_clock(priv, true);
+  ret = pwm_set_apb_clock(priv, true);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-  pwm_dumpregs(priv, "Initially");
+  pwm_dumpregs(dev, "Initially");
 
   /* Configure the PWM output pins, but do not start the timer yet */
 
-  for (i = 0; i < PWM_NCHANNELS; i++)
+  for (i = 0; i < priv->chan_num; i++)
     {
-      pincfg = priv->channels[i].pincfg;
-      if (pincfg == 0)
+      if (priv->channels[i].out1.in_use == 1)
         {
-          continue;
+          /* Do not configure the pin if pincfg is not specified.
+           * This prevents overwriting the PA0 configuration if the
+           * channel is used internally.
+           */
+
+          pincfg = priv->channels[i].out1.pincfg;
+          if (pincfg != 0)
+            {
+              pwminfo("pincfg: %08" PRIx32 "\n", pincfg);
+
+              stm32_configgpio(pincfg);
+              pwm_dumpgpio(pincfg, "PWM setup");
+            }
         }
 
-      pwminfo("pincfg: %08lx\n", pincfg);
+#ifdef HAVE_PWM_COMPLEMENTARY
+      if (priv->channels[i].out2.in_use == 1)
+        {
+          pincfg = priv->channels[i].out2.pincfg;
+
+          /* Do not configure the pin if pincfg is not specified.
+           * This prevents overwriting the PA0 configuration if the
+           * channel is used internally.
+           */
+
+          if (pincfg != 0)
+            {
+              pwminfo("pincfg: %08" PRIx32 "\n", pincfg);
 
-      stm32_configgpio(pincfg);
-      pwm_dumpgpio(pincfg, "PWM setup");
+              stm32_configgpio(pincfg);
+              pwm_dumpgpio(pincfg, "PWM setup");
+            }
+        }
+#endif
     }
 
-  return OK;
+  /* Configure PWM timer with the selected configuration.
+   *
+   * NOTE: We configure PWM here during setup, but leave timer with disabled
+   *       counter, disabled outputs, not configured frequency and duty cycle
+   */
+
+#ifdef CONFIG_PWM_PULSECOUNT
+  if (priv->timtype == TIMTYPE_ADVANCED)
+    {
+      ret = pwm_pulsecount_configure(dev);
+    }
+  else
+#endif
+    {
+      ret = pwm_configure(dev);
+    }
+
+  if (ret < 0)
+    {
+      pwmerr("failed to configure PWM %d\n", priv->timid);
+      ret = ERROR;
+      goto errout;
+    }
+
+errout:
+  return ret;
 }
 
 /****************************************************************************
@@ -2080,8 +3805,9 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev)
 static int pwm_shutdown(struct pwm_lowerhalf_s *dev)
 {
   struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
-  uint32_t pincfg;
-  int i;
+  uint32_t pincfg = 0;
+  int      i      = 0;
+  int      ret    = OK;
 
   pwminfo("TIM%u\n", priv->timid);
 
@@ -2091,27 +3817,43 @@ static int pwm_shutdown(struct pwm_lowerhalf_s *dev)
 
   /* Disable APB1/2 clocking for timer. */
 
-  pwm_set_apb_clock(priv, false);
+  ret = pwm_set_apb_clock(priv, false);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
   /* Then put the GPIO pins back to the default state */
 
-  for (i = 0; i < PWM_NCHANNELS; i++)
+  for (i = 0; i < priv->chan_num; i++)
     {
-      pincfg = priv->channels[i].pincfg;
-      if (pincfg == 0)
+      pincfg = priv->channels[i].out1.pincfg;
+      if (pincfg != 0)
         {
-          continue;
+          pwminfo("pincfg: %08" PRIx32 "\n", pincfg);
+
+          pincfg &= (GPIO_PORT_MASK | GPIO_PIN_MASK);
+          pincfg |= PINCFG_DEFAULT;
+
+          stm32_configgpio(pincfg);
         }
 
-      pwminfo("pincfg: %08lx\n", pincfg);
+#ifdef HAVE_PWM_COMPLEMENTARY
+      pincfg = priv->channels[i].out2.pincfg;
+      if (pincfg != 0)
+        {
+          pwminfo("pincfg: %08" PRIx32 "\n", pincfg);
 
-      pincfg &= (GPIO_PORT_MASK | GPIO_PIN_MASK);
-      pincfg |= GPIO_INPUT | GPIO_FLOAT;
+          pincfg &= (GPIO_PORT_MASK | GPIO_PIN_MASK);
+          pincfg |= PINCFG_DEFAULT;
 
-      stm32_configgpio(pincfg);
+          stm32_configgpio(pincfg);
+        }
+#endif
     }
 
-  return OK;
+errout:
+  return ret;
 }
 
 /****************************************************************************
@@ -2121,7 +3863,7 @@ static int pwm_shutdown(struct pwm_lowerhalf_s *dev)
  *   (Re-)initialize the timer resources and start the pulsed output
  *
  * Input Parameters:
- *   dev - A reference to the lower half PWM driver state structure
+ *   dev  - A reference to the lower half PWM driver state structure
  *   info - A reference to the characteristics of the pulsed output
  *
  * Returned Value:
@@ -2130,12 +3872,19 @@ static int pwm_shutdown(struct pwm_lowerhalf_s *dev)
  ****************************************************************************/
 
 #ifdef CONFIG_PWM_PULSECOUNT
-static int pwm_start(struct pwm_lowerhalf_s *dev,
-                     const struct pwm_info_s *info,
-                     void *handle)
+static int pwm_start_pulsecount(struct pwm_lowerhalf_s *dev,
+                                const struct pwm_info_s *info,
+                                void *handle)
 {
   struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
 
+  /* Generate an indefinite number of pulses */
+
+  if (info->count == 0)
+    {
+      return pwm_start(dev, info);
+    }
+
   /* Check if a pulsecount has been selected */
 
   if (info->count > 0)
@@ -2144,7 +3893,7 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
 
       if (priv->timtype != TIMTYPE_ADVANCED)
         {
-          pwmerr("ERROR: TIM%u cannot support pulse count: %u\n",
+          pwmerr("ERROR: TIM%u cannot support pulse count: %" PRIx32 "\n",
                  priv->timid, info->count);
           return -EPERM;
         }
@@ -2156,16 +3905,16 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
 
   /* Start the time */
 
-  return pwm_timer(priv, info);
+  return pwm_pulsecount_timer(dev, info);
 }
-#else
+#endif /* CONFIG_PWM_PULSECOUNT */
+
 static int pwm_start(struct pwm_lowerhalf_s *dev,
                      const struct pwm_info_s *info)
 {
-  int ret = OK;
   struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
+  int ret = OK;
 
-#ifndef CONFIG_PWM_PULSECOUNT
   /* if frequency has not changed we just update duty */
 
   if (info->frequency == priv->frequency)
@@ -2186,33 +3935,28 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
 
           if (info->channels[i].channel != 0)
             {
-              ret = pwm_update_duty(priv, info->channels[i].channel,
+              ret = pwm_duty_update(dev, info->channels[i].channel,
                                     info->channels[i].duty);
             }
         }
 #else
-      ret = pwm_update_duty(priv, priv->channels[0].channel,
-                            info->duty);
-#endif
+      ret = pwm_duty_update(dev, priv->channels[0].channel, info->duty);
+#endif /* CONFIG_PWM_MULTICHAN */
     }
   else
-#endif
     {
-      ret = pwm_timer(priv, info);
+      ret = pwm_timer(dev, info);
 
-#ifndef CONFIG_PWM_PULSECOUNT
       /* Save current frequency */
 
       if (ret == OK)
         {
           priv->frequency = info->frequency;
         }
-#endif
     }
 
   return ret;
 }
-#endif
 
 /****************************************************************************
  * Name: pwm_stop
@@ -2236,143 +3980,38 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
 static int pwm_stop(struct pwm_lowerhalf_s *dev)
 {
   struct stm32_pwmtimer_s *priv = (struct stm32_pwmtimer_s *)dev;
-  uint32_t resetbit;
-  uint32_t regaddr;
-  uint32_t regval;
-  irqstate_t flags;
+  irqstate_t flags    = 0;
+  uint16_t   outputs  = 0;
+  int        ret = OK;
 
   pwminfo("TIM%u\n", priv->timid);
 
-  /* Determine which timer to reset */
-
-  switch (priv->timid)
-    {
-#ifdef CONFIG_STM32F7_TIM1_PWM
-      case 1:
-        regaddr  = TIMRCCRST_TIM1;
-        resetbit = TIMRST_TIM1;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM2_PWM
-      case 2:
-        regaddr  = TIMRCCRST_TIM2;
-        resetbit = TIMRST_TIM2;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM3_PWM
-      case 3:
-        regaddr  = TIMRCCRST_TIM3;
-        resetbit = TIMRST_TIM3;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM4_PWM
-      case 4:
-        regaddr  = TIMRCCRST_TIM4;
-        resetbit = TIMRST_TIM4;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM5_PWM
-      case 5:
-        regaddr  = TIMRCCRST_TIM5;
-        resetbit = TIMRST_TIM5;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM8_PWM
-      case 8:
-        regaddr  = TIMRCCRST_TIM8;
-        resetbit = TIMRST_TIM8;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM9_PWM
-      case 9:
-        regaddr  = TIMRCCRST_TIM9;
-        resetbit = TIMRST_TIM9;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM10_PWM
-      case 10:
-        regaddr  = TIMRCCRST_TIM10;
-        resetbit = TIMRST_TIM10;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM11_PWM
-      case 11:
-        regaddr  = TIMRCCRST_TIM11;
-        resetbit = TIMRST_TIM11;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM12_PWM
-      case 12:
-        regaddr  = TIMRCCRST_TIM12;
-        resetbit = TIMRST_TIM12;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM13_PWM
-      case 13:
-        regaddr  = TIMRCCRST_TIM13;
-        resetbit = TIMRST_TIM13;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM14_PWM
-      case 14:
-        regaddr  = TIMRCCRST_TIM14;
-        resetbit = TIMRST_TIM14;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM15_PWM
-      case 15:
-        regaddr  = TIMRCCRST_TIM15;
-        resetbit = TIMRST_TIM15;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM16_PWM
-      case 16:
-        regaddr  = TIMRCCRST_TIM16;
-        resetbit = TIMRST_TIM16;
-        break;
-#endif
-#ifdef CONFIG_STM32F7_TIM17_PWM
-      case 17:
-        regaddr  = TIMRCCRST_TIM17;
-        resetbit = TIMRST_TIM17;
-        break;
-#endif
-      default:
-        return -EINVAL;
-    }
-
   /* Disable interrupts momentary to stop any ongoing timer processing and
    * to prevent any concurrent access to the reset register.
    */
 
   flags = enter_critical_section();
 
-#ifndef CONFIG_PWM_PULSECOUNT
   /* Stopped so frequency is zero */
 
   priv->frequency = 0;
-#endif
 
   /* Disable further interrupts and stop the timer */
 
   pwm_putreg(priv, STM32_GTIM_DIER_OFFSET, 0);
   pwm_putreg(priv, STM32_GTIM_SR_OFFSET, 0);
 
-  /* Reset the timer - stopping the output and putting the timer back
-   * into a state where pwm_start() can be called.
-   */
+  /* Disable the timer and timer outputs */
 
-  regval  = getreg32(regaddr);
-  regval |= resetbit;
-  putreg32(regval, regaddr);
+  pwm_timer_enable(dev, false);
+  outputs = pwm_outputs_from_channels(priv);
+  ret = pwm_outputs_enable(dev, outputs, false);
 
-  regval &= ~resetbit;
-  putreg32(regval, regaddr);
   leave_critical_section(flags);
 
-  pwminfo("regaddr: %08lx resetbit: %08lx\n", regaddr, resetbit);
-  pwm_dumpregs(priv, "After stop");
-  return OK;
+  pwm_dumpregs(dev, "After stop");
+
+  return ret;
 }
 
 /****************************************************************************
@@ -2427,7 +4066,7 @@ static int pwm_ioctl(struct pwm_lowerhalf_s *dev, int cmd,
 
 struct pwm_lowerhalf_s *stm32_pwminitialize(int timer)
 {
-  struct stm32_pwmtimer_s *lower;
+  struct stm32_pwmtimer_s *lower = NULL;
 
   pwminfo("TIM%u\n", timer);
 
@@ -2435,114 +4074,125 @@ struct pwm_lowerhalf_s *stm32_pwminitialize(int timer)
     {
 #ifdef CONFIG_STM32F7_TIM1_PWM
       case 1:
-        lower = &g_pwm1dev;
+        {
+          lower = &g_pwm1dev;
 
-        /* Attach but disable the TIM1 update interrupt */
+          /* Attach but disable the TIM1 update interrupt */
 
 #ifdef CONFIG_PWM_PULSECOUNT
-        irq_attach(lower->irq, pwm_tim1interrupt, NULL);
-        up_disable_irq(lower->irq);
+          irq_attach(lower->irq, pwm_tim1interrupt, NULL);
+          up_disable_irq(lower->irq);
 #endif
-        break;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM2_PWM
       case 2:
-        lower = &g_pwm2dev;
-        break;
+        {
+          lower = &g_pwm2dev;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM3_PWM
       case 3:
-        lower = &g_pwm3dev;
-        break;
+        {
+          lower = &g_pwm3dev;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM4_PWM
       case 4:
-        lower = &g_pwm4dev;
-        break;
+        {
+          lower = &g_pwm4dev;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM5_PWM
       case 5:
-        lower = &g_pwm5dev;
-        break;
+        {
+          lower = &g_pwm5dev;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM8_PWM
       case 8:
-        lower = &g_pwm8dev;
+        {
+          lower = &g_pwm8dev;
 
-        /* Attach but disable the TIM8 update interrupt */
+          /* Attach but disable the TIM8 update interrupt */
 
 #ifdef CONFIG_PWM_PULSECOUNT
-        irq_attach(lower->irq, pwm_tim8interrupt, NULL);
-        up_disable_irq(lower->irq);
+          irq_attach(lower->irq, pwm_tim8interrupt, NULL);
+          up_disable_irq(lower->irq);
 #endif
-        break;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM9_PWM
       case 9:
-        lower = &g_pwm9dev;
-        break;
+        {
+          lower = &g_pwm9dev;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM10_PWM
       case 10:
-        lower = &g_pwm10dev;
-        break;
+        {
+          lower = &g_pwm10dev;
+          break;
+        }
+
 #endif
 
 #ifdef CONFIG_STM32F7_TIM11_PWM
       case 11:
-        lower = &g_pwm11dev;
-        break;
+        {
+          lower = &g_pwm11dev;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM12_PWM
       case 12:
-        lower = &g_pwm12dev;
-        break;
+        {
+          lower = &g_pwm12dev;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM13_PWM
       case 13:
-        lower = &g_pwm13dev;
-        break;
+        {
+          lower = &g_pwm13dev;
+          break;
+        }
 #endif
 
 #ifdef CONFIG_STM32F7_TIM14_PWM
       case 14:
-        lower = &g_pwm14dev;
-        break;
-#endif
-
-#ifdef CONFIG_STM32F7_TIM15_PWM
-      case 15:
-        lower = &g_pwm15dev;
-        break;
-#endif
-
-#ifdef CONFIG_STM32F7_TIM16_PWM
-      case 16:
-        lower = &g_pwm16dev;
-        break;
-#endif
-
-#ifdef CONFIG_STM32F7_TIM17_PWM
-      case 17:
-        lower = &g_pwm17dev;
-        break;
+        {
+          lower = &g_pwm14dev;
+          break;
+        }
 #endif
 
       default:
-        pwmerr("ERROR: No such timer configured\n");
-        return NULL;
+        {
+          pwmerr("ERROR: No such timer configured %d\n", timer);
+          lower = NULL;
+          goto errout;
+        }
     }
 
+errout:
   return (struct pwm_lowerhalf_s *)lower;
 }
 
-#endif /* CONFIG_STM32F7_TIMn_PWM, n = 1,...,17 */
+#endif /* CONFIG_STM32F7_PWM */
diff --git a/arch/arm/src/stm32f7/stm32_pwm.h b/arch/arm/src/stm32f7/stm32_pwm.h
index 4e2181adcd..21ebe7cb43 100644
--- a/arch/arm/src/stm32f7/stm32_pwm.h
+++ b/arch/arm/src/stm32f7/stm32_pwm.h
@@ -33,8 +33,15 @@
 
 #include <nuttx/config.h>
 
+#include <nuttx/timers/pwm.h>
+
 #include "chip.h"
 
+#ifdef CONFIG_STM32F7_PWM
+#  include <arch/board/board.h>
+#  include "hardware/stm32_tim.h"
+#endif
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -42,10 +49,10 @@
 /* Configuration ************************************************************/
 
 /* Timer devices may be used for different purposes.  One special purpose is
- * to generate modulated outputs for such things as motor control.  If
- * CONFIG_STM32F7_TIMn is defined then the CONFIG_STM32F7_TIMn_PWM must also
- * be defined to indicate that timer "n" is intended to be used for pulsed
- * output signal generation.
+ * to generate modulated outputs for such things as motor control.
+ * If CONFIG_STM32F7_TIMn is defined then the CONFIG_STM32F7_TIMn_PWM must
+ * also be defined to indicate that timer "n" is intended to be used for
+ * pulsed output signal generation.
  */
 
 #ifndef CONFIG_STM32F7_TIM1
@@ -84,15 +91,6 @@
 #ifndef CONFIG_STM32F7_TIM14
 #  undef CONFIG_STM32F7_TIM14_PWM
 #endif
-#ifndef CONFIG_STM32F7_TIM15
-#  undef CONFIG_STM32F7_TIM15_PWM
-#endif
-#ifndef CONFIG_STM32F7_TIM16
-#  undef CONFIG_STM32F7_TIM16_PWM
-#endif
-#ifndef CONFIG_STM32F7_TIM17
-#  undef CONFIG_STM32F7_TIM17_PWM
-#endif
 
 /* The basic timers (timer 6 and 7) are not capable of generating output
  * pulses
@@ -103,107 +101,62 @@
 
 /* Check if PWM support for any channel is enabled. */
 
-#if defined(CONFIG_STM32F7_TIM1_PWM)  || defined(CONFIG_STM32F7_TIM2_PWM)  || \
-    defined(CONFIG_STM32F7_TIM3_PWM)  || defined(CONFIG_STM32F7_TIM4_PWM)  || \
-    defined(CONFIG_STM32F7_TIM5_PWM)  || defined(CONFIG_STM32F7_TIM8_PWM)  || \
-    defined(CONFIG_STM32F7_TIM9_PWM)  || defined(CONFIG_STM32F7_TIM10_PWM) || \
-    defined(CONFIG_STM32F7_TIM11_PWM) || defined(CONFIG_STM32F7_TIM12_PWM) || \
-    defined(CONFIG_STM32F7_TIM13_PWM) || defined(CONFIG_STM32F7_TIM14_PWM) || \
-    defined(CONFIG_STM32F7_TIM15_PWM) || defined(CONFIG_STM32F7_TIM16_PWM) || \
-    defined(CONFIG_STM32F7_TIM17_PWM)
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <arch/board/board.h>
-#include "hardware/stm32_tim.h"
+#ifdef CONFIG_STM32F7_PWM
 
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
+/* PWM driver channels configuration */
 
-#ifdef CONFIG_PWM_MULTICHAN
+#ifdef CONFIG_STM32F7_PWM_MULTICHAN
 
 #ifdef CONFIG_STM32F7_TIM1_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM1_CH1OUT
-#    define PWM_TIM1_CH1CFG GPIO_TIM1_CH1OUT
-#  else
-#    define PWM_TIM1_CH1CFG 0
-#  endif
 #  define PWM_TIM1_CHANNEL1 1
 #else
 #  define PWM_TIM1_CHANNEL1 0
 #endif
 #ifdef CONFIG_STM32F7_TIM1_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM1_CH2OUT
-#    define PWM_TIM1_CH2CFG GPIO_TIM1_CH2OUT
-#  else
-#    define PWM_TIM1_CH2CFG 0
-#  endif
 #  define PWM_TIM1_CHANNEL2 1
 #else
 #  define PWM_TIM1_CHANNEL2 0
 #endif
 #ifdef CONFIG_STM32F7_TIM1_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM1_CH3OUT
-#    define PWM_TIM1_CH3CFG GPIO_TIM1_CH3OUT
-#  else
-#    define PWM_TIM1_CH3CFG 0
-#  endif
 #  define PWM_TIM1_CHANNEL3 1
 #else
 #  define PWM_TIM1_CHANNEL3 0
 #endif
 #ifdef CONFIG_STM32F7_TIM1_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM1_CH4OUT
-#    define PWM_TIM1_CH4CFG GPIO_TIM1_CH4OUT
-#  else
-#    define PWM_TIM1_CH4CFG 0
-#  endif
 #  define PWM_TIM1_CHANNEL4 1
 #else
 #  define PWM_TIM1_CHANNEL4 0
 #endif
+#ifdef CONFIG_STM32F7_TIM1_CHANNEL5
+#  define PWM_TIM1_CHANNEL5 1
+#else
+#  define PWM_TIM1_CHANNEL5 0
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CHANNEL6
+#  define PWM_TIM1_CHANNEL6 1
+#else
+#  define PWM_TIM1_CHANNEL6 0
+#endif
 #define PWM_TIM1_NCHANNELS (PWM_TIM1_CHANNEL1 + PWM_TIM1_CHANNEL2 + \
-                            PWM_TIM1_CHANNEL3 + PWM_TIM1_CHANNEL4)
+                            PWM_TIM1_CHANNEL3 + PWM_TIM1_CHANNEL4 + \
+                            PWM_TIM1_CHANNEL5 + PWM_TIM1_CHANNEL6)
 
 #ifdef CONFIG_STM32F7_TIM2_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM2_CH1OUT
-#    define PWM_TIM2_CH1CFG GPIO_TIM2_CH1OUT_1
-#  else
-#    define PWM_TIM2_CH1CFG 0
-#  endif
 #  define PWM_TIM2_CHANNEL1 1
 #else
 #  define PWM_TIM2_CHANNEL1 0
 #endif
 #ifdef CONFIG_STM32F7_TIM2_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM2_CH2OUT
-#    define PWM_TIM2_CH2CFG GPIO_TIM2_CH2OUT
-#  else
-#    define PWM_TIM2_CH2CFG 0
-#  endif
 #  define PWM_TIM2_CHANNEL2 1
 #else
 #  define PWM_TIM2_CHANNEL2 0
 #endif
 #ifdef CONFIG_STM32F7_TIM2_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM2_CH3OUT
-#    define PWM_TIM2_CH3CFG GPIO_TIM2_CH3OUT
-#  else
-#    define PWM_TIM2_CH3CFG 0
-#  endif
 #  define PWM_TIM2_CHANNEL3 1
 #else
 #  define PWM_TIM2_CHANNEL3 0
 #endif
 #ifdef CONFIG_STM32F7_TIM2_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM2_CH4OUT
-#    define PWM_TIM2_CH4CFG GPIO_TIM2_CH4OUT
-#  else
-#    define PWM_TIM2_CH4CFG 0
-#  endif
 #  define PWM_TIM2_CHANNEL4 1
 #else
 #  define PWM_TIM2_CHANNEL4 0
@@ -212,41 +165,21 @@
                             PWM_TIM2_CHANNEL3 + PWM_TIM2_CHANNEL4)
 
 #ifdef CONFIG_STM32F7_TIM3_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM3_CH1OUT
-#    define PWM_TIM3_CH1CFG GPIO_TIM3_CH1OUT
-#  else
-#    define PWM_TIM3_CH1CFG 0
-#  endif
 #  define PWM_TIM3_CHANNEL1 1
 #else
 #  define PWM_TIM3_CHANNEL1 0
 #endif
 #ifdef CONFIG_STM32F7_TIM3_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM3_CH2OUT
-#    define PWM_TIM3_CH2CFG GPIO_TIM3_CH2OUT
-#  else
-#    define PWM_TIM3_CH2CFG 0
-#  endif
 #  define PWM_TIM3_CHANNEL2 1
 #else
 #  define PWM_TIM3_CHANNEL2 0
 #endif
 #ifdef CONFIG_STM32F7_TIM3_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM3_CH3OUT
-#    define PWM_TIM3_CH3CFG GPIO_TIM3_CH3OUT
-#  else
-#    define PWM_TIM3_CH3CFG 0
-#  endif
 #  define PWM_TIM3_CHANNEL3 1
 #else
 #  define PWM_TIM3_CHANNEL3 0
 #endif
 #ifdef CONFIG_STM32F7_TIM3_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM3_CH4OUT
-#    define PWM_TIM3_CH4CFG GPIO_TIM3_CH4OUT
-#  else
-#    define PWM_TIM3_CH4CFG 0
-#  endif
 #  define PWM_TIM3_CHANNEL4 1
 #else
 #  define PWM_TIM3_CHANNEL4 0
@@ -255,41 +188,21 @@
                             PWM_TIM3_CHANNEL3 + PWM_TIM3_CHANNEL4)
 
 #ifdef CONFIG_STM32F7_TIM4_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM4_CH1OUT
-#    define PWM_TIM4_CH1CFG GPIO_TIM4_CH1OUT
-#  else
-#    define PWM_TIM4_CH1CFG 0
-#  endif
 #  define PWM_TIM4_CHANNEL1 1
 #else
 #  define PWM_TIM4_CHANNEL1 0
 #endif
 #ifdef CONFIG_STM32F7_TIM4_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM4_CH2OUT
-#    define PWM_TIM4_CH2CFG GPIO_TIM4_CH2OUT
-#  else
-#    define PWM_TIM4_CH2CFG 0
-#  endif
 #  define PWM_TIM4_CHANNEL2 1
 #else
 #  define PWM_TIM4_CHANNEL2 0
 #endif
 #ifdef CONFIG_STM32F7_TIM4_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM4_CH3OUT
-#    define PWM_TIM4_CH3CFG GPIO_TIM4_CH3OUT
-#  else
-#    define PWM_TIM4_CH3CFG 0
-#  endif
 #  define PWM_TIM4_CHANNEL3 1
 #else
 #  define PWM_TIM4_CHANNEL3 0
 #endif
 #ifdef CONFIG_STM32F7_TIM4_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM4_CH4OUT
-#    define PWM_TIM4_CH4CFG GPIO_TIM4_CH4OUT
-#  else
-#    define PWM_TIM4_CH4CFG 0
-#  endif
 #  define PWM_TIM4_CHANNEL4 1
 #else
 #  define PWM_TIM4_CHANNEL4 0
@@ -298,41 +211,21 @@
                             PWM_TIM4_CHANNEL3 + PWM_TIM4_CHANNEL4)
 
 #ifdef CONFIG_STM32F7_TIM5_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM5_CH1OUT
-#    define PWM_TIM5_CH1CFG GPIO_TIM5_CH1OUT
-#  else
-#    define PWM_TIM5_CH1CFG 0
-#  endif
 #  define PWM_TIM5_CHANNEL1 1
 #else
 #  define PWM_TIM5_CHANNEL1 0
 #endif
 #ifdef CONFIG_STM32F7_TIM5_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM5_CH2OUT
-#    define PWM_TIM5_CH2CFG GPIO_TIM5_CH2OUT
-#  else
-#    define PWM_TIM5_CH2CFG 0
-#  endif
 #  define PWM_TIM5_CHANNEL2 1
 #else
 #  define PWM_TIM5_CHANNEL2 0
 #endif
 #ifdef CONFIG_STM32F7_TIM5_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM5_CH3OUT
-#    define PWM_TIM5_CH3CFG GPIO_TIM5_CH3OUT
-#  else
-#    define PWM_TIM5_CH3CFG 0
-#  endif
 #  define PWM_TIM5_CHANNEL3 1
 #else
 #  define PWM_TIM5_CHANNEL3 0
 #endif
 #ifdef CONFIG_STM32F7_TIM5_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM5_CH4OUT
-#    define PWM_TIM5_CH4CFG GPIO_TIM5_CH4OUT
-#  else
-#    define PWM_TIM5_CH4CFG 0
-#  endif
 #  define PWM_TIM5_CHANNEL4 1
 #else
 #  define PWM_TIM5_CHANNEL4 0
@@ -341,371 +234,92 @@
                             PWM_TIM5_CHANNEL3 + PWM_TIM5_CHANNEL4)
 
 #ifdef CONFIG_STM32F7_TIM8_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM8_CH1OUT
-#    define PWM_TIM8_CH1CFG GPIO_TIM8_CH1OUT
-#  else
-#    define PWM_TIM8_CH1CFG 0
-#  endif
 #  define PWM_TIM8_CHANNEL1 1
 #else
 #  define PWM_TIM8_CHANNEL1 0
 #endif
 #ifdef CONFIG_STM32F7_TIM8_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM8_CH2OUT
-#    define PWM_TIM8_CH2CFG GPIO_TIM8_CH2OUT
-#  else
-#    define PWM_TIM8_CH2CFG 0
-#  endif
 #  define PWM_TIM8_CHANNEL2 1
 #else
 #  define PWM_TIM8_CHANNEL2 0
 #endif
 #ifdef CONFIG_STM32F7_TIM8_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM8_CH3OUT
-#    define PWM_TIM8_CH3CFG GPIO_TIM8_CH3OUT
-#  else
-#    define PWM_TIM8_CH3CFG 0
-#  endif
 #  define PWM_TIM8_CHANNEL3 1
 #else
 #  define PWM_TIM8_CHANNEL3 0
 #endif
 #ifdef CONFIG_STM32F7_TIM8_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM8_CH4OUT
-#    define PWM_TIM8_CH4CFG GPIO_TIM8_CH4OUT
-#  else
-#    define PWM_TIM8_CH4CFG 0
-#  endif
 #  define PWM_TIM8_CHANNEL4 1
 #else
 #  define PWM_TIM8_CHANNEL4 0
 #endif
+#ifdef CONFIG_STM32F7_TIM8_CHANNEL5
+#  define PWM_TIM8_CHANNEL5 1
+#else
+#  define PWM_TIM8_CHANNEL5 0
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CHANNEL6
+#  define PWM_TIM8_CHANNEL6 1
+#else
+#  define PWM_TIM8_CHANNEL6 0
+#endif
 #define PWM_TIM8_NCHANNELS (PWM_TIM8_CHANNEL1 + PWM_TIM8_CHANNEL2 + \
-                            PWM_TIM8_CHANNEL3 + PWM_TIM8_CHANNEL4)
+                            PWM_TIM8_CHANNEL3 + PWM_TIM8_CHANNEL4 + \
+                            PWM_TIM8_CHANNEL5 + PWM_TIM8_CHANNEL6)
 
 #ifdef CONFIG_STM32F7_TIM9_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM9_CH1OUT
-#    define PWM_TIM9_CH1CFG GPIO_TIM9_CH1OUT
-#  else
-#    define PWM_TIM9_CH1CFG 0
-#  endif
 #  define PWM_TIM9_CHANNEL1 1
 #else
 #  define PWM_TIM9_CHANNEL1 0
 #endif
 #ifdef CONFIG_STM32F7_TIM9_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM9_CH2OUT
-#    define PWM_TIM9_CH2CFG GPIO_TIM9_CH2OUT
-#  else
-#    define PWM_TIM9_CH2CFG 0
-#  endif
 #  define PWM_TIM9_CHANNEL2 1
 #else
 #  define PWM_TIM9_CHANNEL2 0
 #endif
-#ifdef CONFIG_STM32F7_TIM9_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM9_CH3OUT
-#    define PWM_TIM9_CH3CFG GPIO_TIM9_CH3OUT
-#  else
-#    define PWM_TIM9_CH3CFG 0
-#  endif
-#  define PWM_TIM9_CHANNEL3 1
-#else
-#  define PWM_TIM9_CHANNEL3 0
-#endif
-#ifdef CONFIG_STM32F7_TIM9_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM9_CH4OUT
-#    define PWM_TIM9_CH4CFG GPIO_TIM9_CH4OUT
-#  else
-#    define PWM_TIM9_CH4CFG 0
-#  endif
-#  define PWM_TIM9_CHANNEL4 1
-#else
-#  define PWM_TIM9_CHANNEL4 0
-#endif
-#define PWM_TIM9_NCHANNELS (PWM_TIM9_CHANNEL1 + PWM_TIM9_CHANNEL2 + \
-                            PWM_TIM9_CHANNEL3 + PWM_TIM9_CHANNEL4)
+#define PWM_TIM9_NCHANNELS (PWM_TIM9_CHANNEL1 + PWM_TIM9_CHANNEL2)
 
 #ifdef CONFIG_STM32F7_TIM10_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM10_CH1OUT
-#    define PWM_TIM10_CH1CFG GPIO_TIM10_CH1OUT
-#  else
-#    define PWM_TIM10_CH1CFG 0
-#  endif
 #  define PWM_TIM10_CHANNEL1 1
 #else
 #  define PWM_TIM10_CHANNEL1 0
 #endif
-#ifdef CONFIG_STM32F7_TIM10_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM10_CH2OUT
-#    define PWM_TIM10_CH2CFG GPIO_TIM10_CH2OUT
-#  else
-#    define PWM_TIM10_CH2CFG 0
-#  endif
-#  define PWM_TIM10_CHANNEL2 1
-#else
-#  define PWM_TIM10_CHANNEL2 0
-#endif
-#ifdef CONFIG_STM32F7_TIM10_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM10_CH3OUT
-#    define PWM_TIM10_CH3CFG GPIO_TIM10_CH3OUT
-#  else
-#    define PWM_TIM10_CH3CFG 0
-#  endif
-#  define PWM_TIM10_CHANNEL3 1
-#else
-#  define PWM_TIM10_CHANNEL3 0
-#endif
-#ifdef CONFIG_STM32F7_TIM10_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM10_CH4OUT
-#    define PWM_TIM10_CH4CFG GPIO_TIM10_CH4OUT
-#  else
-#    define PWM_TIM10_CH4CFG 0
-#  endif
-#  define PWM_TIM10_CHANNEL4 1
-#else
-#  define PWM_TIM10_CHANNEL4 0
-#endif
-#define PWM_TIM10_NCHANNELS (PWM_TIM10_CHANNEL1 + PWM_TIM10_CHANNEL2 + \
-                             PWM_TIM10_CHANNEL3 + PWM_TIM10_CHANNEL4)
+#define PWM_TIM10_NCHANNELS (PWM_TIM10_CHANNEL1)
 
 #ifdef CONFIG_STM32F7_TIM11_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM11_CH1OUT
-#    define PWM_TIM11_CH1CFG GPIO_TIM11_CH1OUT
-#  else
-#    define PWM_TIM11_CH1CFG 0
-#  endif
 #  define PWM_TIM11_CHANNEL1 1
 #else
 #  define PWM_TIM11_CHANNEL1 0
 #endif
-#ifdef CONFIG_STM32F7_TIM11_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM11_CH2OUT
-#    define PWM_TIM11_CH2CFG GPIO_TIM11_CH2OUT
-#  else
-#    define PWM_TIM11_CH2CFG 0
-#  endif
-#  define PWM_TIM11_CHANNEL2 1
-#else
-#  define PWM_TIM11_CHANNEL2 0
-#endif
-#ifdef CONFIG_STM32F7_TIM11_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM11_CH3OUT
-#    define PWM_TIM11_CH3CFG GPIO_TIM11_CH3OUT
-#  else
-#    define PWM_TIM11_CH3CFG 0
-#  endif
-#  define PWM_TIM11_CHANNEL3 1
-#else
-#  define PWM_TIM11_CHANNEL3 0
-#endif
-#ifdef CONFIG_STM32F7_TIM11_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM11_CH4OUT
-#    define PWM_TIM11_CH4CFG GPIO_TIM11_CH4OUT
-#  else
-#    define PWM_TIM11_CH4CFG 0
-#  endif
-#  define PWM_TIM11_CHANNEL4 1
-#else
-#  define PWM_TIM11_CHANNEL4 0
-#endif
-#define PWM_TIM11_NCHANNELS (PWM_TIM11_CHANNEL1 + PWM_TIM11_CHANNEL2 + \
-                             PWM_TIM11_CHANNEL3 + PWM_TIM11_CHANNEL4)
+#define PWM_TIM11_NCHANNELS (PWM_TIM11_CHANNEL1)
 
 #ifdef CONFIG_STM32F7_TIM12_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM12_CH1OUT
-#    define PWM_TIM12_CH1CFG GPIO_TIM12_CH1OUT
-#  else
-#    define PWM_TIM12_CH1CFG 0
-#  endif
 #  define PWM_TIM12_CHANNEL1 1
 #else
 #  define PWM_TIM12_CHANNEL1 0
 #endif
 #ifdef CONFIG_STM32F7_TIM12_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM12_CH2OUT
-#    define PWM_TIM12_CH2CFG GPIO_TIM12_CH2OUT
-#  else
-#    define PWM_TIM12_CH2CFG 0
-#  endif
 #  define PWM_TIM12_CHANNEL2 1
 #else
 #  define PWM_TIM12_CHANNEL2 0
 #endif
-#ifdef CONFIG_STM32F7_TIM12_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM12_CH3OUT
-#    define PWM_TIM12_CH3CFG GPIO_TIM12_CH3OUT
-#  else
-#    define PWM_TIM12_CH3CFG 0
-#  endif
-#  define PWM_TIM12_CHANNEL3 1
-#else
-#  define PWM_TIM12_CHANNEL3 0
-#endif
-#ifdef CONFIG_STM32F7_TIM12_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM12_CH4OUT
-#    define PWM_TIM12_CH4CFG GPIO_TIM12_CH4OUT
-#  else
-#    define PWM_TIM12_CH4CFG 0
-#  endif
-#  define PWM_TIM12_CHANNEL4 1
-#else
-#  define PWM_TIM12_CHANNEL4 0
-#endif
-#define PWM_TIM12_NCHANNELS (PWM_TIM12_CHANNEL1 + PWM_TIM12_CHANNEL2 + \
-                             PWM_TIM12_CHANNEL3 + PWM_TIM12_CHANNEL4)
+#define PWM_TIM12_NCHANNELS (PWM_TIM12_CHANNEL1 + PWM_TIM12_CHANNEL2)
 
 #ifdef CONFIG_STM32F7_TIM13_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM13_CH1OUT
-#    define PWM_TIM13_CH1CFG GPIO_TIM13_CH1OUT
-#  else
-#    define PWM_TIM13_CH1CFG 0
-#  endif
 #  define PWM_TIM13_CHANNEL1 1
 #else
 #  define PWM_TIM13_CHANNEL1 0
 #endif
-#ifdef CONFIG_STM32F7_TIM13_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM13_CH2OUT
-#    define PWM_TIM13_CH2CFG GPIO_TIM13_CH2OUT
-#  else
-#    define PWM_TIM13_CH2CFG 0
-#  endif
-#  define PWM_TIM13_CHANNEL2 1
-#else
-#  define PWM_TIM13_CHANNEL2 0
-#endif
-#ifdef CONFIG_STM32F7_TIM13_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM13_CH3OUT
-#    define PWM_TIM13_CH3CFG GPIO_TIM13_CH3OUT
-#  else
-#    define PWM_TIM13_CH3CFG 0
-#  endif
-#  define PWM_TIM13_CHANNEL3 1
-#else
-#  define PWM_TIM13_CHANNEL3 0
-#endif
-#ifdef CONFIG_STM32F7_TIM13_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM13_CH4OUT
-#    define PWM_TIM13_CH4CFG GPIO_TIM13_CH4OUT
-#  else
-#    define PWM_TIM13_CH4CFG 0
-#  endif
-#  define PWM_TIM13_CHANNEL4 1
-#else
-#  define PWM_TIM13_CHANNEL4 0
-#endif
-#define PWM_TIM13_NCHANNELS (PWM_TIM13_CHANNEL1 + PWM_TIM13_CHANNEL2 + \
-                             PWM_TIM13_CHANNEL3 + PWM_TIM13_CHANNEL4)
+#define PWM_TIM13_NCHANNELS (PWM_TIM13_CHANNEL1)
 
 #ifdef CONFIG_STM32F7_TIM14_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM14_CH1OUT
-#    define PWM_TIM14_CH1CFG GPIO_TIM14_CH1OUT
-#  else
-#    define PWM_TIM14_CH1CFG 0
-#  endif
 #  define PWM_TIM14_CHANNEL1 1
 #else
 #  define PWM_TIM14_CHANNEL1 0
 #endif
-#ifdef CONFIG_STM32F7_TIM14_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM14_CH2OUT
-#    define PWM_TIM14_CH2CFG GPIO_TIM14_CH2OUT
-#  else
-#    define PWM_TIM14_CH2CFG 0
-#  endif
-#  define PWM_TIM14_CHANNEL2 1
-#else
-#  define PWM_TIM14_CHANNEL2 0
-#endif
-#ifdef CONFIG_STM32F7_TIM14_CHANNEL3
-#  ifdef CONFIG_STM32F7_TIM14_CH3OUT
-#    define PWM_TIM14_CH3CFG GPIO_TIM14_CH3OUT
-#  else
-#    define PWM_TIM14_CH3CFG 0
-#  endif
-#  define PWM_TIM14_CHANNEL3 1
-#else
-#  define PWM_TIM14_CHANNEL3 0
-#endif
-#ifdef CONFIG_STM32F7_TIM14_CHANNEL4
-#  ifdef CONFIG_STM32F7_TIM14_CH4OUT
-#    define PWM_TIM14_CH4CFG GPIO_TIM14_CH4OUT
-#  else
-#    define PWM_TIM14_CH4CFG 0
-#  endif
-#  define PWM_TIM14_CHANNEL4 1
-#else
-#  define PWM_TIM14_CHANNEL4 0
-#endif
-#define PWM_TIM14_NCHANNELS (PWM_TIM14_CHANNEL1 + PWM_TIM14_CHANNEL2 + \
-                             PWM_TIM14_CHANNEL3 + PWM_TIM14_CHANNEL4)
+#define PWM_TIM14_NCHANNELS (PWM_TIM14_CHANNEL1)
 
-#ifdef CONFIG_STM32F7_TIM15_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM15_CH1OUT
-#    define PWM_TIM15_CH1CFG GPIO_TIM15_CH1OUT
-#  else
-#    define PWM_TIM15_CH1CFG 0
-#  endif
-#  define PWM_TIM15_CHANNEL1 1
-#else
-#  define PWM_TIM15_CHANNEL1 0
-#endif
-#ifdef CONFIG_STM32F7_TIM15_CHANNEL2
-#  ifdef CONFIG_STM32F7_TIM15_CH2OUT
-#    define PWM_TIM15_CH2CFG GPIO_TIM15_CH2OUT
-#  else
-#    define PWM_TIM15_CH2CFG 0
-#  endif
-#  define PWM_TIM15_CHANNEL2 1
-#else
-#  define PWM_TIM15_CHANNEL2 0
-#endif
-#define PWM_TIM15_NCHANNELS (PWM_TIM15_CHANNEL1 + PWM_TIM15_CHANNEL2)
-
-#ifdef CONFIG_STM32F7_TIM16_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM16_CH1OUT
-#    define PWM_TIM16_CH1CFG GPIO_TIM16_CH1OUT
-#  else
-#    define PWM_TIM16_CH1CFG 0
-#  endif
-#  define PWM_TIM16_CHANNEL1 1
-#else
-#  define PWM_TIM16_CHANNEL1 0
-#endif
-#define PWM_TIM16_NCHANNELS PWM_TIM16_CHANNEL1
-
-#ifdef CONFIG_STM32F7_TIM17_CHANNEL1
-#  ifdef CONFIG_STM32F7_TIM17_CH1OUT
-#    define PWM_TIM17_CH1CFG GPIO_TIM17_CH1OUT
-#  else
-#    define PWM_TIM17_CH1CFG 0
-#  endif
-#  define PWM_TIM17_CHANNEL1 1
-#else
-#  define PWM_TIM17_CHANNEL1 0
-#endif
-#define PWM_TIM17_NCHANNELS PWM_TIM17_CHANNEL1
-
-#define PWM_MAX(a, b) ((a) > (b) ? (a) : (b))
-
-#define PWM_NCHANNELS PWM_MAX(PWM_TIM1_NCHANNELS, \
-                      PWM_MAX(PWM_TIM2_NCHANNELS, \
-                      PWM_MAX(PWM_TIM3_NCHANNELS, \
-                      PWM_MAX(PWM_TIM4_NCHANNELS, \
-                      PWM_MAX(PWM_TIM5_NCHANNELS, \
-                      PWM_MAX(PWM_TIM8_NCHANNELS, \
-                      PWM_MAX(PWM_TIM9_NCHANNELS, \
-                      PWM_MAX(PWM_TIM10_NCHANNELS, \
-                      PWM_MAX(PWM_TIM11_NCHANNELS, \
-                      PWM_MAX(PWM_TIM12_NCHANNELS, \
-                      PWM_MAX(PWM_TIM13_NCHANNELS, \
-                      PWM_MAX(PWM_TIM14_NCHANNELS, \
-                      PWM_MAX(PWM_TIM15_NCHANNELS, \
-                      PWM_MAX(PWM_TIM16_NCHANNELS, \
-                              PWM_TIM17_NCHANNELS))))))))))))))
-
-#else
+#else  /* !CONFIG_PWM_MULTICHAN */
 
 /* For each timer that is enabled for PWM usage, we need the following
  * additional configuration settings:
@@ -726,22 +340,19 @@
 #  elif CONFIG_STM32F7_TIM1_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM1_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM1_CH1MODE  CONFIG_STM32F7_TIM1_CHMODE
-#    define PWM_TIM1_CH1CFG            GPIO_TIM1_CH1OUT
 #  elif CONFIG_STM32F7_TIM1_CHANNEL == 2
 #    define CONFIG_STM32F7_TIM1_CHANNEL2 1
 #    define CONFIG_STM32F7_TIM1_CH2MODE  CONFIG_STM32F7_TIM1_CHMODE
-#    define PWM_TIM1_CH2CFG            GPIO_TIM1_CH2OUT
 #  elif CONFIG_STM32F7_TIM1_CHANNEL == 3
 #    define CONFIG_STM32F7_TIM1_CHANNEL3 1
 #    define CONFIG_STM32F7_TIM1_CH3MODE  CONFIG_STM32F7_TIM1_CHMODE
-#    define PWM_TIM1_CH3CFG            GPIO_TIM1_CH3OUT
 #  elif CONFIG_STM32F7_TIM1_CHANNEL == 4
 #    define CONFIG_STM32F7_TIM1_CHANNEL4 1
 #    define CONFIG_STM32F7_TIM1_CH4MODE  CONFIG_STM32F7_TIM1_CHMODE
-#    define PWM_TIM1_CH4CFG            GPIO_TIM1_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM1_CHANNEL"
 #  endif
+#  define PWM_TIM1_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM2_PWM
@@ -750,22 +361,19 @@
 #  elif CONFIG_STM32F7_TIM2_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM2_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM2_CH1MODE  CONFIG_STM32F7_TIM2_CHMODE
-#    define PWM_TIM2_CH1CFG            GPIO_TIM2_CH1OUT_1
 #  elif CONFIG_STM32F7_TIM2_CHANNEL == 2
 #    define CONFIG_STM32F7_TIM2_CHANNEL2 1
 #    define CONFIG_STM32F7_TIM2_CH2MODE  CONFIG_STM32F7_TIM2_CHMODE
-#    define PWM_TIM2_CH2CFG            GPIO_TIM2_CH2OUT
 #  elif CONFIG_STM32F7_TIM2_CHANNEL == 3
 #    define CONFIG_STM32F7_TIM2_CHANNEL3 1
 #    define CONFIG_STM32F7_TIM2_CH3MODE  CONFIG_STM32F7_TIM2_CHMODE
-#    define PWM_TIM2_CH3CFG            GPIO_TIM2_CH3OUT
 #  elif CONFIG_STM32F7_TIM2_CHANNEL == 4
 #    define CONFIG_STM32F7_TIM2_CHANNEL4 1
 #    define CONFIG_STM32F7_TIM2_CH4MODE  CONFIG_STM32F7_TIM2_CHMODE
-#    define PWM_TIM2_CH4CFG            GPIO_TIM2_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM2_CHANNEL"
 #  endif
+#  define PWM_TIM2_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM3_PWM
@@ -774,22 +382,19 @@
 #  elif CONFIG_STM32F7_TIM3_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM3_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM3_CH1MODE  CONFIG_STM32F7_TIM3_CHMODE
-#    define PWM_TIM3_CH1CFG            GPIO_TIM3_CH1OUT
 #  elif CONFIG_STM32F7_TIM3_CHANNEL == 2
 #    define CONFIG_STM32F7_TIM3_CHANNEL2 1
 #    define CONFIG_STM32F7_TIM3_CH2MODE  CONFIG_STM32F7_TIM3_CHMODE
-#    define PWM_TIM3_CH2CFG            GPIO_TIM3_CH2OUT
 #  elif CONFIG_STM32F7_TIM3_CHANNEL == 3
 #    define CONFIG_STM32F7_TIM3_CHANNEL3 1
 #    define CONFIG_STM32F7_TIM3_CH3MODE  CONFIG_STM32F7_TIM3_CHMODE
-#    define PWM_TIM3_CH3CFG            GPIO_TIM3_CH3OUT
 #  elif CONFIG_STM32F7_TIM3_CHANNEL == 4
 #    define CONFIG_STM32F7_TIM3_CHANNEL4 1
 #    define CONFIG_STM32F7_TIM3_CH4MODE  CONFIG_STM32F7_TIM3_CHMODE
-#    define PWM_TIM3_CH4CFG            GPIO_TIM3_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM3_CHANNEL"
 #  endif
+#  define PWM_TIM3_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM4_PWM
@@ -798,22 +403,19 @@
 #  elif CONFIG_STM32F7_TIM4_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM4_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM4_CH1MODE  CONFIG_STM32F7_TIM4_CHMODE
-#    define PWM_TIM4_CH1CFG            GPIO_TIM4_CH1OUT
 #  elif CONFIG_STM32F7_TIM4_CHANNEL == 2
 #    define CONFIG_STM32F7_TIM4_CHANNEL2 1
 #    define CONFIG_STM32F7_TIM4_CH2MODE  CONFIG_STM32F7_TIM4_CHMODE
-#    define PWM_TIM4_CH2CFG            GPIO_TIM4_CH2OUT
 #  elif CONFIG_STM32F7_TIM4_CHANNEL == 3
 #    define CONFIG_STM32F7_TIM4_CHANNEL3 1
 #    define CONFIG_STM32F7_TIM4_CH3MODE  CONFIG_STM32F7_TIM4_CHMODE
-#    define PWM_TIM4_CH3CFG            GPIO_TIM4_CH3OUT
 #  elif CONFIG_STM32F7_TIM4_CHANNEL == 4
 #    define CONFIG_STM32F7_TIM4_CHANNEL4 1
 #    define CONFIG_STM32F7_TIM4_CH4MODE  CONFIG_STM32F7_TIM4_CHMODE
-#    define PWM_TIM4_CH4CFG            GPIO_TIM4_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM4_CHANNEL"
 #  endif
+#  define PWM_TIM4_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM5_PWM
@@ -822,22 +424,19 @@
 #  elif CONFIG_STM32F7_TIM5_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM5_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM5_CH1MODE  CONFIG_STM32F7_TIM5_CHMODE
-#    define PWM_TIM5_CH1CFG            GPIO_TIM5_CH1OUT
 #  elif CONFIG_STM32F7_TIM5_CHANNEL == 2
 #    define CONFIG_STM32F7_TIM5_CHANNEL2 1
 #    define CONFIG_STM32F7_TIM5_CH2MODE  CONFIG_STM32F7_TIM5_CHMODE
-#    define PWM_TIM5_CH2CFG            GPIO_TIM5_CH2OUT
 #  elif CONFIG_STM32F7_TIM5_CHANNEL == 3
 #    define CONFIG_STM32F7_TIM5_CHANNEL3 1
 #    define CONFIG_STM32F7_TIM5_CH3MODE  CONFIG_STM32F7_TIM5_CHMODE
-#    define PWM_TIM5_CH3CFG            GPIO_TIM5_CH3OUT
 #  elif CONFIG_STM32F7_TIM5_CHANNEL == 4
 #    define CONFIG_STM32F7_TIM5_CHANNEL4 1
 #    define CONFIG_STM32F7_TIM5_CH4MODE  CONFIG_STM32F7_TIM5_CHMODE
-#    define PWM_TIM5_CH4CFG            GPIO_TIM5_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM5_CHANNEL"
 #  endif
+#  define PWM_TIM5_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM8_PWM
@@ -846,22 +445,19 @@
 #  elif CONFIG_STM32F7_TIM8_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM8_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM8_CH1MODE  CONFIG_STM32F7_TIM8_CHMODE
-#    define PWM_TIM8_CH1CFG            GPIO_TIM8_CH1OUT
 #  elif CONFIG_STM32F7_TIM8_CHANNEL == 2
 #    define CONFIG_STM32F7_TIM8_CHANNEL2 1
 #    define CONFIG_STM32F7_TIM8_CH2MODE  CONFIG_STM32F7_TIM8_CHMODE
-#    define PWM_TIM8_CH2CFG            GPIO_TIM8_CH2OUT
 #  elif CONFIG_STM32F7_TIM8_CHANNEL == 3
 #    define CONFIG_STM32F7_TIM8_CHANNEL3 1
 #    define CONFIG_STM32F7_TIM8_CH3MODE  CONFIG_STM32F7_TIM8_CHMODE
-#    define PWM_TIM8_CH3CFG            GPIO_TIM8_CH3OUT
 #  elif CONFIG_STM32F7_TIM8_CHANNEL == 4
 #    define CONFIG_STM32F7_TIM8_CHANNEL4 1
 #    define CONFIG_STM32F7_TIM8_CH4MODE  CONFIG_STM32F7_TIM8_CHMODE
-#    define PWM_TIM8_CH4CFG            GPIO_TIM8_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM8_CHANNEL"
 #  endif
+#  define PWM_TIM8_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM9_PWM
@@ -870,22 +466,13 @@
 #  elif CONFIG_STM32F7_TIM9_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM9_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM9_CH1MODE  CONFIG_STM32F7_TIM9_CHMODE
-#    define PWM_TIM9_CH1CFG            GPIO_TIM9_CH1OUT
 #  elif CONFIG_STM32F7_TIM9_CHANNEL == 2
 #    define CONFIG_STM32F7_TIM9_CHANNEL2 1
 #    define CONFIG_STM32F7_TIM9_CH2MODE  CONFIG_STM32F7_TIM9_CHMODE
-#    define PWM_TIM9_CH2CFG            GPIO_TIM9_CH2OUT
-#  elif CONFIG_STM32F7_TIM9_CHANNEL == 3
-#    define CONFIG_STM32F7_TIM9_CHANNEL3 1
-#    define CONFIG_STM32F7_TIM9_CH3MODE  CONFIG_STM32F7_TIM9_CHMODE
-#    define PWM_TIM9_CH3CFG            GPIO_TIM9_CH3OUT
-#  elif CONFIG_STM32F7_TIM9_CHANNEL == 4
-#    define CONFIG_STM32F7_TIM9_CHANNEL4 1
-#    define CONFIG_STM32F7_TIM9_CH4MODE  CONFIG_STM32F7_TIM9_CHMODE
-#    define PWM_TIM9_CH4CFG            GPIO_TIM9_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM9_CHANNEL"
 #  endif
+#  define PWM_TIM9_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM10_PWM
@@ -894,22 +481,10 @@
 #  elif CONFIG_STM32F7_TIM10_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM10_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM10_CH1MODE  CONFIG_STM32F7_TIM10_CHMODE
-#    define PWM_TIM10_CH1CFG            GPIO_TIM10_CH1OUT
-#  elif CONFIG_STM32F7_TIM10_CHANNEL == 2
-#    define CONFIG_STM32F7_TIM10_CHANNEL2 1
-#    define CONFIG_STM32F7_TIM10_CH2MODE  CONFIG_STM32F7_TIM10_CHMODE
-#    define PWM_TIM10_CH2CFG            GPIO_TIM10_CH2OUT
-#  elif CONFIG_STM32F7_TIM10_CHANNEL == 3
-#    define CONFIG_STM32F7_TIM10_CHANNEL3 1
-#    define CONFIG_STM32F7_TIM10_CH3MODE  CONFIG_STM32F7_TIM10_CHMODE
-#    define PWM_TIM10_CH3CFG            GPIO_TIM10_CH3OUT
-#  elif CONFIG_STM32F7_TIM10_CHANNEL == 4
-#    define CONFIG_STM32F7_TIM10_CHANNEL4 1
-#    define CONFIG_STM32F7_TIM10_CH4MODE  CONFIG_STM32F7_TIM10_CHMODE
-#    define PWM_TIM10_CH4CFG            GPIO_TIM10_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM10_CHANNEL"
 #  endif
+#  define PWM_TIM10_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM11_PWM
@@ -918,22 +493,10 @@
 #  elif CONFIG_STM32F7_TIM11_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM11_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM11_CH1MODE  CONFIG_STM32F7_TIM11_CHMODE
-#    define PWM_TIM11_CH1CFG            GPIO_TIM11_CH1OUT
-#  elif CONFIG_STM32F7_TIM11_CHANNEL == 2
-#    define CONFIG_STM32F7_TIM11_CHANNEL2 1
-#    define CONFIG_STM32F7_TIM11_CH2MODE  CONFIG_STM32F7_TIM11_CHMODE
-#    define PWM_TIM11_CH2CFG            GPIO_TIM11_CH2OUT
-#  elif CONFIG_STM32F7_TIM11_CHANNEL == 3
-#    define CONFIG_STM32F7_TIM11_CHANNEL3 1
-#    define CONFIG_STM32F7_TIM11_CH3MODE  CONFIG_STM32F7_TIM11_CHMODE
-#    define PWM_TIM11_CH3CFG            GPIO_TIM11_CH3OUT
-#  elif CONFIG_STM32F7_TIM11_CHANNEL == 4
-#    define CONFIG_STM32F7_TIM11_CHANNEL4 1
-#    define CONFIG_STM32F7_TIM11_CH4MODE  CONFIG_STM32F7_TIM11_CHMODE
-#    define PWM_TIM11_CH4CFG            GPIO_TIM11_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM11_CHANNEL"
 #  endif
+#  define PWM_TIM11_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM12_PWM
@@ -942,22 +505,13 @@
 #  elif CONFIG_STM32F7_TIM12_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM12_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM12_CH1MODE  CONFIG_STM32F7_TIM12_CHMODE
-#    define PWM_TIM12_CH1CFG            GPIO_TIM12_CH1OUT
 #  elif CONFIG_STM32F7_TIM12_CHANNEL == 2
 #    define CONFIG_STM32F7_TIM12_CHANNEL2 1
 #    define CONFIG_STM32F7_TIM12_CH2MODE  CONFIG_STM32F7_TIM12_CHMODE
-#    define PWM_TIM12_CH2CFG            GPIO_TIM12_CH2OUT
-#  elif CONFIG_STM32F7_TIM12_CHANNEL == 3
-#    define CONFIG_STM32F7_TIM12_CHANNEL3 1
-#    define CONFIG_STM32F7_TIM12_CH3MODE  CONFIG_STM32F7_TIM12_CHMODE
-#    define PWM_TIM12_CH3CFG            GPIO_TIM12_CH3OUT
-#  elif CONFIG_STM32F7_TIM12_CHANNEL == 4
-#    define CONFIG_STM32F7_TIM12_CHANNEL4 1
-#    define CONFIG_STM32F7_TIM12_CH4MODE  CONFIG_STM32F7_TIM12_CHMODE
-#    define PWM_TIM12_CH4CFG            GPIO_TIM12_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM12_CHANNEL"
 #  endif
+#  define PWM_TIM12_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM13_PWM
@@ -966,22 +520,10 @@
 #  elif CONFIG_STM32F7_TIM13_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM13_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM13_CH1MODE  CONFIG_STM32F7_TIM13_CHMODE
-#    define PWM_TIM13_CH1CFG            GPIO_TIM13_CH1OUT
-#  elif CONFIG_STM32F7_TIM13_CHANNEL == 2
-#    define CONFIG_STM32F7_TIM13_CHANNEL2 1
-#    define CONFIG_STM32F7_TIM13_CH2MODE  CONFIG_STM32F7_TIM13_CHMODE
-#    define PWM_TIM13_CH2CFG            GPIO_TIM13_CH2OUT
-#  elif CONFIG_STM32F7_TIM13_CHANNEL == 3
-#    define CONFIG_STM32F7_TIM13_CHANNEL3 1
-#    define CONFIG_STM32F7_TIM13_CH3MODE  CONFIG_STM32F7_TIM13_CHMODE
-#    define PWM_TIM13_CH3CFG            GPIO_TIM13_CH3OUT
-#  elif CONFIG_STM32F7_TIM13_CHANNEL == 4
-#    define CONFIG_STM32F7_TIM13_CHANNEL4 1
-#    define CONFIG_STM32F7_TIM13_CH4MODE  CONFIG_STM32F7_TIM13_CHMODE
-#    define PWM_TIM13_CH4CFG            GPIO_TIM13_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM13_CHANNEL"
 #  endif
+#  define PWM_TIM13_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32F7_TIM14_PWM
@@ -990,72 +532,472 @@
 #  elif CONFIG_STM32F7_TIM14_CHANNEL == 1
 #    define CONFIG_STM32F7_TIM14_CHANNEL1 1
 #    define CONFIG_STM32F7_TIM14_CH1MODE  CONFIG_STM32F7_TIM14_CHMODE
-#    define PWM_TIM14_CH1CFG            GPIO_TIM14_CH1OUT
-#  elif CONFIG_STM32F7_TIM14_CHANNEL == 2
-#    define CONFIG_STM32F7_TIM14_CHANNEL2 1
-#    define CONFIG_STM32F7_TIM14_CH2MODE  CONFIG_STM32F7_TIM14_CHMODE
-#    define PWM_TIM14_CH2CFG            GPIO_TIM14_CH2OUT
-#  elif CONFIG_STM32F7_TIM14_CHANNEL == 3
-#    define CONFIG_STM32F7_TIM14_CHANNEL3 1
-#    define CONFIG_STM32F7_TIM14_CH3MODE  CONFIG_STM32F7_TIM14_CHMODE
-#    define PWM_TIM14_CH3CFG            GPIO_TIM14_CH3OUT
-#  elif CONFIG_STM32F7_TIM14_CHANNEL == 4
-#    define CONFIG_STM32F7_TIM14_CHANNEL4 1
-#    define CONFIG_STM32F7_TIM14_CH4MODE  CONFIG_STM32F7_TIM14_CHMODE
-#    define PWM_TIM14_CH4CFG            GPIO_TIM14_CH4OUT
 #  else
 #    error "Unsupported value of CONFIG_STM32F7_TIM14_CHANNEL"
 #  endif
+#  define PWM_TIM14_NCHANNELS 1
 #endif
 
-#ifdef CONFIG_STM32F7_TIM15_PWM
-#  if !defined(CONFIG_STM32F7_TIM15_CHANNEL)
-#    error "CONFIG_STM32F7_TIM15_CHANNEL must be provided"
-#  elif CONFIG_STM32F7_TIM15_CHANNEL == 1
-#    define CONFIG_STM32F7_TIM15_CHANNEL1 1
-#    define CONFIG_STM32F7_TIM15_CH1MODE  CONFIG_STM32F7_TIM15_CHMODE
-#    define PWM_TIM15_CH1CFG            GPIO_TIM15_CH1OUT
-#  elif CONFIG_STM32F7_TIM15_CHANNEL == 2
-#    define CONFIG_STM32F7_TIM15_CHANNEL2 1
-#    define CONFIG_STM32F7_TIM15_CH2MODE  CONFIG_STM32F7_TIM15_CHMODE
-#    define PWM_TIM15_CH2CFG            GPIO_TIM15_CH2OUT
-#  else
-#    error "Unsupported value of CONFIG_STM32F7_TIM15_CHANNEL"
-#  endif
+#endif /* CONFIG_STM32F7_PWM_MULTICHAN */
+
+#ifdef CONFIG_STM32F7_TIM1_CH1OUT
+#  define PWM_TIM1_CH1CFG GPIO_TIM1_CH1OUT
+#else
+#  define PWM_TIM1_CH1CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CH1NOUT
+#  define PWM_TIM1_CH1NCFG GPIO_TIM1_CH1NOUT
+#else
+#  define PWM_TIM1_CH1NCFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CH2OUT
+#  define PWM_TIM1_CH2CFG GPIO_TIM1_CH2OUT
+#else
+#  define PWM_TIM1_CH2CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CH2NOUT
+#  define PWM_TIM1_CH2NCFG GPIO_TIM1_CH2NOUT
+#else
+#  define PWM_TIM1_CH2NCFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CH3OUT
+#  define PWM_TIM1_CH3CFG GPIO_TIM1_CH3OUT
+#else
+#  define PWM_TIM1_CH3CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CH3NOUT
+#  define PWM_TIM1_CH3NCFG GPIO_TIM1_CH3NOUT
+#else
+#  define PWM_TIM1_CH3NCFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM1_CH4OUT
+#  define PWM_TIM1_CH4CFG GPIO_TIM1_CH4OUT
+#else
+#  define PWM_TIM1_CH4CFG 0
 #endif
 
-#ifdef CONFIG_STM32F7_TIM16_PWM
-#  if !defined(CONFIG_STM32F7_TIM16_CHANNEL)
-#    error "CONFIG_STM32F7_TIM16_CHANNEL must be provided"
-#  elif CONFIG_STM32F7_TIM16_CHANNEL == 1
-#    define CONFIG_STM32F7_TIM16_CHANNEL1 1
-#    define CONFIG_STM32F7_TIM16_CH1MODE  CONFIG_STM32F7_TIM16_CHMODE
-#    define PWM_TIM16_CH1CFG            GPIO_TIM16_CH1OUT
-#  else
-#    error "Unsupported value of CONFIG_STM32F7_TIM16_CHANNEL"
-#  endif
+#ifdef CONFIG_STM32F7_TIM2_CH1OUT
+#  define PWM_TIM2_CH1CFG GPIO_TIM2_CH1OUT
+#else
+#  define PWM_TIM2_CH1CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM2_CH2OUT
+#  define PWM_TIM2_CH2CFG GPIO_TIM2_CH2OUT
+#else
+#  define PWM_TIM2_CH2CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM2_CH3OUT
+#  define PWM_TIM2_CH3CFG GPIO_TIM2_CH3OUT
+#else
+#  define PWM_TIM2_CH3CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM2_CH4OUT
+#  define PWM_TIM2_CH4CFG GPIO_TIM2_CH4OUT
+#else
+#  define PWM_TIM2_CH4CFG 0
 #endif
 
-#ifdef CONFIG_STM32F7_TIM17_PWM
-#  if !defined(CONFIG_STM32F7_TIM17_CHANNEL)
-#    error "CONFIG_STM32F7_TIM17_CHANNEL must be provided"
-#  elif CONFIG_STM32F7_TIM17_CHANNEL == 1
-#    define CONFIG_STM32F7_TIM17_CHANNEL1 1
-#    define CONFIG_STM32F7_TIM17_CH1MODE  CONFIG_STM32F7_TIM17_CHMODE
-#    define PWM_TIM17_CH1CFG            GPIO_TIM17_CH1OUT
-#  else
-#    error "Unsupported value of CONFIG_STM32F7_TIM17_CHANNEL"
-#  endif
+#ifdef CONFIG_STM32F7_TIM3_CH1OUT
+#  define PWM_TIM3_CH1CFG GPIO_TIM3_CH1OUT
+#else
+#  define PWM_TIM3_CH1CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM3_CH2OUT
+#  define PWM_TIM3_CH2CFG GPIO_TIM3_CH2OUT
+#else
+#  define PWM_TIM3_CH2CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM3_CH3OUT
+#  define PWM_TIM3_CH3CFG GPIO_TIM3_CH3OUT
+#else
+#  define PWM_TIM3_CH3CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM3_CH4OUT
+#  define PWM_TIM3_CH4CFG GPIO_TIM3_CH4OUT
+#else
+#  define PWM_TIM3_CH4CFG 0
+#endif
+
+#ifdef CONFIG_STM32F7_TIM4_CH1OUT
+#  define PWM_TIM4_CH1CFG GPIO_TIM4_CH1OUT
+#else
+#  define PWM_TIM4_CH1CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM4_CH2OUT
+#  define PWM_TIM4_CH2CFG GPIO_TIM4_CH2OUT
+#else
+#  define PWM_TIM4_CH2CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM4_CH3OUT
+#  define PWM_TIM4_CH3CFG GPIO_TIM4_CH3OUT
+#else
+#  define PWM_TIM4_CH3CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM4_CH4OUT
+#  define PWM_TIM4_CH4CFG GPIO_TIM4_CH4OUT
+#else
+#  define PWM_TIM4_CH4CFG 0
 #endif
 
-#define PWM_NCHANNELS 1
+#ifdef CONFIG_STM32F7_TIM5_CH1OUT
+#  define PWM_TIM5_CH1CFG GPIO_TIM5_CH1OUT
+#else
+#  define PWM_TIM5_CH1CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM5_CH2OUT
+#  define PWM_TIM5_CH2CFG GPIO_TIM5_CH2OUT
+#else
+#  define PWM_TIM5_CH2CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM5_CH3OUT
+#  define PWM_TIM5_CH3CFG GPIO_TIM5_CH3OUT
+#else
+#  define PWM_TIM5_CH3CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM5_CH4OUT
+#  define PWM_TIM5_CH4CFG GPIO_TIM5_CH4OUT
+#else
+#  define PWM_TIM5_CH4CFG 0
+#endif
 
+#ifdef CONFIG_STM32F7_TIM8_CH1OUT
+#  define PWM_TIM8_CH1CFG GPIO_TIM8_CH1OUT
+#else
+#  define PWM_TIM8_CH1CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CH1NOUT
+#  define PWM_TIM8_CH1NCFG GPIO_TIM8_CH1NOUT
+#else
+#  define PWM_TIM8_CH1NCFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CH2OUT
+#  define PWM_TIM8_CH2CFG GPIO_TIM8_CH2OUT
+#else
+#  define PWM_TIM8_CH2CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CH2NOUT
+#  define PWM_TIM8_CH2NCFG GPIO_TIM8_CH2NOUT
+#else
+#  define PWM_TIM8_CH2NCFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CH3OUT
+#  define PWM_TIM8_CH3CFG GPIO_TIM8_CH3OUT
+#else
+#  define PWM_TIM8_CH3CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CH3NOUT
+#  define PWM_TIM8_CH3NCFG GPIO_TIM8_CH3NOUT
+#else
+#  define PWM_TIM8_CH3NCFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM8_CH4OUT
+#  define PWM_TIM8_CH4CFG GPIO_TIM8_CH4OUT
+#else
+#  define PWM_TIM8_CH4CFG 0
+#endif
+
+#ifdef CONFIG_STM32F7_TIM9_CH1OUT
+#  define PWM_TIM9_CH1CFG GPIO_TIM9_CH1OUT
+#else
+#  define PWM_TIM9_CH1CFG 0
+#endif
+
+#ifdef CONFIG_STM32F7_TIM9_CH2OUT
+#  define PWM_TIM9_CH2CFG GPIO_TIM9_CH2OUT
+#else
+#  define PWM_TIM9_CH2CFG 0
+#endif
+
+#ifdef CONFIG_STM32F7_TIM10_CH1OUT
+#  define PWM_TIM10_CH1CFG GPIO_TIM10_CH1OUT
+#else
+#  define PWM_TIM10_CH1CFG 0
+#endif
+
+#ifdef CONFIG_STM32F7_TIM11_CH1OUT
+#  define PWM_TIM11_CH1CFG GPIO_TIM11_CH1OUT
+#else
+#  define PWM_TIM11_CH1CFG 0
+#endif
+
+#ifdef CONFIG_STM32F7_TIM12_CH1OUT
+#  define PWM_TIM12_CH1CFG GPIO_TIM12_CH1OUT
+#else
+#  define PWM_TIM12_CH1CFG 0
+#endif
+#ifdef CONFIG_STM32F7_TIM12_CH2OUT
+#  define PWM_TIM12_CH2CFG GPIO_TIM12_CH2OUT
+#else
+#  define PWM_TIM12_CH2CFG 0
+#endif
+
+#ifdef CONFIG_STM32F7_TIM13_CH1OUT
+#  define PWM_TIM13_CH1CFG GPIO_TIM13_CH1OUT
+#else
+#  define PWM_TIM13_CH1CFG 0
+#endif
+
+#ifdef CONFIG_STM32F7_TIM14_CH1OUT
+#  define PWM_TIM14_CH1CFG GPIO_TIM14_CH1OUT
+#else
+#  define PWM_TIM14_CH1CFG 0
+#endif
+
+/* Complementary outputs support */
+
+#if defined(CONFIG_STM32F7_TIM1_CH1NOUT) || defined(CONFIG_STM32F7_TIM1_CH2NOUT) || \
+    defined(CONFIG_STM32F7_TIM1_CH3NOUT)
+#  define HAVE_TIM1_COMPLEMENTARY
+#endif
+#if defined(CONFIG_STM32F7_TIM8_CH1NOUT) || defined(CONFIG_STM32F7_TIM8_CH2NOUT) || \
+    defined(CONFIG_STM32F7_TIM8_CH3NOUT)
+#  define HAVE_TIM8_COMPLEMENTARY
+#endif
+#if defined(HAVE_TIM1_COMPLEMENTARY) || defined(HAVE_TIM8_COMPLEMENTARY)
+#  define HAVE_PWM_COMPLEMENTARY
+#endif
+
+/* Low-level ops helpers ****************************************************/
+
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+
+/* NOTE:
+ * low-level ops accept pwm_lowerhalf_s as first argument, but llops access
+ *       can be found in stm32_pwm_dev_s
+ */
+
+#define PWM_SETUP(dev)                                                             \
+        (dev)->ops->setup((struct pwm_lowerhalf_s *)dev)
+#define PWM_SHUTDOWN(dev)                                                          \
+        (dev)->ops->shutdown((struct pwm_lowerhalf_s *)dev)
+#define PWM_CCR_UPDATE(dev, index, ccr)                                            \
+        (dev)->llops->ccr_update((struct pwm_lowerhalf_s *)dev, index, ccr)
+#define PWM_MODE_UPDATE(dev, index, mode)                                          \
+        (dev)->llops->mode_update((struct pwm_lowerhalf_s *)dev, index, mode)
+#define PWM_CCR_GET(dev, index)                                                    \
+        (dev)->llops->ccr_get((struct pwm_lowerhalf_s *)dev, index)
+#define PWM_ARR_UPDATE(dev, arr)                                                   \
+        (dev)->llops->arr_update((struct pwm_lowerhalf_s *)dev, arr)
+#define PWM_ARR_GET(dev)                                                           \
+        (dev)->llops->arr_get((struct pwm_lowerhalf_s *)dev)
+#define PWM_RCR_UPDATE(dev, rcr)                                                   \
+        (dev)->llops->rcr_update((struct pwm_lowerhalf_s *)dev, rcr)
+#define PWM_RCR_GET(dev)                                                           \
+        (dev)->llops->rcr_get((struct pwm_lowerhalf_s *)dev)
+#ifdef CONFIG_STM32F7_PWM_TRGO
+#  define PWM_TRGO_SET(dev, trgo)                                                  \
+        (dev)->llops->trgo_set((struct pwm_lowerhalf_s *)dev, trgo)
+#endif
+#define PWM_OUTPUTS_ENABLE(dev, out, state)                                        \
+        (dev)->llops->outputs_enable((struct pwm_lowerhalf_s *)dev, out, state)
+#define PWM_SOFT_UPDATE(dev)                                                       \
+        (dev)->llops->soft_update((struct pwm_lowerhalf_s *)dev)
+#define PWM_CONFIGURE(dev)                                                         \
+        (dev)->llops->configure((struct pwm_lowerhalf_s *)dev)
+#define PWM_SOFT_BREAK(dev, state)                                                 \
+        (dev)->llops->soft_break((struct pwm_lowerhalf_s *)dev, state)
+#define PWM_FREQ_UPDATE(dev, freq)                                                 \
+        (dev)->llops->freq_update((struct pwm_lowerhalf_s *)dev, freq)
+#define PWM_TIM_ENABLE(dev, state)                                                 \
+        (dev)->llops->tim_enable((struct pwm_lowerhalf_s *)dev, state)
+#ifdef CONFIG_DEBUG_PWM_INFO
+#  define PWM_DUMP_REGS(dev, msg)                                                  \
+        (dev)->llops->dump_regs((struct pwm_lowerhalf_s *)dev, msg)
+#else
+#  define PWM_DUMP_REGS(dev, msg)
+#endif
+#define PWM_DT_UPDATE(dev, dt)                                                     \
+        (dev)->llops->dt_update((struct pwm_lowerhalf_s *)dev, dt)
 #endif
 
 /****************************************************************************
  * Public Types
  ****************************************************************************/
 
+/* Timer mode */
+
+enum stm32_pwm_tim_mode_e
+{
+  STM32_TIMMODE_COUNTUP   = 0,
+  STM32_TIMMODE_COUNTDOWN = 1,
+  STM32_TIMMODE_CENTER1   = 2,
+  STM32_TIMMODE_CENTER2   = 3,
+  STM32_TIMMODE_CENTER3   = 4,
+};
+
+/* Timer output polarity */
+
+enum stm32_pwm_pol_e
+{
+  STM32_POL_POS  = 0,
+  STM32_POL_NEG  = 1,
+};
+
+/* Timer output IDLE state */
+
+enum stm32_pwm_idle_e
+{
+  STM32_IDLE_INACTIVE = 0,
+  STM32_IDLE_ACTIVE   = 1
+};
+
+/* PWM channel mode */
+
+enum stm32_pwm_chanmode_e
+{
+  STM32_CHANMODE_FRZN        = 0,  /* CCRx matches has no effects on outputs */
+  STM32_CHANMODE_CHACT       = 1,  /* OCxREF active on match */
+  STM32_CHANMODE_CHINACT     = 2,  /* OCxREF inactive on match */
+  STM32_CHANMODE_OCREFTOG    = 3,  /* OCxREF toggles when TIMy_CNT=TIMyCCRx */
+  STM32_CHANMODE_OCREFLO     = 4,  /* OCxREF is forced low */
+  STM32_CHANMODE_OCREFHI     = 5,  /* OCxREF is forced high */
+  STM32_CHANMODE_PWM1        = 6,  /* PWM mode 1 */
+  STM32_CHANMODE_PWM2        = 7,  /* PWM mode 2 */
+  STM32_CHANMODE_COMBINED1   = 8,  /* Combined PWM mode 1 */
+  STM32_CHANMODE_COMBINED2   = 9,  /* Combined PWM mode 2 */
+  STM32_CHANMODE_ASYMMETRIC1 = 10, /* Asymmetric PWM mode 1 */
+  STM32_CHANMODE_ASYMMETRIC2 = 11, /* Asymmetric PWM mode 2 */
+};
+
+/* PWM timer channel */
+
+enum stm32_pwm_chan_e
+{
+  STM32_PWM_CHAN1  = 1,
+  STM32_PWM_CHAN2  = 2,
+  STM32_PWM_CHAN3  = 3,
+  STM32_PWM_CHAN4  = 4,
+  STM32_PWM_CHAN5  = 5,
+  STM32_PWM_CHAN6  = 6,
+};
+
+/* PWM timer channel output */
+
+enum stm32_pwm_output_e
+{
+  STM32_PWM_OUT1  = (1 << 0),
+  STM32_PWM_OUT1N = (1 << 1),
+  STM32_PWM_OUT2  = (1 << 2),
+  STM32_PWM_OUT2N = (1 << 3),
+  STM32_PWM_OUT3  = (1 << 4),
+  STM32_PWM_OUT3N = (1 << 5),
+  STM32_PWM_OUT4  = (1 << 6),
+
+  /* 1 << 7 reserved - no complementary output for CH4 */
+
+  /* Only available inside micro */
+
+  STM32_PWM_OUT5  = (1 << 8),
+
+  /* 1 << 9 reserved - no complementary output for CH5 */
+
+  STM32_PWM_OUT6  = (1 << 10),
+
+  /* 1 << 11 reserved - no complementary output for CH6 */
+};
+
+#ifdef CONFIG_STM32F7_PWM_LL_OPS
+
+/* This structure provides the publicly visible representation of the
+ * "lower-half" PWM driver structure.
+ */
+
+struct stm32_pwm_dev_s
+{
+  /* The first field of this state structure must be a pointer to the PWM
+   * callback structure to be consistent with upper-half PWM driver.
+   */
+
+  const struct pwm_ops_s *ops;
+
+  /* Publicly visible portion of the "lower-half" PWM driver structure */
+
+  const struct stm32_pwm_ops_s *llops;
+
+  /* Require cast-compatibility with private "lower-half" PWM structure */
+};
+
+/* Low-level operations for PWM */
+
+struct pwm_lowerhalf_s;
+struct stm32_pwm_ops_s
+{
+  /* Update CCR register */
+
+  int (*ccr_update)(struct pwm_lowerhalf_s *dev,
+                    uint8_t index, uint32_t ccr);
+
+  /* Update PWM mode */
+
+  int (*mode_update)(struct pwm_lowerhalf_s *dev,
+                     uint8_t index, uint32_t mode);
+
+  /* Get CCR register */
+
+  uint32_t (*ccr_get)(struct pwm_lowerhalf_s *dev, uint8_t index);
+
+  /* Update ARR register */
+
+  int (*arr_update)(struct pwm_lowerhalf_s *dev, uint32_t arr);
+
+  /* Get ARR register */
+
+  uint32_t (*arr_get)(struct pwm_lowerhalf_s *dev);
+
+  /* Update RCR register */
+
+  int (*rcr_update)(struct pwm_lowerhalf_s *dev, uint16_t rcr);
+
+  /* Get RCR register */
+
+  uint16_t (*rcr_get)(struct pwm_lowerhalf_s *dev);
+
+#ifdef CONFIG_STM32F7_PWM_TRGO
+  /* Set TRGO/TRGO2 register */
+
+  int (*trgo_set)(struct pwm_lowerhalf_s *dev, uint8_t trgo);
+#endif
+
+  /* Enable outputs */
+
+  int (*outputs_enable)(struct pwm_lowerhalf_s *dev, uint16_t outputs,
+                        bool state);
+
+  /* Software update */
+
+  int (*soft_update)(struct pwm_lowerhalf_s *dev);
+
+  /* PWM configure */
+
+  int (*configure)(struct pwm_lowerhalf_s *dev);
+
+  /* Software break */
+
+  int (*soft_break)(struct pwm_lowerhalf_s *dev, bool state);
+
+  /* Update frequency */
+
+  int (*freq_update)(struct pwm_lowerhalf_s *dev, uint32_t frequency);
+
+  /* Enable timer counter */
+
+  int (*tim_enable)(struct pwm_lowerhalf_s *dev, bool state);
+
+#ifdef CONFIG_DEBUG_PWM_INFO
+  /* Dump timer registers */
+
+  void (*dump_regs)(struct pwm_lowerhalf_s *dev, const char *msg);
+#endif
+
+#ifdef HAVE_PWM_COMPLEMENTARY
+  /* Deadtime update */
+
+  int (*dt_update)(struct pwm_lowerhalf_s *dev, uint8_t dt);
+#endif
+};
+
+#endif /* CONFIG_STM32F7_PWM_LL_OPS */
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -1100,5 +1042,5 @@ struct pwm_lowerhalf_s *stm32_pwminitialize(int timer);
 #endif
 
 #endif /* __ASSEMBLY__ */
-#endif /* CONFIG_STM32F7_TIMx_PWM */
+#endif /* CONFIG_STM32F7_PWM */
 #endif /* __ARCH_ARM_SRC_STM32F7_STM32_PWM_H */