PWM 配置
17 Dec 2024
Read time: 8 minute(s)
内核配置
-
在 SDK 根目录下,执行下列命令,进入 kernel 的功能配置界面:
make kernel-menuconfig
或使用简写命令
make km
-
在内核配置界面,按如下选择:
Linux Device Drivers ---> [*] Pulse-Width Modulation (PWM) Support ---> <*> ArtInChip PWM support <*> ArtInChip EPWM support
-
如需设置 PWM 模块的背光控制功能,执行下列配置,否则可跳过。
在 SDK 根目录下执行 make kernel-menuconfig 或 make me,进入 kernel 的功能配置,按如下选择:
Linux Device Drivers ---> Graphics support ---> Backlight & LCD device support ---> <*> Lowlevel Backlight controls <*> Generic PWM based Backlight Driver
-
如使用 logo 功能,须在 Boot 阶段打开屏幕背光,否则可跳过。
在 SDK 根目录下执行 make kernel-menuconfig 或 make me,进入 kernel 的功能配置,按如下选择:
U-Boot Device Drivers ---> [*] Enable support for pulse-width modulation devices (PWM) [*] Enable support for ArtInChip PWM Graphics support ---> [*] Generic PWM based Backlight Driver
DTS 参数配置
PWM 驱动支持从 DTS 中配置的自定义参数,如下表所示:
参数名称 | 类型 | 取值范围 | 功能说明 |
---|---|---|---|
mode | String | up/down/up-down-count | 配置增减模式 |
tb-clk-rate | Integer | (0, 24000000) | 时基计数器的工作时钟 |
action0 | String | none/low/high/inverse | 多个关键时点的触发行为 |
action1 | String | none/low/high/inverse | 多个关键时点的触发行为 |
default-level | Integer | [0, 1] | 默认/初始电平 |
注:
为了方便表达,所有参数名称都省略了前缀 “aic,”。
表中 action0 和 action1 四种取值的含义,定义如下:
Action 类型 | 行为描述 |
---|---|
none | 不做任何变化,保持之前的输出电平 |
low | 跳变为 0 电平 |
high | 跳变为 1 电平 |
inverse | 跳变为反向的电平,比如从 0 跳变为 1 |
时钟配置
PWM 模块涉及时钟的衍生关系:
EWM 模块涉及时钟的衍生关系:
其中,前两个时钟在 PWM 控制器的节点中配置,后两个时钟在 Board 中的 PWM 子节点(对应通道)中配置。
注:
容易混淆的 sysclk:
-
PWM 驱动中,按照惯例将父时钟称作 sysclk,即上图的 PLL INT1。
-
PWM 硬件 spec 中,将上图中的 PWM Clk 称作 sysclk。
D211 配置
common/d211.dtsi 中的参数配置:
pwm: pwm@19240000 {
compatible = "artinchip,aic-pwm-v1.0";
reg = <0x0 0x19240000 0x0 0x1000>;
interrupts-extended = <&plic0 90 IRQ_TYPE_LEVEL_HIGH>;
#pwm-cells = <3>;
clocks = <&cmu CLK_PWM>, <&cmu CLK_PLL_INT1>;
clock-names = "pwm", "sysclk";
resets = <&rst RESET_PWM>;
clock-rate = <48000000>;
};
epwm: epwm@18200000 {
compatible = "artinchip,aic-epwm-v1.0";
reg = <0x0 0x18200000 0x0 0x600>, <0 0x1820F000 0x0 0x1000>;
interrupts-extended = <&plic0 25 IRQ_TYPE_LEVEL_HIGH>;
#pwm-cells = <3>;
clocks = <&cmu CLK_PWMCS>, <&cmu CLK_PLL_INT1>;
clock-names = "pwmcs", "sysclk";
resets = <&rst RESET_PWMCS>;
clock-rate = <48000000>;
status = "disabled";
};
Board 配置
- PWM 通道配置xxx/board.dts 中的参数配置:
&pwm { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&pwm2_pins_b>; /* mode: up-count, down-count, up-down-count action: none, low, high, inverse */ pwm0 { aic,mode = "up-count"; aic,tb-clk-rate = <24000000>; aic,rise-edge-delay = <10>; aic,fall-edge-delay = <10>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "low", "none", "high"; aic,action1 = "none", "none", "none", "high", "none", "low"; status = "disabled"; }; pwm1 { aic,mode = "down-count"; aic,tb-clk-rate = <24000000>; aic,rise-edge-delay = <10>; aic,fall-edge-delay = <10>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "low", "none", "high"; aic,action1 = "none", "none", "none", "high", "none", "low"; status = "disabled"; }; pwm2 { aic,mode = "up-count"; aic,tb-clk-rate = <24000000>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "high", "low", "none"; aic,action1 = "none", "none", "none", "low", "high", "none"; aic,default-level = <0>; aic,rise-edge-delay = <10>; aic,fall-edge-delay = <10>; status = "okay"; }; pwm3 { aic,mode = "up-count"; aic,tb-clk-rate = <24000000>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "low", "high", "none"; aic,action1 = "none", "none", "none", "high", "low", "none"; aic,rise-edge-delay = <10>; aic,fall-edge-delay = <10>; status = "disabled"; }; }; &epwm { status = "disabled"; pinctrl-names = "default"; pinctrl-0 = <&epwm0_pins_a>, <&epwm1_pins_a>, <&epwm2_pins_a>; /* mode: up-count, down-count, up-down-count action: none, low, high, inverse */ epwm0 { aic,mode = "up-count"; aic,tb-clk-rate = <24000000>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "high", "none", "low"; aic,action1 = "none", "high", "none", "none", "none", "low"; status = "disabled"; }; epwm1 { aic,mode = "up-count"; aic,tb-clk-rate = <24000000>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "high", "none", "low"; aic,action1 = "none", "high", "none", "none", "none", "low"; status = "disabled"; }; epwm2 { aic,mode = "up-count"; aic,tb-clk-rate = <24000000>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "high", "none", "low"; aic,action1 = "none", "high", "none", "none", "none", "low"; status = "disabled"; }; epwm3 { aic,mode = "up-count"; aic,tb-clk-rate = <24000000>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "high", "none", "low"; aic,action1 = "none", "high", "none", "none", "none", "low"; status = "disabled"; }; epwm4 { aic,mode = "up-count"; aic,tb-clk-rate = <24000000>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "high", "none", "low"; aic,action1 = "none", "high", "none", "none", "none", "low"; status = "disabled"; }; epwm5 { aic,mode = "up-count"; aic,tb-clk-rate = <24000000>; /* CBD, CBU, CAD, CAU, PRD, ZRO */ aic,action0 = "none", "none", "none", "high", "none", "low"; aic,action1 = "none", "high", "none", "none", "none", "low"; status = "disabled"; }; };
- 背光控制配置需要在 xxx/board.dts 中新增一个 backlight 节点,如下:
backlight: backlight { compatible = "pwm-backlight"; /* pwm node name; pwm device No.; period_ns; pwm_polarity */ pwms = <&pwm 2 1000000 0>; brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>; default-brightness-level = <8>; status = "okay"; };
其中 “&pwm 2” 表示要使用 pwm2 通道作为背光控制用(要确认和硬件上的电路连接是一致的)。
在屏幕 panel 节点中,需要引用 backlight:panel_lvds { compatible = "artinchip,aic-general-lvds-panel"; data-mapping = "vesa-24"; data-channel = "single-link1"; backlight = <&backlight>; status = "okay"; ... };