Enabling PWM on Pin 63 for the Colibri-IMX8X

Here is my tdx-info output

root@zepto-gmr-imx8-26:~# ./tdx-info 

Software summary
------------------------------------------------------------
Bootloader:               U-Boot
Kernel version:           5.4.193-5.7.4-devel+git.61d265bd311b #1 SMP PREEMPT Tue Nov 14 12:41:56 UTC 2023
Kernel command line:      root=PARTUUID=f5773f52-02 ro rootwait video=imxdpufb5:off video=imxdpufb6:off video=imxdpufb7:off
Distro name:              NAME="TDX Wayland with XWayland"
Distro version:           VERSION_ID=5.7.4-devel-20251124203524-build.0
Distro variant:           -
Hostname:                 zepto-gmr-imx8-26
------------------------------------------------------------

Hardware info
------------------------------------------------------------
HW model:                 Toradex Colibri iMX8QXP on Colibri Evaluation Board V3
Toradex version:          0038 V1.0D
Serial number:            06800820
Processor arch:           aarch64
Available block devices:
                          NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
                          mmcblk0 179:0 0 7.1G 0 disk 
                          mmcblk0p1 179:1 0 48M 0 part /boot
                          mmcblk0p2 179:2 0 7G 0 part /
                          mmcblk0boot0 179:32 0 16M 1 disk 
                          mmcblk0boot1 179:64 0 16M 1 disk 
------------------------------------------------------------

On the Toradex Colibri IMX8X I am trying to enabled PWM for pins 63 (PWM_H - ADMA.FTM.CH2, Column heater 1), 61 (PWM3/PWM_E - LSIO.PWM3.OUT, Column heater 2) and 67 (PWM2/PWM_D - LSIO.PWM2.OUT, sample heater). I got pins 67 and 61 working just find but I am having some issues with pin 63. below I have some code snippets showing the device tree changes I am trying to make as well as the output on the SOM. Let me know if you need more information or it looks like I am doing things incorrectly. Thanks for the help!

I made sure that CONFIG_PWM_FSL_FTM is enabled

$ root@zepto-gmr-imx8-26:~# zcat /proc/config.gz | grep CONFIG_PWM_FSL_FTM $ CONFIG_PWM_FSL_FTM=y

Here are my relevant device tree changes
imx8x-colibri.dtsi

…

&iomuxc {
	colibri-imx8qxp {
		
		…
		
		// /* Colibri optional CAN on PS2 /
		// pinctrl_flexcan2: flexcan1grp {
		// 	fsl,pins = <
		// 		IMX8QXP_FLEXCAN1_TX_ADMA_FLEXCAN1_TX 0x21 / SODIMM 55 /
		// 		IMX8QXP_FLEXCAN1_RX_ADMA_FLEXCAN1_RX 0x21 / SODIMM 63 /
		// 	>;
		// };
		
		…
		
		/ PWM Pin for Sample Thermistor Heater (PWMD) /
		pinctrl_pwm_d: pwmd {
			fsl,pins = <
				IMX8QXP_UART1_RTS_B_LSIO_PWM2_OUT 0x60 / SODIMM 67 */
			>;
		};

		/* PWM Pin for Column 2 Thermistor Heater (PWME) */
		pinctrl_pwm_e: pwme {
			fsl,pins = <
				IMX8QXP_UART1_CTS_B_LSIO_PWM3_OUT 0x60 /* SODIMM 61 */
			>;
		};

		/* PWM Pin for Column 1 Thermistor Heater (PWMH) */
		pinctrl_pwm_h: pwmh {
			fsl,pins = <
				IMX8QXP_FLEXCAN1_RX_ADMA_FTM_CH2 0x60 /* SODIMM 63 */
			>;
		};
	}
}

…

imx8x-colibri-eval-v3.dtsi

…

/* Enable PWM for the Sample thermister */
&pwm2 {
	pinctrl-names = “default”;
	pinctrl-0 = <&pinctrl_pwm_d>;
	status = “okay”;
};

&adma_pwm {
	pinctrl-names = “default”;
	pinctrl-0 = <&pinctrl_pwm_h>; /* Use PWM_H instead of PWM_A */
	status = “okay”;
};

/* Enable PWM for the Column 2 heater */
&pwm3 {
	pinctrl-names = “default”;
	pinctrl-0 = <&pinctrl_pwm_e>;
	status = “okay”;
};

/ {
	leds {
		compatible = “pwm-leds”;

		/*
		 * Column 1 Heater (PWM_H / &pwm_adma)
		 * Maps to SODIMM 63
		 */
		col1_heater {
		    label = "col1_heater";
		    pwms = <&adma_pwm 0 1000000 0>; /* 1kHz, normal polarity */
		    max-brightness = <255>;
		    default-brightness-level = <0>; /* Use this for default-off */
		};

		/*
		 * Sample Heater (PWM_D / &pwm2)
		 * Maps to SODIMM 67
		 */
		sample_heater {
		    label = "sample_heater";
		    pwms = <&pwm2 0 1000000 0>; /* 1kHz, normal polarity */
		    max-brightness = <255>;
		    default-brightness-level = <0>; /* Use this for default-off */
		};

		/*
		 * Column 2 Heater (PWM_E / &pwm3)
		 * Maps to SODIMM 61
		 */
		col2_heater {
		    label = "col2_heater";
		    pwms = <&pwm3 0 1000000 0>; /* 1kHz, normal polarity */
		    max-brightness = <255>;
		    default-brightness-level = <0>; /* Use this for default-off */
		};
	};
};

&backlight {
	status = “disabled”;
	/delete-property/ pwms; /* Remove the PWM reference entirely */
};

&flexcan1 {
	status = “disabled”;
	/delete-property/ pinctrl-names;
	/delete-property/ pinctrl-0;
	/delete-property/ xceiver-supply;
};

On the SOM it looks like each heater is being set properly but I don’t get any pwm signal on pin 63 (I do get pwm signals on pins 61 and 67)

root@zepto-gmr-imx8-26:~# cat /sys/kernel/debug/pwm
platform/5d030000.pwm, 1 PWM devicepwm-0 (col2_heater ): requested period: 1000000 ns duty: 0 ns polarity: normal

platform/5d020000.pwm, 1 PWM devicepwm-0 (sample_heater ): requested period: 1000000 ns duty: 0 ns polarity: normal

platform/5a190000.pwm, 1 PWM devicepwm-0 (col1_heater ): requested period: 1000000 ns duty: 0 ns polarity: normal

root@zepto-gmr-imx8-26:~# echo 255 > /sys/class/leds/col1_heater/brightness
root@zepto-gmr-imx8-26:~# echo 255 > /sys/class/leds/col2_heater/brightness
root@zepto-gmr-imx8-26:~# echo 255 > /sys/class/leds/sample_heater/brightness
root@zepto-gmr-imx8-26:~# cat /sys/kernel/debug/pwm
platform/5d030000.pwm, 1 PWM devicepwm-0 (col2_heater ): requested enabled period: 1000000 ns duty: 1000000 ns polarity: normal

platform/5d020000.pwm, 1 PWM devicepwm-0 (sample_heater ): requested enabled period: 1000000 ns duty: 1000000 ns polarity: normal

platform/5a190000.pwm, 1 PWM devicepwm-0 (col1_heater ): requested enabled period: 1000000 ns duty: 1000000 ns polarity: normal

root@zepto-gmr-imx8-26:~# echo 0 > /sys/class/leds/sample_heater/brightness
root@zepto-gmr-imx8-26:~# echo 0 > /sys/class/leds/col2_heater/brightness
root@zepto-gmr-imx8-26:~# echo 0 > /sys/class/leds/col1_heater/brightness
root@zepto-gmr-imx8-26:~# cat /sys/kernel/debug/pwm
platform/5d030000.pwm, 1 PWM devicepwm-0 (col2_heater ): requested period: 1000000 ns duty: 0 ns polarity: normal

