====== PWM ====== ===== Introduction ===== This page introduces the usage of hardware PWM, and leads you to control the hardware PWM on the [[products:sbc:common:applications:gpio:40pin-header|40-Pin Header]]. ===== PWM Reference Table ===== | ^ PWM ^ PIN ^ GPIO name ^ DT overlay node ^ Device node ^ ^ VIM1 | ''PWM_AO_A'' | 35 | ''GPIOAO_3'' | ''pwm_ao_a'' | /sys/class/pwm/pwmchip4 | ^ VIM2 | ''PWM_D'' | 35 | ''GPIODV_28'' | ''pwm_d'' | /sys/class/pwm/pwmchip1 | ^ VIM3 | ''PWM_F'' | 35 | ''GPIOH_5'' | ''pwm_f'' | /sys/class/pwm/pwmchip4 | ^ VIM3L | ''PWM_F'' | 35 | ''GPIOH_5'' | ''pwm_f'' | /sys/class/pwm/pwmchip0 | ^ VIM4 | ''PWM_F'' | 35 | ''GPIOY_8'' | ''pwm_f'' | /sys/class/pwm/pwmchip4 | ^ VIM1S | ''PWM_F'' | 35 | ''GPIOZ_6'' | ''pwm_f'' | /sys/class/pwm/pwmchip0 | ===== Enable PWM ===== ==== Linux ==== In order to use the PWM, you need to enable the PWM function via [[products:sbc:common:configurations:device-tree-overlay|Device Tree Overlay]]. Edit ''/boot/env.txt'' to add the pwm node to ''overlays'' node if it doesn't exist. Take VIM3 as an example to enable ''PWM_F'', you need to add ''pwm_f'' node to ''overlays'' node if it doesn't exist. ```shell overlays=uart3 pwm_f i2c3 i2s os08a10 watchdog ``` After reboot, you will see the pwm device node. ```shell $ ls /sys/class/pwm/pwmchip4 device export npwm power subsystem uevent unexport ``` Edit ''/boot/env.txt'' to add the pwm node to ''overlays'' node if it doesn't exist. Take VIM3L as an example to enable ''PWM_F'', you need to add ''pwm_f'' node to ''overlays'' node if it doesn't exist. ```shell overlays=uart3 pwm_f i2c3 i2s watchdog ``` After reboot, you will see the pwm device node. ```shell $ ls /sys/class/pwm/pwmchip0 device export npwm power subsystem uevent unexport ``` Edit ''/boot/dtb/amlogic/kvim3.dtb.overlay.env'' to add pwm node to ''fdt_overlays'' node if it doesn't exist. You need to add ''pwm_f'' to node ''fdt_overlays'' if it doesn't exist to enable ''PWM_F''. ```shell fdt_overlays=pwm_f ``` After reboot, you will see the pwm device node. Edit ''/boot/dtb/amlogic/kvim3l.dtb.overlay.env'' to add pwm node to ''fdt_overlays'' node if it doesn't exist. You need to add ''pwm_f'' to node ''fdt_overlays'' if it doesn't exist to enable ''PWM_F''. ```shell fdt_overlays=pwm_f ``` After reboot, you will see the pwm device node. Edit ''/boot/dtb/amlogic/kvim4.dtb.overlay.env'' to add pwm node to ''fdt_overlays'' node if it doesn't exist. You need to add ''pwm_f'' to node ''fdt_overlays'' if it doesn't exist to enable ''PWM_F''. ```shell fdt_overlays=pwm_f ``` After reboot, you will see the pwm device node. ```shell $ ls /sys/class/pwm/pwmchip4 device export npwm power subsystem uevent unexport ``` Edit ''/boot/dtb/amlogic/kvim1s.dtb.overlay.env'' to add pwm node to ''fdt_overlays'' node if it doesn't exist. You need to add ''pwm_f'' to node ''fdt_overlays'' if it doesn't exist to enable ''PWM_F''. ```shell fdt_overlays=pwm_f ``` After reboot, you will see the pwm device node. ```shell $ ls /sys/class/pwm/pwmchip0 device export npwm power subsystem uevent unexport ``` ==== Android ==== The ''PWM'' function is disabled by default, you need to modify the dts to enable it. ```diff diff --git a/arch/arm64/boot/dts/amlogic/kvim4.dts b/arch/arm64/boot/dts/amlogic/kvim4.dts --- a/arch/arm64/boot/dts/amlogic/kvim4.dts +++ b/arch/arm64/boot/dts/amlogic/kvim4.dts &pwm_ef { + pinctrl-names = "default"; + pinctrl-0 = <&pwm_f_pins>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/amlogic/kvim4n.dts b/arch/arm64/boot/dts/amlogic/kvim4n.dts --- a/arch/arm64/boot/dts/amlogic/kvim4n.dts +++ b/arch/arm64/boot/dts/amlogic/kvim4n.dts &pwm_ef { + pinctrl-names = "default"; + pinctrl-0 = <&pwm_f_pins>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/amlogic/mesont7_an400-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesont7_an400-panel.dtsi --- a/arch/arm64/boot/dts/amlogic/mesont7_an400-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesont7_an400-panel.dtsi @@ -1442,13 +1442,13 @@ backlight1{ compatible = "amlogic, backlight-t7"; - status = "okay"; + status = "disabled"; index = <1>; key_valid = <0>; pinctrl-names = "pwm_on", "pwm_off"; - pinctrl-0 = <&pwm_f_pins>; - pinctrl-1 = <&bl1_pwm_off_pins>; pinctrl_version = <2>; /* for uboot */ interrupts = <0 197 1 ``` The ''PWM'' function is disabled by default, you need to modify the dts to enable it. ```diff --- a/arch/arm64/boot/dts/amlogic/kvim1s.dts +++ b/arch/arm64/boot/dts/amlogic/kvim1s.dts @@ -1411,8 +1411,8 @@ }; &pwm_ef { - /*pinctrl-0 = <&pwm_f_pins2>;*/ - /*pinctrl-names = "default";*/ + pinctrl-0 = <&pwm_f_pins2>; + pinctrl-names = "default"; status = "okay"; }; ``` ===== Control PWM ===== **Enable PWM:** ```shell echo 1 | sudo tee /sys/class/pwm/pwmchip4/export echo 1000000 | sudo tee /sys/class/pwm/pwmchip4/pwm1/period echo 500000 | sudo tee /sys/class/pwm/pwmchip4/pwm1/duty_cycle echo 1 | sudo tee /sys/class/pwm/pwmchip4/pwm1/enable ``` ```shell echo 1 | sudo tee /sys/class/pwm/pwmchip1/export echo 1000000 | sudo tee /sys/class/pwm/pwmchip1/pwm1/period echo 500000 | sudo tee /sys/class/pwm/pwmchip1/pwm1/duty_cycle echo 1 | sudo tee /sys/class/pwm/pwmchip1/pwm1/enable ``` ```shell echo 1 | sudo tee /sys/class/pwm/pwmchip0/export echo 1000000 | sudo tee /sys/class/pwm/pwmchip0/pwm1/period echo 500000 | sudo tee /sys/class/pwm/pwmchip0/pwm1/duty_cycle echo 1 | sudo tee /sys/class/pwm/pwmchip0/pwm1/enable ``` Use an oscilloscope to check if the pins have been successfully enabled. {{products:sbc:common:applications:gpio:pwm-oscilloscope.png|pwm-oscilloscope}} If you use an oscilloscope to view the PWM waveform, remember that the SBC and the oscilloscope need to share the same GND (ground). **Disable PWM:** ```shell echo 0 | sudo tee /sys/class/pwm/pwmchip4/pwm1/enable ``` ```shell echo 0 | sudo tee /sys/class/pwm/pwmchip1/pwm1/enable ``` ```shell echo 0 | sudo tee /sys/class/pwm/pwmchip0/pwm1/enable ``` ===== Disable PWM to Use GPIO ===== If you want to use normal GPIO instead of PWM, you can remove the PWM node in [[products:sbc:common:configurations:device-tree-overlay|Device Tree Overlay]].