电路
RK3566主板外接了一个MIPI接口涉嫌头模组,I2C接口I2C2,模组Sensor为GC2053,模组的设备地址为0x37(地址需和模组厂家确定),电路如下:
?管脚连接关系如下:
GPIO0_C1------>CAM_PWND(GPIO电平1.8V)
GPIO0_C0------>CAM_RESET(GPIO电平1.8V)
GPIO4_A7------>CAM_CLKOUT0(GPIO电平3.3V)通过分压电阻转为1.8V电平的时钟CAM_CLKOUT(对于分压电阻的选择比较讲究,电路图中的阻值不合适)
修改文件
DTS文件加入GC2053的配置
i2c节点下加入gc2053节点:
gc2053: gc2053@37 {
status = "okay";
compatible = "galaxycore,gc2053";
reg = <0x37>;
clocks = <&cru CLK_CAM0_OUT>;
clock-names = "xvclk";
pinctrl-names = "rockchip,camera_default", "rockchip,camera_sleep";
pinctrl-0 = <&cam_clkout0>;
pinctrl-1 = <&cam_sleep>;
power-domains = <&power RK3568_PD_VI>;
reset-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_LOW>;
pwdn-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_LOW>;
//reset pin control by hardware,used this pin switch to mipi input
//1->2LANE(LANE 0&1) FRONT camera, 0->4LANE REAR camera
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "front";
rockchip,camera-module-name = "YT-RV1109-2-V1";
rockchip,camera-module-lens-name = "40IR-2MP-F20";
port {
gc2053_out: endpoint {
remote-endpoint = <&mipi_in_ucam0>;
data-lanes = <1 2>;
};
};
};
DTS文件中再加入dphy节点的配置:?
&csi2_dphy_hw {
status = "okay";
};
&csi2_dphy0 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
mipi_in_ucam0: endpoint@0 {
reg = <0>;
remote-endpoint = <&gc2053_out>;
data-lanes = <1 2>;
};
};
port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
csidphy0_out: endpoint@0 {
reg = <0>;
remote-endpoint = <&isp0_in>;
};
};
};
};
节点pinctrl下增加cam_sleep节点:
cam {
cam_sleep: cam-sleep {
rockchip,pins =
/* cam_sleep */
<4 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
cam_clkout0节点已在rk3568.dtsi文件文件中定义:
cam {
/omit-if-no-ref/
cam_clkout0: cam-clkout0 {
rockchip,pins =
/* cam_clkout0 */
<4 RK_PA7 1 &pcfg_pull_none>;
};
/omit-if-no-ref/
cam_clkout1: cam-clkout1 {
rockchip,pins =
/* cam_clkout1 */
<4 RK_PB0 1 &pcfg_pull_none>;
};
};
内核加入驱动
官方的sdk ./kernel/drivers/media/i2c下已经包含了rockchip厂家的工程师调试过的gc2053的驱动,只需要在编译内核时加入对GC2053的支持即可:
?Device Drivers > Multimedia support > I2C Encoders, decoders, sensors and other helper chips 选中GalaxyCore GC2053 sensor support
保存配置文件,然后从新编译内核。
调试
将编译的内核镜像烧写到设备,设备启动后i2c总线上没有检测到0x37的设备:
[root@RK356X:/]# i2cdetect -y 2
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
启动日志也显示gc2053的驱动加载失败:
[root@RK356X:/]# dmesg | grep gc
[ 0.000000] Linux version 4.19.193 (caiyong@ubt0001) (gcc version 6.3.1 20170404 (Linaro GCC 6.3-2017.05), GNU ld (Linaro_Binutils-2017.05) 2.27.0.20161019) #31 SMP Mon Jun 13 11:56:01 CST 2022
[ 1.019617] gc2053 2-0037: driver version: 00.01.01
[ 1.019718] gc2053 2-0037: Failed to get power-gpios
[ 1.019740] gc2053 2-0037: Looking up dovdd-supply from device tree
[ 1.019751] gc2053 2-0037: Looking up dovdd-supply property in node /i2c@fe5b0000/gc2053@37 failed
[ 1.019778] gc2053 2-0037: 2-0037 supply dovdd not found, using dummy regulator
[ 1.019872] gc2053 2-0037: Linked as a consumer to regulator.0
[ 1.019890] gc2053 2-0037: Looking up avdd-supply from device tree
[ 1.019898] gc2053 2-0037: Looking up avdd-supply property in node /i2c@fe5b0000/gc2053@37 failed
[ 1.019912] gc2053 2-0037: 2-0037 supply avdd not found, using dummy regulator
[ 1.019964] gc2053 2-0037: Looking up dvdd-supply from device tree
[ 1.019973] gc2053 2-0037: Looking up dvdd-supply property in node /i2c@fe5b0000/gc2053@37 failed
[ 1.019985] gc2053 2-0037: 2-0037 supply dvdd not found, using dummy regulator
[ 1.020037] gc2053 2-0037: lane_num(2) pixel_rate(118800000)
[ 1.025878] gc2053 2-0037: gc2053 read reg(0xf0 val:0x0) failed !
[ 1.026089] gc2053 2-0037: gc2053 read reg(0xf1 val:0x0) failed !
[ 1.026107] gc2053 2-0037: gc2053_read_reg failed (-6)
参考官方文档<Rockchip_Trouble_Shooting_Linux4.4_Camera_CN.pdf>里面有提到“Sensor ID识别不到, I2C通讯失败”的问题分析:
?我怀疑是mclk时钟没有产生,所以按照文档的指导将gc2053.c驱动代码中__gc2053_power_off()的实现注释了?:
static void __gc2053_power_off(struct gc2053 *gc2053)
{
/*
int ret;
struct device *dev = &gc2053->client->dev;
if (!IS_ERR(gc2053->pwdn_gpio))
gpiod_set_value_cansleep(gc2053->pwdn_gpio, 1);
if (gc2053->clkout_enabled_index)
clk_disable_unprepare(gc2053->xvclk);
if (!IS_ERR(gc2053->reset_gpio))
gpiod_set_value_cansleep(gc2053->reset_gpio, 1);
if (!IS_ERR_OR_NULL(gc2053->pins_sleep)) {
ret = pinctrl_select_state(gc2053->pinctrl,
gc2053->pins_sleep);
if (ret < 0)
dev_dbg(dev, "could not set pins\n");
}
if (!IS_ERR(gc2053->power_gpio))
gpiod_set_value_cansleep(gc2053->power_gpio, 0);
regulator_bulk_disable(GC2053_NUM_SUPPLIES, gc2053->supplies);
*/
}
再次编译内核,将内核烧写到主板,用示波器还是测量不到cam_clkout0上有24MHz的时钟,有尝试断开R91,直接测量处理器的GPIO4_A4管脚,还是没有时钟。
借用外部时钟进行调试
在硬件上断开CAM_CLKOUT0与摄像头模组的连接,将主板上的pwm4连接到摄像头模组的MCLK引脚上,使用shell指令开启pwm4输出8MHz的时钟,再次通过i2c tool工具可检测到i2c 2总线上有0x37的设备了:
[root@RK356X:/sys/devices/platform/fe6e0000.pwm/pwm/pwmchip0/pwm0]# echo 0 > ena
ble
[root@RK356X:/sys/devices/platform/fe6e0000.pwm/pwm/pwmchip0/pwm0]# echo 63 > du
ty_cycle
[root@RK356X:/sys/devices/platform/fe6e0000.pwm/pwm/pwmchip0/pwm0]# echo 125 > p
eriod
[root@RK356X:/sys/devices/platform/fe6e0000.pwm/pwm/pwmchip0/pwm0]# echo 1 > ena
ble
[root@RK356X:/sys/devices/platform/fe6e0000.pwm/pwm/pwmchip0/pwm0]# i2cdetect -y
2
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- 37 -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
排查时钟问题
根据官方<Rockchip_Developer_Guide_Linux4.4_4.19_Clock_CN.pdf>对时钟进行排查
[root@RK356X:/]# cat /sys/kernel/debug/clk/clk_summary
enable prepare protect duty
clock count count count rate accuracy phase cycle
---------------------------------------------------------------------------------------------
xin_osc0_usbphy0_g 1 1 0 24000000 0 0 50000
clk_usbphy0_ref 2 2 0 24000000 0 0 50000
usb480m_phy 2 2 0 480000000 0 0 50000
usb480m 1 1 0 480000000 0 0 50000
clk_cam0_out 2 2 0 24000000 0 0 50000
可见clk_cam0_out配置正确。
排查GPIO的配置问题
GRF_GPIO4A_IOMUX_H Address: Operational Base + offset (0x0064)
31:16 | RW | 0x0000 | write_enable Write enable for lower 16bits, each bit is individual. 1'b0: Write access disable 1'b1: Write access enable | 15 | RO | 0x0 | reserved | 14:12 | RW | 0x0 | gpio4a7_sel 3'h0: GPIO4_A7 3'h1: CAM_CLKOUT0 3'h2: EBC_SDCE1 3'h3: GMAC1_RXD0M1 3'h4: SPI3_CS1M0 3'h5: I2S1_LRCKRXM1 |
查询IO寄存器:
SYS_GRF 0xFDC60000
GRF_GPIO4A_IOMUX_L 0x0060?
GRF_GPIO4A_IOMUX_H 0x0064?
[root@RK356X:/sys/kernel/debug/clk/clk_cam0_out]# io -4 -l 0x8 0xFDC60060
fdc60060: 00000000 00001000
[root@RK356X:/]# io -4 -w 0xFDC60064 0x10001000
[root@RK356X:/]# io -4 -l 0x8 0xFDC60060
fdc60060: 00004400 00001000
bit[14:12]=001; GPIO4A7选择CAM_CLK_OUT0功能;
排查PD_VI电源域问题
由于cam时钟使用的电源域为RK3568_PD_VI,所以查询下PD_VI的状态:
[root@RK356X:/]# cd /sys/kernel/debug/pm_genpd/
[root@RK356X:/sys/kernel/debug/pm_genpd]# ls
pd_gpu pd_pipe pd_rkvdec pd_vi pd_vpu
pd_npu pd_rga pd_rkvenc pd_vo pm_genpd_summary
[root@RK356X:/sys/kernel/debug/pm_genpd]# cd pd_vi/
[root@RK356X:/sys/kernel/debug/pm_genpd/pd_vi]# cat current_state
off-0
当前状态是关闭状态,可能只有当有相应的外设启用时才会开启。
查看PD_VI日志?
[root@RK356X:/sys/kernel/debug/pm_genpd/pd_vo]# dmesg | grep pd_vi
[ 0.439066] rockchip-pm-domain fdd90000.power-management:power-controller: Looking up pd_vi-supply from device tree
[ 0.439081] rockchip-pm-domain fdd90000.power-management:power-controller: Looking up pd_vi-supply property in node /power-management@fdd90000/power-controller failed
有个failed,看起来似乎有问题,但是无法找到原因。
使用有源晶振给Sensor提供时钟,再次调试
使用一颗24MHz的有源时钟给Sensor的MCLK管脚提供24MHz的时钟,有源晶振的电源使用1.8V供电。
设备启动完成后,通过i2c-tool工具查看i2c2总线上是否有0x37的设备:
[root@RK356X:/]# i2cdetect -y 2
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- UU -- -- -- -- -- --
30: -- -- -- -- -- -- -- 37 -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
可以看到总线上有0x37的设备,但是设备没加入驱动中。
通过i2cget命令读取0xF0和0小F1寄存器获取gc2053的CHIP ID:
[root@RK356X:/]# i2cget -f -y 2 0x37 0xF0
0x20
[root@RK356X:/]# i2cget -f -y 2 0x37 0xF1
0x53
查看开机日志,确认gc2053的驱动是否加载成功:
[root@RK356X:/]# dmesg | grep gc
[ 0.000000] Linux version 4.19.193 (caiyong@ubt0001) (gcc version 6.3.1 20170404 (Linaro GCC 6.3-2017.05), GNU ld (Linaro_Binutils-2017.05) 2.27.0.20161019) #31 SMP Mon Jun 13 11:56:01 CST 2022
[ 1.019617] gc2053 2-0037: driver version: 00.01.01
[ 1.019718] gc2053 2-0037: Failed to get power-gpios
[ 1.019740] gc2053 2-0037: Looking up dovdd-supply from device tree
[ 1.019751] gc2053 2-0037: Looking up dovdd-supply property in node /i2c@fe5b0000/gc2053@37 failed
[ 1.019778] gc2053 2-0037: 2-0037 supply dovdd not found, using dummy regulator
[ 1.019872] gc2053 2-0037: Linked as a consumer to regulator.0
[ 1.019890] gc2053 2-0037: Looking up avdd-supply from device tree
[ 1.019898] gc2053 2-0037: Looking up avdd-supply property in node /i2c@fe5b0000/gc2053@37 failed
[ 1.019912] gc2053 2-0037: 2-0037 supply avdd not found, using dummy regulator
[ 1.019964] gc2053 2-0037: Looking up dvdd-supply from device tree
[ 1.019973] gc2053 2-0037: Looking up dvdd-supply property in node /i2c@fe5b0000/gc2053@37 failed
[ 1.019985] gc2053 2-0037: 2-0037 supply dvdd not found, using dummy regulator
[ 1.020037] gc2053 2-0037: lane_num(2) pixel_rate(118800000)
[ 1.025878] gc2053 2-0037: gc2053 read reg(0xf0 val:0x0) failed !
[ 1.026089] gc2053 2-0037: gc2053 read reg(0xf1 val:0x0) failed !
[ 1.026107] gc2053 2-0037: gc2053_read_reg failed (-6)
通过日志得知,gc2053的驱动加载失败了。
断电后立即上电,再查看开机日志,确认gc2053的驱动是否加载成功:
[root@RK356X:/]# dmesg | grep gc2053
[ 1.021564] gc2053 2-0037: driver version: 00.01.01
[ 1.021704] gc2053 2-0037: Failed to get power-gpios
[ 1.021726] gc2053 2-0037: Looking up dovdd-supply from device tree
[ 1.021737] gc2053 2-0037: Looking up dovdd-supply property in node /i2c@fe5b0000/gc2053@37 failed
[ 1.021764] gc2053 2-0037: 2-0037 supply dovdd not found, using dummy regulator
[ 1.021847] gc2053 2-0037: Linked as a consumer to regulator.0
[ 1.021863] gc2053 2-0037: Looking up avdd-supply from device tree
[ 1.021872] gc2053 2-0037: Looking up avdd-supply property in node /i2c@fe5b0000/gc2053@37 failed
[ 1.021884] gc2053 2-0037: 2-0037 supply avdd not found, using dummy regulator
[ 1.021933] gc2053 2-0037: Looking up dvdd-supply from device tree
[ 1.021942] gc2053 2-0037: Looking up dvdd-supply property in node /i2c@fe5b0000/gc2053@37 failed
[ 1.021953] gc2053 2-0037: 2-0037 supply dvdd not found, using dummy regulator
[ 1.022024] gc2053 2-0037: lane_num(2) pixel_rate(118800000)
[ 1.030406] gc2053 2-0037: Detected GC2053 sensor
[ 1.030477] rockchip-csi2-dphy csi2-dphy0: dphy0 matches m00_f_gc2053 2-0037:bus type 4
这一次驱动加载成功了,可能是由于有源晶振冷启动时间比较长,加载驱动时,还没有产生时钟。
显示拓扑结构
执行media-ctl -p -d /dev/media0命令:
[root@RK356X:/]# media-ctl -p -d /dev/media0
- entity 67: rockchip-csi2-dphy0 (2 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev2
pad0: Sink
[fmt:SGRBG10_1X10/1920x1080@10000/300000 field:none]
<- "m00_f_gc2053 2-0037":0 [ENABLED]
pad1: Source
[fmt:SGRBG10_1X10/1920x1080@10000/300000 field:none]
-> "rkisp-csi-subdev":0 [ENABLED]
- entity 70: m00_f_gc2053 2-0037 (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev3
pad0: Source
[fmt:SGRBG10_1X10/1920x1080@10000/300000 field:none]
-> "rockchip-csi2-dphy0":0 [ENABLED]
拍摄图像?
设备接上显示屏及触屏再次启动设备,开机后点击桌面的qcamera进去相机程序,并且摄像头正常的话可以显示图像:
不过运行了30分钟后,就没有图像输出了,重新上电也没有图像输出了,可能是sensor太热烧坏了。
查找问题
在qcamera运行时,通过示波器可以测量到CAM_CLKOUT0(GPIO4_A7)产生了24MHz的时钟,通过此现象可知CAM_CLKOUT0可以产生时钟,但是需要在启动sensor后才会产生,所以官方文档提到的注释power_off()函数的实现mclk会一直产生这个不准确。不过用示波器测量经过R91、R95分压之后就没有时钟了,怀疑是分压电阻的阻值不合适导致了时钟没有产生。
取下R95,将R91改为1K,分压之后的波形如下:
?取下R95,将R91改为620Ω,分压之后的波形如下:
?R95改为620Ω,将R91改为100Ω,示波器探头改为x10档位,分压之后的波形如下:
?经过多次调试,将R91改为100Ω,R95改为300Ω,测量分压之后才有正确的24MHz的时钟:
?最大是2.04v,最小没到0v,如果要将最大调到1.8v以下,需要将R95再改小。
还原硬件,再次测试
主板启动后,通过开机日志可以看到gc2053的驱动加载成功了,i2c tool也能检测到i2c 2总线上有0x37的设备。
总结
对于高速时钟信号的电平转换,采用分压电阻时,阻值选择小一些,或者使用电平转换IC。
|