[RK3128][Android 6.0] RTC芯片PCF8563调试记录

硬件平台:RK3128
Android版本:6.0
Kernel版本:3.10.92

任务描述:
Rk3128 Android 6.0平台调试rtc芯片PCF8563,本以为很容易,结果碰到一些问题,在此记录下来。

一、添加设备信息
Dts中添加I2C设备:
rtc@51 {
compatible = "nxp,pcf8563";
reg = <0x51>;
irq_gpio = <&gpio0 GPIO_D4 IRQ_TYPE_EDGE_FALLING>;
};
二、驱动调试
配置内核开关,使用内核默认驱动kernel/drivers/rtc/rtc-pcf8563.c。

I2C通信成功后,RTC就可以工作了。

但后来又遇到两个问题:


问题一、开机显示初始时间
通过查看开机日志发现如下错误:
low voltage detected, date/time is not reliable.
retrieved date/time is not valid.
出现第一条错误后,读取的时间有错误,校验不过,因此开机并不显示rtc中保存的时间,查看AT8563规格书(AT8563完全兼容PCF8563)发现这是VL位被置位。当VL为1时无法保证时间的准确,同样根据规格书提示,在检测到VL为1时,重新初始化寄存器时间值。

解决办法:
在驱动初始化时如果检测到VL=1,即重新初始化寄存器,同时把VL置0;

问题二、开机设置正确时间后,重启机器,时间仍为RTC中原始值,也就是说正确的时间并没有设置到RTC中,而RTC一直走着一个错误的时间,并在开机时显示。

分析过程:
通过查看日志发现在系统时间更改后,pcf8563_set_datetime并未执行,也就是说正确的时间并没有写入到RTC中,再往前跟发现alarm_set_rtc中alarmtimer_get_rtcdev出了问题。即没有获取到设备,而设备就是rtcdev这个全局变量。

然后祭出我们的度娘大法,找到了http://bbs.csdn.net/topics/391882411
这个帖子,帖子里已经说的很清楚了。

根本原因:
根据帖子描述,rtc注册到alarmtimer_rtc_add_device这一步时有两个判断条件:

static int alarmtimer_rtc_add_device(struct device *dev, struct class_interface *class_intf) { unsigned long flags; struct rtc_device *rtc = to_rtc_device(dev); if (rtcdev) return -EBUSY; if (!rtc->ops->set_alarm) return -1; if (!device_may_wakeup(rtc->dev.parent)) return -1; spin_lock_irqsave(&rtcdev_lock, flags); if (!rtcdev) { rtcdev = rtc; /* hold a reference so it doesn't go away */ get_device(dev); } spin_unlock_irqrestore(&rtcdev_lock, flags); return 0; }




首先,pcf8563驱动中没有实现set_alarm,所以此处直接返回。
其次,实现了set_alarm后,第二条仍然不能通过。
所以,rtc设备并没有赋值给rtcdev,设置时间时当然也就获取不到了。

解决办法:
1、实现set_alarm函数,此项目并不需要alarm功能,随便写个空函数即可。
【[RK3128][Android 6.0] RTC芯片PCF8563调试记录】2、在pcf8563_probe中添加device_init_wakeup(&client->dev, true);
device_init_wakeup是设置该设备能不能唤醒设备,我们这里设为true。


总结:
没想到小小的RTC也几经波折,内核修炼之路任重道远...

    推荐阅读