記一次移植GT9271無法正常通信

 移植匯頂的TP GT9271時,發現i2c通信不上,檢查了TP的供電和復位腳及硬件連接,都沒發現問題,然後發現內核有如下的報錯信息。

[49533.829164] gpio-272 (goodix_ts_int): _gpiod_direction_output_raw: tried to set a GPIO tied to an IRQ as output
[49533.849418] goodix-ts 3-005d: I2c read failed,dev:5d,reg:8047,size:1
[49533.849433] goodix-ts 3-005d: GTP i2c test failed time 1
[49533.871495] goodix-ts 3-005d: I2c read failed,dev:5d,reg:8047,size:1
[49533.871510] goodix-ts 3-005d: GTP i2c test failed time 2
[49533.895621] goodix-ts 3-005d: I2c read failed,dev:5d,reg:8047,size:1
[49533.895634] goodix-ts 3-005d: GTP i2c test failed time 

但爲什麼設置io口爲輸出也報錯呢 ,查看相應的代碼

drivers/gpio/gpiolib.c

static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
{
	struct gpio_chip *gc = desc->gdev->chip;
	int val = !!value;
	int ret;

	/* GPIOs used for IRQs shall not be set as output */
	if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) {
		gpiod_err(desc,
			  "%s: tried to set a GPIO tied to an IRQ as output\n",
			  __func__);
		return -EIO;
	}

	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
		/* First see if we can enable open drain in hardware */
		ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
						  PIN_CONFIG_DRIVE_OPEN_DRAIN);
		if (!ret)
			goto set_output_value;
		/* Emulate open drain by not actively driving the line high */
		if (val)
			return gpiod_direction_input(desc);
	}
	else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
		ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
						  PIN_CONFIG_DRIVE_OPEN_SOURCE);
		if (!ret)
			goto set_output_value;
		/* Emulate open source by not actively driving the line low */
		if (!val)
			return gpiod_direction_input(desc);
	} else {
		gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
					    PIN_CONFIG_DRIVE_PUSH_PULL);
	}

set_output_value:
	if (!gc->set || !gc->direction_output) {
		gpiod_warn(desc,
		       "%s: missing set() or direction_output() operations\n",
		       __func__);
		return -EIO;
	}

	ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), val);
	if (!ret)
		set_bit(FLAG_IS_OUT, &desc->flags);
	trace_gpio_value(desc_to_gpio(desc), 0, val);
	trace_gpio_direction(desc_to_gpio(desc), 0, ret);
	return ret;
}

原來,內核默認禁止中斷設置成輸出,這也合理,一般設置成中斷模式的引腳,只需設置成輸入模式,然後讀取引腳的狀態即可。

但爲什麼代碼裏將中斷腳設置成輸出呢。

查看規格書https://github.com/hadess/gt9xx

居然用中斷腳來進行通信了 ,跟普通的中斷腳不一樣了。

但爲什麼高通/MTK他們用這份驅動沒有問題了,原來他們用pinctrl的方式控制引腳狀態,但展訊平臺還沒支持pinctrl這種方式,用的是普通的gpio模式,所以有這樣的問題。那要怎麼修改呢。

一種方式是先釋放中斷,拉低或拉高gpio後,重新設置成中斷模式。

第二種方式是屏蔽_gpiod_direction_output_raw的返回,讓代碼跑下去。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章