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 8X system-on-module there are:

  • On the {cpu-family} system-on-chip:

    • Four PWM channels from the FlexTimer module.

    • One PWM channel from the parallel display interface.

    • Two PWM channels from the MIPI-DSI interface.

  • On the MCA

    • Three PWM controllers (each one with several channels).

The current v5.4 BSP does not support the four PWM channels from the FlexTimer module in the CPU.

This chapter describes the PWM channels from the CPU. See MCA Pulse Width Modulation (PWM) for information about the MCA PWM controllers.

On the ConnectCore 8X SBC Pro:

  • Parallel LCD PWM is available at SPI0_CS1 pad on the expansion connector.

  • MIPI-DSI0 PWM0 is routed to LVDS0 connector for backlight management.

  • MIPI-DSI1 PWM0 is routed to LVDS1 connector for backlight management.

Kernel configuration

You can manage the {cpu-family} PWM driver support through the following kernel configuration option:

  • i.MX27 PWM support (CONFIG_PWM_IMX27)

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

Kernel driver

The driver for the {cpu-family} PWM is located at:

File Description

drivers/pwm/pwm-imx27.c

PWM driver

Device tree bindings and customization

The {cpu-family} PWM interface is documented at Documentation/devicetree/bindings/pwm/imx-pwm.txt.

{cpu-family} PWM interfaces

The common {cpu-family} CPU device tree file contains entries for the MIPI-DSI PWM channels and the LCD PWM channel:

{cpu-family} device tree
	adma_pwm: pwm@5a190000 {
		compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm";
		reg = <0x5a190000 0x1000>;
		clocks = <&adma_pwm_lpcg 0>, <&adma_pwm_lpcg 1>;
		clock-names = "per", "ipg";
		assigned-clocks = <&clk IMX_SC_R_LCD_0_PWM_0 IMX_SC_PM_CLK_PER>;
		assigned-clock-rates = <24000000>;
		#pwm-cells = <2>;
		power-domains = <&pd IMX_SC_R_LCD_0_PWM_0>;
		status = "disabled";
	};

	...

	pwm_mipi_lvds0: pwm@56224000 {
		compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm";
		reg = <0x56224000 0x1000>;
		clocks = <&mipi0_pwm_lpcg 0>,
			 <&mipi0_pwm_lpcg 1>,
			 <&mipi0_pwm_lpcg 2>;
		clock-names = "per", "ipg", "32k";
		assigned-clocks = <&clk IMX_SC_R_MIPI_0_I2C_0 IMX_SC_PM_CLK_PER>;
		assigned-clock-rates = <24000000>;
		#pwm-cells = <2>;
		power-domains = <&pd IMX_SC_R_MIPI_0_PWM_0>;
		status = "disabled";
	};

	...

	pwm_mipi_lvds1: pwm@56244000 {
		compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm";
		reg = <0x56244000 0x1000>;
		clocks = <&mipi1_pwm_lpcg 0>,
			 <&mipi1_pwm_lpcg 1>,
			 <&mipi1_pwm_lpcg 2>;
		clock-names = "per", "ipg", "32k";
		assigned-clocks = <&clk IMX_SC_R_MIPI_1_I2C_0 IMX_SC_PM_CLK_PER>;
		assigned-clock-rates = <24000000>;
		#pwm-cells = <2>;
		power-domains = <&pd IMX_SC_R_MIPI_1_PWM_0>;
		status = "disabled";
	};

IOMUX configuration

You must configure the pads that are to be used as {cpu-family} PWMs. See Pin multiplexing (IOMUX).

{cpu-family} pads should only have one IOMUX configuration. Remove other configurations for those pads, like GPIO, when configuring them as PWMs.

The following external pads are configured as PWMs on the default device tree:

  • On the ConnectCore 8X SBC Pro LVDS0 connector:

    Pad Signal PWM

    16

    MIPI_DSI0_PWM0_OUT

    MIPI-DSI0 PWM0

Example: MIPI-DSI0 PWM0 on ConnectCore 8X SBC Pro

For example, MIPI-DSI0 PWM0 is available on pin 16 of the LVDS0 connector of the ConnectCore 8X SBC Pro.

The device tree must:

  • Configure the IOMUX of pad MIPI_DSI0_GPIO0_00 to work as PWM

  • Enable the PWM node

  • Since it’s connected to the display, enable the backlight node as consumer of the PWM

ConnectCore 8X SBC Pro device tree
	lvds_backlight0: lvds_backlight@0 {
		compatible = "pwm-backlight";
		pwms = <&pwm_mipi_lvds0 0 100000 0>;

		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
				     10 11 12 13 14 15 16 17 18 19
				     20 21 22 23 24 25 26 27 28 29
				     30 31 32 33 34 35 36 37 38 39
				     40 41 42 43 44 45 46 47 48 49
				     50 51 52 53 54 55 56 57 58 59
				     60 61 62 63 64 65 66 67 68 69
				     70 71 72 73 74 75 76 77 78 79
				     80 81 82 83 84 85 86 87 88 89
				     90 91 92 93 94 95 96 97 98 99
				    100>;
		default-brightness-level = <80>;
		power-supply = <&reg_5v_display>;
	};

	...

&pwm_mipi_lvds0 {
	status = "okay";
};

...

&iomuxc {

	...

	pinctrl_lvds0: lvds0grp {
		fsl,pins = <
			/* LVDS0 touch interrupt */
			SC_P_QSPI0B_DATA2_LSIO_GPIO3_IO20	0x06000020
			/* LVDS0 PWM backlight */
			SC_P_MIPI_DSI0_GPIO0_00_MIPI_DSI0_PWM0_OUT	0x00000020
		>;
	};

	...
};

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,imx8qxp-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

You can access the PWM channels from your Android application. See PWM API for more information about the PWM APIx.

Sample application

The PWM Sample Application demonstrates the usage of the PWM API. In this example you can list all the available PWM chips and channels and configure the different PWM parameters.

Go to GitHub to see the application instructions and source code.