platform/5d020000.pwm, 1 PWM devicepwm-0 (sample_heater ): requested period: 1000000 ns duty: 0 ns polarity: normal

platform/5a190000.pwm, 1 PWM devicepwm-0 (col1_heater ): requested period: 1000000 ns duty: 0 ns polarity: normal

Hi, I’m the Toradex AI Assistant.

I might make mistakes or occasionally get you wrong. Our support team will step in if needed.


Looking at your configuration for the Colibri iMX8X, I can see that pins 61 and 67 are working correctly, but pin 63 (SODIMM 63) is not generating a PWM signal despite showing up correctly in the debug output.

Issue Analysis

According to the Colibri iMX8X PWM mapping (1), SODIMM 63 should be using the ADMA_FTM controller, which you’ve correctly referenced as &adma_pwm. However, there are a few potential issues with your configuration:

Pin Mapping Verification

For the Colibri iMX8X, the PWM pin assignments are (1):

Toradex Name NXP/Freescale Name sysfs path Note
PWM_A ADMA_LCD_PWM0 /sys/class/pwm/pwmchip0/ Used for backlight control
PWM_B LSIO_PWM0 /sys/class/pwm/pwmchip1/ -
PWM_C LSIO_PWM1 /sys/class/pwm/pwmchip2/ -
PWM_D LSIO_PWM2 /sys/class/pwm/pwmchip3/ -

Troubleshooting Steps

1. Check FTM Controller Status

First, verify that the FTM controller is properly enabled in your device tree. The FTM controller might need additional configuration beyond just the pinmux settings.

2. Verify Pin Function

Check if SODIMM 63 has any conflicts with other peripherals. You’ve correctly disabled the FlexCAN1 interface, but ensure there are no other conflicting configurations.

3. Clock Configuration

The FTM controller might require specific clock settings that differ from the regular PWM controllers. Check if the &adma_pwm node requires additional clock configuration.

4. Alternative Approach

Since pins 61 and 67 are working with the LSIO PWM controllers, you might want to consider using a different pin that uses one of the working LSIO PWM controllers if your hardware design allows it.

Device Tree Debugging

To debug further, you can:

  1. Check the device tree compilation: Ensure your device tree changes are being applied correctly by examining the compiled device tree blob.

  2. Verify pinmux settings: Use the pinmux debugging tools to confirm that SODIMM 63 is correctly configured for the FTM function.

  3. Test direct PWM access: Try accessing the PWM directly through sysfs instead of through the LED framework to isolate the issue (1):

# cd /sys/class/pwm/pwmchip0/
# echo 0 > export
# echo 1000000 > pwm0/period
# echo 500000 > pwm0/duty_cycle
# echo 1 > pwm0/enable

Recommendation

Given that the software shows the PWM is being configured correctly (as seen in /sys/kernel/debug/pwm), but no signal appears on the pin, this suggests either a pinmux issue or a clock/controller configuration problem specific to the FTM controller. I’d recommend checking the FTM controller’s clock configuration and ensuring all required clocks are enabled for the ADMA domain.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

@ToradexAI

In the “PWM (Linux)” web page it lists these PWM channels for the colibri imx8x

PWM_A ADMA_LCD_PWM0 /sys/class/pwm/pwmchip0/ Used for backlight control (/sys/class/backlight/backlight/)
PWM_B LSIO_PWM0 /sys/class/pwm/pwmchip1/ -
PWM_C LSIO_PWM1 /sys/class/pwm/pwmchip2/ -
PWM_D LSIO_PWM2 /sys/class/pwm/pwmchip3/ -

and also says this “Colibri: 4 PWMs, PWM through PWM . The PWM is traditionally used for display backlight brightness control.”
But in the pinout design tool it lists PWM_A - PWM_J (as well as PWM_M4).

The three I’m trying to use are

PWM_D - Pin 67
PWM_E - Pin 61
PWM_H - Pin 63

Using the pinout design tool the list of possible conflicts I found are

CAN_1_RX
DIGITAL_AUDIO_2_AC97
DIGITAL_AUDIO_2_I2S_MASTER_DOUT
DIGITAL_AUDIO_2_I2S_SLAVE_DOUT
DIGITAL_AUDIO_2_SAI_TX_DATA
GPIO_SODIMM_63
TIMER_1_IN_2

I was thinking that maybe the backlight was conflicting with it so thats why I tried disabling the backlight but that made no difference

Last, how should I go about checking the FTM Controller status and Clock Configuration?

Thank you for the clarification! You’re absolutely correct about the discrepancy between the documentation and the pinout design tool. The key issue is that PWM_H (SODIMM 63) uses the FTM (FlexTimer Module) controller, which is different from the standard LSIO PWM controllers used by PWM_D and PWM_E.

Understanding the PWM Controllers

Based on your configuration, you have:

  • PWM_D (Pin 67): LSIO_PWM2 - Working :white_check_mark:
  • PWM_E (Pin 61): LSIO_PWM3 - Working :white_check_mark:
  • PWM_H (Pin 63): ADMA_FTM_CH2 - Not working :cross_mark:

The FTM controller operates differently from the standard PWM controllers and requires additional configuration.

Checking FTM Controller Status

1. Verify FTM Controller in Device Tree

First, check if the FTM controller node exists and is properly configured. Look for the FTM controller definition in your device tree:

# Check if FTM controller is present in the device tree
find /proc/device-tree -name "*ftm*" -type d

2. Check FTM Driver Status

Verify that the FTM driver is loaded and the controller is recognized:

# Check if FTM driver is loaded
lsmod | grep ftm

# Check FTM controller registration in dmesg
dmesg | grep -i ftm

# Look for PWM controller registration
dmesg | grep -i pwm

3. Clock Configuration Verification

The FTM controller requires specific clock configuration(1). Check the clock status:

# Check clock tree for FTM-related clocks
find /sys/kernel/debug/clk -name "*ftm*" -o -name "*adma*"

# Check if ADMA clocks are enabled
cat /sys/kernel/debug/clk/clk_summary | grep -i adma

Device Tree Configuration Issues

Looking at your device tree, there might be an issue with the FTM controller reference. The FTM controller typically needs to be explicitly defined and enabled. You may need to add or verify the FTM controller node definition(2).

Suggested Device Tree Modifications

In your imx8x-colibri-eval-v3.dtsi, instead of using &adma_pwm, you might need to reference the specific FTM controller. Try modifying your configuration:

/* Enable FTM controller for PWM_H */
&ftm0 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_pwm_h>;
    status = "okay";
};

And in your LED configuration, reference the FTM controller:

col1_heater {
    label = "col1_heater";
    pwms = <&ftm0 2 1000000 0>; /* Channel 2, 1kHz, normal polarity */
    max-brightness = <255>;
    default-brightness-level = <0>;
};

Alternative Debugging Steps

1. Check Pin Function Assignment

Verify that SODIMM 63 is correctly assigned to the FTM function:

# Check current pin function
cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep -A5 -B5 "pin 63"

2. Manual PWM Testing

Try accessing the PWM directly through sysfs to bypass the LED framework:

# Find the correct PWM chip for FTM
ls /sys/class/pwm/

# If there's a pwmchip that corresponds to FTM (might be different from 0-3)
echo 2 > /sys/class/pwm/pwmchipX/export
echo 1000000 > /sys/class/pwm/pwmchipX/pwm2/period
echo 500000 > /sys/class/pwm/pwmchipX/pwm2/duty_cycle
echo 1 > /sys/class/pwm/pwmchipX/pwm2/enable

Conflict Resolution

