diff options
Diffstat (limited to 'drivers/rtc/rtc-ab8500.c')
| -rw-r--r-- | drivers/rtc/rtc-ab8500.c | 196 |
1 files changed, 36 insertions, 160 deletions
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 727e2f5d14d9..ed2b6b8bb3bf 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -1,7 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) ST-Ericsson SA 2010 * - * License terms: GNU General Public License (GPL) version 2 * Author: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com> * * RTC clock driver for the RTC part of the AB8500 Power management chip. @@ -18,6 +18,7 @@ #include <linux/mfd/abx500/ab8500.h> #include <linux/delay.h> #include <linux/of.h> +#include <linux/pm_wakeirq.h> #define AB8500_RTC_SOFF_STAT_REG 0x00 #define AB8500_RTC_CC_CONF_REG 0x01 @@ -35,10 +36,6 @@ #define AB8500_RTC_FORCE_BKUP_REG 0x0D #define AB8500_RTC_CALIB_REG 0x0E #define AB8500_RTC_SWITCH_STAT_REG 0x0F -#define AB8540_RTC_ALRM_SEC 0x22 -#define AB8540_RTC_ALRM_MIN_LOW_REG 0x23 -#define AB8540_RTC_ALRM_MIN_MID_REG 0x24 -#define AB8540_RTC_ALRM_MIN_HI_REG 0x25 /* RtcReadRequest bits */ #define RTC_READ_REQUEST 0x01 @@ -49,7 +46,6 @@ #define RTC_STATUS_DATA 0x01 #define COUNTS_PER_SEC (0xF000 / 60) -#define AB8500_RTC_EPOCH 2000 static const u8 ab8500_rtc_time_regs[] = { AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, @@ -62,28 +58,6 @@ static const u8 ab8500_rtc_alarm_regs[] = { AB8500_RTC_ALRM_MIN_LOW_REG }; -static const u8 ab8540_rtc_alarm_regs[] = { - AB8540_RTC_ALRM_MIN_HI_REG, AB8540_RTC_ALRM_MIN_MID_REG, - AB8540_RTC_ALRM_MIN_LOW_REG, AB8540_RTC_ALRM_SEC -}; - -/* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */ -static unsigned long get_elapsed_seconds(int year) -{ - unsigned long secs; - struct rtc_time tm = { - .tm_year = year - 1900, - .tm_mday = 1, - }; - - /* - * This function calculates secs from 1970 and not from - * 1900, even if we supply the offset from year 1900. - */ - rtc_tm_to_time(&tm, &secs); - return secs; -} - static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) { unsigned long timeout = jiffies + HZ; @@ -126,11 +100,8 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) secs = secs / COUNTS_PER_SEC; secs = secs + (mins * 60); - /* Add back the initially subtracted number of seconds */ - secs += get_elapsed_seconds(AB8500_RTC_EPOCH); - - rtc_time_to_tm(secs, tm); - return rtc_valid_tm(tm); + rtc_time64_to_tm(secs, tm); + return 0; } static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) @@ -139,20 +110,7 @@ static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; unsigned long no_secs, no_mins, secs = 0; - if (tm->tm_year < (AB8500_RTC_EPOCH - 1900)) { - dev_dbg(dev, "year should be equal to or greater than %d\n", - AB8500_RTC_EPOCH); - return -EINVAL; - } - - /* Get the number of seconds since 1970 */ - rtc_tm_to_time(tm, &secs); - - /* - * Convert it to the number of seconds since 01-01-2000 00:00:00, since - * we only have a small counter in the RTC. - */ - secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); + secs = rtc_tm_to_time64(tm); no_mins = secs / 60; @@ -210,12 +168,9 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); secs = mins * 60; - /* Add back the initially subtracted number of seconds */ - secs += get_elapsed_seconds(AB8500_RTC_EPOCH); - - rtc_time_to_tm(secs, &alarm->time); + rtc_time64_to_tm(secs, &alarm->time); - return rtc_valid_tm(&alarm->time); + return 0; } static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) @@ -229,37 +184,9 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) { int retval, i; unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; - unsigned long mins, secs = 0, cursec = 0; - struct rtc_time curtm; - - if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { - dev_dbg(dev, "year should be equal to or greater than %d\n", - AB8500_RTC_EPOCH); - return -EINVAL; - } - - /* Get the number of seconds since 1970 */ - rtc_tm_to_time(&alarm->time, &secs); - - /* - * Check whether alarm is set less than 1min. - * Since our RTC doesn't support alarm resolution less than 1min, - * return -EINVAL, so UIE EMUL can take it up, incase of UIE_ON - */ - ab8500_rtc_read_time(dev, &curtm); /* Read current time */ - rtc_tm_to_time(&curtm, &cursec); - if ((secs - cursec) < 59) { - dev_dbg(dev, "Alarm less than 1 minute not supported\r\n"); - return -EINVAL; - } + unsigned long mins; - /* - * Convert it to the number of seconds since 01-01-2000 00:00:00, since - * we only have a small counter in the RTC. - */ - secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); - - mins = secs / 60; + mins = (unsigned long)rtc_tm_to_time64(&alarm->time) / 60; buf[2] = mins & 0xFF; buf[1] = (mins >> 8) & 0xFF; @@ -276,43 +203,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) return ab8500_rtc_irq_enable(dev, alarm->enabled); } -static int ab8540_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - int retval, i; - unsigned char buf[ARRAY_SIZE(ab8540_rtc_alarm_regs)]; - unsigned long mins, secs = 0; - - if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { - dev_dbg(dev, "year should be equal to or greater than %d\n", - AB8500_RTC_EPOCH); - return -EINVAL; - } - - /* Get the number of seconds since 1970 */ - rtc_tm_to_time(&alarm->time, &secs); - - /* - * Convert it to the number of seconds since 01-01-2000 00:00:00 - */ - secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); - mins = secs / 60; - - buf[3] = secs % 60; - buf[2] = mins & 0xFF; - buf[1] = (mins >> 8) & 0xFF; - buf[0] = (mins >> 16) & 0xFF; - - /* Set the alarm time */ - for (i = 0; i < ARRAY_SIZE(ab8540_rtc_alarm_regs); i++) { - retval = abx500_set_register_interruptible(dev, AB8500_RTC, - ab8540_rtc_alarm_regs[i], buf[i]); - if (retval < 0) - return retval; - } - - return ab8500_rtc_irq_enable(dev, alarm->enabled); -} - static int ab8500_rtc_set_calibration(struct device *dev, int calibration) { int retval; @@ -405,15 +295,14 @@ static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR, ab8500_sysfs_show_rtc_calibration, ab8500_sysfs_store_rtc_calibration); -static int ab8500_sysfs_rtc_register(struct device *dev) -{ - return device_create_file(dev, &dev_attr_rtc_calibration); -} +static struct attribute *ab8500_rtc_attrs[] = { + &dev_attr_rtc_calibration.attr, + NULL +}; -static void ab8500_sysfs_rtc_unregister(struct device *dev) -{ - device_remove_file(dev, &dev_attr_rtc_calibration); -} +static const struct attribute_group ab8500_rtc_sysfs_files = { + .attrs = ab8500_rtc_attrs, +}; static irqreturn_t rtc_alarm_handler(int irq, void *data) { @@ -434,18 +323,11 @@ static const struct rtc_class_ops ab8500_rtc_ops = { .alarm_irq_enable = ab8500_rtc_irq_enable, }; -static const struct rtc_class_ops ab8540_rtc_ops = { - .read_time = ab8500_rtc_read_time, - .set_time = ab8500_rtc_set_time, - .read_alarm = ab8500_rtc_read_alarm, - .set_alarm = ab8540_rtc_set_alarm, - .alarm_irq_enable = ab8500_rtc_irq_enable, -}; - -static struct platform_device_id ab85xx_rtc_ids[] = { +static const struct platform_device_id ab85xx_rtc_ids[] = { { "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, }, - { "ab8540-rtc", (kernel_ulong_t)&ab8540_rtc_ops, }, + { /* sentinel */ } }; +MODULE_DEVICE_TABLE(platform, ab85xx_rtc_ids); static int ab8500_rtc_probe(struct platform_device *pdev) { @@ -479,48 +361,42 @@ static int ab8500_rtc_probe(struct platform_device *pdev) return -ENODEV; } - device_init_wakeup(&pdev->dev, true); + devm_device_init_wakeup(&pdev->dev); - rtc = devm_rtc_device_register(&pdev->dev, "ab8500-rtc", - (struct rtc_class_ops *)platid->driver_data, - THIS_MODULE); - if (IS_ERR(rtc)) { - dev_err(&pdev->dev, "Registration failed\n"); - err = PTR_ERR(rtc); - return err; - } + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + rtc->ops = (struct rtc_class_ops *)platid->driver_data; err = devm_request_threaded_irq(&pdev->dev, irq, NULL, - rtc_alarm_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT, + rtc_alarm_handler, IRQF_ONESHOT, "ab8500-rtc", rtc); if (err < 0) return err; + devm_pm_set_wake_irq(&pdev->dev, irq); platform_set_drvdata(pdev, rtc); - err = ab8500_sysfs_rtc_register(&pdev->dev); - if (err) { - dev_err(&pdev->dev, "sysfs RTC failed to register\n"); - return err; - } + set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features); + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features); - return 0; -} + rtc->range_max = (1ULL << 24) * 60 - 1; // 24-bit minutes + 59 secs + rtc->start_secs = RTC_TIMESTAMP_BEGIN_2000; + rtc->set_start_time = true; -static int ab8500_rtc_remove(struct platform_device *pdev) -{ - ab8500_sysfs_rtc_unregister(&pdev->dev); + err = rtc_add_group(rtc, &ab8500_rtc_sysfs_files); + if (err) + return err; - return 0; + return devm_rtc_register_device(rtc); } static struct platform_driver ab8500_rtc_driver = { .driver = { .name = "ab8500-rtc", - .owner = THIS_MODULE, }, .probe = ab8500_rtc_probe, - .remove = ab8500_rtc_remove, .id_table = ab85xx_rtc_ids, }; |
