You are here: Digi Embedded Yocto > System development > Linux v4.1 Board Support Package > Devices and interfaces > Pulse-width modulation (PWM)

Pulse-width Modulation (PWM)

Pulse-width modulation (PWM) is a technique that modifies the duty-cycle of a pulsing signal to encode information or to control the amount of energy provided to a charge.

On the ConnectCore 6UL system-on-module there are:

On the ConnectCore 6UL SBC Express:

On the ConnectCore 6UL SBC Pro:

Kernel configuration

You can manage the i.MX6UL PWM driver support through the following kernel configuration option:

This option is enabled as built-in on the default ConnectCore 6UL kernel configuration file.

Platform driver mapping

The driver for the i.MX6UL PWM is located at:

File

Description

drivers/pwm/pwm-imx.c

PWM driver

Device tree bindings and customization

The i.MX6UL PWM interface is documented at Documentation/devicetree/bindings/pwm/imx-pwm.txt.

i.MX6UL PWM interfaces

The common i.MX6UL CPU device tree file contains entries for all the PWM channels, however it it only defines the clock of PWM1 and uses a dummy clock source for the rest of PWM channels, which remain disabled:

Common i.MX6UL device tree 
            pwm1: pwm@02080000 {
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x02080000 0x4000>;
                interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_PWM1>,
                     <&clks IMX6UL_CLK_PWM1>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
 
            pwm2: pwm@02084000 {
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x02084000 0x4000>;
                interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_DUMMY>,
                     <&clks IMX6UL_CLK_DUMMY>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
 
            pwm3: pwm@02088000 {
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x02088000 0x4000>;
                interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_DUMMY>,
                     <&clks IMX6UL_CLK_DUMMY>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
 
            pwm4: pwm@0208c000 {
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x0208c000 0x4000>;
                interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_DUMMY>,
                     <&clks IMX6UL_CLK_DUMMY>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
 
            pwm5: pwm@020f0000 {
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x020f0000 0x4000>;
                interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_DUMMY>,
                     <&clks IMX6UL_CLK_DUMMY>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
 
            pwm6: pwm@020f4000 {
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x020f4000 0x4000>;
                interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_DUMMY>,
                     <&clks IMX6UL_CLK_DUMMY>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
 
            pwm7: pwm@020f8000 {
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x020f8000 0x4000>;
                interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_DUMMY>,
                     <&clks IMX6UL_CLK_DUMMY>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            };
 
            pwm8: pwm@020fc000 {
                compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
                reg = <0x020fc000 0x4000>;
                interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6UL_CLK_DUMMY>,
                     <&clks IMX6UL_CLK_DUMMY>;
                clock-names = "ipg", "per";
                #pwm-cells = <2>;
            }

You must assign appropriate clocks to a PWM channel in order to use it.

Example: PWM4 on ConnectCore 6UL SBC Express

For example, PWM4 is available on the ConnectCore 6UL SBC Express expansion connector which corresponds to pad LCD_DATA03 of the CPU. You must:

ConnectCore 6UL SBC Express
&pwm4 {
       pinctrl-names = "default";
       pinctrl-0 = <&pinctrl_pwm4>;
       clocks = <&clks IMX6UL_CLK_PWM4>,
                <&clks IMX6UL_CLK_PWM4>;
};
 
&iomuxc {
    imx6ul-ccimx6ul {
               pinctrl_pwm4: pwm4grp {
                       fsl,pins = <
                               MX6UL_PAD_LCD_DATA03__PWM4_OUT          0x11080
                       >;
               };
    };
};

Depending on the frequency of the PWM signal and the hardware around it, you must enable the pad settings carefully (the numerical value following the IOMUX definition on the device tree). See Documentation/devicetree/bindings/pinctrl/fsl,imx6ul-pinctrl.txt for information about the different values. Also see the NXP application note AN5078 Influence of pin setting on system function and performance for additional information.

Using the PWM channels

Control PWM signal from sysfs

Each of the eight PWM interfaces is registered in the system as a standalone PWM controller.

On the ConnectCore 6UL SBC Express:

On the ConnectCore 6UL SBC Pro:

The PWM interfaces appear under /sys/class/pwm:

~# ls /sys/class/pwm/
pwmchip0

As with any other device in Linux, the PWM channels start numbering with an index of 0, which corresponds to the first PWM channel probed, as per the channels enabled on the device tree.

Each PWM interface only manages one PWM signal. You can confirm this by printing the value of npwm (number of PWM signals controlled by an interface):

~# cat /sys/class/pwm/pwmchip0/npwm
1

To access the PWM channel, export its index (0 since there is only one):

~# echo 0 > /sys/class/pwm/pwmchip0/export

Now you can access the PWM channel and configure its settings:

~# ls /sys/class/pwm/pwmchip0/pwm0/
duty_cycle  enable      period      polarity    power       uevent

Period and duty cycle are given in nanoseconds. For example, for a 100 kHz signal with 50% duty cycle:

~# echo 10000 > /sys/class/pwm/pwmchip0/pwm0/period
~# echo 5000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle

To enable the PWM signal:

~# echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable

See also

 

© 2017 Digi International Inc. All rights reserved.
Pulse-width Modulation (PWM) updated on 19 May 2017 02:58:18 PM