You mentioned potential conflicts. Since you’ve already disabled FlexCAN1, ensure that no other conflicting peripherals are enabled. The key conflicts to check:

  1. CAN_1_RX: Already disabled :white_check_mark:
  2. Audio interfaces: Check if any SAI or audio controllers are using this pin
  3. Timer functions: Verify no timer peripherals conflict

Next Steps

  1. Check FTM controller presence in your device tree source files
  2. Verify FTM driver loading in kernel logs
  3. Test manual PWM access through sysfs
  4. Review clock configuration for the ADMA domain

The fundamental issue appears to be that the FTM controller requires different handling than the standard LSIO PWM controllers. The FTM controller may not be properly initialized or the device tree reference might be incorrect.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Please note that X1 pin 63 is routed to the FLEXCAN1_RX ball, which can be muxed to the FlexTimer Module (FTM). This is quite different from the “regular” PWM module used for driving standard PWM channels. Your pinctrl_pwm node should be bound to ftm_pwm0: and its clock must also be enabled. Please check this thread:

Hello,

Thank you for the response.

I added this to imx8qxp-ss-adma.dtsi

&dma_subsys {
    // This part already existed
	lcdif_mux_regs: mux-regs@5a170000 {
		compatible = "fsl,imx8qxp-lcdif-mux-regs", "syscon";
		reg = <0x5a170000 0x4>;
	};

	ftm_pwm0: pwm@5a8a0000 {
		compatible = "fsl,vf610-ftm-pwm";
		reg = <0x5A8A0000 0x10000>;
		#pwm-cells = <3>;
		clock-names = "ftm_sys", "ftm_ext", "ftm_fix", "ftm_cnt_clk_en", "ipg";
		clocks = <&ftm0_lpcg 0>,
			<&ftm0_lpcg 0>,
			<&ftm0_lpcg 0>,
			<&ftm0_lpcg 0>,
			<&ftm0_lpcg 1>;
		assigned-clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>;
		assigned-clock-rates = <24000000>;
		power-domains = <&pd IMX_SC_R_LCD_0_PWM_0>;
		big-endian;
		status = "okay";
	};


	ftm0_lpcg: clock-controller@5aca0000 {
		compatible = "fsl,imx8qxp-lpcg";
		reg = <0x5aca0000 0x10000>;
		#clock-cells = <1>;
		clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>,
			<&dma_ipg_clk>;
		bit-offset = <0 16>;
		clock-output-names = "ftm0_lpcg_clk",
			"ftm0_lpcg_ipg_clk";
		power-domains = <&pd IMX_SC_R_FTM_0>;
		status = "okay";
	};
};

In imx8x-colibri.dtsi I changed it to

		pinctrl_ftm_pwm_0: pwm4 {
			fsl,pins = <
				IMX8QXP_UART2_RX_ADMA_FTM_CH0    0x61
			>;
		};

In imx8x-colibri-eval-v3.dtsi I changed it to


/* Disable UART2 to release SODIMM 63 for PWM usage */
&lpuart2 {
    status = "disabled";
};

/* Enable PWM for the Sample thermister */
&pwm2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm_d>; 
	status = "okay";
};

/* Enable PWM for the Column heater 1 */
&ftm_pwm0 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_ftm_pwm_0>;
	status = "okay";
};

/* Enable PWM for the Column heater 2 */
&pwm3 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm_e>; 
	status = "okay";
};

/ {
    leds {
        compatible = "pwm-leds";

        /*
         * Column 1 Heater (PWM_H / &pwm_adma)
         * Maps to SODIMM 63
         */
		col1_heater {
			label = "col1_heater";
			pwms = <&ftm_pwm0 0 1000000 0>; /* Channel 2, 1kHz, normal polarity */
			max-brightness = <255>;
			default-brightness-level = <0>;
		};

        /*
         * Sample Heater (PWM_D / &pwm2)
         * Maps to SODIMM 67
         */
        sample_heater {
            label = "sample_heater";
            pwms = <&pwm2 0 1000000 0>; /* 1kHz, normal polarity */
            max-brightness = <255>;
            default-brightness-level = <0>; /* Use this for default-off */
        };

        /*
         * Column 2 Heater (PWM_E / &pwm3)
         * Maps to SODIMM 61
         */
        col2_heater {
            label = "col2_heater";
            pwms = <&pwm3 0 1000000 0>; /* 1kHz, normal polarity */
            max-brightness = <255>;
            default-brightness-level = <0>; /* Use this for default-off */
        };
    };
};

&backlight {
	status = "disabled";
	/delete-property/ pwms; /* Remove the PWM reference entirely */
};

&flexcan1 {
	status = "disabled";
	/delete-property/ pinctrl-names;
	/delete-property/ pinctrl-0;
	/delete-property/ xceiver-supply;
};

I don’t get anything when I try setting the pwm for col1_heater but I get weird behavior where if I turn on sample_heater or col2_heater than col1_heater turns on. below is a screenshot where channel 1 is sample_heater, channel 2 is col1_heater (not working properly), and channel 3 is col2_heater.

Here is some output from the IMX8X

root@zepto-gmr-imx8-26:~# dmesg | grep -i ftm
[    0.252982] fsl-ftm-pwm 5a8a0000.pwm: regmap init failed
root@zepto-gmr-imx8-26:~# dmesg | grep -i pwm
[    0.252982] fsl-ftm-pwm 5a8a0000.pwm: regmap init failed
[    2.310731] of_pwm_get(): can't parse "pwms" property
[    2.315841] pwm-backlight backlight: unable to request PWM
[    2.315931] pwm-backlight: probe of backlight failed with error -2


root@zepto-gmr-imx8-26:~# echo 126 > /sys/class/leds/col1_heater/brightness
root@zepto-gmr-imx8-26:~# echo 126 > /sys/class/leds/col2_heater/brightness
root@zepto-gmr-imx8-26:~# echo 126 > /sys/class/leds/sample_heater/brightness


root@zepto-gmr-imx8-26:~# cat /sys/kernel/debug/pwm  
platform/5d030000.pwm, 1 PWM device
 pwm-0   (col2_heater         ): requested enabled period: 1000000 ns duty: 494117 ns polarity: normal

platform/5d020000.pwm, 1 PWM device
 pwm-0   (sample_heater       ): requested enabled period: 1000000 ns duty: 494117 ns polarity: normal

platform/5a190000.pwm, 1 PWM device
 pwm-0   ((null)              ): period: 2730667 ns duty: 0 ns polarity: normal

platform/5a8a0000.pwm, 8 PWM devices
 pwm-0   (col1_heater         ): requested enabled period: 1000000 ns duty: 494117 ns polarity: normal
 pwm-1   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-2   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-3   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-4   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-5   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-6   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-7   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
root@zepto-gmr-imx8-26:~# 

@ToradexAI

Great progress! You’re very close to getting this working. The key issues I can identify from your configuration and the error messages:

Primary Issues

1. FTM Driver Initialization Error

The critical error in your dmesg output is:

fsl-ftm-pwm 5a8a0000.pwm: regmap init failed

This indicates the FTM controller isn’t initializing properly, likely due to incorrect device tree configuration.

2. Pin Mapping Mismatch

You’re using IMX8QXP_UART2_RX_ADMA_FTM_CH0 but SODIMM 63 should map to FLEXCAN1_RX, not UART2_RX. According to the i.MX 8/8X pinmuxing guide (1), for i.MX 8X based modules, pin configuration requires specific device tree nodes with the fsl,pins property (1).

Device Tree Corrections

Fix the Pin Mapping

In your imx8x-colibri.dtsi, change the pinctrl configuration:

pinctrl_ftm_pwm_0: pwm4 {
    fsl,pins = <
        IMX8QXP_FLEXCAN1_RX_ADMA_FTM_CH2    0x60    /* SODIMM 63 */
    >;
};

(1)

Correct FTM Controller Configuration

