I have enabled CONFIG_RTC_DRV_SNVS configuration to build the SNVS SRTC driver "rtc-snvs.c" in my Android project. When the system boots up, I can see SRTC is working, the command "cat /sys/class/rtc/rtc1/time" returns the time. However when I try to set time from Android, it calls snvs_rtc_set_time() to set the time and the call hangs in the infinite loop waiting for SRTC to be re-enabled. Why does this happen? How to fix it?
int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct rtc_drv_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
unsigned long time;
int ret;
u32 lp_cr;
u64 old_time_47bit, new_time_47bit;
printk("+-+-+-+-%s\n", __FUNCTION__);ret = rtc_tm_to_time(tm, &time);
if (ret != 0)
return ret;old_time_47bit = (((u64) (__raw_readl(ioaddr + SNVS_LPSRTCMR) &
((0x1 << CNTR_TO_SECS_SH) - 1)) << 32) |
((u64) __raw_readl(ioaddr + SNVS_LPSRTCLR)));/* Disable RTC first */
lp_cr = __raw_readl(ioaddr + SNVS_LPCR) & ~SNVS_LPCR_SRTC_ENV;
__raw_writel(lp_cr, ioaddr + SNVS_LPCR);
printk("1\n");
while (__raw_readl(ioaddr + SNVS_LPCR) & SNVS_LPCR_SRTC_ENV)
;/* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
__raw_writel(time << CNTR_TO_SECS_SH, ioaddr + SNVS_LPSRTCLR);
__raw_writel(time >> (32 - CNTR_TO_SECS_SH), ioaddr + SNVS_LPSRTCMR);/* Enable RTC again */
__raw_writel(lp_cr | SNVS_LPCR_SRTC_ENV, ioaddr + SNVS_LPCR);
printk("2\n");
while (!(__raw_readl(ioaddr + SNVS_LPCR) & SNVS_LPCR_SRTC_ENV)) // hangs here
;.
.
.
}
Please note that if fuse value SEC_CONFIG[1] bit is 0, it causes SNVS SRTC can't be accessed.
You need to set it to 1, open mode.
Have a great day,
Victor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Victor,
How do I read and write the fuse SEC_CONFIG[1]? In the driver rtc-snvs.c file, I cannot find ways to do it.
Jeffrey
The eFuses in i.MX6 processor are internal one-time programmable bits used for the configuration.
You can manage eFuses with "iim" u-boot command. Type "iim help" for the details.
The address of SEC_CONFIG fuse is 0x460.
Please refer the table 5-9 "Fusemap Descriptions" of i.MX 6 Reference Manual for the details.
Have a great day,
Victor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Victor,
One more question, there is no "iim" command in my u-boot. Is there a way to read the fuse value in Linux kernel (similar to this SEC_CONFIG mode discussion)? Does reading /sys/fsl_otp/HW_OCOTP_CFG5 give me SEC_CONFIG values?
Thank you.
Jeffrey
In Linux the fuses are accessible with its sysfs under /sys/class/misc/fuse point.
Have a great day,
Victor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Victor,
Thank you.
Jeffrey
Hi Victor,
Thank you for the prompt response. I will take a look at the "iim" command.
However if the SEC_CONFIG[1] is set to closed position, then the SNVS SRTC cannot be used anymore?
In this case, what RTC can be used to to implement the alarm which wakes up iMX6 from suspend?
Thank you.
Jeffrey