解决摄像头驱动起不来的情况

一,保留现场

换了个板子和kernel版本后,ov13850驱动起不来了,报如下错误

root@feifeirk:/tmp# insmod rk_ov.ko

335.315715 rk_ov: loading out-of-tree module taints kernel.

335.322983 ov13850 3-0010: driver version: 00.01.03

335.328061 ov13850 3-0010: GPIO lookup for consumer reset

335.333545 ov13850 3-0010: using device tree for GPIO lookup

335.339356 of_get_named_gpiod_flags: parsed 'reset-gpios' property of node '/i2c@ff150000/ov13850@100' - status (0)

335.350337 ov13850 3-0010: GPIO lookup for consumer pwdn

335.355762 ov13850 3-0010: using device tree for GPIO lookup

335.361522 of_get_named_gpiod_flags: parsed 'pwdn-gpios' property of node '/i2c@ff150000/ov13850@100' - status (0)

335.374348 ov13850 3-0010: Unexpected sensor id(000000), ret(-5)

root@feifeirk:/tmp#

跟踪日志到ov13850_probe->ov13850_check_sensor_id

ret = ov13850_read_reg(client, OV13850_REG_CHIP_ID,

OV13850_REG_VALUE_16BIT, &id);

if (id != CHIP_ID) {

dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);

return -ENODEV;

}

原先的代码ov13850_check_sensor_id出错后会关闭power

ret = ov13850_check_sensor_id(ov13850, client);

if (ret)

goto err_power_off;

先改成直接返回成功,保留现场

ret = ov13850_check_sensor_id(ov13850, client);

return 0;

二,分析pin脚和pwr

引脚:

引脚3表示数字电压DVDD,给芯片的数字信号供电,CIF_POWER (GPIO7_B4)引脚控制

引脚4是芯片引脚出来的电压IOVDD,rk3288中受DVP_PWR(GPIO0_B3)控制

引脚7是模拟电压AVDD,给芯片中的模拟器件供电,比如camera供电就要用到AVDD,也是相对于DVDD区别出来的,rk3288中受DVP_PWR(GPIO0_B3)控制

引脚11复位信号输出,GPIO2_B7,硬件上拉

引脚12是Power Down 信号输出,GPIO2_B6

引脚14是时钟输出(提供给外部摄像头的主时钟),GPIO2_B3

电源引脚3/4/7先不看,直接量电压。

reset和Power Down都是高,都是正常的,引脚14暂时还用不到,说明pin脚没有问题。

三,分析power

从dts中总结有三个:

dvdd_1v2: dvdd-1v2 {

status = "okay";

compatible = "regulator-fixed";

enable-active-high;

gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;

pinctrl-names = "default";

pinctrl-0 = <&cif_pwr>;

regulator-name = "dvdd_1v2";

};

vcc28_dvp: vcc28-dvp-regulator {

compatible = "regulator-fixed";

enable-active-high;

gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>;

pinctrl-names = "default";

pinctrl-0 = <&dvp_pwr>;

regulator-name = "vcc28_dvp";

regulator-min-microvolt = <2800000>;

regulator-max-microvolt = <2800000>;

regulator-always-on;

vin-supply = <&vcc_io>;

};

dovdd_1v8: dovdd-1v8-regulator {

compatible = "regulator-fixed";

regulator-name = "dovdd_1v8";

regulator-min-microvolt = <1800000>;

regulator-max-microvolt = <1800000>;

regulator-always-on;

regulator-boot-on;

vin-supply = <&vcc28_dvp>;

};

root@feifeirk:/tmp# ls /sys/class/regulator/regulator.*/name

/sys/class/regulator/regulator.0/name

/sys/class/regulator/regulator.1/name

/sys/class/regulator/regulator.10/name

/sys/class/regulator/regulator.11/name

/sys/class/regulator/regulator.12/name

/sys/class/regulator/regulator.13/name

/sys/class/regulator/regulator.14/name

/sys/class/regulator/regulator.15/name

/sys/class/regulator/regulator.16/name

/sys/class/regulator/regulator.17/name

/sys/class/regulator/regulator.18/name

/sys/class/regulator/regulator.19/name

/sys/class/regulator/regulator.2/name

/sys/class/regulator/regulator.20/name

/sys/class/regulator/regulator.21/name

/sys/class/regulator/regulator.3/name

