7.2.9. PWM 驱动调试指南

X3有两类控制器:一类是标准PWM,有3组,每组三个,共9个,另一类是LPWM,主要用于支持Sensor的同步曝光。

  • PWM 默认支持频率范围是192MHz到46.8KHz,每组PWM的占空比寄存器RATIO精度为8bit。

  • LPWM 默认支持频率范围是100KHz到24.4Hz,没有占空比寄存器,只有一个高电平持续时间HIGH,HIGH寄存器配置单位是us,最大支持设置高电平为160us,所以LPWM的占空比与频率有关。

  • LPWM是为了Sensor 同步设计的,不是一个通用的PWM,单纯PWM功能建议使用PWM。

7.2.9.1. 驱动代码

代码路径

drivers/pwm/pwm-hobot.c

内核配置

Device Drivers
    ->  Pulse-Width Modulation (PWM) Support
        ->  Hobot PWM controller support
        ->  Hobot lite PWM controller support

DTS节点配置

hobot-xj3.dtsi这个文件里面有pwmlpwm的配置,一般来讲不需要做任何修改。

/* arch/arm64/boot/dts/hobot/hobot-xj3.dtsi */
lpwm: lpwm@0xA500D000 {
    compatible = "hobot,hobot-lpwm";
    reg = <0 0xA5018000 0 0x1000>;
    interrupt-parent = <&gic>;
    interrupts = <0 68 4>;
    pinctrl-names = "lpwm0", "lpwm1","lpwm2","lpwm3", "lpwm_pps";
    pinctrl-0 = <&lpwm0_func>;
    pinctrl-1 = <&lpwm1_func>;
    pinctrl-2 = <&lpwm2_func>;
    pinctrl-3 = <&lpwm3_func>;
    pinctrl-4 = <&lpwm_pps>;
    clocks = <&lpwm_mclk>;
    clock-names = "lpwm_mclk";
    status = "disabled";
};

pwm_c0: pwm@0xA500D000 {
    compatible = "hobot,hobot-pwm";
    #pwm-cells = <3>;
    reg = <0 0xA500D000 0 0x1000>;
    interrupt-parent = <&gic>;
    interrupts = <0 44 4>;
    pinctrl-names = "pwm0", "pwm1","pwm2";
    pinctrl-0 = <&pwm0_func>;
    pinctrl-1 = <&pwm1_func>;
    pinctrl-2 = <&pwm2_func>;
    clocks = <&pwm0_mclk>;
    clock-names = "pwm_mclk";
    status = "disabled";
};
...

当需要使能对应串口的时候,可以到对应的板级文件修改,这里以hobot-x3-sdb_v4.dts为例,使能pwm0-2pwm3-5

/* arch/arm64/boot/dts/hobot/hobot-x3-sdb_v4.dts */
...
&pwm_c0 {
	status = "okay";
	pinctrl-0 = <&pwm0_func>;
	pinctrl-1 = <>;
	pinctrl-2 = <>;
};
&pwm_c1 {
	status = "okay";
	pinctrl-0 = <>;
	pinctrl-1 = <&pwm4_func>;
	pinctrl-2 = <>;
};
...

7.2.9.2. 测试

用户可以使用如下脚本进行pwm功能测试,并进行信号测量,验证pwm工作是否正常。

echo 8 8 8 8  > /proc/sys/kernel/printk
for i in 0 3
do
        cd /sys/class/pwm/pwmchip${i}
        echo 0 > export
        echo 1 > export
        echo 2 > export
 
        cd pwm0
        echo 10000 > period
        echo 3000  > duty_cycle
        echo 1 > enable
  
        cd ../pwm1
        echo 10000 > period
        echo 1000  > duty_cycle
        echo 1 > enable
 
        cd ../pwm2
        echo 10000 > period
        echo 1000  > duty_cycle
        echo 1 > enable
done
#以下是进行寄存器读取
echo "pwm0 pinctrl:`devmem 0xa6004010 32`"
echo "pwm1 pinctrl:`devmem 0xa6004058 32`"
echo "pwm2 pinctrl:`devmem 0xa600405C 32`"
echo "pwm3 pinctrl:`devmem 0xa6004060 32`"
echo "pwm4 pinctrl:`devmem 0xa6004064 32`"
echo "pwm5 pinctrl:`devmem 0xa6004048 32`"
echo "pwm6 pinctrl:`devmem 0xa600404C 32`"
echo "pwm7 pinctrl:`devmem 0xa6004030 32`"
echo "pwm8 pinctrl:`devmem 0xa6004034 32`"
 
echo "Regs of PWM 0 1 2:"
echo "PWM_EN      `devmem 0xA500d000 32`"
echo "PWM_SLICE   `devmem 0xA500d004 32`"
echo "PWM_FREQ    `devmem 0xA500d008 32`"
echo "PWM_FREQ1   `devmem 0xA500d00C 32`"
echo "PWM_RATIO   `devmem 0xA500d014 32`"
echo "PWM_SRCPND  `devmem 0xA500d01C 32`"
echo "PWM_INTMASK `devmem 0xA500d020 32`"
 
echo "Regs of PWM 3 4 5:"
echo "PWM_EN      `devmem 0xA500e000 32`"
echo "PWM_SLICE   `devmem 0xA500e004 32`"
echo "PWM_FREQ    `devmem 0xA500e008 32`"
echo "PWM_FREQ1   `devmem 0xA500e00C 32`"
echo "PWM_RATIO   `devmem 0xA500e014 32`"
echo "PWM_SRCPND  `devmem 0xA500e01C 32`"
echo "PWM_INTMASK `devmem 0xA500e020 32`"