上一次講到USB不啟動問題是由與Vivado工程中的EMIO引腳未正確配置造成的,那么軟件上又是如何使用這個引腳的呢?
首先,Xilinx提供的Linux 開發包中已經包含了gpio的驅動和sysfs進行配套,並在設備樹文件中對OTG-RESETN進行了初始化配置和聲明。
其次,在實際使用中,USB-OTG的驅動向系統申請了OTG-RESETN的使用權,用來對PHY芯片完成配置。
啟動后,查看sysfs中GPIO的相關狀態信息:
root@linaro-ubuntu-desktop:~# cat /sys/kernel/debug/gpio gpiochip0: GPIOs 906-1023, parent: platform/e000a000.gpio, zynq_gpio: gpio-991 ( |ulpi resetb ) out hi root@linaro-ubuntu-desktop:~#
991號gpio正被使用,標簽為“ulpi resetb”,從字面意思可以知道,它與USB-PHY和復位信號有一定關系。該gpio為輸出狀態,電平為高。
USB-PHY芯片是低復位,此時是正常工作的。
在Linux內核中查找字符串“ulpi resetb”,位於與USB-HOST驅動文件目錄中。
z@ubuntu:~/WORK/Linux_xilinx/linux$ find . -type f -name "*.c" | xargs grep "ulpi resetb" ./drivers/usb/chipidea/core.c: GPIOF_INIT_LOW, "ulpi resetb");
打開這個文件,找到相關代碼,發現USB-PHY芯片初始化時進行了兩項工作
一是讀取設備樹中相關配置;二是向sysfs文件系統申請該gpio,並設置低電平,標簽內容為“ulpi resetb”。
static int ci_hdrc_create_ulpi_phy(struct device *dev, struct ci_hdrc *ci) { struct usb_phy *ulpi; int reset_gpio; int ret; reset_gpio = of_get_named_gpio(dev->parent->of_node, "xlnx,phy-reset-gpio", 0); //讀取設備樹中相關配置 if (gpio_is_valid(reset_gpio)) { ret = devm_gpio_request_one(dev, reset_gpio, //向sysfs文件系統申請該gpio,並進行初始化 GPIOF_INIT_LOW, "ulpi resetb"); if (ret) { dev_err(dev, "Failed to request ULPI reset gpio: %d\n", ret); return ret; } msleep(5); gpio_set_value_cansleep(reset_gpio, 1); msleep(1); } ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); if (ulpi) { ulpi->io_priv = ci->hw_bank.abs + 0x170; ci->usb_phy = ulpi; } return 0; }
再來看看設備樹,由上面驅動信息可知,這個991號引腳在設備樹中名字是“xlnx,phy-reset-gpio”, 在目錄中搜一下
z@ubuntu:~/WORK/Linux_xilinx/linux/arch/arm/boot/dts$ find . -type f -name "*zynq*.dts*" | xargs grep "phy-reset-gpio" ./zynq-picozed-sdr2.dtsi: xlnx,phy-reset-gpio = <&gpio0 7 0>; ./zynq-zc702.dts: phy-reset-gpio = <&gpio0 11 0>; ./zynq-microzed.dtsi: xlnx,phy-reset-gpio = <&gpio0 7 0>; ./zynq-zc706.dtsi: xlnx,phy-reset-gpio = <&gpio0 7 0>; ./zynq-picozed-sdr-userspace.dts: xlnx,phy-reset-gpio = <&gpio0 7 0>; ./zynq-picozed-sdr1.dtsi: xlnx,phy-reset-gpio = <&gpio0 7 0>; ./zynq-zed.dtsi: xlnx,phy-reset-gpio = <&gpio0 85 0>; ./zynq-zc702.dtsi: xlnx,phy-reset-gpio = <&gpio0 7 0>; ./zynq-mini-itx.dtsi: xlnx,phy-reset-gpio = <&gpio0 7 0>;
zynq-zed.dtsi正是生成設備樹的依賴文件,正是usb0中的一個配置。
&usb0 { xlnx,phy-reset-gpio = <&gpio0 85 0>; };
現在還剩下一個問題,就是gpio-991和<&gpio0 85 0>是什么關系?
ZYNQ有54個MIO和64個EMIO,總共118個gpio。排列順序如圖所示,gpio的基地址是0xE000_A000。

設備樹中gpio0的描述如下
gpio0: gpio@e000a000 { compatible = "xlnx,zynq-gpio-1.0"; #gpio-cells = <2>; clocks = <&clkc 42>; gpio-controller; interrupt-controller; #interrupt-cells = <2>; interrupt-parent = <&intc>; interrupts = <0 20 4>; reg = <0xe000a000 0x1000>; };
OTG-RESETN 對應的網絡為gpib_bd[31],在118中的順序為54位MIO+31EMIO=85,正好是gpio0的第85個。
那么sysfs中的991又是如何來的呢?
gpiochip0: GPIOs 906-1023, parent: platform/e000a000.gpio, zynq_gpio: gpio-991 ( |ulpi resetb ) out hi
實際上,906-1023 共有118個gpio號,從906開始偏移85個,正好也是991,即OTG-RESETN信號引腳。
假設在終端中輸入如下命令:
root@linaro-ubuntu-desktop:~# echo 979 > /sys/class/gpio/export #申請端口號 root@linaro-ubuntu-desktop:~# echo out > /sys/class/gpio/gpio979/direction #指定IO方向 root@linaro-ubuntu-desktop:~# echo 1 > /sys/class/gpio/gpio979/value #寫入IO值 root@linaro-ubuntu-desktop:~# cat /sys/kernel/debug/gpio gpiochip0: GPIOs 906-1023, parent: platform/e000a000.gpio, zynq_gpio: gpio-979 ( |sysfs ) out hi gpio-991 ( |ulpi resetb ) out hi root@linaro-ubuntu-desktop:~#
會發現,ZedBoard上的LD0被點亮,參考xdc約束文件;
set_property -dict {PACKAGE_PIN T22 IOSTANDARD LVCMOS33} [get_ports gpio_bd[19]] ; ## LD0
906開始偏移54+19個單元,正好是979.
以上就是對Vivado中自己搭建ZYNQ系統遇到的一點問題進行的探索,后續我將把從零搭建最小系統介紹下,讓大家可以比較深入的認識一下ZYNQ的硬件環境使用。
PS:目前我也是初學,這些內容權當拋磚引玉,有什么錯誤的地方,還請高手指正,不勝感激。
