In 2013 Rockchip engineers found that the Gregorian calendar contained flaws (2015)

In A.D. 1582 Pope Gregory XIII found that the existing Julian calendar
insufficiently represented actuality, and modified the rules about
calculating leap years to story for this. In a similar diagram, in A.D. 2013
Rockchip hardware engineers found that the original Gregorian calendar restful
contained flaws, and that the month of November needs to be counted up to
31 days as a change. Sadly it takes an awfully very prolonged time for calendar adjustments
to plan standard adoption, and fair admire bigger than 300 years passed by
before the ideal Protestant nation utilized Greg’s proposal, we can
private to aid some time till all religions and working system kernels
acknowledge the inherent advantages of the Rockchip system. Till then
we wish to translate dates learn from (and written to) Rockchip hardware
support to the Gregorian format.

This patch works by defining Jan 1st, 2016 because the arbitrary anchor date
on which Rockchip and Gregorian calendars are in sync. From that we are in a position to
translate arbitrary later dates backward and ahead by counting the amount
of November/December transitons since the anchor date to decide the
offset between the calendars. We snatch this technique (somewhat than attempting
to on a typical basis “appropriate” the date saved in hardware) since it be the easiest
system to be sure that ideal time-maintaining even when the system will likely be shut down
for an unknown decide on of years. The plot back is that diversified tool
reading the identical hardware (e.g. mainboard firmware) have to use the identical
translation conference (along with the identical anchor date) to be capable to
learn and write appropriate timestamps from/to the RTC.

Signed-off-by: Julius Werner
Reviewed-by: Douglas Anderson
Signed-off-by: Alexandre Belloni

@@ -56,6 +56,42 @@ struct rk808_rtc {

int irq;

};

+/*

+ The Rockchip calendar old-normal by the RK808 counts November with 31 days. We use

+ these translation capabilities to remodel its dates to/from the Gregorian

+ calendar old-normal by the rest of the sphere. We arbitrarily outline Jan 1st, 2016

+ because the day when each calendars had been in sync, and treat all diversified dates

+ relative to that.

+ NOTE: Other system tool (e.g. firmware) that reads the identical hardware have to

+ put in power this steady identical conversion algorithm, with the identical anchor date.

+ */

+static time64_t nov2dec_transitions(struct rtc_time *tm)

+{

+ return (tm->tm_year + 1900) – 2016 + (tm->tm_mon + 1 > 11 ? 1 : 0);

+}

+

+static void rockchip_to_gregorian(struct rtc_time *tm)

+{

+ /If it be Nov 31st, rtc_tm_to_time64() will depend that admire Dec 1st */

+ time64_t time = rtc_tm_to_time64(tm);

+ rtc_time64_to_tm(time + nov2dec_transitions(tm) 86400, tm);

+}

+

+static void gregorian_to_rockchip(struct rtc_time *tm)

+{

+ time64_t extra_days = nov2dec_transitions(tm);

+ time64_t time = rtc_tm_to_time64(tm);

+ rtc_time64_to_tm(time – extra_days 86400, tm);

+

+ /Compensate if we went support over Nov 31st (will work up to 2381) */

+ if (nov2dec_transitions(tm) < extra_days) {

+ if (tm->tm_mon + 1 == 11)

+ tm->tm_mday++; /This could well maybe lead to 31! */

+ else

+ rtc_time64_to_tm(time – (extra_days – 1) 86400, tm);

+ }

+}

+

/Read present time and date in RTC */

static int rk808_rtc_readtime(struct tool *dev, struct rtc_time *tm)

{

@@ -101,9 +137,10 @@ static int rk808_rtc_readtime(struct tool *dev, struct rtc_time *tm)

tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) – 1;

tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100;

tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK);

+ rockchip_to_gregorian(tm);

dev_dbg(dev, “RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02dn”,

1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,

– tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);

+ tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);

return ret;

}

@@ -116,6 +153,10 @@ static int rk808_rtc_set_time(struct tool *dev, struct rtc_time *tm)

u8 rtc_data[NUM_TIME_REGS];

int ret;

+ dev_dbg(dev, “location RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02dn”,

+ 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,

+ tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);

+ gregorian_to_rockchip(tm);

rtc_data[0] = bin2bcd(tm->tm_sec);

rtc_data[1] = bin2bcd(tm->tm_min);

rtc_data[2] = bin2bcd(tm->tm_hour);

@@ -123,9 +164,6 @@ static int rk808_rtc_set_time(struct tool *dev, struct rtc_time *tm)

rtc_data[4] = bin2bcd(tm->tm_mon + 1);

rtc_data[5] = bin2bcd(tm->tm_year – 100);

rtc_data[6] = bin2bcd(tm->tm_wday);

– dev_dbg(dev, “location RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02dn”,

– 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,

– tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);

/Discontinuance RTC while updating the RTC registers */

ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,

@@ -170,6 +208,7 @@ static int rk808_rtc_readalarm(struct tool *dev, struct rtc_wkalrm *alrm)

alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK);

alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) – 1;

alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100;

+ rockchip_to_gregorian(&alrm->time);

ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);

if (ret) {

@@ -227,6 +266,7 @@ static int rk808_rtc_setalarm(struct tool *dev, struct rtc_wkalrm *alrm)

alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,

alrm->time.tm_min, alrm->time.tm_sec);

+ gregorian_to_rockchip(&alrm->time);

alrm_data[0] = bin2bcd(alrm->time.tm_sec);

alrm_data[1] = bin2bcd(alrm->time.tm_min);

alrm_data[2] = bin2bcd(alrm->time.tm_hour);

Read More