For use by the EFI loader RTC set time boot service, import
rtc_calc_weekday() from U-Boot.

Signed-off-by: Ahmad Fatoum <[email protected]>
---
 drivers/rtc/rtc-lib.c | 48 +++++++++++++++++++++++++++++++++++++++++++
 include/rtc.h         | 11 ++++++++++
 2 files changed, 59 insertions(+)

diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
index 3709d46cbe16..4f2993ac12bd 100644
--- a/drivers/rtc/rtc-lib.c
+++ b/drivers/rtc/rtc-lib.c
@@ -73,6 +73,54 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
 }
 EXPORT_SYMBOL(rtc_time_to_tm);
 
+// SPDX-SnippetBegin
+// SPDX-Snippet-Comment: Origin-URL: 
https://github.com/u-boot/u-boot/blob/467382ca03758e4f3f13107e3a83669e93a7461e/lib/date.c
+
+static int month_offset[] = {
+       0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+/*
+ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
+ */
+int rtc_calc_weekday(struct rtc_time *tm)
+{
+       int leaps_to_date;
+       int last_year;
+       int day;
+
+       if (tm->tm_year < 1753)
+               return -1;
+       last_year = tm->tm_year - 1;
+
+       /* Number of leap corrections to apply up to end of last year */
+       leaps_to_date = last_year / 4 - last_year / 100 + last_year / 400;
+
+       /*
+        * This year is a leap year if it is divisible by 4 except when it is
+        * divisible by 100 unless it is divisible by 400
+        *
+        * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 is.
+        */
+       if (tm->tm_year % 4 == 0 &&
+           ((tm->tm_year % 100 != 0) || (tm->tm_year % 400 == 0)) &&
+           tm->tm_mon > 2) {
+               /* We are past Feb. 29 in a leap year */
+               day = 1;
+       } else {
+               day = 0;
+       }
+
+       day += last_year * 365 + leaps_to_date + month_offset[tm->tm_mon - 1] +
+                       tm->tm_mday;
+       tm->tm_wday = day % 7;
+
+       return 0;
+}
+EXPORT_SYMBOL(rtc_calc_weekday);
+
+// SPDX-SnippetEnd
+
 /*
  * Does the rtc_time represent a valid date/time?
  */
diff --git a/include/rtc.h b/include/rtc.h
index 0766f0408216..c3e277320557 100644
--- a/include/rtc.h
+++ b/include/rtc.h
@@ -54,4 +54,15 @@ static inline struct rtc_device *rtc_lookup(const char *name)
 
 const char *time_str(struct rtc_time *tm);
 
+/**
+ * rtc_calc_weekday() - Work out the weekday from a time
+ *
+ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK).
+ * It sets time->tm_wdaay to the correct day of the week.
+ *
+ * @time:      Time to inspect. tm_wday is updated
+ * Return: 0 if OK, -EINVAL if the weekday could not be determined
+ */
+int rtc_calc_weekday(struct rtc_time *time);
+
 #endif /* _RTC_H_ */
-- 
2.47.3


Reply via email to