/* * This function is used to obtain the RTC time or the alarm value in * second.
*/ static time64_t get_alarm_or_time(struct device *dev, int time_alarm)
{ struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr;
u32 day = 0, hr = 0, min = 0, sec = 0, hr_min = 0;
/* * This function sets the RTC alarm value or the time value.
*/ staticvoid set_alarm_or_time(struct device *dev, int time_alarm, time64_t time)
{
u32 tod, day, hr, min, sec, temp; struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr;
day = div_s64_rem(time, 86400, &tod);
/* time is within a day now */
hr = tod / 3600;
tod -= hr * 3600;
/* time is within an hour now */
min = tod / 60;
sec = tod - min * 60;
/* * This function updates the RTC alarm registers and then clears all the * interrupt status bits.
*/ staticvoid rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
{
time64_t time; struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr;
time = rtc_tm_to_time64(alrm);
/* clear all the interrupt status bits */
writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR);
set_alarm_or_time(dev, MXC_RTC_ALARM, time);
}
/* * This function reads the current RTC time into tm in Gregorian date.
*/ staticint mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
time64_t val;
/* Avoid roll-over from reading the different registers */ do {
val = get_alarm_or_time(dev, MXC_RTC_TIME);
} while (val != get_alarm_or_time(dev, MXC_RTC_TIME));
rtc_time64_to_tm(val, tm);
return 0;
}
/* * This function sets the internal RTC time based on tm in Gregorian date.
*/ staticint mxc_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
time64_t time = rtc_tm_to_time64(tm);
/* Avoid roll-over from reading the different registers */ do {
set_alarm_or_time(dev, MXC_RTC_TIME, time);
} while (time != get_alarm_or_time(dev, MXC_RTC_TIME));
return 0;
}
/* * This function reads the current alarm value into the passed in 'alrm' * argument. It updates the alrm's pending field value based on the whether * an alarm interrupt occurs or not.
*/ staticint mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr;
/* * This function sets the RTC alarm based on passed in alrm.
*/ staticint mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
/* * Set the start date as beginning of the current year. This can * be overridden using device tree.
*/
rtc_time64_to_tm(ktime_get_real_seconds(), &tm);
rtc->start_secs = mktime64(tm.tm_year, 1, 1, 0, 0, 0);
rtc->set_start_time = true;
} else { /* 16bit days + hours minutes seconds */
rtc->range_max = (1 << 16) * 86400ULL - 1;
}
pdata->clk_ipg = devm_clk_get_enabled(&pdev->dev, "ipg"); if (IS_ERR(pdata->clk_ipg)) {
dev_err(&pdev->dev, "unable to get ipg clock!\n"); return PTR_ERR(pdata->clk_ipg);
}
pdata->clk_ref = devm_clk_get_enabled(&pdev->dev, "ref"); if (IS_ERR(pdata->clk_ref)) {
dev_err(&pdev->dev, "unable to get ref clock!\n"); return PTR_ERR(pdata->clk_ref);
}
if (pdata->irq >= 0) {
device_init_wakeup(&pdev->dev, true);
ret = dev_pm_set_wake_irq(&pdev->dev, pdata->irq); if (ret)
dev_err(&pdev->dev, "failed to enable irq wake\n");
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.