Your FTM controller definition in imx8qxp-ss-adma.dtsi needs adjustment. The power domain and resource assignments appear incorrect:

ftm_pwm0: pwm@5a8a0000 {
    compatible = "fsl,vf610-ftm-pwm";
    reg = <0x5A8A0000 0x10000>;
    #pwm-cells = <3>;
    clock-names = "ftm_sys", "ftm_ext", "ftm_fix", "ftm_cnt_clk_en", "ipg";
    clocks = <&ftm0_lpcg 0>,
        <&ftm0_lpcg 0>,
        <&ftm0_lpcg 0>,
        <&ftm0_lpcg 0>,
        <&ftm0_lpcg 1>;
    assigned-clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>;
    assigned-clock-rates = <24000000>;
    power-domains = <&pd IMX_SC_R_FTM_0>;  /* Changed from LCD_0_PWM_0 */
    big-endian;
    status = "okay";
};

Update LED Configuration

In your LED configuration, use channel 2 since SODIMM 63 maps to FTM_CH2:

col1_heater {
    label = "col1_heater";
    pwms = <&ftm_pwm0 2 1000000 0>; /* Channel 2, not 0 */
    max-brightness = <255>;
    default-brightness-level = <0>;
};

(1)

Debugging Steps

1. Verify Pin Function

Check that the pin is correctly configured:

cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep -A5 -B5 "63"

2. Check FTM Resources

Verify the FTM controller resources are available:

# Check if FTM resources are properly assigned
dmesg | grep -i "ftm\|resource"

# Verify clock configuration
cat /sys/kernel/debug/clk/clk_summary | grep -i ftm

Understanding the Current Behavior

The weird behavior you’re seeing (col1_heater turning on when you activate other PWMs) suggests there might be:

  1. Clock domain interference - The FTM controller shares clock resources with other PWM controllers
  2. Incorrect channel mapping - Using channel 0 instead of channel 2
  3. Power domain issues - The power domain assignment might be affecting other PWM controllers

Recommended Next Steps

  1. Fix the pin mapping to use FLEXCAN1_RX_ADMA_FTM_CH2
  2. Correct the power domain to IMX_SC_R_FTM_0
  3. Update the PWM channel to channel 2 in the LED configuration
  4. Rebuild and test the device tree
  5. Check dmesg for the “regmap init failed” error resolution

The key insight is that SODIMM 63 specifically maps to FTM channel 2, not channel 0, and requires the correct FLEXCAN1_RX pin function assignment (1).

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

I’m still getting the same behavior where col1_heater will only turn on when col2_heater or sample_heater are turned on. Here is the output for the commands you listed.

