使用如下设备树配置,启动到寻找sd卡分区之后就无法启动。
屏蔽pinctrl部分可以启动,能够加载event,但是无法操作,会报错:root@luckfox:/# echo 44 > /sys/class/gpio/export
bash: echo: write error: Device or resource busy
查看gpio信息如下:
root@luckfox:/# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/ff940000.gpio, gpio0:
gpio-0 ( |sysfs ) in hi
gpio-10 ( |GPIO_Key_Screenlock ) in lo IRQ ACTIVE LOW
gpio-14 ( |pwr ) out hi ACTIVE LOW
gpio-15 ( |BTN-A ) in lo IRQ ACTIVE LOW
gpio-21 ( |vdd-cpux ) out lo
gpiochip1: GPIOs 32-63, parent: platform/ff870000.gpio, gpio1:
gpio-42 ( |reset ) out hi ACTIVE LOW
gpio-43 ( |KEY-VOLUMEDOWN ) in lo IRQ ACTIVE LOW
gpio-44 ( |KEY-VOLUMEUP ) in lo IRQ ACTIVE LOW
gpio-45 ( |BTN-X ) in lo IRQ ACTIVE LOW
gpio-46 ( |BTN-Y ) in lo IRQ ACTIVE LOW
gpio-47 ( |BTN-B ) in lo IRQ ACTIVE LOW
gpio-51 ( |sysfs ) in lo
gpio-58 ( |work-led ) out lo
gpiochip2: GPIOs 64-95, parent: platform/ff1c0000.gpio, gpio2:
gpio-73 ( |DPAD-UP ) in lo IRQ ACTIVE LOW
gpio-74 ( |DPAD-LEFT ) in lo IRQ ACTIVE LOW
gpio-75 ( |DPAD-RIGHT ) in lo IRQ ACTIVE LOW
gpio-76 ( |DPAD-DOWN ) in lo IRQ ACTIVE LOW
gpio-77 ( |BTN-SELECT ) in lo IRQ ACTIVE LOW
gpio-78 ( |BTN-MODE ) in lo IRQ ACTIVE LOW
gpio-79 ( |BTN-START ) in lo IRQ ACTIVE LOW
gpiochip3: GPIOs 96-127, parent: platform/ff1d0000.gpio, gpio3:
gpio-104 ( |sysfs ) in lo
gpiochip4: GPIOs 128-159, parent: platform/ff1e0000.gpio, gpio4:
root@luckfox:/# piochip0: GPIOs 0-31, parent: platform/ff940000.gpio, gpio0:
o-0 ( |sysfs ) in hi
bash: piochip0:: command not found
gpio-10 ( |GPIO_Key_Sroot@luckfox:/# gpio-0 ( |sysfs ) in hi
bash: syntax error near unexpected token `|'
root@luckfox:/# gpio-10 ( |GPIO_Key_Screenlock ) in lo IRQ ACTIVE LOW
Lbash: syntax error near unexpected token `|'
OW
root@luckfox:/# gpio-14 ( |pwr ) out hi ACTIVE LOW
bash: syntax error near unexpected token `|'
) root@luckfox:/# gpio-15 ( |BTN-A ) in lo IRQ ACTIVE LOW
bash: syntax error near unexpected token `|'
|vdd-cpux root@luckfox:/# gpio-21 ( |vdd-cpux ) out lo
bash: syntax error near unexpected token `|'
贴出有问题的gpio-keys部分:
gpio_power: gpio-power {
status = "okay";
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&pwrbtn>;
key_screenlock:key-screenlock {
label = "GPIO_Key_Screenlock";
linux,code = <KEY_SCREENLOCK>;
linux,input-type = <1>;
gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
wakeup-source;
debounce-interval = <100>;
};
pwr: pwr {
gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
label = "Core Power Off";
};
};
gpioPad: gpioPad {
status = "okay";
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&gpio_pad>;
button_a:button-a {
label = "BTN-A";
linux,code = <BTN_SOUTH>;
gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
button_b:button-b {
label = "BTN-B";
linux,code = <BTN_EAST>;
gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
button_x:button-x {
label = "BTN-X";
linux,code = <BTN_NORTH>;
gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>;
autorepeat;
debounce-interval = <100>;
};
button_y:button-y {
label = "BTN-Y";
linux,code = <BTN_WEST>;
gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>;
autorepeat;
debounce-interval = <100>;
};
button_up:button-up {
label = "DPAD-UP";
linux,code = <BTN_DPAD_UP>;
gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
button_down:button-down {
label = "DPAD-DOWN";
linux,code = <BTN_DPAD_DOWN>;
gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
button_left:button-left {
label = "DPAD-LEFT";
linux,code = <BTN_DPAD_LEFT>;
gpios = <&gpio2 RK_PB2 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
button_right:button-right {
label = "DPAD-RIGHT";
linux,code = <BTN_DPAD_RIGHT>;
gpios = <&gpio2 RK_PB3 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
button_select:button-select {
label = "BTN-SELECT";
linux,code = <BTN_SELECT>;
gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
button_start:button-start {
label = "BTN-START";
linux,code = <BTN_START>;
gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
button_memu:button-memu {
label = "BTN-MODE";
linux,code = <BTN_MODE>;
gpios = <&gpio2 RK_PB6 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
};
gpioVolume:gpioVolume{
status = "okay";
compatible = "gpio-keys";
autorepeat;
pinctrl-names = "default";
pinctrl-0 = <&gpio_volume>;
button_volumeup:button-volumeup {
label = "KEY-VOLUMEUP";
linux,code = <KEY_VOLUMEUP>;
gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
button_volumedown:button-volumedown {
label = "KEY-VOLUMEDOWN";
linux,code = <KEY_VOLUMEDOWN>;
gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_LOW>;
debounce-interval = <100>;
};
};
&gpio0 {
gpio-controller;
//gpio-cells = <2>;
interrupt-controller;
//interrupt-cells = <2>;
};
&gpio1 {
gpio-controller;
//gpio-cells = <2>;
interrupt-controller;
//interrupt-cells = <2>;
};
&gpio2 {
gpio-controller;
//gpio-cells = <2>;
interrupt-controller;
//interrupt-cells = <2>;
};
&pinctrl {
powerBtn {
pwrbtn: pwrbtn {
rockchip,pin =
<0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>,
<0 RK_PB6 RK_FUNC_GPIO &pcfg_output_high>;
};
};
gpioPad {
gpio_pad: gpio-pad {
rockchip,pin =
<0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,
<1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,
<1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>,
<1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>,
<2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>,
<2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>,
<2 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>,
<2 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>,
<2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>,
<2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,
<2 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
gpioVolume{
gpio_volume: gpio-volume {
rockchip,pin =
<1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>,
<1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
};
离线
请教一下,这个怎么改,多谢。
离线
&pinctrl {}里的 rockchip,pin 修改成 rockchip,pins
离线
这个现象我感觉重点不在 “gpio-keys 不能用”,而是在 把一个输出控制脚塞进 gpio-keys 以后,pinctrl 太早把它拉成了输出高。这类问题很像:系统还没进屋,门口保安已经按了电源键,内核只能一脸懵地说“我刚挂载完分区,怎么人没了”。
几个点可以分开看:
echo 44 > /sys/class/gpio/export 报 Device or resource busy 是正常的。
这个脚已经被 gpio-keys 申请走了,debug 里也能看到:
gpio-44 ( |KEY-VOLUMEUP ) in lo IRQ ACTIVE LOW被 input 驱动占用后,sysfs 再 export 就会 busy。这个不是根因,反而说明设备树生效了。
gpio_power 里面这个节点很可疑:
pwr: pwr {
gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
label = "Core Power Off";
}; gpio-keys 的子节点本质上应该是“输入按键”,通常要有 linux,code,而且 pinctrl 也应该配输入/上拉。你这里 PB6 又在 pinctrl 里写成:
<0 RK_PB6 RK_FUNC_GPIO &pcfg_output_high>这等于在 gpio-keys probe 前后把一个 key 类节点配置成输出高。debug 里也显示:
gpio-14 ( |pwr ) out hi ACTIVE LOW 所以它已经不是“按键”了,更像一个电源控制脚。放在 gpio-keys 下面不合适。
建议先把 PB6 从 gpio-keys 里拿掉,只保留真正的输入键:
gpio_power: gpio-power {
status = "okay";
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&pwrbtn>;
key_screenlock: key-screenlock {
label = "GPIO_Key_Screenlock";
linux,code = <KEY_SCREENLOCK>;
gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
wakeup-source;
debounce-interval = <100>;
};
}; 然后 pwrbtn 里也只放 PB2:
pwrbtn: pwrbtn {
rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
}; 注意 Rockchip pinctrl 一般是 rockchip,pins,不是 rockchip,pin,不同内核可能兼容情况不一样,最好和原厂 dtsi 里的写法保持一致。
如果 PB6 真的是“关机/电源保持/PMIC 控制”脚,那应该单独用合适的驱动,比如 gpio-poweroff、regulator、gpio-hog,或者板级电源控制节点,不要混在 gpio-keys 里。否则它就像一个披着按键马甲的电源开关,input 子系统还没开始工作,它已经开始决定整机命运了。
&gpio0/&gpio1/&gpio2 这些节点一般 SoC dtsi 已经定义好了,不建议在板级 dts 里重复加:
gpio-controller;
interrupt-controller;除非你确认原始 dtsi 缺失。板级通常只需要引用 GPIO,不需要重新声明控制器属性。
我建议排查顺序:
第一步:删掉 pwr: pwr 和 PB6 的 pcfg_output_high,只保留输入按键,看能不能稳定 boot;
第二步:每组 gpio-keys 分开打开,先 screenlock,再 volume,再 gamepad;
第三步:启动后用 evtest 或 getevent 看 input 事件;
第四步:PB6 如果确实要控制电源,再单独建 poweroff/regulator/gpio-hog 逻辑。
一句话:gpio-keys 只适合管“别人按我”,不适合管“我去拉别人电源”。 现在这个配置看起来就是把门铃和总闸接到一个驱动下面了,能不玄学才怪。
离线