目录
imx8qm支持xen特性,可以在一块板子上运行两个系统(Linux+Android),但是资源只有一份,所以,在调试的过程中要特别注意资源的分配, linux使用的设备树文件为dom0,Android使用的设备树为domu
接下来我就记录一下我在调试的过程中遇到的问题
一 Linux端配置usdhc接口
wifi设备使用sdio接口与cpu通信,首先检查Android系统的默认资源里有没有wifi所使用的mmc接口,以我所使用的imx8qm平台为例,在主板上,wifi芯片使用usdhc3接口,默认的usdhc3接口没有配置在Android系统端,
所以,第一件时间就是把usdhc3接口分配给Android使用,打开Linux的dom0设备树
在domu(android使用的)节点下面的pads添加usdhc3接口使用的IO口
domu {
pads = <
/* usdhc3 wifi sdio */
SC_P_USDHC2_CLK
SC_P_USDHC2_CMD
SC_P_USDHC2_DATA0
SC_P_USDHC2_DATA1
SC_P_USDHC2_DATA2
SC_P_USDHC2_DATA3
SC_P_USDHC2_VSELECT
SC_P_USDHC2_WP
SC_P_USDHC2_CD_B
>;
};
在smmu节点中添加usdhc3
打开usdhc3节点,并使用关键字"xen,passthrough"标记为传输给domu的节点
&usdhc3 {
xen,passthrough;
#stream-id-cells = <1>;
iommus = <&smmu>;
};
按照已有的usdhc1添加的
配置完了之后,使用xl create /etc/xen/domu-imx8qm-mek-androidauto.cfg 启动虚拟机,一开始是不成功的,因为没有修改对应的domu-imx8qm-mek-androidauto.cfg配置文件,按照usdhc1添加usdhc3进去就可以了
启动虚拟机开启Android系统,在启动log中搜索usdh3相关信息,可以看到报错,报错内容为无法获取clk,这个问题我也是检查了很久,多次修改都没用效果,最后才找到了原因,
就是在dom0设备树中添加usdh3的时候没有在rsrcs中添加
SC_R_SDHC_2这个引脚可以在代码中搜索一下,就是时钟的配置引脚,好了,到这里就可以使用了
二 Android端配置usdhc3
运行xen虚拟机的时候,同时运行了Linux和Android系统,所以,要修改某一个具体的设备,一般都需要两边都修改,本次的话,Linux那端是主要修改的地方,Android端根据已有的usdhc1添加usdhc3的信息即可,不用再多说明
三 问题
1 打开usdhc3接口之后,在Android系统开机之后查看开机Log,发现其始终不能检测到wifi设备,如果检测到了的话,在/sys/bus/mmc/devices/目录下可以看到生成的mmc节点,
后来原因找到了,是因为只配置了wifi en引脚,并没有配置wifi 的时钟引脚,后来通过示波器测量才检测到
mmc扫描sdio wifi
不加载wifi驱动也是可以扫描到设备的
但是,扫描之前必须先reset wifi_en引脚,和配置wifi设备所需的时钟引脚提供时钟
2 上面的问题引发出的gpio的分配,可以在dom0和domu中看到它已经有一些gpio的配置了,再说明一下
首先,在Linux端的dom0设备树中的domu节点中,在pads属性中添加所需要分配给Android使用的gpio,然后在gpios属性中添加具体的引脚,如下
pads = <
/* usdhc3 wifi sdio */
SC_P_USDHC2_CLK
SC_P_USDHC2_CMD
SC_P_USDHC2_DATA0
SC_P_USDHC2_DATA1
SC_P_USDHC2_DATA2
SC_P_USDHC2_DATA3
SC_P_USDHC2_VSELECT
SC_P_USDHC2_WP
SC_P_USDHC2_CD_B
>;
gpios = <&gpio0 7 GPIO_ACTIVE_LOW>,
<&gpio1 13 GPIO_ACTIVE_LOW>,
<&gpio1 27 GPIO_ACTIVE_LOW>,
<&gpio1 28 GPIO_ACTIVE_LOW>,
<&gpio4 6 GPIO_ACTIVE_LOW>,
<&gpio4 9 GPIO_ACTIVE_LOW>,
<&gpio4 11 GPIO_ACTIVE_HIGH>,
<&gpio4 19 GPIO_ACTIVE_HIGH>,
<&gpio4 22 GPIO_ACTIVE_LOW>,
<&gpio4 26 GPIO_ACTIVE_HIGH>,
<&gpio4 25 GPIO_ACTIVE_HIGH>,
<&gpio4 27 GPIO_ACTIVE_LOW>,
<&gpio4 29 GPIO_ACTIVE_LOW>,
<&gpio5 2 GPIO_ACTIVE_HIGH>;
然后,再配置gpio为
&gpio1 {
xen,shared;
};
可以看到,它并不是完成传输过去的,而是两边共享的,最后在Android设备树中把相应引脚配置为"okay"即可
3 最后一个问题,也是遇到的最重要的问题,虽然通过上面的办法把gpio共享到Android端了,并且在代码中也可以读取到gpio了,但是,读取的gpio引脚号和之前的不一样?
仔细检查了很多遍,在设备树中配置的引脚是完全一样的,比如下面这样
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_app_gpio>;
gps-pwn-gpios = <&gpio3 0 GPIO_ACTIVE_HIGH>;
wifi-pwn-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
在程序里会把这个表示转化为一个具体的gpio标号,我根据代码中获取到的引脚标号去检查,发现并不是gpio5 2,
最后终于找到了问题所在,坑爹啊,把Linux端的gpio信息和Android端的gpio信息打印出来,cat /sys/kernel/debug/gpio
Linux
gpiochip7: GPIOs 256-287, parent: platform/5d0f0000.gpio, 5d0f0000.gpio:
gpiochip6: GPIOs 288-319, parent: platform/5d0e0000.gpio, 5d0e0000.gpio:
gpiochip5: GPIOs 320-351, parent: platform/5d0d0000.gpio, 5d0d0000.gpio:
gpiochip4: GPIOs 352-383, parent: platform/5d0c0000.gpio, 5d0c0000.gpio:
gpiochip3: GPIOs 384-415, parent: platform/5d0b0000.gpio, 5d0b0000.gpio:
gpiochip2: GPIOs 416-447, parent: platform/5d0a0000.gpio, 5d0a0000.gpio:
gpiochip1: GPIOs 448-479, parent: platform/5d090000.gpio, 5d090000.gpio:
gpiochip0: GPIOs 480-511, parent: platform/5d080000.gpio, 5d080000.gpio:
Android
gpiochip4: GPIOs 352-383, parent: platform/58222000.gpio, 58222000.gpio:
gpiochip3: GPIOs 384-415, parent: platform/5d0d0000.gpio, 5d0d0000.gpio:
gpiochip2: GPIOs 416-447, parent: platform/5d0c0000.gpio, 5d0c0000.gpio:
gpiochip1: GPIOs 448-479, parent: platform/5d090000.gpio, 5d090000.gpio:
gpiochip0: GPIOs 480-511, parent: platform/5d080000.gpio, 5d080000.gpio:
可以看到,Android的gpiochip3后面的基地址是5d0d0000,而Linux的gpio5的基地址也是5d0d0000,所以,在Android这端的gpio3就是Linux共享的gpio5,和具体的gpio引脚号并没有关系,
而他前面的gpiochip3: GPIOs 384-415信息误导了我,让我以为在这边的gpio引脚号要和LInux那边一样才行,太坑爹了.