root@zepto-gmr-imx8-26:~# cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep -A5 -B5 "63"
pin 58 (IMX8QXP_ESAI0_SCKT): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 59 (IMX8QXP_ESAI0_TX0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 60 (IMX8QXP_ESAI0_TX1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 61 (IMX8QXP_ESAI0_TX2_RX3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 62 (IMX8QXP_ESAI0_TX3_RX2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 63 (IMX8QXP_ESAI0_TX4_RX1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 64 (IMX8QXP_ESAI0_TX5_RX0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 65 (IMX8QXP_SPDIF0_RX): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 66 (IMX8QXP_SPDIF0_TX): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 67 (IMX8QXP_SPDIF0_EXT_CLK): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 68 (IMX8QXP_COMP_CTL_GPIO_1V8_3V3_GPIORHB): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog0grp
--
pin 158 (IMX8QXP_QSPI0A_DATA2): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog1grp
pin 159 (IMX8QXP_QSPI0A_DATA3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 160 (IMX8QXP_QSPI0A_DQS): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 161 (IMX8QXP_QSPI0A_SS0_B): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 162 (IMX8QXP_QSPI0A_SS1_B): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 163 (IMX8QXP_QSPI0A_SCLK): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog2grp
pin 164 (IMX8QXP_COMP_CTL_GPIO_1V8_3V3_QSPI0A): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 165 (IMX8QXP_QSPI0B_SCLK): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 166 (IMX8QXP_QSPI0B_DATA0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 167 (IMX8QXP_QSPI0B_DATA1): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog1grp
pin 168 (IMX8QXP_QSPI0B_DATA2): (MUX UNCLAIMED) (GPIO UNCLAIMED)


root@zepto-gmr-imx8-26:~# dmesg | grep -i "ftm\|resource"
[    0.213765] kvm [1]: GICv3: no GICV resource entry
[    0.252663] fsl-ftm-pwm 5a8a0000.pwm: regmap init failed
[    3.063812] pci_bus 0000:00: root bus resource [bus 00-ff]
[    3.069320] pci_bus 0000:00: root bus resource [io  0x0000-0xffff]
[    3.075539] pci_bus 0000:00: root bus resource [mem 0x70000000-0x7fefffff]


root@zepto-gmr-imx8-26:~# cat /sys/kernel/debug/clk/clk_summary | grep -i ftm
 ftm1_clk                             0        0        0           0          0     0  50000
 ftm0_clk                             0        1        0    24000000          0     0  50000
    ftm0_lpcg_clk                     0        1        0    24000000          0     0  50000
    ftm0_lpcg_ipg_clk                 1        1        0   160000000          0     0  50000


I also am not seeing pwm_fsl_ftm listed when I call the command lsmod (this was listed in the linked thread from above).

root@zepto-gmr-imx8-26:~# lsmod
Module                  Size  Used by
8021q                  36864  0
rfcomm                 90112  2
btusb                  57344  0
btrtl                  24576  1 btusb
btintel                32768  1 btusb
btbcm                  20480  1 btusb
slip                   24576  1
bluetooth             593920  32 btrtl,btintel,btbcm,btusb,rfcomm
usb_f_rndis            45056  2
u_ether                24576  1 usb_f_rndis
ecdh_generic           16384  1 bluetooth
ecc                    32768  1 ecdh_generic
crct10dif_ce           16384  1
mwifiex_pcie           45056  0
mwifiex               299008  1 mwifiex_pcie
cfg80211              409600  1 mwifiex
rfkill                 36864  5 bluetooth,cfg80211
ad7879_i2c             16384  0
ad7879                 16384  1 ad7879_i2c
mcp251x                24576  0
can_dev                36864  1 mcp251x
mxc_jpeg_encdec        57344  0
libcomposite           73728  10 usb_f_rndis
configfs               53248  3 usb_f_rndis,libcomposite
galcore               425984  0

Not sure if I’m understanding it correctly but in the other thread it noted

“I can also see device as below. We tried all channel and not able to see any change on pin.

/sys/devices/platform/bus@5a000000/5a8a0000.pwm/pwm/pwmchip4#“

but I only see pwmchip0

root@zepto-gmr-imx8-26:~# ls /sys/devices/platform/bus\@5a000000/5a8a0000.pwm/pwm/

pwmchip0

@ToradexAI

Looking at your debug output, there are several critical issues that need to be addressed:

Primary Issues Identified

1. Pin Mux Not Applied

The most critical issue is shown in your pinctrl debug output:

pin 63 (IMX8QXP_ESAI0_TX4_RX1): (MUX UNCLAIMED) (GPIO UNCLAIMED)

This indicates that SODIMM 63 is not being configured at all. The pin should show as claimed by your FTM controller, but it’s showing as unclaimed.

2. FTM Driver Initialization Failure

The persistent error:

fsl-ftm-pwm 5a8a0000.pwm: regmap init failed

This suggests the FTM controller hardware isn’t being properly initialized, likely due to incorrect device tree configuration.

3. Missing FTM Driver Module

The pwm_fsl_ftm module isn’t loaded, which is required for FTM PWM functionality.

Device Tree Configuration Issues

Based on the i.MX 8/8X pinmuxing documentation (1), for i.MX 8X based modules, pin configuration requires a device tree node inside the pin controller node with the property fsl,pins (1). Each pin requires three integers to be assigned to the property (1).

Correct Pin Mapping for SODIMM 63

The issue is that you need to use the correct pin macro for SODIMM 63. Looking at your Colibri iMX8X, SODIMM 63 should map to FLEXCAN1_RX, which can be muxed to FTM_CH2.

In your imx8x-colibri.dtsi, the pinctrl configuration should be:

pinctrl_ftm_pwm_0: pwm4 {
    fsl,pins = <
        IMX8QXP_FLEXCAN1_RX_ADMA_FTM_CH2    0x60    /* SODIMM 63 */
    >;
};

(1)

FTM Controller Configuration

The FTM controller definition needs to be corrected. Based on the pinmuxing guide (1), the third integer defines the pin settings in hexadecimal notation (1).

Verify Kernel Configuration

First, ensure the FTM PWM driver is enabled:

# Check if FTM PWM is compiled as module or built-in
zcat /proc/config.gz | grep CONFIG_PWM_FSL_FTM

If it shows CONFIG_PWM_FSL_FTM=m, you need to load the module:

modprobe pwm-fsl-ftm

Debugging Steps

1. Check Device Tree Compilation

Verify your device tree changes are being applied:

# Check if your FTM controller node exists
find /proc/device-tree -name "*5a8a0000*" -type d

2. Verify Pin Function Assignment

The fact that pin 63 shows as “MUX UNCLAIMED” means your pinctrl configuration isn’t being applied. This could be due to:

  • Incorrect pin macro name
  • Device tree compilation issues
  • Missing pinctrl reference

3. Check FTM Resources

# Check system resources for FTM
cat /proc/iomem | grep 5a8a0000

Recommended Fix Sequence

  1. Verify the correct pin macro for SODIMM 63 on Colibri iMX8X
  2. Load the FTM PWM driver if it’s compiled as a module
  3. Check device tree compilation to ensure your changes are applied
  4. Verify the FTM controller address and resources match your hardware

The key issue is that your pin mux configuration isn’t being applied, which means the FTM controller can’t access the pin. Once the pin is properly claimed by the FTM controller, the “regmap init failed” error should resolve.

The cross-interference you’re seeing between PWM channels suggests there might be shared clock or power domain issues, but the primary problem is that SODIMM 63 isn’t being configured for FTM functionality at all.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

I am still getting the same issues

root@zepto-gmr-imx8-26:~# cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep -A5 -B5 "63"
pin 58 (IMX8QXP_ESAI0_SCKT): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 59 (IMX8QXP_ESAI0_TX0): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 60 (IMX8QXP_ESAI0_TX1): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 61 (IMX8QXP_ESAI0_TX2_RX3): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 62 (IMX8QXP_ESAI0_TX3_RX2): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 63 (IMX8QXP_ESAI0_TX4_RX1): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 64 (IMX8QXP_ESAI0_TX5_RX0): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 65 (IMX8QXP_SPDIF0_RX): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 66 (IMX8QXP_SPDIF0_TX): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 67 (IMX8QXP_SPDIF0_EXT_CLK): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins
pin 68 (IMX8QXP_COMP_CTL_GPIO_1V8_3V3_GPIORHB): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog0grp
--
pin 158 (IMX8QXP_QSPI0A_DATA2): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog1grp
pin 159 (IMX8QXP_QSPI0A_DATA3): backlight (GPIO UNCLAIMED) function colibri-imx8qxp group gpio-bl-on
pin 160 (IMX8QXP_QSPI0A_DQS): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 161 (IMX8QXP_QSPI0A_SS0_B): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 162 (IMX8QXP_QSPI0A_SS1_B): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 163 (IMX8QXP_QSPI0A_SCLK): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog2grp
pin 164 (IMX8QXP_COMP_CTL_GPIO_1V8_3V3_QSPI0A): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 165 (IMX8QXP_QSPI0B_SCLK): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 166 (IMX8QXP_QSPI0B_DATA0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 167 (IMX8QXP_QSPI0B_DATA1): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog1grp
pin 168 (IMX8QXP_QSPI0B_DATA2): (MUX UNCLAIMED) (GPIO UNCLAIMED)

and

root@zepto-gmr-imx8-26:~# dmesg | grep -i "ftm"
[    0.252109] fsl-ftm-pwm 5a8a0000.pwm: regmap init failed

and the lack of pwm_fsl_ftm when calling lsmod

Could you give me the code snippets to enable PWM on pin 63 for each file so I can make sure I am working with the same code

I believe these are the files we are working with:

imx8qxp-ss-adma.dtsi (Is this the correct file for modifying dma_subsys?)
imx8x-colibri.dtsi
imx8x-colibri-eval-v3.dtsi

@ToradexAI

I can see the critical issue now! Pin 63 is being claimed by the LCD controller (5a180000.lcdif), which is why your FTM configuration isn’t working. You need to disable the LCD interface to free up the pin.

Root Cause Analysis

Your debug output shows:

pin 63 (IMX8QXP_ESAI0_TX4_RX1): 5a180000.lcdif (GPIO UNCLAIMED) function colibri-imx8qxp group lcdif-pins

This means SODIMM 63 is already claimed by the LCD controller, preventing the FTM controller from using it.

Complete Device Tree Configuration

Based on the device tree customization guide (1) and pinmuxing documentation (2), here are the exact code snippets for each file:

1. imx8x-colibri.dtsi

Add the FTM pinctrl configuration:

&iomuxc {
    colibri-imx8qxp {
        
        /* Existing pinctrl groups... */
        
        /* PWM Pin for Sample Thermistor Heater (PWMD) */
        pinctrl_pwm_d: pwmd {
            fsl,pins = <
                IMX8QXP_UART1_RTS_B_LSIO_PWM2_OUT 0x60 /* SODIMM 67 */
            >;
        };

        /* PWM Pin for Column 2 Thermistor Heater (PWME) */
        pinctrl_pwm_e: pwme {
            fsl,pins = <
                IMX8QXP_UART1_CTS_B_LSIO_PWM3_OUT 0x60 /* SODIMM 61 */
            >;
        };

        /* PWM Pin for Column 1 Thermistor Heater (PWMH) - FTM */
        pinctrl_ftm_pwm_0: ftmpwm0 {
            fsl,pins = <
                IMX8QXP_FLEXCAN1_RX_ADMA_FTM_CH2 0x60 /* SODIMM 63 */
            >;
        };
    };
};

(2)

2. imx8qxp-ss-adma.dtsi

Add the FTM controller and clock configuration:

&dma_subsys {
    /* Existing nodes... */
    
    ftm_pwm0: pwm@5a8a0000 {
        compatible = "fsl,vf610-ftm-pwm";
        reg = <0x5A8A0000 0x10000>;
        #pwm-cells = <3>;
        clock-names = "ftm_sys", "ftm_ext", "ftm_fix", "ftm_cnt_clk_en", "ipg";
        clocks = <&ftm0_lpcg 0>,
            <&ftm0_lpcg 0>,
            <&ftm0_lpcg 0>,
            <&ftm0_lpcg 0>,
            <&ftm0_lpcg 1>;
        assigned-clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>;
        assigned-clock-rates = <24000000>;
        power-domains = <&pd IMX_SC_R_FTM_0>;
        big-endian;
        status = "disabled";
    };

    ftm0_lpcg: clock-controller@5aca0000 {
        compatible = "fsl,imx8qxp-lpcg";
        reg = <0x5aca0000 0x10000>;
        #clock-cells = <1>;
        clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>,
            <&dma_ipg_clk>;
        bit-offset = <0 16>;
        clock-output-names = "ftm0_lpcg_clk",
            "ftm0_lpcg_ipg_clk";
        power-domains = <&pd IMX_SC_R_FTM_0>;
        status = "okay";
    };
};

(1)

3. imx8x-colibri-eval-v3.dtsi

Configure the PWM controllers and disable conflicting interfaces:

/* CRITICAL: Disable LCD controller to free pin 63 */
&lcdif {
    status = "disabled";
};

/* Disable UART2 to release SODIMM 63 for PWM usage */
&lpuart2 {
    status = "disabled";
};

/* Disable FlexCAN1 to avoid conflicts */
&flexcan1 {
    status = "disabled";
    /delete-property/ pinctrl-names;
    /delete-property/ pinctrl-0;
    /delete-property/ xceiver-supply;
};

/* Disable backlight */
&backlight {
    status = "disabled";
    /delete-property/ pwms;
};

/* Enable PWM controllers */
&pwm2 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_pwm_d>; 
    status = "okay";
};

&pwm3 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_pwm_e>; 
    status = "okay";
};

&ftm_pwm0 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_ftm_pwm_0>;
    status = "okay";
};

/ {
    leds {
        compatible = "pwm-leds";

        /* Sample Heater (PWM_D / &pwm2) - SODIMM 67 */
        sample_heater {
            label = "sample_heater";
            pwms = <&pwm2 0 1000000 0>;
            max-brightness = <255>;
            default-brightness-level = <0>;
        };

        /* Column 2 Heater (PWM_E / &pwm3) - SODIMM 61 */
        col2_heater {
            label = "col2_heater";
            pwms = <&pwm3 0 1000000 0>;
            max-brightness = <255>;
            default-brightness-level = <0>;
        };

        /* Column 1 Heater (FTM PWM) - SODIMM 63 */
        col1_heater {
            label = "col1_heater";
            pwms = <&ftm_pwm0 2 1000000 0>; /* Channel 2 for FTM_CH2 */
            max-brightness = <255>;
            default-brightness-level = <0>;
        };
    };
};

(3)

Key Changes Made

  1. Disabled LCD controller (&lcdif) - This was claiming pin 63
  2. Used correct FTM channel 2 - SODIMM 63 maps to FTM_CH2
  3. Proper pin macro - IMX8QXP_FLEXCAN1_RX_ADMA_FTM_CH2 for SODIMM 63 (2)
  4. Correct power domain - IMX_SC_R_FTM_0 for FTM controller

Verification Steps

After applying these changes:

  1. Check pin assignment:
cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep -A5 -B5 "63"

Pin 63 should now show as claimed by FTM controller, not LCD.

  1. Verify FTM initialization:
dmesg | grep -i ftm

Should no longer show “regmap init failed”.

  1. Test PWM functionality:
echo 255 > /sys/class/leds/col1_heater/brightness

The key issue was that the LCD controller was claiming pin 63, preventing the FTM controller from accessing it. Disabling the LCD controller should resolve this conflict (1).

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

In imx8x-colibri-eval-v3.dtsi I get an error for the lcdif node

Colibri-imx8/build/tmp/work-shared/colibri-imx8x/kernel-source/arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi:225.1-7 Label or path lcdif not found
FATAL ERROR: Syntax error parsing input tree

I do see display_lcdif in imx8x-colibri.dtsi:

/* Colibri Parallel RGB */
	display_lcdif: display@disp1 {
		compatible = "fsl,imx-lcdif-mux-display";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_lcdif>;
		clocks = <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_BYPASS>,
			 <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_MISC0>;
		clock-names = "bypass_div", "pixel";
		assigned-clocks = <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_MISC0>;
		assigned-clock-parents = <&clk IMX_SC_R_LCD_0 IMX_SC_PM_CLK_BYPASS>;
		fsl,lcdif-mux-regs = <&lcdif_mux_regs>;
		fsl,interface-pix-fmt = "rgb666";
		power-domains = <&pd IMX_SC_R_LCD_0>;
		status = "disabled";

		#address-cells = <1>;
		#size-cells = <0>;

		port@0 {
			reg = <0>;

			lcd_display_in: endpoint {
				remote-endpoint = <&dpu_disp1_lcdif>;
			};
		};
	};

@ToradexAI

You’re correct! The LCD controller node is named display_lcdif, not lcdif. Here’s the corrected configuration:

Corrected imx8x-colibri-eval-v3.dtsi

/* CRITICAL: Disable LCD controller to free pin 63 */
&display_lcdif {
    status = "disabled";
};

/* Disable UART2 to release SODIMM 63 for PWM usage */
&lpuart2 {
    status = "disabled";
};

/* Disable FlexCAN1 to avoid conflicts */
&flexcan1 {
    status = "disabled";
    /delete-property/ pinctrl-names;
    /delete-property/ pinctrl-0;
    /delete-property/ xceiver-supply;
};

/* Disable backlight */
&backlight {
    status = "disabled";
    /delete-property/ pwms;
};

/* Enable PWM controllers */
&pwm2 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_pwm_d>; 
    status = "okay";
};

&pwm3 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_pwm_e>; 
    status = "okay";
};

&ftm_pwm0 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_ftm_pwm_0>;
    status = "okay";
};

/ {
    leds {
        compatible = "pwm-leds";

        /* Sample Heater (PWM_D / &pwm2) - SODIMM 67 */
        sample_heater {
            label = "sample_heater";
            pwms = <&pwm2 0 1000000 0>;
            max-brightness = <255>;
            default-brightness-level = <0>;
        };

        /* Column 2 Heater (PWM_E / &pwm3) - SODIMM 61 */
        col2_heater {
            label = "col2_heater";
            pwms = <&pwm3 0 1000000 0>;
            max-brightness = <255>;
            default-brightness-level = <0>;
        };

        /* Column 1 Heater (FTM PWM) - SODIMM 63 */
        col1_heater {
            label = "col1_heater";
            pwms = <&ftm_pwm0 2 1000000 0>; /* Channel 2 for FTM_CH2 */
            max-brightness = <255>;
            default-brightness-level = <0>;
        };
    };
};

(1), (2)

Additional Check: Disable LCD Pinctrl

You may also need to disable the LCD pinctrl configuration that’s claiming pin 63. In your imx8x-colibri.dtsi, you might need to modify or disable the pinctrl_lcdif group that includes SODIMM 63.

Look for the pinctrl_lcdif definition and either:

  1. Remove SODIMM 63 from the LCD pinctrl group, or
  2. Comment out the entire LCD pinctrl group

Verification Steps

After making this change:

  1. Compile and deploy your device tree

  2. Check pin assignment:

    cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep -A5 -B5 "63"
    

    Pin 63 should no longer show as claimed by 5a180000.lcdif

  3. Verify FTM initialization:

    dmesg | grep -i ftm
    

The key issue was using the wrong node name. The LCD controller node is display_lcdif, not lcdif. This should resolve the compilation error and properly disable the LCD controller to free up pin 63 for FTM PWM usage (1).

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Unfortunatly I am still getting the same issues. Here is the output from the commands.

root@zepto-gmr-imx8-26:~# cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep -A5 -B5 "63"
pin 58 (IMX8QXP_ESAI0_SCKT): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 59 (IMX8QXP_ESAI0_TX0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 60 (IMX8QXP_ESAI0_TX1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 61 (IMX8QXP_ESAI0_TX2_RX3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 62 (IMX8QXP_ESAI0_TX3_RX2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 63 (IMX8QXP_ESAI0_TX4_RX1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 64 (IMX8QXP_ESAI0_TX5_RX0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 65 (IMX8QXP_SPDIF0_RX): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 66 (IMX8QXP_SPDIF0_TX): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 67 (IMX8QXP_SPDIF0_EXT_CLK): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 68 (IMX8QXP_COMP_CTL_GPIO_1V8_3V3_GPIORHB): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog0grp
--
pin 158 (IMX8QXP_QSPI0A_DATA2): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog1grp
pin 159 (IMX8QXP_QSPI0A_DATA3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 160 (IMX8QXP_QSPI0A_DQS): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 161 (IMX8QXP_QSPI0A_SS0_B): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 162 (IMX8QXP_QSPI0A_SS1_B): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 163 (IMX8QXP_QSPI0A_SCLK): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog2grp
pin 164 (IMX8QXP_COMP_CTL_GPIO_1V8_3V3_QSPI0A): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 165 (IMX8QXP_QSPI0B_SCLK): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 166 (IMX8QXP_QSPI0B_DATA0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 167 (IMX8QXP_QSPI0B_DATA1): scu:pinctrl (GPIO UNCLAIMED) (HOG) function colibri-imx8qxp group hog1grp
pin 168 (IMX8QXP_QSPI0B_DATA2): (MUX UNCLAIMED) (GPIO UNCLAIMED)



root@zepto-gmr-imx8-26:~# dmesg | grep -i "ftm"
[    0.254569] fsl-ftm-pwm 5a8a0000.pwm: regmap init failed



root@zepto-gmr-imx8-26:~# cat /sys/kernel/debug/pwm                         
platform/5d030000.pwm, 1 PWM device
 pwm-0   (col2_heater         ): requested period: 1000000 ns duty: 0 ns polarity: normal

platform/5d020000.pwm, 1 PWM device
 pwm-0   (sample_heater       ): requested period: 1000000 ns duty: 0 ns polarity: normal

platform/5a190000.pwm, 1 PWM device
 pwm-0   ((null)              ): period: 2730667 ns duty: 0 ns polarity: normal

platform/5a8a0000.pwm, 8 PWM devices
 pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-1   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-2   (col1_heater         ): requested enabled period: 1000000 ns duty: 0 ns polarity: normal
 pwm-3   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-4   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-5   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-6   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-7   ((null)              ): period: 0 ns duty: 0 ns polarity: normal

imx8qxp-ss-adma.dtsi

&dma_subsys {
	lcdif_mux_regs: mux-regs@5a170000 {
		compatible = "fsl,imx8qxp-lcdif-mux-regs", "syscon";
		reg = <0x5a170000 0x4>;
	};

	ftm_pwm0: pwm@5a8a0000 {
        compatible = "fsl,vf610-ftm-pwm";
        reg = <0x5A8A0000 0x10000>;
        #pwm-cells = <3>;
        clock-names = "ftm_sys", "ftm_ext", "ftm_fix", "ftm_cnt_clk_en", "ipg";
        clocks = <&ftm0_lpcg 0>,
            <&ftm0_lpcg 0>,
            <&ftm0_lpcg 0>,
            <&ftm0_lpcg 0>,
            <&ftm0_lpcg 1>;
        assigned-clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>;
        assigned-clock-rates = <24000000>;
        power-domains = <&pd IMX_SC_R_FTM_0>;
        big-endian;
        status = "disabled";
    };

    ftm0_lpcg: clock-controller@5aca0000 {
        compatible = "fsl,imx8qxp-lpcg";
        reg = <0x5aca0000 0x10000>;
        #clock-cells = <1>;
        clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>,
            <&dma_ipg_clk>;
        bit-offset = <0 16>;
        clock-output-names = "ftm0_lpcg_clk",
            "ftm0_lpcg_ipg_clk";
        power-domains = <&pd IMX_SC_R_FTM_0>;
        status = "okay";
    };
};

imx8x-colibri.dtsi

        pinctrl_ftm_pwm_0: ftmpwm0 {
            fsl,pins = <
                IMX8QXP_FLEXCAN1_RX_ADMA_FTM_CH2 0x60 /* SODIMM 63 */
            >;
        };

imx8x-colibri-eval-v3.dtsi

/* CRITICAL: Disable LCD controller to free pin 63 */
&display_lcdif {
    status = "disabled";
};

/* Disable UART2 to release SODIMM 63 for PWM usage */
&lpuart2 {
    status = "disabled";
};

/* Disable FlexCAN1 to avoid conflicts */
&flexcan1 {
    status = "disabled";
    /delete-property/ pinctrl-names;
    /delete-property/ pinctrl-0;
    /delete-property/ xceiver-supply;
};

/* Disable backlight */
&backlight {
    status = "disabled";
    /delete-property/ pwms;
};

/* Enable PWM for the Sample thermister */
&pwm2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm_d>; 
	#pwm-cells = <3>;
	status = "okay";
};

/* Enable PWM for the Column heater 1 */
// &ftm_pwm0 {
// 	pinctrl-names = "default";
// 	pinctrl-0 = <&pinctrl_ftm_pwm_0>;
// 	#pwm-cells = <3>;
// 	status = "okay";
// };
/* Connect to the standard NXP node 'adma_ftm0' */
&ftm_pwm0 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_ftm_pwm_0>;
    status = "okay";
};


/* Enable PWM for the Column heater 2 */
&pwm3 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm_e>; 
	status = "okay";
};

/ {
    leds {
        compatible = "pwm-leds";

        /*
         * Column 1 Heater (PWM_H / &pwm_adma)
         * Maps to SODIMM 63
         */
        col1_heater {
            label = "col1_heater";
            pwms = <&ftm_pwm0 2 1000000 0>; /* Channel 2 for FTM_CH2 */
            max-brightness = <255>;
            default-brightness-level = <0>;
        };

        /*
         * Sample Heater (PWM_D / &pwm2)
         * Maps to SODIMM 67
         */
        sample_heater {
            label = "sample_heater";
            pwms = <&pwm2 0 1000000 0>; /* 1kHz, normal polarity */
            max-brightness = <255>;
            default-brightness-level = <0>; /* Use this for default-off */
        };

        /*
         * Column 2 Heater (PWM_E / &pwm3)
         * Maps to SODIMM 61
         */
        col2_heater {
            label = "col2_heater";
            pwms = <&pwm3 0 1000000 0>; /* 1kHz, normal polarity */
            max-brightness = <255>;
            default-brightness-level = <0>; /* Use this for default-off */
        };
    };
};

Also when I look at the logic analyzer col1_heater is stuck high like where as the other to are low. To mean this is showing that it isn’t being set up properly. @ToradexAI

Looking at your output, I can see several critical issues that need to be resolved:

Critical Issues Identified

1. Pin Still Not Claimed

Your debug output shows:

pin 63 (IMX8QXP_ESAI0_TX4_RX1): (MUX UNCLAIMED) (GPIO UNCLAIMED)

This means your pinctrl configuration is still not being applied to pin 63.

2. FTM Driver Still Failing

The persistent error:

fsl-ftm-pwm 5a8a0000.pwm: regmap init failed

indicates the FTM controller hardware initialization is failing.

3. Wrong Pin Mapping

The fundamental issue is that SODIMM 63 does not map to FLEXCAN1_RX on the Colibri iMX8X. Looking at the Colibri Evaluation Board datasheet (1), SODIMM 63 is available on the GPIO breakout area, but you need to verify the correct SoC ball name for this specific module.

Device Tree Debugging Steps

1. Verify Pin Mapping

First, you need to find the correct pin macro for SODIMM 63 on the Colibri iMX8X. The pin mapping varies between different Toradex modules (2).

2. Check Device Tree Compilation

Verify your device tree changes are being compiled and applied:

# Check if FTM node exists in compiled device tree
find /proc/device-tree -name "*5a8a0000*" -type d

# Check if your pinctrl node exists
find /proc/device-tree -name "*ftmpwm0*" -type d

3. Load FTM Driver Module

The FTM PWM driver might be compiled as a module. Try loading it manually:

# Check if FTM PWM is available as module
modprobe pwm-fsl-ftm

# Verify module loading
lsmod | grep ftm

Alternative Approach: Use Available PWM Channels

Since you have PWM_D (SODIMM 67) and PWM_E (SODIMM 61) working correctly, and both use LSIO PWM controllers, I recommend checking if there are other available LSIO PWM channels you can use instead of the problematic FTM controller.

Looking at your current working configuration (3), you could:

  1. Use PWM_B or PWM_C if available on different SODIMM pins
  2. Check if PWM_A is available (though it’s typically used for backlight)

Corrected Device Tree Approach

Based on the device tree customization principles (2), here’s a systematic approach:

1. Find the Correct Pin Macro

You need to identify the correct SoC ball name for SODIMM 63 on Colibri iMX8X. This might not be FLEXCAN1_RX.

2. Simplified FTM Configuration

Try this minimal FTM configuration in your imx8qxp-ss-adma.dtsi:

&dma_subsys {
    ftm_pwm0: pwm@5a8a0000 {
        compatible = "fsl,vf610-ftm-pwm";
        reg = <0x5A8A0000 0x10000>;
        #pwm-cells = <3>;
        clocks = <&ftm0_lpcg 0>, <&ftm0_lpcg 1>;
        clock-names = "ftm_sys", "ftm_cnt_clk_en";
        power-domains = <&pd IMX_SC_R_FTM_0>;
        status = "disabled";
    };

    ftm0_lpcg: clock-controller@5aca0000 {
        compatible = "fsl,imx8qxp-lpcg";
        reg = <0x5aca0000 0x10000>;
        #clock-cells = <1>;
        clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>,
            <&dma_ipg_clk>;
        bit-offset = <0 16>;
        clock-output-names = "ftm0_lpcg_clk",
            "ftm0_lpcg_ipg_clk";
        power-domains = <&pd IMX_SC_R_FTM_0>;
        status = "okay";
    };
};

Immediate Troubleshooting Steps

  1. Verify the correct pin macro for SODIMM 63 on your specific module
  2. Load the FTM driver module manually
  3. Check device tree compilation to ensure your nodes exist
  4. Consider using an alternative PWM channel that uses LSIO controllers

The root cause appears to be either an incorrect pin macro or the FTM driver not being properly loaded. The “regmap init failed” error suggests the hardware resources aren’t being properly assigned to the FTM controller (2).

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

On the datasheet it says that pin 63 i.MX 8x Ball Name is FLEXCAN1_RX and alternate function 2 (ALT2) is ADMA.FTM.CH2

”63 FLEXCAN1_RX AA33 ADMA.FLEXCAN1.RX ADMA.SAI2.RXFS ADMA.FTM.CH2 ADMA.SAI1.TXD LSIO.GPIO1.IO17 GPIO ALT0 PD VDD_CAN_UART_3P3”

I believe ADMA.FTM.CH2 is what I need to enable PWM on pin 63. Looking at the datasheet:

“Besides the standard PWM interfaces, the 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. The FTM and the TPM for the M4 core are available on the module edge connector as
alternate functions.”

"
Table Interface Description-43 TPM and FTM Interface Signals (incompatible with other modules)
X1 Pin# Colibri Standard Function i.MX 8X Ball Name i.MX 8X Function I/O Remarks
63 PS2 SCL1 FLEXCAN1_RX ADMA.FTM.CH2 I/O
"

@ToradexAI

Perfect! The datasheet confirms that SODIMM 63 maps to FLEXCAN1_RX with ALT2 function ADMA.FTM.CH2. Now I can see the issue - your pin configuration and FTM setup are correct, but there are some missing elements.

Root Cause Analysis

Looking at your configuration, the pin mapping is correct, but the FTM driver initialization is still failing. The key issues are:

  1. FTM driver module not loaded
  2. Possible missing device tree includes
  3. Clock configuration needs refinement

Complete Working Configuration

Based on the device tree customization guide (1) and the community forum examples (2), here’s the corrected configuration:

1. Load FTM PWM Driver Module

First, ensure the FTM PWM driver is loaded:

# Load the FTM PWM driver module
modprobe pwm-fsl-ftm

# Verify it's loaded
lsmod | grep ftm

2. Corrected imx8qxp-ss-adma.dtsi

&dma_subsys {
    lcdif_mux_regs: mux-regs@5a170000 {
        compatible = "fsl,imx8qxp-lcdif-mux-regs", "syscon";
        reg = <0x5a170000 0x4>;
    };

    ftm0_lpcg: clock-controller@5aca0000 {
        compatible = "fsl,imx8qxp-lpcg";
        reg = <0x5aca0000 0x10000>;
        #clock-cells = <1>;
        clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>,
            <&dma_ipg_clk>;
        bit-offset = <0 16>;
        clock-output-names = "ftm0_lpcg_clk",
            "ftm0_lpcg_ipg_clk";
        power-domains = <&pd IMX_SC_R_FTM_0>;
        status = "okay";
    };

    ftm_pwm0: pwm@5a8a0000 {
        compatible = "fsl,vf610-ftm-pwm";
        reg = <0x5A8A0000 0x10000>;
        #pwm-cells = <3>;
        clock-names = "ftm_sys", "ftm_ext", "ftm_fix", "ftm_cnt_clk_en", "ipg";
        clocks = <&ftm0_lpcg 0>,
            <&ftm0_lpcg 0>,
            <&ftm0_lpcg 0>,
            <&ftm0_lpcg 0>,
            <&ftm0_lpcg 1>;
        assigned-clocks = <&clk IMX_SC_R_FTM_0 IMX_SC_PM_CLK_PER>;
        assigned-clock-rates = <24000000>;
        power-domains = <&pd IMX_SC_R_FTM_0>;
        big-endian;
        status = "disabled";
    };
};

(1)

3. Verify imx8x-colibri.dtsi Pinctrl

Your pinctrl configuration is correct:

pinctrl_ftm_pwm_0: ftmpwm0 {
    fsl,pins = <
        IMX8QXP_FLEXCAN1_RX_ADMA_FTM_CH2 0x60 /* SODIMM 63 */
    >;
};

4. Updated imx8x-colibri-eval-v3.dtsi

/* Disable conflicting interfaces */
&display_lcdif {
    status = "disabled";
};

&lpuart2 {
    status = "disabled";
};

&flexcan1 {
    status = "disabled";
    /delete-property/ pinctrl-names;
    /delete-property/ pinctrl-0;
    /delete-property/ xceiver-supply;
};

&backlight {
    status = "disabled";
    /delete-property/ pwms;
};

/* Enable PWM controllers */
&pwm2 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_pwm_d>; 
    status = "okay";
};

&pwm3 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_pwm_e>; 
    status = "okay";
};

&ftm_pwm0 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_ftm_pwm_0>;
    status = "okay";
};

/ {
    leds {
        compatible = "pwm-leds";

        sample_heater {
            label = "sample_heater";
            pwms = <&pwm2 0 1000000 0>;
            max-brightness = <255>;
            default-brightness-level = <0>;
        };

        col2_heater {
            label = "col2_heater";
            pwms = <&pwm3 0 1000000 0>;
            max-brightness = <255>;
            default-brightness-level = <0>;
        };

        col1_heater {
            label = "col1_heater";
            pwms = <&ftm_pwm0 2 1000000 0>; /* Channel 2 for FTM_CH2 */
            max-brightness = <255>;
            default-brightness-level = <0>;
        };
    };
};

(3)

Debugging Steps

  1. Load the FTM driver module first
  2. Check device tree compilation:
    find /proc/device-tree -name "*ftm*" -type d
    
  3. Verify pin assignment after reboot:
    cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep -A5 -B5 "63"
    
  4. Check FTM initialization:
    dmesg | grep -i ftm
    

The key missing piece was likely the FTM PWM driver module not being loaded. The “regmap init failed” error suggests the driver couldn’t initialize the hardware registers, which often happens when the driver module isn’t available (2).

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.