NXP

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

2019-07-12 12:26发布

硬件平台: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这一步时有两个判断条件:    
  1. static int alarmtimer_rtc_add_device(struct device *dev,
  2. struct class_interface *class_intf)
  3. {
  4. unsigned long flags;
  5. struct rtc_device *rtc = to_rtc_device(dev);
  6.  
  7. if (rtcdev)
  8. return -EBUSY;
  9.  
  10. if (!rtc->ops->set_alarm)
  11. return -1;
  12. if (!device_may_wakeup(rtc->dev.parent))
  13. return -1;
  14.  
  15. spin_lock_irqsave(&rtcdev_lock, flags);
  16. if (!rtcdev) {
  17. rtcdev = rtc;
  18. /* hold a reference so it doesn't go away */
  19. get_device(dev);
  20. }
  21. spin_unlock_irqrestore(&rtcdev_lock, flags);
  22. return 0;
  23. }
    首先,pcf8563驱动中没有实现set_alarm,所以此处直接返回。 其次,实现了set_alarm后,第二条仍然不能通过。 所以,rtc设备并没有赋值给rtcdev,设置时间时当然也就获取不到了。   解决办法: 1、实现set_alarm函数,此项目并不需要alarm功能,随便写个空函数即可。 2、在pcf8563_probe中添加device_init_wakeup(&client->dev, true); device_init_wakeup是设置该设备能不能唤醒设备,我们这里设为true。     总结: 没想到小小的RTC也几经波折,内核修炼之路任重道远...