static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm) { NvU32 now; #if SYNC_EXTERNAL_RTC_TO_INTERNAL_RTC struct rtc_time iner_rtc_tm; unsigned long iner_now; int ret = 0; #endif if (hPmu == NULL) return -1; if (!NvOdmPmuReadRtc(hPmu, &now)) { printk("NvOdmPmuReadRtc failed\n"); return -1; } rtc_time_to_tm(now, tm); #if SYNC_EXTERNAL_RTC_TO_INTERNAL_RTC /* Read internal RTC time, if there are different, set internal rtc with external rtc time */ ret = internal_tegra_rtc_read_time(&iner_rtc_tm); if(ret) return ret; ret = rtc_tm_to_time(&iner_rtc_tm, &iner_now); if((ret == 0) && (now != iner_now)) { ret = internal_tegra_rtc_set_time(tm); /* Set internal rtc with external rtc time */ } return ret; #else return 0; #endif }
static int __init tegra_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; NvU32 initial; if (NvOdmPmuDeviceOpen(&hPmu) == NV_FALSE) { pr_debug("%s: NvOdmPmuDeviceOpen failed\n", pdev->name); return -ENXIO; } /* if the SoCs PMU has't been properly initialized, a bogus large * value may be returned which triggers the Y2038 bug in the kernel. * work-around this issue by checking the initial value of the PMU * and then clobbering it if the value is bogus */ if (NvOdmPmuReadRtc(hPmu, &initial) && ((time_t)initial < 0)) { if(!NvOdmPmuWriteRtc(hPmu, 0)) return -EINVAL; } rtc = rtc_device_register(pdev->name, &pdev->dev, &tegra_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { pr_debug("%s: can't register RTC device, err %ld\n", pdev->name, PTR_ERR(rtc)); NvOdmPmuDeviceClose(hPmu); return -1; } platform_set_drvdata(pdev, rtc); return 0; }
static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) { struct rtc_time *time = &wkalrm->time; NvU32 now; NvU32 alarm_sec; struct rtc_time now_time; printk("%s(): wkalrm->enabled=%d\n", __func__, wkalrm?wkalrm->enabled:-1); pr_debug("wkalrm->enabled = %d\n", wkalrm->enabled); if (wkalrm->enabled == 0) { if(!NvOdmPmuWriteAlarm(hPmu, 0)) return -EINVAL; return 0; } if (!NvOdmPmuReadRtc(hPmu, &now)) { pr_debug("NvOdmPmuReadRtc failed\n"); return -1; } rtc_time_to_tm(now, &now_time); pr_debug( "read now_time %02d:%02d:%02d %02d/%02d/%04d\n", now_time.tm_hour, now_time.tm_min, now_time.tm_sec, now_time.tm_mon + 1, now_time.tm_mday, now_time.tm_year + 1900); pr_debug("write alarm_time %02d:%02d:%02d %02d/%02d/%04d\n", time->tm_hour, time->tm_min, time->tm_sec, time->tm_mon+1, time->tm_mday, time->tm_yday+1900); alarm_sec = (NvU32)mktime(now_time.tm_year + 1900, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); if (alarm_sec < now) alarm_sec = (NvU32)mktime(now_time.tm_year + 1901, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); pr_debug("alarm_sec = %u\n", alarm_sec); if(!NvOdmPmuWriteAlarm(hPmu, alarm_sec-now)) return -EINVAL; #if SYNC_EXTERNAL_RTC_TO_INTERNAL_RTC return internal_tegra_rtc_set_alarm(wkalrm); #else pr_info("%s():enter.\n", __func__); /* Alarm set */ events |= RTC_IRQF | RTC_AF; if (rtc) rtc_update_irq(rtc, 1, events); return NV_TRUE; #endif }
static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm) { NvU32 now; if (hPmu == NULL) return -1; if (!NvOdmPmuReadRtc(hPmu, &now)) { printk("NvOdmPmuReadRtc failed\n"); return -1; } rtc_time_to_tm(now, tm); return 0; }
NvBool NvRmPmuReadRtc( NvRmDeviceHandle hRmDevice, NvU32* pCount) { NvBool ReturnStatus = NV_FALSE; if (!s_PmuSupportedEnv) return NV_FALSE; NV_ASSERT(s_Pmu.hMutex); NvOsMutexLock(s_Pmu.hMutex); ReturnStatus = NvOdmPmuReadRtc(s_Pmu.hOdmPmu, pCount); NvOsMutexUnlock(s_Pmu.hMutex); return ReturnStatus; }
static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) { struct rtc_time *time = &wkalrm->time; NvU32 now; NvU32 alarm_sec; struct rtc_time now_time; pr_debug("wkalrm->enabled = %d\n", wkalrm->enabled); if (wkalrm->enabled == 0) return 0; if (!NvOdmPmuReadRtc(hPmu, &now)) { pr_debug("NvOdmPmuReadRtc failed\n"); return -1; } rtc_time_to_tm(now, &now_time); pr_debug( "read now_time %02d:%02d:%02d %02d/%02d/%04d\n", now_time.tm_hour, now_time.tm_min, now_time.tm_sec, now_time.tm_mon + 1, now_time.tm_mday, now_time.tm_year + 1900); pr_debug("write alarm_time %02d:%02d:%02d %02d/%02d/%04d\n", time->tm_hour, time->tm_min, time->tm_sec, time->tm_mon+1, time->tm_mday, time->tm_yday+1900); alarm_sec = (NvU32)mktime(now_time.tm_year + 1900, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); if (alarm_sec < now) alarm_sec = (NvU32)mktime(now_time.tm_year + 1901, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); pr_debug("alarm_sec = %u\n", alarm_sec); if(!NvOdmPmuWriteAlarm(hPmu, alarm_sec-now)) return -EINVAL; #if SYNC_EXTERNAL_RTC_TO_INTERNAL_RTC return internal_tegra_rtc_set_alarm(wkalrm); #else return 0; #endif }