/sys/class/regulator/regulator.4/name

/sys/class/regulator/regulator.5/name

/sys/class/regulator/regulator.6/name

/sys/class/regulator/regulator.7/name

/sys/class/regulator/regulator.8/name

/sys/class/regulator/regulator.9/name

root@feifeirk:/tmp# cat /sys/class/regulator/regulator.*/name

regulator-dummy

dvdd_1v2

vcc_ddr

vcc_io

vdd_log

vcc_20

vccio_sd

vdd10_lcd

vcca_codec

vcc_lan

vccio_pmu

vdd_10

vcc28_dvp

vcc_18

vcc18_lcd

dovdd_1v8

vcc1v8_sys

vcc_host

vcc_phy

vcc_sys

vdd_cpu

vdd_gpu

root@feifeirk:/tmp# cat /sys/class/regulator/regulator.*/state

disabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

万用表量三个电源都没有问题,

但是cat /sys/class/regulator/regulator.*/state查看dvdd_1v2偶尔没有state文件,说明dvdd_1v2电源有关闭情况。

给dvdd_1v2加上regulator-always-on属性后测试/sys/class/regulator/regulator稳定了,但还是probe失败。

四,分析原因

分析可能的原因:

1,dovdd_1v8需要io_domain配置dvp-supply = <&dovdd_1v8>,且摄像头驱动要在iodomain配置之后启动电源,iodomain寄存器配置错误

2,三个电源的启动顺序不对,影响了时序

3,reset或pwdn有拉低再拉高情况,没有走正常的pm_ops

第一点通过读寄存器验证没有问题

第二点通过临时去掉休眠,直接在probe关闭三个电源后,reset和pwdn拉低后,重新操作电源启动测试,

第三点通过确认dts没有干扰后,在每次操作reset和pwdn加日志打印确认拉高拉低确认

五,修复后的代码

1,dvdd_1v2加了regulator-always-on属性

2,增加了CONFIG_VIDEO_OV13850=y,将驱动写入了内核,这个是想看iodomain和ov的配置顺序,虽然没有问题,但是保留了这个修改

3,13850驱动里面,修改

(1)

(2)

(3)

改了这几处之后正常出流了:

因为发现dvdd_1v2中间被系统关闭了,所以ko改成编进内核,切屏蔽了dev_pm_ops,电源不被系统接管;

ov13850_s_power直接返回是临时屏蔽isp调用摄像头的s_pwr off功能造成的干扰,s_pwr off里面后操作reset拉低,先临时关闭;

因为ov13850_s_power直接返回了,所以里面的初始化序列加载了probe函数里面。

六,总结

修复的代码方式只是规避,但是能证明问题跟硬件没关系,跟三个pwr的顺序或reset有关,后续微调就能找到问题,比较好解决了。

开始以为引脚有问题,测量和加日志后发现没有任何问题。当时还怀疑硬件出问题了,这个引脚比较多,时序复杂,示波器line不够,如果没有一个出流的方案估计得上逻辑分析仪测试下电源启动顺序了,找到一个规避方法就能来回切换测试了。

相关推荐
Moshow郑锴32 分钟前
Ubuntu 26.04 更换阿里云源镜像
linux·运维·ubuntu
Jason_chen43 分钟前
Linux 6.2 串口机制深度解析:AI驱动的自适应通信与零信任串口安全架构
linux
xiangw@GZ1 小时前
802.11全系列标准调制编码与速率档对应关系
网络·单片机·嵌入式硬件·架构
希希之光1 小时前
Aurix Tc3xx Port&Dio模块总结
单片机·嵌入式硬件
ShineWinsu2 小时前
对于Linux:线程概念与分页存储管理的解析
linux·运维·服务器·面试·线程·进程·虚拟空间地址
日拱一卒的小田2 小时前
ZYNQ学习笔记2-ZYNQ的UART控制器1
单片机·嵌入式硬件
用户3946235365242 小时前
Uboot - DM框架
linux
我想走路带风2 小时前
OPENWRT-Day01
stm32·单片机·嵌入式硬件
ACP广源盛139246256733 小时前
GSV2221@ACP#DP 1.4 MST 多屏转换芯片,物理 AI 多模态交互的视觉中枢
大数据·人工智能·嵌入式硬件·gpt·spark
鹤落晴春3 小时前
RH124问答5:管理本地用户和组
linux·运维·服务器