| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) ST-Ericsson SA 2010 |
|---|
| 3 | 4 | * |
|---|
| 4 | | - * License terms: GNU General Public License (GPL) version 2 |
|---|
| 5 | 5 | * Author: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com> |
|---|
| 6 | 6 | * |
|---|
| 7 | 7 | * RTC clock driver for the RTC part of the AB8500 Power management chip. |
|---|
| .. | .. |
|---|
| 46 | 46 | #define RTC_STATUS_DATA 0x01 |
|---|
| 47 | 47 | |
|---|
| 48 | 48 | #define COUNTS_PER_SEC (0xF000 / 60) |
|---|
| 49 | | -#define AB8500_RTC_EPOCH 2000 |
|---|
| 50 | 49 | |
|---|
| 51 | 50 | static const u8 ab8500_rtc_time_regs[] = { |
|---|
| 52 | 51 | AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, |
|---|
| .. | .. |
|---|
| 58 | 57 | AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG, |
|---|
| 59 | 58 | AB8500_RTC_ALRM_MIN_LOW_REG |
|---|
| 60 | 59 | }; |
|---|
| 61 | | - |
|---|
| 62 | | -/* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */ |
|---|
| 63 | | -static unsigned long get_elapsed_seconds(int year) |
|---|
| 64 | | -{ |
|---|
| 65 | | - unsigned long secs; |
|---|
| 66 | | - struct rtc_time tm = { |
|---|
| 67 | | - .tm_year = year - 1900, |
|---|
| 68 | | - .tm_mday = 1, |
|---|
| 69 | | - }; |
|---|
| 70 | | - |
|---|
| 71 | | - /* |
|---|
| 72 | | - * This function calculates secs from 1970 and not from |
|---|
| 73 | | - * 1900, even if we supply the offset from year 1900. |
|---|
| 74 | | - */ |
|---|
| 75 | | - rtc_tm_to_time(&tm, &secs); |
|---|
| 76 | | - return secs; |
|---|
| 77 | | -} |
|---|
| 78 | 60 | |
|---|
| 79 | 61 | static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) |
|---|
| 80 | 62 | { |
|---|
| .. | .. |
|---|
| 118 | 100 | secs = secs / COUNTS_PER_SEC; |
|---|
| 119 | 101 | secs = secs + (mins * 60); |
|---|
| 120 | 102 | |
|---|
| 121 | | - /* Add back the initially subtracted number of seconds */ |
|---|
| 122 | | - secs += get_elapsed_seconds(AB8500_RTC_EPOCH); |
|---|
| 123 | | - |
|---|
| 124 | | - rtc_time_to_tm(secs, tm); |
|---|
| 103 | + rtc_time64_to_tm(secs, tm); |
|---|
| 125 | 104 | return 0; |
|---|
| 126 | 105 | } |
|---|
| 127 | 106 | |
|---|
| .. | .. |
|---|
| 131 | 110 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; |
|---|
| 132 | 111 | unsigned long no_secs, no_mins, secs = 0; |
|---|
| 133 | 112 | |
|---|
| 134 | | - if (tm->tm_year < (AB8500_RTC_EPOCH - 1900)) { |
|---|
| 135 | | - dev_dbg(dev, "year should be equal to or greater than %d\n", |
|---|
| 136 | | - AB8500_RTC_EPOCH); |
|---|
| 137 | | - return -EINVAL; |
|---|
| 138 | | - } |
|---|
| 139 | | - |
|---|
| 140 | | - /* Get the number of seconds since 1970 */ |
|---|
| 141 | | - rtc_tm_to_time(tm, &secs); |
|---|
| 142 | | - |
|---|
| 143 | | - /* |
|---|
| 144 | | - * Convert it to the number of seconds since 01-01-2000 00:00:00, since |
|---|
| 145 | | - * we only have a small counter in the RTC. |
|---|
| 146 | | - */ |
|---|
| 147 | | - secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); |
|---|
| 113 | + secs = rtc_tm_to_time64(tm); |
|---|
| 148 | 114 | |
|---|
| 149 | 115 | no_mins = secs / 60; |
|---|
| 150 | 116 | |
|---|
| .. | .. |
|---|
| 202 | 168 | mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); |
|---|
| 203 | 169 | secs = mins * 60; |
|---|
| 204 | 170 | |
|---|
| 205 | | - /* Add back the initially subtracted number of seconds */ |
|---|
| 206 | | - secs += get_elapsed_seconds(AB8500_RTC_EPOCH); |
|---|
| 171 | + rtc_time64_to_tm(secs, &alarm->time); |
|---|
| 207 | 172 | |
|---|
| 208 | | - rtc_time_to_tm(secs, &alarm->time); |
|---|
| 209 | | - |
|---|
| 210 | | - return rtc_valid_tm(&alarm->time); |
|---|
| 173 | + return 0; |
|---|
| 211 | 174 | } |
|---|
| 212 | 175 | |
|---|
| 213 | 176 | static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) |
|---|
| .. | .. |
|---|
| 224 | 187 | unsigned long mins, secs = 0, cursec = 0; |
|---|
| 225 | 188 | struct rtc_time curtm; |
|---|
| 226 | 189 | |
|---|
| 227 | | - if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { |
|---|
| 228 | | - dev_dbg(dev, "year should be equal to or greater than %d\n", |
|---|
| 229 | | - AB8500_RTC_EPOCH); |
|---|
| 230 | | - return -EINVAL; |
|---|
| 231 | | - } |
|---|
| 232 | | - |
|---|
| 233 | 190 | /* Get the number of seconds since 1970 */ |
|---|
| 234 | | - rtc_tm_to_time(&alarm->time, &secs); |
|---|
| 191 | + secs = rtc_tm_to_time64(&alarm->time); |
|---|
| 235 | 192 | |
|---|
| 236 | 193 | /* |
|---|
| 237 | 194 | * Check whether alarm is set less than 1min. |
|---|
| .. | .. |
|---|
| 239 | 196 | * return -EINVAL, so UIE EMUL can take it up, incase of UIE_ON |
|---|
| 240 | 197 | */ |
|---|
| 241 | 198 | ab8500_rtc_read_time(dev, &curtm); /* Read current time */ |
|---|
| 242 | | - rtc_tm_to_time(&curtm, &cursec); |
|---|
| 199 | + cursec = rtc_tm_to_time64(&curtm); |
|---|
| 243 | 200 | if ((secs - cursec) < 59) { |
|---|
| 244 | 201 | dev_dbg(dev, "Alarm less than 1 minute not supported\r\n"); |
|---|
| 245 | 202 | return -EINVAL; |
|---|
| 246 | 203 | } |
|---|
| 247 | | - |
|---|
| 248 | | - /* |
|---|
| 249 | | - * Convert it to the number of seconds since 01-01-2000 00:00:00, since |
|---|
| 250 | | - * we only have a small counter in the RTC. |
|---|
| 251 | | - */ |
|---|
| 252 | | - secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); |
|---|
| 253 | 204 | |
|---|
| 254 | 205 | mins = secs / 60; |
|---|
| 255 | 206 | |
|---|
| .. | .. |
|---|
| 360 | 311 | ab8500_sysfs_show_rtc_calibration, |
|---|
| 361 | 312 | ab8500_sysfs_store_rtc_calibration); |
|---|
| 362 | 313 | |
|---|
| 363 | | -static int ab8500_sysfs_rtc_register(struct device *dev) |
|---|
| 364 | | -{ |
|---|
| 365 | | - return device_create_file(dev, &dev_attr_rtc_calibration); |
|---|
| 366 | | -} |
|---|
| 314 | +static struct attribute *ab8500_rtc_attrs[] = { |
|---|
| 315 | + &dev_attr_rtc_calibration.attr, |
|---|
| 316 | + NULL |
|---|
| 317 | +}; |
|---|
| 367 | 318 | |
|---|
| 368 | | -static void ab8500_sysfs_rtc_unregister(struct device *dev) |
|---|
| 369 | | -{ |
|---|
| 370 | | - device_remove_file(dev, &dev_attr_rtc_calibration); |
|---|
| 371 | | -} |
|---|
| 319 | +static const struct attribute_group ab8500_rtc_sysfs_files = { |
|---|
| 320 | + .attrs = ab8500_rtc_attrs, |
|---|
| 321 | +}; |
|---|
| 372 | 322 | |
|---|
| 373 | 323 | static irqreturn_t rtc_alarm_handler(int irq, void *data) |
|---|
| 374 | 324 | { |
|---|
| .. | .. |
|---|
| 429 | 379 | |
|---|
| 430 | 380 | device_init_wakeup(&pdev->dev, true); |
|---|
| 431 | 381 | |
|---|
| 432 | | - rtc = devm_rtc_device_register(&pdev->dev, "ab8500-rtc", |
|---|
| 433 | | - (struct rtc_class_ops *)platid->driver_data, |
|---|
| 434 | | - THIS_MODULE); |
|---|
| 435 | | - if (IS_ERR(rtc)) { |
|---|
| 436 | | - dev_err(&pdev->dev, "Registration failed\n"); |
|---|
| 437 | | - err = PTR_ERR(rtc); |
|---|
| 438 | | - return err; |
|---|
| 439 | | - } |
|---|
| 382 | + rtc = devm_rtc_allocate_device(&pdev->dev); |
|---|
| 383 | + if (IS_ERR(rtc)) |
|---|
| 384 | + return PTR_ERR(rtc); |
|---|
| 385 | + |
|---|
| 386 | + rtc->ops = (struct rtc_class_ops *)platid->driver_data; |
|---|
| 440 | 387 | |
|---|
| 441 | 388 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
|---|
| 442 | 389 | rtc_alarm_handler, IRQF_ONESHOT, |
|---|
| .. | .. |
|---|
| 447 | 394 | dev_pm_set_wake_irq(&pdev->dev, irq); |
|---|
| 448 | 395 | platform_set_drvdata(pdev, rtc); |
|---|
| 449 | 396 | |
|---|
| 450 | | - err = ab8500_sysfs_rtc_register(&pdev->dev); |
|---|
| 451 | | - if (err) { |
|---|
| 452 | | - dev_err(&pdev->dev, "sysfs RTC failed to register\n"); |
|---|
| 453 | | - return err; |
|---|
| 454 | | - } |
|---|
| 455 | | - |
|---|
| 456 | 397 | rtc->uie_unsupported = 1; |
|---|
| 457 | 398 | |
|---|
| 458 | | - return 0; |
|---|
| 399 | + rtc->range_max = (1ULL << 24) * 60 - 1; // 24-bit minutes + 59 secs |
|---|
| 400 | + rtc->start_secs = RTC_TIMESTAMP_BEGIN_2000; |
|---|
| 401 | + rtc->set_start_time = true; |
|---|
| 402 | + |
|---|
| 403 | + err = rtc_add_group(rtc, &ab8500_rtc_sysfs_files); |
|---|
| 404 | + if (err) |
|---|
| 405 | + return err; |
|---|
| 406 | + |
|---|
| 407 | + return rtc_register_device(rtc); |
|---|
| 459 | 408 | } |
|---|
| 460 | 409 | |
|---|
| 461 | 410 | static int ab8500_rtc_remove(struct platform_device *pdev) |
|---|
| 462 | 411 | { |
|---|
| 463 | 412 | dev_pm_clear_wake_irq(&pdev->dev); |
|---|
| 464 | 413 | device_init_wakeup(&pdev->dev, false); |
|---|
| 465 | | - ab8500_sysfs_rtc_unregister(&pdev->dev); |
|---|
| 466 | 414 | |
|---|
| 467 | 415 | return 0; |
|---|
| 468 | 416 | } |
|---|