diff options
Diffstat (limited to 'drivers/rtc/rtc-ds1305.c')
| -rw-r--r-- | drivers/rtc/rtc-ds1305.c | 108 |
1 files changed, 41 insertions, 67 deletions
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 72b22935eb62..d4de401548b4 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * rtc-ds1305.c -- driver for DS1305 and DS1306 SPI RTC chips * * Copyright (C) 2008 David Brownell - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include <linux/kernel.h> #include <linux/init.h> @@ -203,8 +199,7 @@ static int ds1305_get_time(struct device *dev, struct rtc_time *time) time->tm_hour, time->tm_mday, time->tm_mon, time->tm_year, time->tm_wday); - /* Time may not be set */ - return rtc_valid_tm(time); + return 0; } static int ds1305_set_time(struct device *dev, struct rtc_time *time) @@ -330,23 +325,19 @@ static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm) u8 buf[1 + DS1305_ALM_LEN]; /* convert desired alarm to time_t */ - status = rtc_tm_to_time(&alm->time, &later); - if (status < 0) - return status; + later = rtc_tm_to_time64(&alm->time); /* Read current time as time_t */ status = ds1305_get_time(dev, &tm); if (status < 0) return status; - status = rtc_tm_to_time(&tm, &now); - if (status < 0) - return status; + now = rtc_tm_to_time64(&tm); /* make sure alarm fires within the next 24 hours */ if (later <= now) return -EINVAL; - if ((later - now) > 24 * 60 * 60) - return -EDOM; + if ((later - now) > ds1305->rtc->alarm_offset_max) + return -ERANGE; /* disable alarm if needed */ if (ds1305->ctrl[0] & DS1305_AEI0) { @@ -444,13 +435,12 @@ static const struct rtc_class_ops ds1305_ops = { static void ds1305_work(struct work_struct *work) { struct ds1305 *ds1305 = container_of(work, struct ds1305, work); - struct mutex *lock = &ds1305->rtc->ops_lock; struct spi_device *spi = ds1305->spi; u8 buf[3]; int status; /* lock to protect ds1305->ctrl */ - mutex_lock(lock); + rtc_lock(ds1305->rtc); /* Disable the IRQ, and clear its status ... for now, we "know" * that if more than one alarm is active, they're in sync. @@ -468,7 +458,7 @@ static void ds1305_work(struct work_struct *work) if (status < 0) dev_dbg(&spi->dev, "clear irq --> %d\n", status); - mutex_unlock(lock); + rtc_unlock(ds1305->rtc); if (!test_bit(FLAG_EXITING, &ds1305->flags)) enable_irq(spi->irq); @@ -514,58 +504,36 @@ static void msg_init(struct spi_message *m, struct spi_transfer *x, spi_message_add_tail(x, m); } -static ssize_t -ds1305_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int ds1305_nvram_read(void *priv, unsigned int off, void *buf, + size_t count) { - struct spi_device *spi; + struct ds1305 *ds1305 = priv; + struct spi_device *spi = ds1305->spi; u8 addr; struct spi_message m; struct spi_transfer x[2]; - int status; - - spi = to_spi_device(kobj_to_dev(kobj)); addr = DS1305_NVRAM + off; msg_init(&m, x, &addr, count, NULL, buf); - status = spi_sync(spi, &m); - if (status < 0) - dev_err(&spi->dev, "nvram %s error %d\n", "read", status); - return (status < 0) ? status : count; + return spi_sync(spi, &m); } -static ssize_t -ds1305_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int ds1305_nvram_write(void *priv, unsigned int off, void *buf, + size_t count) { - struct spi_device *spi; + struct ds1305 *ds1305 = priv; + struct spi_device *spi = ds1305->spi; u8 addr; struct spi_message m; struct spi_transfer x[2]; - int status; - - spi = to_spi_device(kobj_to_dev(kobj)); addr = (DS1305_WRITE | DS1305_NVRAM) + off; msg_init(&m, x, &addr, count, buf, NULL); - status = spi_sync(spi, &m); - if (status < 0) - dev_err(&spi->dev, "nvram %s error %d\n", "write", status); - return (status < 0) ? status : count; + return spi_sync(spi, &m); } -static struct bin_attribute nvram = { - .attr.name = "nvram", - .attr.mode = S_IRUGO | S_IWUSR, - .read = ds1305_nvram_read, - .write = ds1305_nvram_write, - .size = DS1305_NVRAM_LEN, -}; - /*----------------------------------------------------------------------*/ /* @@ -579,6 +547,14 @@ static int ds1305_probe(struct spi_device *spi) u8 addr, value; struct ds1305_platform_data *pdata = dev_get_platdata(&spi->dev); bool write_ctrl = false; + struct nvmem_config ds1305_nvmem_cfg = { + .name = "ds1305_nvram", + .word_size = 1, + .stride = 1, + .size = DS1305_NVRAM_LEN, + .reg_read = ds1305_nvram_read, + .reg_write = ds1305_nvram_write, + }; /* Sanity check board setup data. This may be hooked up * in 3wire mode, but we don't care. Note that unless @@ -708,13 +684,21 @@ static int ds1305_probe(struct spi_device *spi) dev_dbg(&spi->dev, "AM/PM\n"); /* register RTC ... from here on, ds1305->ctrl needs locking */ - ds1305->rtc = devm_rtc_device_register(&spi->dev, "ds1305", - &ds1305_ops, THIS_MODULE); - if (IS_ERR(ds1305->rtc)) { - status = PTR_ERR(ds1305->rtc); - dev_dbg(&spi->dev, "register rtc --> %d\n", status); + ds1305->rtc = devm_rtc_allocate_device(&spi->dev); + if (IS_ERR(ds1305->rtc)) + return PTR_ERR(ds1305->rtc); + + ds1305->rtc->ops = &ds1305_ops; + ds1305->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + ds1305->rtc->range_max = RTC_TIMESTAMP_END_2099; + ds1305->rtc->alarm_offset_max = 24 * 60 * 60; + + ds1305_nvmem_cfg.priv = ds1305; + status = devm_rtc_register_device(ds1305->rtc); + if (status) return status; - } + + devm_rtc_nvmem_register(ds1305->rtc, &ds1305_nvmem_cfg); /* Maybe set up alarm IRQ; be ready to handle it triggering right * away. NOTE that we don't share this. The signal is active low, @@ -734,29 +718,19 @@ static int ds1305_probe(struct spi_device *spi) } } - /* export NVRAM */ - status = sysfs_create_bin_file(&spi->dev.kobj, &nvram); - if (status < 0) { - dev_err(&spi->dev, "register nvram --> %d\n", status); - } - return 0; } -static int ds1305_remove(struct spi_device *spi) +static void ds1305_remove(struct spi_device *spi) { struct ds1305 *ds1305 = spi_get_drvdata(spi); - sysfs_remove_bin_file(&spi->dev.kobj, &nvram); - /* carefully shut down irq and workqueue, if present */ if (spi->irq) { set_bit(FLAG_EXITING, &ds1305->flags); devm_free_irq(&spi->dev, spi->irq, ds1305); cancel_work_sync(&ds1305->work); } - - return 0; } static struct spi_driver ds1305_driver = { |
