Fsl_pwm with Colibri iMX8X

IMX8X datasheet pg 51 mentions.

i.MX 8X features a Timer PWM Modules (TPM), tightly
coupled to f the Cortex M4 core. The TMB is based on a simple timer known for many years from
the HCS08 8-bit microcontrollers. Besides generating PWM signals, it can also be used for input-
capture and output-compare functions. The TPM is dedicated to the M4 core. However, there is a
FlexTimer (FTM) module for the main cores. The FTM builds upon the TPM, but enhances it by
additional dead time insertion hardware, fault control input, signed up counter function, enhancing
the triggering functionality, and allowing the polarity and initialization to be controlled.

I need SODIMM 19 and SODIMM 21 to be used as PWM (duty_cycle to be set in userspace).
I chose these as pinout designer shows these under pwm pins. But I am unable to find any references for imx8x device tree to make these pins work as FTM-PWM.
I need guidance for device tree changes to instantiate 2 pwm on pins 19 and 21, and if it needs any different way to control from userspace.
My other PWMs are controlled using /sys/class/pwm/pwmchip file access

Hey @crsl,

The X1 pins 19 and 21 can be controlled via the Flex Timer Module. Here is the documentation for modifying the device tree : FTM for BSP 6.

A few things to keep in mind:
What OS you are using (I linked for downstream BSP 6) Is this correct?
You will also need to disable device tree nodes that are currently utilizing those pins.
You will need to utilize pin multiplexing for a new pinctrl group via to reference in your new FTM pwm nodes.

Looking at the source driver, it does look like the FTM driver adds the pwm chip to the pwm framework. So you should be able to see it in userspace. I have not validated this though.


Thanks @eric.tx .
OS is multimedia image - uname -r 5.4.115-5.3.0-devel+git.dbdbcabf0f98

From the link you’ve shared, I’ve added following block, I have taken care of the pinctrl (disabled from uart block and created new pingroup)

