diff --git a/Documentation/platforms/arm/imxrt/index.rst b/Documentation/platforms/arm/imxrt/index.rst index 62f946f603d..bfa4b464117 100644 --- a/Documentation/platforms/arm/imxrt/index.rst +++ b/Documentation/platforms/arm/imxrt/index.rst @@ -168,6 +168,47 @@ Pulse width modulator supported in i.MX RT1010 and higher. Multiple channels opt Output on pin B is currently supported only as a complementary option to pin A. The lower-half of this driver is initialize by calling :c:func:`imxrt_pwminitialize`. +PWM module can be synchronized by an external signal. The external signal used for synchronization +is selected by IMXRT_FLEXPWMx_MODx_SYNC_SRC config option. The number in IMXRT_FLEXPWM4_MOD4_SYNC_SRC +corresponds with the XBAR number. Following numbers can be used for synchronization of PWMs with other +PWM module when using iMXRT1020, iMXRT1050 or iMXRT1060. + +- PWM1 Module 1 = 40 +- PWM1 Module 2 = 41 +- PWM1 Module 3 = 42 +- PWM1 Module 4 = 43 +- PWM2 Module 1 = 44 +- PWM2 Module 2 = 45 +- PWM2 Module 3 = 46 +- PWM2 Module 4 = 47 +- PWM3 Module 1 = 48 +- PWM3 Module 2 = 49 +- PWM3 Module 3 = 50 +- PWM3 Module 4 = 51 +- PWM4 Module 1 = 52 +- PWM4 Module 2 = 53 +- PWM4 Module 3 = 54 +- PWM4 Module 4 = 55 + +iMXRT1170 has different XBAR connections: + +- PWM1 Module 1 = 74 +- PWM1 Module 2 = 75 +- PWM1 Module 3 = 76 +- PWM1 Module 4 = 77 +- PWM2 Module 1 = 78 +- PWM2 Module 2 = 79 +- PWM2 Module 3 = 80 +- PWM2 Module 4 = 81 +- PWM3 Module 1 = 82 +- PWM3 Module 2 = 83 +- PWM3 Module 3 = 84 +- PWM3 Module 4 = 85 +- PWM4 Module 1 = 86 +- PWM4 Module 2 = 87 +- PWM4 Module 3 = 88 +- PWM4 Module 4 = 89 + SAI --- diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig index 66d21210e6f..5a3695ae43d 100644 --- a/arch/arm/src/imxrt/Kconfig +++ b/arch/arm/src/imxrt/Kconfig @@ -592,6 +592,27 @@ config IMXRT_FLEXPWM1_MOD1_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM1_MOD1_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM1_PWM1_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM1_MOD1_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM1_MOD1_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM1_MOD2 @@ -604,6 +625,27 @@ config IMXRT_FLEXPWM1_MOD2_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM1_MOD2_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM1_PWM2_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM1_MOD2_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM1_MOD2_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM1_MOD3 @@ -616,6 +658,27 @@ config IMXRT_FLEXPWM1_MOD3_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM1_MOD3_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM1_PWM3_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM1_MOD3_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM1_MOD3_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM1_MOD4 @@ -628,6 +691,27 @@ config IMXRT_FLEXPWM1_MOD4_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM1_MOD4_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM1_PWM4_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM1_MOD4_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM1_MOD4_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif endmenu # IMXRT_FLEXPWM1 @@ -645,6 +729,27 @@ config IMXRT_FLEXPWM2_MOD1_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM2_MOD1_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM2_PWM1_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM2_MOD1_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM2_MOD1_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM2_MOD2 @@ -657,6 +762,27 @@ config IMXRT_FLEXPWM2_MOD2_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM2_MOD2_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM2_PWM2_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM2_MOD2_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM2_MOD2_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM2_MOD3 @@ -669,6 +795,27 @@ config IMXRT_FLEXPWM2_MOD3_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM2_MOD3_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM2_PWM3_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM2_MOD3_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM2_MOD3_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM2_MOD4 @@ -681,6 +828,27 @@ config IMXRT_FLEXPWM2_MOD4_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM2_MOD4_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM2_PWM4_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM2_MOD4_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM2_MOD4_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif endmenu # IMXRT_FLEXPWM2 @@ -698,6 +866,27 @@ config IMXRT_FLEXPWM3_MOD1_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM3_MOD1_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM3_PWM1_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM3_MOD1_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM3_MOD1_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM3_MOD2 @@ -710,6 +899,27 @@ config IMXRT_FLEXPWM3_MOD2_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM3_MOD2_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM3_PWM2_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM3_MOD2_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM3_MOD2_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM3_MOD3 @@ -722,6 +932,27 @@ config IMXRT_FLEXPWM3_MOD3_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM3_MOD3_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM3_PWM3_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM3_MOD3_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM3_MOD3_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM3_MOD4 @@ -734,6 +965,27 @@ config IMXRT_FLEXPWM3_MOD4_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM3_MOD4_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM3_PWM4_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM3_MOD4_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM3_MOD4_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif endmenu # IMXRT_FLEXPWM3 @@ -751,6 +1003,27 @@ config IMXRT_FLEXPWM4_MOD1_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM4_MOD1_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM4_PWM1_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM4_MOD1_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM4_MOD1_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM4_MOD2 @@ -763,6 +1036,27 @@ config IMXRT_FLEXPWM4_MOD2_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM4_MOD2_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM4_PWM2_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM4_MOD2_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM4_MOD2_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM4_MOD3 @@ -775,6 +1069,27 @@ config IMXRT_FLEXPWM4_MOD3_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM4_MOD3_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM4_PWM3_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM4_MOD3_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM4_MOD3_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif config IMXRT_FLEXPWM4_MOD4 @@ -787,6 +1102,27 @@ config IMXRT_FLEXPWM4_MOD4_COMP bool "Use complementary output" default n +config IMXRT_FLEXPWM4_MOD4_TRIG + bool "Enable trigger generation" + default n + ---help--- + Use PWM submodule to trigger FLEXPWM4_PWM4_OUT_TRIG01 output + from submodule 1. This can be used to generate an + interrupt that can trigger ADC conversion or synchronize + other PWMs for example. + +config IMXRT_FLEXPWM4_MOD4_SYNC_SRC + int "Synchronization source signal" + default -1 + range -1 130 + ---help--- + PWM module can be synchronized by an external signal. This + config option selects the signal's source. The number in + IMXRT_FLEXPWM4_MOD4_SYNC_SRC corresponds with the XBAR + number (please refer to the documentation for XBAR numbers). + + -1 (default value) means the module is not to be synchronized. + endif endmenu # IMXRT_FLEXPWM4 diff --git a/arch/arm/src/imxrt/imxrt_flexpwm.c b/arch/arm/src/imxrt/imxrt_flexpwm.c index 6032c18a925..b06cd5751a5 100644 --- a/arch/arm/src/imxrt/imxrt_flexpwm.c +++ b/arch/arm/src/imxrt/imxrt_flexpwm.c @@ -40,6 +40,7 @@ #include "imxrt_config.h" #include "imxrt_flexpwm.h" #include "imxrt_periphclks.h" +#include "imxrt_xbar.h" #include "hardware/imxrt_flexpwm.h" #include "hardware/imxrt_pinmux.h" #include "hardware/imxrt_ccm.h" @@ -57,7 +58,7 @@ #endif #define MODULE_OFFSET 0x60 -#define CLK_FREQ 132000000 +#define CLK_FREQ 150000000 #define PWM_RES 65535 /**************************************************************************** @@ -78,10 +79,13 @@ struct imxrt_flexpwm_module_s { uint8_t module; /* Number of PWM module */ bool used; /* True if the module is used */ + bool trig_en; struct imxrt_flexpwm_out_s out_a; /* PWM output */ struct imxrt_flexpwm_out_s out_b; /* PWM output */ bool complementary; /* True if outputs are complementary */ uint32_t irq; /* Combined interrupt */ + uint16_t ext_sync; + int16_t sync_src; }; struct imxrt_flexpwm_s @@ -134,6 +138,11 @@ static struct imxrt_flexpwm_module_s g_pwm1_modules[] = { .module = 1, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM1_MOD1_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -145,16 +154,24 @@ static struct imxrt_flexpwm_module_s g_pwm1_modules[] = .used = true, .pin = GPIO_FLEXPWM1_MOD1_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM1_MOD1_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM1_EXT_SYNC0_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM1_MOD2 { .module = 2, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM1_MOD2_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -166,16 +183,24 @@ static struct imxrt_flexpwm_module_s g_pwm1_modules[] = .used = true, .pin = GPIO_FLEXPWM1_MOD2_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM1_MOD2_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM1_EXT_SYNC1_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM1_MOD3 { .module = 3, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM1_MOD3_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -187,16 +212,24 @@ static struct imxrt_flexpwm_module_s g_pwm1_modules[] = .used = true, .pin = GPIO_FLEXPWM1_MOD3_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM1_MOD3_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM1_EXT_SYNC2_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM1_MOD4 { .module = 4, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM1_MOD4_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -208,10 +241,13 @@ static struct imxrt_flexpwm_module_s g_pwm1_modules[] = .used = true, .pin = GPIO_FLEXPWM1_MOD4_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM1_MOD4_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM1_EXT_SYNC3_SEL_OFFSET, }, #endif }; @@ -236,6 +272,11 @@ static struct imxrt_flexpwm_module_s g_pwm2_modules[] = { .module = 1, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM2_MOD1_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -247,16 +288,24 @@ static struct imxrt_flexpwm_module_s g_pwm2_modules[] = .used = true, .pin = GPIO_FLEXPWM2_MOD1_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM2_MOD1_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM2_EXT_SYNC0_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM2_MOD2 { .module = 2, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM2_MOD2_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -268,16 +317,24 @@ static struct imxrt_flexpwm_module_s g_pwm2_modules[] = .used = true, .pin = GPIO_FLEXPWM2_MOD2_B } - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM2_MOD2_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM2_EXT_SYNC1_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM2_MOD3 { .module = 3, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM2_MOD3_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -289,16 +346,24 @@ static struct imxrt_flexpwm_module_s g_pwm2_modules[] = .used = true, .pin = GPIO_FLEXPWM2_MOD3_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM2_MOD3_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM2_EXT_SYNC2_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM2_MOD4 { .module = 4, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM2_MOD4_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -310,10 +375,13 @@ static struct imxrt_flexpwm_module_s g_pwm2_modules[] = .used = true, .pin = GPIO_FLEXPWM2_MOD4_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM2_MOD4_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM2_EXT_SYNC3_SEL_OFFSET, } #endif }; @@ -338,6 +406,11 @@ static struct imxrt_flexpwm_module_s g_pwm3_modules[] = { .module = 1, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM3_MOD1_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -349,16 +422,24 @@ static struct imxrt_flexpwm_module_s g_pwm3_modules[] = .used = true, .pin = GPIO_FLEXPWM3_MOD1_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM3_MOD1_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM3_EXT_SYNC0_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM3_MOD2 { .module = 2, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM3_MOD2_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -370,16 +451,24 @@ static struct imxrt_flexpwm_module_s g_pwm3_modules[] = .used = true, .pin = GPIO_FLEXPWM3_MOD2_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM3_MOD2_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM3_EXT_SYNC1_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM3_MOD3 { .module = 3, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM3_MOD3_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -391,16 +480,24 @@ static struct imxrt_flexpwm_module_s g_pwm3_modules[] = .used = true, .pin = GPIO_FLEXPWM3_MOD3_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM3_MOD3_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM3_EXT_SYNC2_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM3_MOD4 { .module = 4, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM3_MOD4_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -412,10 +509,13 @@ static struct imxrt_flexpwm_module_s g_pwm3_modules[] = .used = true, .pin = GPIO_FLEXPWM3_MOD4_B }, - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM3_MOD4_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM3_EXT_SYNC3_SEL_OFFSET, }, #endif }; @@ -440,6 +540,11 @@ static struct imxrt_flexpwm_module_s g_pwm4_modules[] = { .module = 1, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM4_MOD1_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -451,16 +556,24 @@ static struct imxrt_flexpwm_module_s g_pwm4_modules[] = .used = true, .pin = GPIO_FLEXPWM4_MOD1_B } - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM4_MOD1_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM4_EXT_SYNC0_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM4_MOD2 { .module = 2, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM4_MOD2_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -472,16 +585,24 @@ static struct imxrt_flexpwm_module_s g_pwm4_modules[] = .used = true, .pin = GPIO_FLEXPWM4_MOD2_B } - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM4_MOD2_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM4_EXT_SYNC1_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM4_MOD3 { .module = 3, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM4_MOD3_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -493,16 +614,24 @@ static struct imxrt_flexpwm_module_s g_pwm4_modules[] = .used = true, .pin = GPIO_FLEXPWM4_MOD3_B } - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM4_MOD3_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM4_EXT_SYNC3_SEL_OFFSET, }, #endif #ifdef CONFIG_IMXRT_FLEXPWM4_MOD4 { .module = 4, .used = true, +#ifdef CONFIG_IMXRT_FLEXPWM4_MOD4_TRIG + .trig_en = true, +#else + .trig_en = false, +#endif .out_a = { .used = true, @@ -514,10 +643,13 @@ static struct imxrt_flexpwm_module_s g_pwm4_modules[] = .used = true, .pin = GPIO_FLEXPWM4_MOD4_B } - .complementary = true + .complementary = true, #else - .complementary = false + .complementary = false, #endif + .sync_src = IMXRT_XBARA1(XBAR_INPUT, + CONFIG_IMXRT_FLEXPWM4_MOD4_SYNC_SRC), + .ext_sync = IMXRT_XBARA1_OUT_FLEXPWM4_EXT_SYNC4_SEL_OFFSET, }, #endif }; @@ -569,12 +701,12 @@ static int pwm_change_freq(struct pwm_lowerhalf_s *dev, uint16_t regval; uint16_t olddiv = getreg16(priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET + MODULE_OFFSET * shift); - uint32_t newdiv = (CLK_FREQ + (info->frequency / 2)) / info->frequency - 1; + uint32_t newdiv = (CLK_FREQ + (info->frequency / 2)) / info->frequency; uint16_t prescale = 0; while (newdiv > PWM_RES && prescale < 7) { - newdiv = newdiv >> 1; + newdiv = (newdiv + 1) >> 1; prescale++; } @@ -595,7 +727,7 @@ static int pwm_change_freq(struct pwm_lowerhalf_s *dev, putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0CTRL_OFFSET + MODULE_OFFSET * shift); - putreg16(newdiv, priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET + putreg16(newdiv - 1, priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET + MODULE_OFFSET * shift); /* Update VAL0, VAL3 and VAL5 registers */ @@ -704,6 +836,7 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev) uint32_t pin = 0; uint16_t regval; uint8_t shift; + int ret; putreg16(FCTRL0_FLVL(15), priv->base + IMXRT_FLEXPWM_FCTRL0_OFFSET); putreg16(0x000f, priv->base + IMXRT_FLEXPWM_FSTS0_OFFSET); @@ -749,15 +882,18 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev) /* Set control registers 1 and 2 */ + regval = 0; + if (!priv->modules[i].complementary) { /* Enable independent PWM_A and PWM_B output */ - regval = SMCTRL2_INDEP; - putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0CTRL2_OFFSET - + MODULE_OFFSET * shift); + regval |= SMCTRL2_INDEP; } + putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0CTRL2_OFFSET + + MODULE_OFFSET * shift); + regval = SMCTRL_FULL; /* Enable full read cycle reload */ putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0CTRL_OFFSET + MODULE_OFFSET * shift); @@ -777,6 +913,19 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev) putreg16(0, priv->base + IMXRT_FLEXPWM_SM0INIT_OFFSET + MODULE_OFFSET * shift); + /* Set fraction value registers */ + + putreg16(0, priv->base + IMXRT_FLEXPWM_SM0FRACVAL1_OFFSET + + MODULE_OFFSET * shift); + putreg16(0, priv->base + IMXRT_FLEXPWM_SM0FRACVAL2_OFFSET + + MODULE_OFFSET * shift); + putreg16(0, priv->base + IMXRT_FLEXPWM_SM0FRACVAL3_OFFSET + + MODULE_OFFSET * shift); + putreg16(0, priv->base + IMXRT_FLEXPWM_SM0FRACVAL4_OFFSET + + MODULE_OFFSET * shift); + putreg16(0, priv->base + IMXRT_FLEXPWM_SM0FRACVAL5_OFFSET + + MODULE_OFFSET * shift); + /* Set value registers */ putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL0_OFFSET @@ -792,6 +941,38 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev) putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL5_OFFSET + MODULE_OFFSET * shift); + /* Is this PWM set to synchronized by external signal (trigger)? */ + + if (priv->modules[i].sync_src != -1) + { + regval = getreg16(priv->base + IMXRT_FLEXPWM_SM0CTRL2_OFFSET + + MODULE_OFFSET * shift); + regval |= SMCTRL2_INIT_SEL_EXT_SYNC | SMCTRL2_FORCE_SEL_EXT_SYNC | + SMCTRL2_FRCEN; + putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0CTRL2_OFFSET + + MODULE_OFFSET * shift); + + /* Connect corresponding XBARs */ + + ret = imxrt_xbar_connect(priv->modules[i].ext_sync, + priv->modules[i].sync_src); + if (ret < 0) + { + pwmerr("ERROR: imxrt_xbar_connect failed: %d\n", ret); + } + } + + if (priv->modules[i].trig_en) + { + /* Use duty cycle register for trigger generation */ + + regval = getreg16(priv->base + IMXRT_FLEXPWM_SM0TCTRL_OFFSET + + MODULE_OFFSET * shift); + regval |= SMT_OUT_TRIG_EN_VAL1; + putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0TCTRL_OFFSET + + MODULE_OFFSET * shift); + } + regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET); regval |= MCTRL_LDOK(1 << shift); putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);