这是本文档旧的修订版!
接口设备树研读和改写
接口设备树PWM片段的解读方法
下面以LVDS背光驱动为例,来分析设备树的相关要素和定义方法。通常,编译出镜像后,设备树位于:tmp/work/ccmp25_dvk-dey-linux/linux-dey/6.1-r0/git/arch/arm64/boot/dts目录下,一般入口是板级的设备树,即:ccmp25-dvk.dts
设备树可相互嵌套,所以常见的做法是板级的dts会include芯片和模块级的dtsi。大部分的接口或接口基础定义是在dtsi完成。对于特定的一个接口,我们通常需要从pin脚定义开始,如果没在dtsi中定义,或是需要给个关联性强的名称来覆盖定义,可以在板级的@pinctrl节点引用处定义它。
以LVDS的背光驱动模块为例,它是一个基于PWM驱动的接口,顶层片段位于:
panel_lvds_pwm_backlight: panel-lvds-pwm-backlight { compatible = "pwm-backlight"; /* node TIM20_CH4 period (ns) */ pwms = <&pwm_lvds_bckl 3 500000 PWM_POLARITY_INVERTED>; brightness-levels = <0 16 22 30 40 55 75 102 138 188 255>; default-brightness-level = <8>; power-supply = <®_5v_board>; status = "disabled"; };
其中,&pwm_lvds_bckl:这是对 PWM 控制器的引用,它定义timers20的子节点中:
&timers20 { /delete-property/dmas; /delete-property/dma-names; status = "okay"; pwm_lvds_bckl: pwm { pinctrl-0 = <&ccmp25_pwm20_pins>; pinctrl-1 = <&ccmp25_pwm20_sleep_pins>; pinctrl-names = "default", "sleep"; status = "okay"; }; timer@19 { status = "okay"; }; };
从名称上可以看出0和1分别对应的子节点,查到这两个定义,发现是同一引脚的两种模式:
ccmp25_pwm20_pins: ccmp25-pwm20-0 { pins { pinmux = <STM32_PINMUX('B', 0, AF8)>; /* TIM20_CH4N */ bias-disable; drive-push-pull; slew-rate = <0>; }; }; 睡眠模式 ccmp25_pwm20_sleep_pins: ccmp25-pwm20-sleep-0 { pins { pinmux = <STM32_PINMUX('B', 0, ANALOG)>; /* TIM20_CH4N */ }; };
结合名称来分析,这pinctrl-0是正常模式,而pinctrl-1是睡眠模式,对应ccmp25_pwm20_pins 用于正常操作模式,而 ccmp25_pwm20_sleep_pins 用于睡眠低功耗模式。大概是高电平时引脚功耗小。 这背光驱动应该是PWM输出,所以这是对应AF8和ANALOG所具备的功能,如果是作为编码器的输入捕获,是不一样的设置。
PLC中的编码器接口设备树
以MP257的参考设计为例,当前的smartIOMUX接口只能选择pwm接口功能而非编码器接口,所以它生成的设备树是这样的结构,分两个定时器节点和&pinctrl的子节点两个部分:
&timersN { pwmX: pwm { pinctrl-names = "default", "sleep"; pinctrl-0 = <&ccmp25_timers1_ch3_pwm_pins>; pinctrl-1 = <&ccmp25_timers1_ch3_pwm_sleep_pins>; status = "okay"; } }