pwm5: pwm@40038000 {
compatible = “fsl,imx8qm-ftm-pwm”;
reg = <0x40038000 0x1000>;
#pwm-cells = <3>;
clock-names = “ftm_sys”, “ftm_ext”,
“ftm_fix”, “ftm_cnt_clk_en”;
clocks = <&clks IMX8QM_CLK_FTM0>,
pinctrl-names = “default”;
pinctrl-0 = <&pinctrl_pwm0_1>;

I get following error

Error: arch/arm64/boot/dts/freescale/imx8qxp-colibri.dtsi:1424.7-19 syntax error
FATAL ERROR: Unable to parse input tree

It may be due to the unit address (40038000), but I’m not sure which address should I enter here for FSL_PWM. Could you please let me know where to look up these to select the correct one?
Apart from address, do you see any other potential issue?

Hello @crsl,
syntax errors on the device-tree can be caused by different reasons. Since you just posted a snippet I cannot say for sure, but I think you’re missing an & in front of pwm5:

&pwm5: pwm@40038000 {
compatible = “fsl,imx8qm-ftm-pwm”;
reg = <0x40038000 0x1000>;
#pwm-cells = <3>;
clock-names = “ftm_sys”, “ftm_ext”,
“ftm_fix”, “ftm_cnt_clk_en”;
clocks = <&clks IMX8QM_CLK_FTM0>,
pinctrl-names = “default”;
pinctrl-0 = <&pinctrl_pwm0_1>;

You want to change this node instead of create a new one. You have to place the node modifications (addressed with the &) in the root of the device-tree, out of the

/ {                                                                                                                                           
        model = "Toradex Colibri iMX8QXP Module";                                                                                             
        compatible = "toradex,colibri-imx8x", "fsl,imx8qxp";                                                                                  

Also, using the change node syntax, you can leave out the parts you don’t want to change, they will be merged automatically. You could do something like this:

&pwm5 {
pinctrl-0 = <&pinctrl_pwm0_1>;

where pinctrl_pwm0_1 is the node you used to define the new pin settings.
Also please note that the best place to do these modifications would be on the carrier board device-tree (if you create your own you can get our device-trees as base and modify them to match your hardware).

Please don’t forget to disable pinctrl nodes that could be touching the same pins you’re using.


Thanks @rafael.tx ,
When I try to address using &pwm5, I get an error saying label or path pwm5 not found.
The default imx8qxp-colibri.dtsi has &pwm0 , &pwm1 and &pwm2. I can add &pwm3 without error but for 4 and 5 I get the not found error.
does fsl have some different node nomenclature?
Has toradex team used the said PWM F and G with Colibri iMX8X? I have been trying many combinations but due to lack of references, It is like shooting in the dark.

Hey @crsl,

How are you doing with this?

The address you see @ the end of a node is set by the SoC. In this case we would have to go to NXP I.MX8X Application Processor Reference Manual to see what these would be. I believe this involves making a basic account and accepting the terms. But here is the link to get that started. https://www.nxp.com/webapp/sps/download/preDownload.jsp?render=true
If this link doesn’t work, you can search for IMX8DQXPRM in their search bar.

Take a look at LSIO Memory Map (table 2-4). You will see the memory addresses allocated for PWM.

We can also verify this with looking at our device tree includes…
imx8qxp-colibri.dtsi → includes imx8qxp.dtsi → includes “imx8-ss-lsio.dtsi”
which has information regarding our pwm pins…

In the node lsio_subsys, we find our lsio_pwm<0,1,2,3>

 36     lsio_pwm0: pwm@5d000000 {
 35         compatible = "fsl,imx8qm-pwm", "fsl,imx27-pwm";
 34         reg = <0x5d000000 0x10000>;
 33         clock-names = "ipg", "per";
 32         clocks = <&pwm0_lpcg 4>,
 31              <&pwm0_lpcg 1>;
 30         assigned-clocks = <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>;
 29         assigned-clock-rates = <24000000>;
 28         #pwm-cells = <2>;
 27         status = "disabled";
 26     };
 24     lsio_pwm1: pwm@5d010000 {
 23         compatible = "fsl,imx8qm-pwm", "fsl,imx27-pwm";
 22         reg = <0x5d010000 0x10000>;
 21         clock-names = "ipg", "per";
 20         clocks = <&pwm1_lpcg 4>,
 19              <&pwm1_lpcg 1>;
 18         assigned-clocks = <&clk IMX_SC_R_PWM_1 IMX_SC_PM_CLK_PER>;
 17         assigned-clock-rates = <24000000>;
 16         #pwm-cells = <2>;
 15         status = "disabled";
 14     };
 12     lsio_pwm2: pwm@5d020000 {
 11         compatible = "fsl,imx8qm-pwm", "fsl,imx27-pwm";
 10         reg = <0x5d020000 0x10000>;
  9         clock-names = "ipg", "per";
  8         clocks = <&pwm2_lpcg 4>,
  7              <&pwm2_lpcg 1>;
  6         assigned-clocks = <&clk IMX_SC_R_PWM_2 IMX_SC_PM_CLK_PER>;
  5         assigned-clock-rates = <24000000>;
  4         #pwm-cells = <2>;
  3         status = "disabled";
  2     };
67      lsio_pwm3: pwm@5d030000 {
  1         compatible = "fsl,imx8qm-pwm", "fsl,imx27-pwm";
  2         reg = <0x5d030000 0x10000>;
  3         clock-names = "ipg", "per";
  4         clocks = <&pwm3_lpcg 4>,
  5              <&pwm3_lpcg 1>;
  6         assigned-clocks = <&clk IMX_SC_R_PWM_3 IMX_SC_PM_CLK_PER>;
  7         assigned-clock-rates = <24000000>;
  8         #pwm-cells = <2>;
  9         status = "disabled";
 10     };

The second value in reg is reference to the size/increment between the pwm nodes.

lsio_pwm0: pwm@5d000000 
lsio_pwm1: pwm@5d010000
lsio_pwm2: pwm@5d020000 
lsio_pwm3: pwm@5d030000 

So I believe the next two pwm pins would look like this:

pwm4: pwm@5d040000
pwm5: pwm@5d050000

The & is a reference to a node label. So if you don’t already have a pwm node, &pwm has nothing to reference.

You could then assign pinctrl nodes via the &pwm4 and &pwm5.


1424 above is the line number in specified file. So providing only a part of the file please let know as well which line DT compiler error really points to.

Ghm. iMX8X address space is quite big to make blind shot hit the right place. nxp.com provides iMX8X reference manual for free.

If you added cortex-m4 tag, then I assumed you are trying to access FTM PWM from M4. Then why do you care about PWM in Linux DT? You only need to make affected pins not used by status=“okay” peripherals on Linux side.


Where you able to get this working on your system? Have you tried with the new information provided in the previous sent message?