imxrt: add support for PWM synchronization

This commit allows the PWM modules to be synchronized by an external
signal (other PWM module for example). The sync source can be selected
from configuration.

PWM module can also now generate a trigger when its timer reaches the duty
cycle. This trigger is used for the synchronization of other modules. It
can also be used for triggering ADC for example in the future.

Thanks to Rastislav Pavlanin and  Jan Spurek from NXP support for
suggestion which helped to solve the inter-module PWM synchronization
task.

Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
Michal Lenc 2022-09-04 21:12:24 +02:00 committed by Masayuki Ishikawa
parent e586f86918
commit 7d877fbbc3
3 changed files with 597 additions and 39 deletions

View File

@ -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
---

View File

@ -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

View File

@ -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);