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-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux

Pull RTC updates from Alexandre Belloni:
"The broken down time conversion is similar to what is done in the time
subsystem since v5.14. The rest is fairly straightforward.

Subsystem:
- Switch to Neri and Schneider time conversion algorithm

Drivers:
- rx8025: add rx8035 support
- s5m: modernize driver and set range"

* tag 'rtc-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux:
rtc: rx8010: select REGMAP_I2C
dt-bindings: rtc: add Epson RX-8025 and RX-8035
rtc: rx8025: implement RX-8035 support
rtc: cmos: remove stale REVISIT comments
rtc: tps65910: Correct driver module alias
rtc: move RTC_LIB_KUNIT_TEST to proper location
rtc: lib_test: add MODULE_LICENSE
rtc: Improve performance of rtc_time64_to_tm(). Add tests.
rtc: s5m: set range
rtc: s5m: enable wakeup only when available
rtc: s5m: signal the core when alarm are not available
rtc: s5m: switch to devm_rtc_allocate_device

+242 -63
+3
Documentation/devicetree/bindings/rtc/trivial-rtc.yaml
··· 32 32 - dallas,ds3232 33 33 # I2C-BUS INTERFACE REAL TIME CLOCK MODULE 34 34 - epson,rx8010 35 + # I2C-BUS INTERFACE REAL TIME CLOCK MODULE 36 + - epson,rx8025 37 + - epson,rx8035 35 38 # I2C-BUS INTERFACE REAL TIME CLOCK MODULE with Battery Backed RAM 36 39 - epson,rx8571 37 40 # I2C-BUS INTERFACE REAL TIME CLOCK MODULE
+10
drivers/rtc/Kconfig
··· 75 75 Say yes here to enable debugging support in the RTC framework 76 76 and individual RTC drivers. 77 77 78 + config RTC_LIB_KUNIT_TEST 79 + tristate "KUnit test for RTC lib functions" if !KUNIT_ALL_TESTS 80 + depends on KUNIT 81 + default KUNIT_ALL_TESTS 82 + help 83 + Enable this option to test RTC library functions. 84 + 85 + If unsure, say N. 86 + 78 87 config RTC_NVMEM 79 88 bool "RTC non volatile storage support" 80 89 select NVMEM ··· 633 624 634 625 config RTC_DRV_RX8010 635 626 tristate "Epson RX8010SJ" 627 + select REGMAP_I2C 636 628 help 637 629 If you say yes here you get support for the Epson RX8010SJ RTC 638 630 chip.
+2
drivers/rtc/Makefile
··· 15 15 rtc-core-$(CONFIG_RTC_INTF_PROC) += proc.o 16 16 rtc-core-$(CONFIG_RTC_INTF_SYSFS) += sysfs.o 17 17 18 + obj-$(CONFIG_RTC_LIB_KUNIT_TEST) += lib_test.o 19 + 18 20 # Keep the list ordered. 19 21 20 22 obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o
+78 -25
drivers/rtc/lib.c
··· 6 6 * Author: Alessandro Zummo <a.zummo@towertech.it> 7 7 * 8 8 * based on arch/arm/common/rtctime.c and other bits 9 + * 10 + * Author: Cassio Neri <cassio.neri@gmail.com> (rtc_time64_to_tm) 9 11 */ 10 12 11 13 #include <linux/export.h> ··· 23 21 /* Leap years */ 24 22 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } 25 23 }; 26 - 27 - #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) 28 24 29 25 /* 30 26 * The number of days in the month. ··· 42 42 } 43 43 EXPORT_SYMBOL(rtc_year_days); 44 44 45 - /* 46 - * rtc_time64_to_tm - Converts time64_t to rtc_time. 47 - * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. 45 + /** 46 + * rtc_time64_to_tm - converts time64_t to rtc_time. 47 + * 48 + * @time: The number of seconds since 01-01-1970 00:00:00. 49 + * (Must be positive.) 50 + * @tm: Pointer to the struct rtc_time. 48 51 */ 49 52 void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) 50 53 { 51 - unsigned int month, year, secs; 54 + unsigned int secs; 52 55 int days; 56 + 57 + u64 u64tmp; 58 + u32 u32tmp, udays, century, day_of_century, year_of_century, year, 59 + day_of_year, month, day; 60 + bool is_Jan_or_Feb, is_leap_year; 53 61 54 62 /* time must be positive */ 55 63 days = div_s64_rem(time, 86400, &secs); ··· 65 57 /* day of the week, 1970-01-01 was a Thursday */ 66 58 tm->tm_wday = (days + 4) % 7; 67 59 68 - year = 1970 + days / 365; 69 - days -= (year - 1970) * 365 70 - + LEAPS_THRU_END_OF(year - 1) 71 - - LEAPS_THRU_END_OF(1970 - 1); 72 - while (days < 0) { 73 - year -= 1; 74 - days += 365 + is_leap_year(year); 75 - } 76 - tm->tm_year = year - 1900; 77 - tm->tm_yday = days + 1; 60 + /* 61 + * The following algorithm is, basically, Proposition 6.3 of Neri 62 + * and Schneider [1]. In a few words: it works on the computational 63 + * (fictitious) calendar where the year starts in March, month = 2 64 + * (*), and finishes in February, month = 13. This calendar is 65 + * mathematically convenient because the day of the year does not 66 + * depend on whether the year is leap or not. For instance: 67 + * 68 + * March 1st 0-th day of the year; 69 + * ... 70 + * April 1st 31-st day of the year; 71 + * ... 72 + * January 1st 306-th day of the year; (Important!) 73 + * ... 74 + * February 28th 364-th day of the year; 75 + * February 29th 365-th day of the year (if it exists). 76 + * 77 + * After having worked out the date in the computational calendar 78 + * (using just arithmetics) it's easy to convert it to the 79 + * corresponding date in the Gregorian calendar. 80 + * 81 + * [1] "Euclidean Affine Functions and Applications to Calendar 82 + * Algorithms". https://arxiv.org/abs/2102.06959 83 + * 84 + * (*) The numbering of months follows rtc_time more closely and 85 + * thus, is slightly different from [1]. 86 + */ 78 87 79 - for (month = 0; month < 11; month++) { 80 - int newdays; 88 + udays = ((u32) days) + 719468; 81 89 82 - newdays = days - rtc_month_days(month, year); 83 - if (newdays < 0) 84 - break; 85 - days = newdays; 86 - } 87 - tm->tm_mon = month; 88 - tm->tm_mday = days + 1; 90 + u32tmp = 4 * udays + 3; 91 + century = u32tmp / 146097; 92 + day_of_century = u32tmp % 146097 / 4; 93 + 94 + u32tmp = 4 * day_of_century + 3; 95 + u64tmp = 2939745ULL * u32tmp; 96 + year_of_century = upper_32_bits(u64tmp); 97 + day_of_year = lower_32_bits(u64tmp) / 2939745 / 4; 98 + 99 + year = 100 * century + year_of_century; 100 + is_leap_year = year_of_century != 0 ? 101 + year_of_century % 4 == 0 : century % 4 == 0; 102 + 103 + u32tmp = 2141 * day_of_year + 132377; 104 + month = u32tmp >> 16; 105 + day = ((u16) u32tmp) / 2141; 106 + 107 + /* 108 + * Recall that January 01 is the 306-th day of the year in the 109 + * computational (not Gregorian) calendar. 110 + */ 111 + is_Jan_or_Feb = day_of_year >= 306; 112 + 113 + /* Converts to the Gregorian calendar. */ 114 + year = year + is_Jan_or_Feb; 115 + month = is_Jan_or_Feb ? month - 12 : month; 116 + day = day + 1; 117 + 118 + day_of_year = is_Jan_or_Feb ? 119 + day_of_year - 306 : day_of_year + 31 + 28 + is_leap_year; 120 + 121 + /* Converts to rtc_time's format. */ 122 + tm->tm_year = (int) (year - 1900); 123 + tm->tm_mon = (int) month; 124 + tm->tm_mday = (int) day; 125 + tm->tm_yday = (int) day_of_year + 1; 89 126 90 127 tm->tm_hour = secs / 3600; 91 128 secs -= tm->tm_hour * 3600;
+81
drivers/rtc/lib_test.c
··· 1 + // SPDX-License-Identifier: LGPL-2.1+ 2 + 3 + #include <kunit/test.h> 4 + #include <linux/rtc.h> 5 + 6 + /* 7 + * Advance a date by one day. 8 + */ 9 + static void advance_date(int *year, int *month, int *mday, int *yday) 10 + { 11 + if (*mday != rtc_month_days(*month - 1, *year)) { 12 + ++*mday; 13 + ++*yday; 14 + return; 15 + } 16 + 17 + *mday = 1; 18 + if (*month != 12) { 19 + ++*month; 20 + ++*yday; 21 + return; 22 + } 23 + 24 + *month = 1; 25 + *yday = 1; 26 + ++*year; 27 + } 28 + 29 + /* 30 + * Checks every day in a 160000 years interval starting on 1970-01-01 31 + * against the expected result. 32 + */ 33 + static void rtc_time64_to_tm_test_date_range(struct kunit *test) 34 + { 35 + /* 36 + * 160000 years = (160000 / 400) * 400 years 37 + * = (160000 / 400) * 146097 days 38 + * = (160000 / 400) * 146097 * 86400 seconds 39 + */ 40 + time64_t total_secs = ((time64_t) 160000) / 400 * 146097 * 86400; 41 + 42 + int year = 1970; 43 + int month = 1; 44 + int mday = 1; 45 + int yday = 1; 46 + 47 + struct rtc_time result; 48 + time64_t secs; 49 + s64 days; 50 + 51 + for (secs = 0; secs <= total_secs; secs += 86400) { 52 + 53 + rtc_time64_to_tm(secs, &result); 54 + 55 + days = div_s64(secs, 86400); 56 + 57 + #define FAIL_MSG "%d/%02d/%02d (%2d) : %ld", \ 58 + year, month, mday, yday, days 59 + 60 + KUNIT_ASSERT_EQ_MSG(test, year - 1900, result.tm_year, FAIL_MSG); 61 + KUNIT_ASSERT_EQ_MSG(test, month - 1, result.tm_mon, FAIL_MSG); 62 + KUNIT_ASSERT_EQ_MSG(test, mday, result.tm_mday, FAIL_MSG); 63 + KUNIT_ASSERT_EQ_MSG(test, yday, result.tm_yday, FAIL_MSG); 64 + 65 + advance_date(&year, &month, &mday, &yday); 66 + } 67 + } 68 + 69 + static struct kunit_case rtc_lib_test_cases[] = { 70 + KUNIT_CASE(rtc_time64_to_tm_test_date_range), 71 + {} 72 + }; 73 + 74 + static struct kunit_suite rtc_lib_test_suite = { 75 + .name = "rtc_lib_test_cases", 76 + .test_cases = rtc_lib_test_cases, 77 + }; 78 + 79 + kunit_test_suite(rtc_lib_test_suite); 80 + 81 + MODULE_LICENSE("GPL");
+1 -7
drivers/rtc/rtc-cmos.c
··· 229 229 if (!pm_trace_rtc_valid()) 230 230 return -EIO; 231 231 232 - /* REVISIT: if the clock has a "century" register, use 233 - * that instead of the heuristic in mc146818_get_time(). 234 - * That'll make Y3K compatility (year > 2070) easy! 235 - */ 236 232 mc146818_get_time(t); 237 233 return 0; 238 234 } 239 235 240 236 static int cmos_set_time(struct device *dev, struct rtc_time *t) 241 237 { 242 - /* REVISIT: set the "century" register if available 243 - * 244 - * NOTE: this ignores the issue whereby updating the seconds 238 + /* NOTE: this ignores the issue whereby updating the seconds 245 239 * takes effect exactly 500ms after we write the register. 246 240 * (Also queueing and other delays before we get this far.) 247 241 */
+41 -5
drivers/rtc/rtc-rx8025.c
··· 60 60 #define RX8025_ADJ_DATA_MAX 62 61 61 #define RX8025_ADJ_DATA_MIN -62 62 62 63 + enum rx_model { 64 + model_rx_unknown, 65 + model_rx_8025, 66 + model_rx_8035, 67 + model_last 68 + }; 69 + 63 70 static const struct i2c_device_id rx8025_id[] = { 64 - { "rx8025", 0 }, 71 + { "rx8025", model_rx_8025 }, 72 + { "rx8035", model_rx_8035 }, 65 73 { } 66 74 }; 67 75 MODULE_DEVICE_TABLE(i2c, rx8025_id); 68 76 69 77 struct rx8025_data { 70 78 struct rtc_device *rtc; 79 + enum rx_model model; 71 80 u8 ctrl1; 72 81 }; 73 82 ··· 109 100 length, values); 110 101 } 111 102 103 + static int rx8025_is_osc_stopped(enum rx_model model, int ctrl2) 104 + { 105 + int xstp = ctrl2 & RX8025_BIT_CTRL2_XST; 106 + /* XSTP bit has different polarity on RX-8025 vs RX-8035. 107 + * RX-8025: 0 == oscillator stopped 108 + * RX-8035: 1 == oscillator stopped 109 + */ 110 + 111 + if (model == model_rx_8025) 112 + xstp = !xstp; 113 + 114 + return xstp; 115 + } 116 + 112 117 static int rx8025_check_validity(struct device *dev) 113 118 { 114 119 struct i2c_client *client = to_i2c_client(dev); 120 + struct rx8025_data *drvdata = dev_get_drvdata(dev); 115 121 int ctrl2; 122 + int xstp; 116 123 117 124 ctrl2 = rx8025_read_reg(client, RX8025_REG_CTRL2); 118 125 if (ctrl2 < 0) ··· 142 117 return -EINVAL; 143 118 } 144 119 145 - if (!(ctrl2 & RX8025_BIT_CTRL2_XST)) { 120 + xstp = rx8025_is_osc_stopped(drvdata->model, ctrl2); 121 + if (xstp) { 146 122 dev_warn(dev, "crystal stopped, date is invalid\n"); 147 123 return -EINVAL; 148 124 } ··· 153 127 154 128 static int rx8025_reset_validity(struct i2c_client *client) 155 129 { 130 + struct rx8025_data *drvdata = i2c_get_clientdata(client); 156 131 int ctrl2 = rx8025_read_reg(client, RX8025_REG_CTRL2); 157 132 158 133 if (ctrl2 < 0) ··· 161 134 162 135 ctrl2 &= ~(RX8025_BIT_CTRL2_PON | RX8025_BIT_CTRL2_VDET); 163 136 137 + if (drvdata->model == model_rx_8025) 138 + ctrl2 |= RX8025_BIT_CTRL2_XST; 139 + else 140 + ctrl2 &= ~(RX8025_BIT_CTRL2_XST); 141 + 164 142 return rx8025_write_reg(client, RX8025_REG_CTRL2, 165 - ctrl2 | RX8025_BIT_CTRL2_XST); 143 + ctrl2); 166 144 } 167 145 168 146 static irqreturn_t rx8025_handle_irq(int irq, void *dev_id) 169 147 { 170 148 struct i2c_client *client = dev_id; 171 149 struct rx8025_data *rx8025 = i2c_get_clientdata(client); 172 - int status; 150 + int status, xstp; 173 151 174 152 rtc_lock(rx8025->rtc); 175 153 status = rx8025_read_reg(client, RX8025_REG_CTRL2); 176 154 if (status < 0) 177 155 goto out; 178 156 179 - if (!(status & RX8025_BIT_CTRL2_XST)) 157 + xstp = rx8025_is_osc_stopped(rx8025->model, status); 158 + if (xstp) 180 159 dev_warn(&client->dev, "Oscillation stop was detected," 181 160 "you may have to readjust the clock\n"); 182 161 ··· 551 518 return -ENOMEM; 552 519 553 520 i2c_set_clientdata(client, rx8025); 521 + 522 + if (id) 523 + rx8025->model = id->driver_data; 554 524 555 525 err = rx8025_init_client(client); 556 526 if (err)
+25 -25
drivers/rtc/rtc-s5m.c
··· 204 204 data[RTC_WEEKDAY] = 1 << tm->tm_wday; 205 205 data[RTC_DATE] = tm->tm_mday; 206 206 data[RTC_MONTH] = tm->tm_mon + 1; 207 - data[RTC_YEAR1] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; 207 + data[RTC_YEAR1] = tm->tm_year - 100; 208 208 209 - if (tm->tm_year < 100) { 210 - pr_err("RTC cannot handle the year %d\n", 211 - 1900 + tm->tm_year); 212 - return -EINVAL; 213 - } else { 214 - return 0; 215 - } 209 + return 0; 216 210 } 217 211 218 212 /* ··· 780 786 if (ret) 781 787 return ret; 782 788 783 - device_init_wakeup(&pdev->dev, 1); 784 - 785 - info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc", 786 - &s5m_rtc_ops, THIS_MODULE); 787 - 789 + info->rtc_dev = devm_rtc_allocate_device(&pdev->dev); 788 790 if (IS_ERR(info->rtc_dev)) 789 791 return PTR_ERR(info->rtc_dev); 790 792 793 + info->rtc_dev->ops = &s5m_rtc_ops; 794 + 795 + if (info->device_type == S5M8763X) { 796 + info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_0000; 797 + info->rtc_dev->range_max = RTC_TIMESTAMP_END_9999; 798 + } else { 799 + info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000; 800 + info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099; 801 + } 802 + 791 803 if (!info->irq) { 792 - dev_info(&pdev->dev, "Alarm IRQ not available\n"); 793 - return 0; 804 + clear_bit(RTC_FEATURE_ALARM, info->rtc_dev->features); 805 + } else { 806 + ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, 807 + s5m_rtc_alarm_irq, 0, "rtc-alarm0", 808 + info); 809 + if (ret < 0) { 810 + dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", 811 + info->irq, ret); 812 + return ret; 813 + } 814 + device_init_wakeup(&pdev->dev, 1); 794 815 } 795 816 796 - ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, 797 - s5m_rtc_alarm_irq, 0, "rtc-alarm0", 798 - info); 799 - if (ret < 0) { 800 - dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", 801 - info->irq, ret); 802 - return ret; 803 - } 804 - 805 - return 0; 817 + return devm_rtc_register_device(info->rtc_dev); 806 818 } 807 819 808 820 #ifdef CONFIG_PM_SLEEP
+1 -1
drivers/rtc/rtc-tps65910.c
··· 467 467 }; 468 468 469 469 module_platform_driver(tps65910_rtc_driver); 470 - MODULE_ALIAS("platform:rtc-tps65910"); 470 + MODULE_ALIAS("platform:tps65910-rtc"); 471 471 MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); 472 472 MODULE_LICENSE("GPL");