Hi everyone,
I'm currently working with the i.MX8MP platform and encountered an issue while configuring a GPIO pin in input/pull-up mode. Here's the scenario:
In one of my drivers, the pin is used in output mode during the probe phase and then switched back to input mode. However, after this process, I found that the pin loses its configuration and is no longer in pull-up mode.
here is the dtb:
gt928@5d {
[...]
pincrtl-0 = <&pinctrl_ts>;
gt928,irq-gpios = <&gpio1 6 GPIO_PULL_UP>;
};
pinctrl_ts: tsgrp {
fsl,pins = <
MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06 0x146 /* 0x146 == pull up, drive strength = 6 */
MX8MP_IOMUXC_SD1_DATA4__GPIO2_IO06 0xd6
>;
};
Here's the call stack for reference:
[ 14.630895] gpio_do_set_config+0x24/0x74
[ 14.630905] gpio_set_config_with_argument+0x38/0x44
[ 14.630911] gpio_set_bias+0x84/0xa4
[ 14.643448] gpiod_direction_input+0x198/0x1ac
[ 14.647892] goodix_irq_direction_input+0x40/0xa4 [goodix]
[ 14.653388] goodix_ts_probe+0x3fc/0x5c8 [goodix]
Upon further investigation, I noticed that the set_config function is not implemented (gpiolib.c do the following check):
gpio_do_set_config(struct gpio_chip *gc, unsigned int offset, unsigned long config) {
{
if (!gc->set_config)
return -ENOTSUPP;
[...]
}
gc->set_config = pca953x_gpio_set_config;
or
gc->set_config = ep93xx_gpio_set_config;
Thank you in advance for your help!
Best regards,
Alexandre
已解决! 转到解答。
This is how I resolved my problem.
Based on my findings, placing <&pinctrl_ts> under the touchscreen node doesn't apply the pin function correctly.
&i2c3 {
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>,<&pinctrl_ts>;
status = "okay";
ov5640_0: ov5640_mipi@3c {
status = "disabled";
};
gt928@5d {
compatible = "goodix,gt928";
reg = <0x5d>;
pincrtl-names = "default";
pincrtl-0 = <&pinctrl_ts>;
interrupt-parent = <&gpio1>;
interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
gt928,irq-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
gt928,reset-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
touchscreen-inverted-x;
status = "okay";
};
};
[...]
&iomuxc {
pinctrl_ts: tsgrp {
fsl,pins = <
MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06 0x146 /* 0x146 == pull up, drive strength = 6 */
MX8MP_IOMUXC_SD1_DATA4__GPIO2_IO06 0xd6
>;
};
};
However, when I move it to the &i2c3 node, the pins are configured properly.
Thank you for your time!
This is how I resolved my problem.
Based on my findings, placing <&pinctrl_ts> under the touchscreen node doesn't apply the pin function correctly.
&i2c3 {
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>,<&pinctrl_ts>;
status = "okay";
ov5640_0: ov5640_mipi@3c {
status = "disabled";
};
gt928@5d {
compatible = "goodix,gt928";
reg = <0x5d>;
pincrtl-names = "default";
pincrtl-0 = <&pinctrl_ts>;
interrupt-parent = <&gpio1>;
interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
gt928,irq-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
gt928,reset-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
touchscreen-inverted-x;
status = "okay";
};
};
[...]
&iomuxc {
pinctrl_ts: tsgrp {
fsl,pins = <
MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06 0x146 /* 0x146 == pull up, drive strength = 6 */
MX8MP_IOMUXC_SD1_DATA4__GPIO2_IO06 0xd6
>;
};
};
However, when I move it to the &i2c3 node, the pins are configured properly.
Thank you for your time!
The gpio iomux value has been written with imx_pmx_set before gpio driver probe, so there is no need to use set_config function in gpio driver. The imx_pinctrl_probe
For gpio io expander driver, this function is need, because there is no another driver setting pull up/down.
Best Regards
Zhiming
I test such behavior on GPIO3_IO16(gpio-80). The iomux value in device tree will not be covered. There is no such issue using sysfs to control gpio.
NXP i.MX Release Distro 6.6-nanbield imx8mp-lpddr4-evk ttymxc1
imx8mp-lpddr4-evk login: [ 14.532349] fec 30be0000.ethernet eth0: Link is Up - 1Gbps/Full - flow control off
imx8mp-lpddr4-evk login: root
root@imx8mp-lpddr4-evk:~# echo 80 > /sys/class/gpio/export
root@imx8mp-lpddr4-evk:~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/30200000.gpio, 30200000.gpio:
gpio-10 ( |reset ) out hi ACTIVE LOW
gpio-14 ( |regulator-vbus ) out hi
gpiochip1: GPIOs 32-63, parent: platform/30210000.gpio, 30210000.gpio:
gpio-38 ( |regulator-pcie ) out hi
gpio-39 ( |PCIe reset ) out hi
gpio-44 ( |cd ) in hi ACTIVE LOW
gpio-51 ( |regulator-usdhc2 ) out lo
gpiochip2: GPIOs 64-95, parent: platform/30220000.gpio, 30220000.gpio:
gpio-80 ( |sysfs ) out hi
gpiochip3: GPIOs 96-127, parent: platform/30230000.gpio, 30230000.gpio:
gpio-98 ( |PHY reset ) out hi ACTIVE LOW
gpio-116 ( |switch ) out hi ACTIVE LOW
gpio-118 ( |PHY reset ) out hi ACTIVE LOW
gpio-123 ( |regulator-can2-stby ) out lo
gpio-124 ( |Headphone detection ) in lo
gpio-125 ( |regulator-audio-pwr ) out hi
gpiochip4: GPIOs 128-159, parent: platform/30240000.gpio, 30240000.gpio:
gpio-133 ( |regulator-can1-stby ) out lo
gpio-141 ( |spi1 CS0 ) out hi ACTIVE LOW
gpio-149 ( |host-wake ) in hi ACTIVE LOW
gpiochip5: GPIOs 512-527, parent: i2c/2-0020, 2-0020, can sleep:
gpio-512 (EXT_PWREN1 )
gpio-513 (EXT_PWREN2 )
gpio-514 (CAN1/I2C5_SEL )
gpio-515 (PDM/CAN2_SEL )
gpio-516 (FAN_EN )
gpio-517 (PWR_MEAS_IO1 )
gpio-518 (PWR_MEAS_IO2 )
gpio-519 (EXP_P0_7 )
gpio-520 (EXP_P1_0 )
gpio-521 (EXP_P1_1 )
gpio-522 (EXP_P1_2 )
gpio-523 (EXP_P1_3 )
gpio-524 (EXP_P1_4 )
gpio-525 (EXP_P1_5 )
gpio-526 (EXP_P1_6 )
gpio-527 (EXP_P1_7 )
root@imx8mp-lpddr4-evk:~# memtool -32 30330380 1
E
Reading 0x1 count starting at address 0x30330380
0x30330380: 00000140
root@imx8mp-lpddr4-evk:~# echo in > /sys/class/gpio/gpio80/direction
root@imx8mp-lpddr4-evk:~# memtool -32 30330380 1
E
Reading 0x1 count starting at address 0x30330380
0x30330380: 00000140
root@imx8mp-lpddr4-evk:~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/30200000.gpio, 30200000.gpio:
gpio-10 ( |reset ) out hi ACTIVE LOW
gpio-14 ( |regulator-vbus ) out hi
gpiochip1: GPIOs 32-63, parent: platform/30210000.gpio, 30210000.gpio:
gpio-38 ( |regulator-pcie ) out hi
gpio-39 ( |PCIe reset ) out hi
gpio-44 ( |cd ) in hi ACTIVE LOW
gpio-51 ( |regulator-usdhc2 ) out lo
gpiochip2: GPIOs 64-95, parent: platform/30220000.gpio, 30220000.gpio:
gpio-80 ( |sysfs ) in hi
gpiochip3: GPIOs 96-127, parent: platform/30230000.gpio, 30230000.gpio:
gpio-98 ( |PHY reset ) out hi ACTIVE LOW
gpio-116 ( |switch ) out hi ACTIVE LOW
gpio-118 ( |PHY reset ) out hi ACTIVE LOW
gpio-123 ( |regulator-can2-stby ) out lo
gpio-124 ( |Headphone detection ) in lo
gpio-125 ( |regulator-audio-pwr ) out hi
gpiochip4: GPIOs 128-159, parent: platform/30240000.gpio, 30240000.gpio:
gpio-133 ( |regulator-can1-stby ) out lo
gpio-141 ( |spi1 CS0 ) out hi ACTIVE LOW
gpio-149 ( |host-wake ) in hi ACTIVE LOW
gpiochip5: GPIOs 512-527, parent: i2c/2-0020, 2-0020, can sleep:
gpio-512 (EXT_PWREN1 )
gpio-513 (EXT_PWREN2 )
gpio-514 (CAN1/I2C5_SEL )
gpio-515 (PDM/CAN2_SEL )
gpio-516 (FAN_EN )
gpio-517 (PWR_MEAS_IO1 )
gpio-518 (PWR_MEAS_IO2 )
gpio-519 (EXP_P0_7 )
gpio-520 (EXP_P1_0 )
gpio-521 (EXP_P1_1 )
gpio-522 (EXP_P1_2 )
gpio-523 (EXP_P1_3 )
gpio-524 (EXP_P1_4 )
gpio-525 (EXP_P1_5 )
gpio-526 (EXP_P1_6 )
gpio-527 (EXP_P1_7 )
I think maybe you miss some code in your driver, you can refer the sysfs code, have you add mutex during your operation?