Need help setting clock source for PWM, 100khz frequency target

So on the Verdin IMX8MP within yocto, I need to drive the 4 PWM signals at 20khz-200khz Ideally 100khz but bare minimum 20, for a backlight driver I’m using to convert the signal into DC dimming.
These sort of frequencies should easily be possible. But the default clock source on Yocto appears to only max out at 300hz, so clearly a setting is wrong somewhere…

Im assuming I need to set to one of the high speed mhz clocks and then divide that down some how?

Any tips on how to do this?

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

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


Hello! I understand you need to generate PWM signals at higher frequencies (20 kHz–200 kHz) on the Verdin iMX8M Plus for a backlight driver, but you’re seeing a much lower maximum frequency in Yocto. Let’s go through what you can do to achieve these higher PWM output frequencies.

1. Hardware & PWM Channel Availability

First, please note that the Verdin iMX8M Plus exposes three PWMs:

  • PWM_1: /sys/class/pwm/pwmchip0/
  • PWM_2: /sys/class/pwm/pwmchip1/
  • PWM_3_DSI (for display backlight): /sys/class/pwm/pwmchip2/ (source)

If you require four independent PWMs, additional configuration or alternative pins may be necessary as only three are directly available.

2. Why Are You Limited to 300 Hz?

The frequency of a standard Linux PWM interface is determined by the period you set via sysfs (or another interface), and the minimum period is limited by the input clock to the PWM controller and its hardware prescaler. When the input clock is low, the achievable frequency is also low.

Most often, device tree settings define the input clock source and frequency for the PWM controllers. If you’re limited to low frequencies like ~300 Hz, it likely means the PWM controller is being clocked from a low-frequency clock source (like a 32 kHz or 24 MHz oscillator) and/or the prescaler is set incorrectly.

3. How to Change the PWM Clock Source or Frequency

a. Device Tree Adjustments

To use a higher-frequency clock, adjust the device tree to assign one of the SOC’s MHz-level clocks as the input to the PWM block. This involves:

  1. Locating the PWM Node
    Find the relevant PWM node in your device tree (commonly imx-pwm.* nodes).

  2. Assigning the Correct Clock
    Check the clocks = <&clk>; property on the PWM node. Assign a high-speed clock (such as 24 MHz or higher), if available.

  3. Example (device tree fragment):

    &pwm1 {
        clocks = <&clks IMX8MP_CLK_24M>;
        ...
    };
    

    Replace IMX8MP_CLK_24M with the appropriate high-speed clock for your SoC.

  4. Rebuild and Deploy the Device Tree

b. PWM Configuration via Sysfs

Once the correct clock is set, you can use the sysfs interface to set the period:

cd /sys/class/pwm/pwmchipX/
echo 0 > export
# For 100 kHz: period = 1/100,000 = 0.00001 s = 10,000 ns
echo 10000 > pwm0/period
# For 50% duty cycle:
echo 5000 > pwm0/duty_cycle
echo 1 > pwm0/enable

(reference)

If the kernel still doesn’t allow such a short period and reports an out-of-range error, the input clock and/or prescaler setup remains insufficient and device tree/source code further adjustment is required.

c. Limitations

  • The PWM controller has a 16-bit counter and a 12-bit prescaler (source), so maximum frequency is still limited by the counter size and the input clock speed.
  • You can calculate the maximum achievable frequency as:
    f_PWM = clock_in / (prescaler * period_cnt)
    With maximum clock and minimal prescaler.

d. Reboot

After rebuilding and deploying the new device tree with the faster clock, reboot the board and re-try configuring the high-frequency PWM.


4. Summary

  • You need to set a high-frequency clock as the source for the PWM controller in the device tree.
  • After adjusting, you can achieve periods as low as your hardware allows, sufficient for 20–200 kHz output.
  • Only three hardware PWM channels are available on Verdin iMX8M Plus—test if these suffice for your application.

For more detailed device tree setup, please see:

If you need a concrete device tree file example, let me know your current one and I can help further.

Best regards,
Toradex AI Assistant.

In uboot i found the pwm hardware with fdt but the clocks are listed as such…
Im not sure if those are addresses pointing to the correct clocks or not. I was expecting to see a readable pointer.

        compatible = "fsl,imx8mp-pwm", "fsl,imx27-pwm";
        reg = <0x30660000 0x00010000>;
        interrupts = <0x00000000 0x00000051 0x00000004>;
        clocks = <0x00000002 0x000000dc 0x00000002 0x000000dc>;
        clock-names = "ipg", "per";
        #pwm-cells = <0x00000003>;
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <0x0000002c>;
        phandle = <0x000000cf>;
};

but according to the device tree i should be loading…

pwm1: pwm@30660000 {
				compatible = "fsl,imx8mp-pwm", "fsl,imx27-pwm";
				reg = <0x30660000 0x10000>;
				interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clk IMX8MP_CLK_PWM1_ROOT>,
					 <&clk IMX8MP_CLK_PWM1_ROOT>;
				clock-names = "ipg", "per";
				#pwm-cells = <2>;
				status = "disabled";
			};

Also whats odd “clock-controller@30380000” isnt under /soc@0/ like it is in the tree. So im not even sure this tree is loading correctly into uboot.

Ok that took a while but i managed to figure out we are using the <&clk IMX8MP_CLK_PWM1_ROOT> by looking at linux/include/dt-bindings/clock/imx8mp-clock.h at master · torvalds/linux · GitHub finding its dec number and checking that against hex. …

Now I just need to know why IMX8MP_CLK_PWM1_ROOT limited me to about 300hz… What clock is that based from.

I cant actually confirm where PWM1_ROOT points to other than dec 220
and at least in the compiled device tree address 2 dc, So I dont even know if it really is pointing to the correct clock to begin with.

I will try to manually set a clock though.

Ok got it working at 100khz.
In uboot it boiled down to fdt set /soc@0/bus@30400000/pwm@30660000 clocks <0x2 0xdc 0x2 0x50>

Had some help from gemini to figure that out… And basically this is pointing to the 24mhz clock.

So the AI assistant is correct to suggest to set that clock in the device tree.

There are some strange oddities still regarding the source tree not matching the compiled tree…