Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'rtc-4.4-3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux

Pull RTC fixes from Alexandre Belloni:
"Late fixes for the RTC subsystem for 4.4:

A fix for a nasty hardware bug in rk808 and an initialization
reordering in da9063 to fix a possible crash"

* tag 'rtc-4.4-3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux:
rtc: da9063: fix access ordering error during RTC interrupt at system power on
rtc: rk808: Compensate for Rockchip calendar deviation on November 31st

+54 -15
+10 -11
drivers/rtc/rtc-da9063.c
··· 483 483 484 484 platform_set_drvdata(pdev, rtc); 485 485 486 - irq_alarm = platform_get_irq_byname(pdev, "ALARM"); 487 - ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL, 488 - da9063_alarm_event, 489 - IRQF_TRIGGER_LOW | IRQF_ONESHOT, 490 - "ALARM", rtc); 491 - if (ret) { 492 - dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n", 493 - irq_alarm, ret); 494 - return ret; 495 - } 496 - 497 486 rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC, 498 487 &da9063_rtc_ops, THIS_MODULE); 499 488 if (IS_ERR(rtc->rtc_dev)) ··· 490 501 491 502 da9063_data_to_tm(data, &rtc->alarm_time, rtc); 492 503 rtc->rtc_sync = false; 504 + 505 + irq_alarm = platform_get_irq_byname(pdev, "ALARM"); 506 + ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL, 507 + da9063_alarm_event, 508 + IRQF_TRIGGER_LOW | IRQF_ONESHOT, 509 + "ALARM", rtc); 510 + if (ret) 511 + dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n", 512 + irq_alarm, ret); 513 + 493 514 return ret; 494 515 } 495 516
+44 -4
drivers/rtc/rtc-rk808.c
··· 56 56 int irq; 57 57 }; 58 58 59 + /* 60 + * The Rockchip calendar used by the RK808 counts November with 31 days. We use 61 + * these translation functions to convert its dates to/from the Gregorian 62 + * calendar used by the rest of the world. We arbitrarily define Jan 1st, 2016 63 + * as the day when both calendars were in sync, and treat all other dates 64 + * relative to that. 65 + * NOTE: Other system software (e.g. firmware) that reads the same hardware must 66 + * implement this exact same conversion algorithm, with the same anchor date. 67 + */ 68 + static time64_t nov2dec_transitions(struct rtc_time *tm) 69 + { 70 + return (tm->tm_year + 1900) - 2016 + (tm->tm_mon + 1 > 11 ? 1 : 0); 71 + } 72 + 73 + static void rockchip_to_gregorian(struct rtc_time *tm) 74 + { 75 + /* If it's Nov 31st, rtc_tm_to_time64() will count that like Dec 1st */ 76 + time64_t time = rtc_tm_to_time64(tm); 77 + rtc_time64_to_tm(time + nov2dec_transitions(tm) * 86400, tm); 78 + } 79 + 80 + static void gregorian_to_rockchip(struct rtc_time *tm) 81 + { 82 + time64_t extra_days = nov2dec_transitions(tm); 83 + time64_t time = rtc_tm_to_time64(tm); 84 + rtc_time64_to_tm(time - extra_days * 86400, tm); 85 + 86 + /* Compensate if we went back over Nov 31st (will work up to 2381) */ 87 + if (nov2dec_transitions(tm) < extra_days) { 88 + if (tm->tm_mon + 1 == 11) 89 + tm->tm_mday++; /* This may result in 31! */ 90 + else 91 + rtc_time64_to_tm(time - (extra_days - 1) * 86400, tm); 92 + } 93 + } 94 + 59 95 /* Read current time and date in RTC */ 60 96 static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) 61 97 { ··· 137 101 tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1; 138 102 tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100; 139 103 tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK); 104 + rockchip_to_gregorian(tm); 140 105 dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", 141 106 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, 142 - tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec); 107 + tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec); 143 108 144 109 return ret; 145 110 } ··· 153 116 u8 rtc_data[NUM_TIME_REGS]; 154 117 int ret; 155 118 119 + dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", 120 + 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, 121 + tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec); 122 + gregorian_to_rockchip(tm); 156 123 rtc_data[0] = bin2bcd(tm->tm_sec); 157 124 rtc_data[1] = bin2bcd(tm->tm_min); 158 125 rtc_data[2] = bin2bcd(tm->tm_hour); ··· 164 123 rtc_data[4] = bin2bcd(tm->tm_mon + 1); 165 124 rtc_data[5] = bin2bcd(tm->tm_year - 100); 166 125 rtc_data[6] = bin2bcd(tm->tm_wday); 167 - dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", 168 - 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, 169 - tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec); 170 126 171 127 /* Stop RTC while updating the RTC registers */ 172 128 ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, ··· 208 170 alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK); 209 171 alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1; 210 172 alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100; 173 + rockchip_to_gregorian(&alrm->time); 211 174 212 175 ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg); 213 176 if (ret) { ··· 266 227 alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour, 267 228 alrm->time.tm_min, alrm->time.tm_sec); 268 229 230 + gregorian_to_rockchip(&alrm->time); 269 231 alrm_data[0] = bin2bcd(alrm->time.tm_sec); 270 232 alrm_data[1] = bin2bcd(alrm->time.tm_min); 271 233 alrm_data[2] = bin2bcd(alrm->time.tm_hour);