diff options
Diffstat (limited to 'drivers/rtc')
62 files changed, 1112 insertions, 650 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5c0790eed656..e72f65b61176 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -374,11 +374,11 @@ config RTC_DRV_MAX77686 will be called rtc-max77686. config RTC_DRV_RK808 - tristate "Rockchip RK805/RK808/RK818 RTC" + tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC" depends on MFD_RK808 help If you say yes here you will get support for the - RTC of RK805, RK808 and RK818 PMIC. + RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC. This driver can also be built as a module. If so, the module will be called rk808-rtc. @@ -498,6 +498,14 @@ config RTC_DRV_M41T80_WDT help If you say Y here you will get support for the watchdog timer in the ST M41T60 and M41T80 RTC chips series. +config RTC_DRV_BD70528 + tristate "ROHM BD70528 PMIC RTC" + help + If you say Y here you will get support for the RTC + on ROHM BD70528 Power Management IC. + + This driver can also be built as a module. If so, the module + will be called rtc-bd70528. config RTC_DRV_BQ32K tristate "TI BQ32000" @@ -554,7 +562,7 @@ config RTC_DRV_TPS6586X config RTC_DRV_TPS65910 tristate "TI TPS65910 RTC driver" - depends on RTC_CLASS && MFD_TPS65910 + depends on MFD_TPS65910 help If you say yes here you get support for the RTC on the TPS65910 chips. @@ -812,6 +820,7 @@ config RTC_DRV_MAX6902 config RTC_DRV_PCF2123 tristate "NXP PCF2123" + select REGMAP_SPI help If you say yes here you get support for the NXP PCF2123 RTC chip. diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 9d997faa2c26..6b09c21dc1b6 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_RTC_DRV_ASPEED) += rtc-aspeed.o obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o +obj-$(CONFIG_RTC_DRV_BD70528) += rtc-bd70528.o obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o obj-$(CONFIG_RTC_DRV_BRCMSTB) += rtc-brcmstb-waketimer.o diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 4124f4dd376b..72b7ddc43116 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -633,7 +633,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer) { struct rtc_device *rtc; ktime_t period; - int count; + u64 count; rtc = container_of(timer, struct rtc_device, pie_timer); diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 73697e4b18a9..434285f495e0 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Real Time Clock driver for Marvell 88PM860x PMIC * * Copyright (c) 2010 Marvell International Ltd. * Author: Haojian Zhuang <haojian.zhuang@marvell.com> - * - * 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> diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c new file mode 100644 index 000000000000..f9bdd555e1a2 --- /dev/null +++ b/drivers/rtc/rtc-bd70528.c @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// Copyright (C) 2018 ROHM Semiconductors +// +// RTC driver for ROHM BD70528 PMIC + +#include <linux/bcd.h> +#include <linux/mfd/rohm-bd70528.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/rtc.h> + +/* + * We read regs RTC_SEC => RTC_YEAR + * this struct is ordered according to chip registers. + * Keep it u8 only to avoid padding issues. + */ +struct bd70528_rtc_day { + u8 sec; + u8 min; + u8 hour; +} __packed; + +struct bd70528_rtc_data { + struct bd70528_rtc_day time; + u8 week; + u8 day; + u8 month; + u8 year; +} __packed; + +struct bd70528_rtc_wake { + struct bd70528_rtc_day time; + u8 ctrl; +} __packed; + +struct bd70528_rtc_alm { + struct bd70528_rtc_data data; + u8 alm_mask; + u8 alm_repeat; +} __packed; + +struct bd70528_rtc { + struct rohm_regmap_dev *mfd; + struct device *dev; +}; + +static int bd70528_set_wake(struct rohm_regmap_dev *bd70528, + int enable, int *old_state) +{ + int ret; + unsigned int ctrl_reg; + + ret = regmap_read(bd70528->regmap, BD70528_REG_WAKE_EN, &ctrl_reg); + if (ret) + return ret; + + if (old_state) { + if (ctrl_reg & BD70528_MASK_WAKE_EN) + *old_state |= BD70528_WAKE_STATE_BIT; + else + *old_state &= ~BD70528_WAKE_STATE_BIT; + + if (!enable == !(*old_state & BD70528_WAKE_STATE_BIT)) + return 0; + } + + if (enable) + ctrl_reg |= BD70528_MASK_WAKE_EN; + else + ctrl_reg &= ~BD70528_MASK_WAKE_EN; + + return regmap_write(bd70528->regmap, BD70528_REG_WAKE_EN, + ctrl_reg); +} + +static int bd70528_set_elapsed_tmr(struct rohm_regmap_dev *bd70528, + int enable, int *old_state) +{ + int ret; + unsigned int ctrl_reg; + + /* + * TBD + * What is the purpose of elapsed timer ? + * Is the timeout registers counting down, or is the disable - re-enable + * going to restart the elapsed-time counting? If counting is restarted + * the timeout should be decreased by the amount of time that has + * elapsed since starting the timer. Maybe we should store the monotonic + * clock value when timer is started so that if RTC is set while timer + * is armed we could do the compensation. This is a hack if RTC/system + * clk are drifting. OTOH, RTC controlled via I2C is in any case + * inaccurate... + */ + ret = regmap_read(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN, + &ctrl_reg); + if (ret) + return ret; + + if (old_state) { + if (ctrl_reg & BD70528_MASK_ELAPSED_TIMER_EN) + *old_state |= BD70528_ELAPSED_STATE_BIT; + else + *old_state &= ~BD70528_ELAPSED_STATE_BIT; + + if ((!enable) == (!(*old_state & BD70528_ELAPSED_STATE_BIT))) + return 0; + } + + if (enable) + ctrl_reg |= BD70528_MASK_ELAPSED_TIMER_EN; + else + ctrl_reg &= ~BD70528_MASK_ELAPSED_TIMER_EN; + + return regmap_write(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN, + ctrl_reg); +} + +static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state, + int *old_state) +{ + int ret; + + ret = bd70528_wdt_set(r->mfd, new_state & BD70528_WDT_STATE_BIT, + old_state); + if (ret) { + dev_err(r->dev, + "Failed to disable WDG for RTC setting (%d)\n", ret); + return ret; + } + ret = bd70528_set_elapsed_tmr(r->mfd, + new_state & BD70528_ELAPSED_STATE_BIT, + old_state); + if (ret) { + dev_err(r->dev, + "Failed to disable 'elapsed timer' for RTC setting\n"); + return ret; + } + ret = bd70528_set_wake(r->mfd, new_state & BD70528_WAKE_STATE_BIT, + old_state); + if (ret) { + dev_err(r->dev, + "Failed to disable 'wake timer' for RTC setting\n"); + return ret; + } + + return ret; +} + +static int bd70528_re_enable_rtc_based_timers(struct bd70528_rtc *r, + int old_state) +{ + return bd70528_set_rtc_based_timers(r, old_state, NULL); +} + +static int bd70528_disable_rtc_based_timers(struct bd70528_rtc *r, + int *old_state) +{ + return bd70528_set_rtc_based_timers(r, 0, old_state); +} + +static inline void tmday2rtc(struct rtc_time *t, struct bd70528_rtc_day *d) +{ + d->sec &= ~BD70528_MASK_RTC_SEC; + d->min &= ~BD70528_MASK_RTC_MINUTE; + d->hour &= ~BD70528_MASK_RTC_HOUR; + d->sec |= bin2bcd(t->tm_sec); + d->min |= bin2bcd(t->tm_min); + d->hour |= bin2bcd(t->tm_hour); +} + +static inline void tm2rtc(struct rtc_time *t, struct bd70528_rtc_data *r) +{ + r->day &= ~BD70528_MASK_RTC_DAY; + r->week &= ~BD70528_MASK_RTC_WEEK; + r->month &= ~BD70528_MASK_RTC_MONTH; + /* + * PM and 24H bits are not used by Wake - thus we clear them + * here and not in tmday2rtc() which is also used by wake. + */ + r->time.hour &= ~(BD70528_MASK_RTC_HOUR_PM | BD70528_MASK_RTC_HOUR_24H); + + tmday2rtc(t, &r->time); + /* + * We do always set time in 24H mode. + */ + r->time.hour |= BD70528_MASK_RTC_HOUR_24H; + r->day |= bin2bcd(t->tm_mday); + r->week |= bin2bcd(t->tm_wday); + r->month |= bin2bcd(t->tm_mon + 1); + r->year = bin2bcd(t->tm_year - 100); +} + +static inline void rtc2tm(struct bd70528_rtc_data *r, struct rtc_time *t) +{ + t->tm_sec = bcd2bin(r->time.sec & BD70528_MASK_RTC_SEC); + t->tm_min = bcd2bin(r->time.min & BD70528_MASK_RTC_MINUTE); + t->tm_hour = bcd2bin(r->time.hour & BD70528_MASK_RTC_HOUR); + /* + * If RTC is in 12H mode, then bit BD70528_MASK_RTC_HOUR_PM + * is not BCD value but tells whether it is AM or PM + */ + if (!(r->time.hour & BD70528_MASK_RTC_HOUR_24H)) { + t->tm_hour %= 12; + if (r->time.hour & BD70528_MASK_RTC_HOUR_PM) + t->tm_hour += 12; + } + t->tm_mday = bcd2bin(r->day & BD70528_MASK_RTC_DAY); + t->tm_mon = bcd2bin(r->month & BD70528_MASK_RTC_MONTH) - 1; + t->tm_year = 100 + bcd2bin(r->year & BD70528_MASK_RTC_YEAR); + t->tm_wday = bcd2bin(r->week & BD70528_MASK_RTC_WEEK); +} + +static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a) +{ + struct bd70528_rtc_wake wake; + struct bd70528_rtc_alm alm; + int ret; + struct bd70528_rtc *r = dev_get_drvdata(dev); + struct rohm_regmap_dev *bd70528 = r->mfd; + + ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_WAKE_START, + &wake, sizeof(wake)); + if (ret) { + dev_err(dev, "Failed to read wake regs\n"); + return ret; + } + + ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START, + &alm, sizeof(alm)); + if (ret) { + dev_err(dev, "Failed to read alarm regs\n"); + return ret; + } + + tm2rtc(&a->time, &alm.data); + tmday2rtc(&a->time, &wake.time); + + if (a->enabled) { + alm.alm_mask &= ~BD70528_MASK_ALM_EN; + wake.ctrl |= BD70528_MASK_WAKE_EN; + } else { + alm.alm_mask |= BD70528_MASK_ALM_EN; + wake.ctrl &= ~BD70528_MASK_WAKE_EN; + } + + ret = regmap_bulk_write(bd70528->regmap, + BD70528_REG_RTC_WAKE_START, &wake, + sizeof(wake)); + if (ret) { + dev_err(dev, "Failed to set wake time\n"); + return ret; + } + ret = regmap_bulk_write(bd70528->regmap, BD70528_REG_RTC_ALM_START, + &alm, sizeof(alm)); + if (ret) + dev_err(dev, "Failed to set alarm time\n"); + + return ret; +} + +static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a) +{ + struct bd70528_rtc_alm alm; + int ret; + struct bd70528_rtc *r = dev_get_drvdata(dev); + struct rohm_regmap_dev *bd70528 = r->mfd; + + ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START, + &alm, sizeof(alm)); + if (ret) { + dev_err(dev, "Failed to read alarm regs\n"); + return ret; + } + + rtc2tm(&alm.data, &a->time); + a->time.tm_mday = -1; + a->time.tm_mon = -1; + a->time.tm_year = -1; + a->enabled = !(alm.alm_mask & BD70528_MASK_ALM_EN); + a->pending = 0; + + return 0; +} + +static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t) +{ + int ret, tmpret, old_states; + struct bd70528_rtc_data rtc_data; + struct bd70528_rtc *r = dev_get_drvdata(dev); + struct rohm_regmap_dev *bd70528 = r->mfd; + + ret = bd70528_disable_rtc_based_timers(r, &old_states); + if (ret) + return ret; + + tmpret = regmap_bulk_read(bd70528->regmap, + BD70528_REG_RTC_START, &rtc_data, + sizeof(rtc_data)); + if (tmpret) { + dev_err(dev, "Failed to read RTC time registers\n"); + goto renable_out; + } + tm2rtc(t, &rtc_data); + + tmpret = regmap_bulk_write(bd70528->regmap, + BD70528_REG_RTC_START, &rtc_data, + sizeof(rtc_data)); + if (tmpret) { + dev_err(dev, "Failed to set RTC time\n"); + goto renable_out; + } + +renable_out: + ret = bd70528_re_enable_rtc_based_timers(r, old_states); + if (tmpret) + ret = tmpret; + + return ret; +} + +static int bd70528_set_time(struct device *dev, struct rtc_time *t) +{ + int ret; + struct bd70528_rtc *r = dev_get_drvdata(dev); + + bd70528_wdt_lock(r->mfd); + ret = bd70528_set_time_locked(dev, t); + bd70528_wdt_unlock(r->mfd); + return ret; +} + +static int bd70528_get_time(struct device *dev, struct rtc_time *t) +{ + struct bd70528_rtc *r = dev_get_drvdata(dev); + struct rohm_regmap_dev *bd70528 = r->mfd; + struct bd70528_rtc_data rtc_data; + int ret; + + /* read the RTC date and time registers all at once */ + ret = regmap_bulk_read(bd70528->regmap, + BD70528_REG_RTC_START, &rtc_data, + sizeof(rtc_data)); + if (ret) { + dev_err(dev, "Failed to read RTC time (err %d)\n", ret); + return ret; + } + + rtc2tm(&rtc_data, t); + + return 0; +} + +static int bd70528_alm_enable(struct device *dev, unsigned int enabled) +{ + int ret; + unsigned int enableval = BD70528_MASK_ALM_EN; + struct bd70528_rtc *r = dev_get_drvdata(dev); + + if (enabled) + enableval = 0; + + bd70528_wdt_lock(r->mfd); + ret = bd70528_set_wake(r->mfd, enabled, NULL); + if (ret) { + dev_err(dev, "Failed to change wake state\n"); + goto out_unlock; + } + ret = regmap_update_bits(r->mfd->regmap, BD70528_REG_RTC_ALM_MASK, + BD70528_MASK_ALM_EN, enableval); + if (ret) + dev_err(dev, "Failed to change alarm state\n"); + +out_unlock: + bd70528_wdt_unlock(r->mfd); + return ret; +} + +static const struct rtc_class_ops bd70528_rtc_ops = { + .read_time = bd70528_get_time, + .set_time = bd70528_set_time, + .read_alarm = bd70528_read_alarm, + .set_alarm = bd70528_set_alarm, + .alarm_irq_enable = bd70528_alm_enable, +}; + +static irqreturn_t alm_hndlr(int irq, void *data) +{ + struct rtc_device *rtc = data; + + rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF | RTC_PF); + return IRQ_HANDLED; +} + +static int bd70528_probe(struct platform_device *pdev) +{ + struct bd70528_rtc *bd_rtc; + struct rohm_regmap_dev *mfd; + int ret; + struct rtc_device *rtc; + int irq; + unsigned int hr; + + mfd = dev_get_drvdata(pdev->dev.parent); + if (!mfd) { + dev_err(&pdev->dev, "No MFD driver data\n"); + return -EINVAL; + } + bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL); + if (!bd_rtc) + return -ENOMEM; + + bd_rtc->mfd = mfd; + bd_rtc->dev = &pdev->dev; + + irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm"); + + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get irq\n"); + return irq; + } + + platform_set_drvdata(pdev, bd_rtc); + + ret = regmap_read(mfd->regmap, BD70528_REG_RTC_HOUR, &hr); + + if (ret) { + dev_err(&pdev->dev, "Failed to reag RTC clock\n"); + return ret; + } + + if (!(hr & BD70528_MASK_RTC_HOUR_24H)) { + struct rtc_time t; + + ret = bd70528_get_time(&pdev->dev, &t); + + if (!ret) + ret = bd70528_set_time(&pdev->dev, &t); + + if (ret) { + dev_err(&pdev->dev, + "Setting 24H clock for RTC failed\n"); + return ret; + } + } + + device_set_wakeup_capable(&pdev->dev, true); + device_wakeup_enable(&pdev->dev); + + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) { + dev_err(&pdev->dev, "RTC device creation failed\n"); + return PTR_ERR(rtc); + } + + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->ops = &bd70528_rtc_ops; + + /* Request alarm IRQ prior to registerig the RTC */ + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, &alm_hndlr, + IRQF_ONESHOT, "bd70528-rtc", rtc); + if (ret) + return ret; + + /* + * BD70528 irq controller is not touching the main mask register. + * So enable the RTC block interrupts at main level. We can just + * leave them enabled as irq-controller should disable irqs + * from sub-registers when IRQ is disabled or freed. + */ + ret = regmap_update_bits(mfd->regmap, + BD70528_REG_INT_MAIN_MASK, + BD70528_INT_RTC_MASK, 0); + if (ret) { + dev_err(&pdev->dev, "Failed to enable RTC interrupts\n"); + return ret; + } + + ret = rtc_register_device(rtc); + if (ret) + dev_err(&pdev->dev, "Registering RTC failed\n"); + + return ret; +} + +static struct platform_driver bd70528_rtc = { + .driver = { + .name = "bd70528-rtc" + }, + .probe = bd70528_probe, +}; + +module_platform_driver(bd70528_rtc); + +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); +MODULE_DESCRIPTION("BD70528 RTC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index ef52741000a8..4a63f0cd2321 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Driver for TI BQ32000 RTC. * * Copyright (C) 2009 Semihalf. * Copyright (C) 2014 Pavel Machek <pavel@denx.de> * - * 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. - * * You can get hardware description at * http://www.ti.com/lit/ds/symlink/bq32000.pdf */ diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 2d502fc85698..e04d6e862c42 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> diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 07530fe1da2a..1f7e8aefc1eb 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips. * @@ -5,10 +6,6 @@ * Copyright (C) 2006 David Brownell * Copyright (C) 2009 Matthias Fuchs (rx8025 support) * Copyright (C) 2012 Bertrand Achard (nvram access fixes) - * - * 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/acpi.h> @@ -225,6 +222,45 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) return -EINVAL; } + tmp = regs[DS1307_REG_SECS]; + switch (ds1307->type) { + case ds_1307: + case m41t0: + case m41t00: + case m41t11: + if (tmp & DS1307_BIT_CH) + return -EINVAL; + break; + case ds_1308: + case ds_1338: + if (tmp & DS1307_BIT_CH) + return -EINVAL; + + ret = regmap_read(ds1307->regmap, DS1307_REG_CONTROL, &tmp); + if (ret) + return ret; + if (tmp & DS1338_BIT_OSF) + return -EINVAL; + break; + case ds_1340: + if (tmp & DS1340_BIT_nEOSC) + return -EINVAL; + + ret = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp); + if (ret) + return ret; + if (tmp & DS1340_BIT_OSF) + return -EINVAL; + break; + case mcp794xx: + if (!(tmp & MCP794XX_BIT_ST)) + return -EINVAL; + + break; + default: + break; + } + t->tm_sec = bcd2bin(regs[DS1307_REG_SECS] & 0x7f); t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f); tmp = regs[DS1307_REG_HOUR] & 0x3f; @@ -289,7 +325,17 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) if (t->tm_year > 199 && chip->century_bit) regs[chip->century_reg] |= chip->century_bit; - if (ds1307->type == mcp794xx) { + switch (ds1307->type) { + case ds_1308: + case ds_1338: + regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL, + DS1338_BIT_OSF, 0); + break; + case ds_1340: + regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG, + DS1340_BIT_OSF, 0); + break; + case mcp794xx: /* * these bits were cleared when preparing the date/time * values and need to be set again before writing the @@ -297,6 +343,9 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) */ regs[DS1307_REG_SECS] |= MCP794XX_BIT_ST; regs[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN; + break; + default: + break; } dev_dbg(dev, "%s: %7ph\n", "write", regs); @@ -1705,7 +1754,6 @@ static int ds1307_probe(struct i2c_client *client, break; } -read_rtc: /* read RTC registers */ err = regmap_bulk_read(ds1307->regmap, chip->offset, regs, sizeof(regs)); @@ -1714,75 +1762,11 @@ read_rtc: goto exit; } - /* - * minimal sanity checking; some chips (like DS1340) don't - * specify the extra bits as must-be-zero, but there are - * still a few values that are clearly out-of-range. - */ - tmp = regs[DS1307_REG_SECS]; - switch (ds1307->type) { - case ds_1307: - case m41t0: - case m41t00: - case m41t11: - /* clock halted? turn it on, so clock can tick. */ - if (tmp & DS1307_BIT_CH) { - regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); - dev_warn(ds1307->dev, "SET TIME!\n"); - goto read_rtc; - } - break; - case ds_1308: - case ds_1338: - /* clock halted? turn it on, so clock can tick. */ - if (tmp & DS1307_BIT_CH) - regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); - - /* oscillator fault? clear flag, and warn */ - if (regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) { - regmap_write(ds1307->regmap, DS1307_REG_CONTROL, - regs[DS1307_REG_CONTROL] & - ~DS1338_BIT_OSF); - dev_warn(ds1307->dev, "SET TIME!\n"); - goto read_rtc; - } - break; - case ds_1340: - /* clock halted? turn it on, so clock can tick. */ - if (tmp & DS1340_BIT_nEOSC) - regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); - - err = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp); - if (err) { - dev_dbg(ds1307->dev, "read error %d\n", err); - goto exit; - } - - /* oscillator fault? clear flag, and warn */ - if (tmp & DS1340_BIT_OSF) { - regmap_write(ds1307->regmap, DS1340_REG_FLAG, 0); - dev_warn(ds1307->dev, "SET TIME!\n"); - } - break; - case mcp794xx: - /* make sure that the backup battery is enabled */ - if (!(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) { - regmap_write(ds1307->regmap, DS1307_REG_WDAY, - regs[DS1307_REG_WDAY] | - MCP794XX_BIT_VBATEN); - } - - /* clock halted? turn it on, so clock can tick. */ - if (!(tmp & MCP794XX_BIT_ST)) { - regmap_write(ds1307->regmap, DS1307_REG_SECS, - MCP794XX_BIT_ST); - dev_warn(ds1307->dev, "SET TIME!\n"); - goto read_rtc; - } - - break; - default: - break; + if (ds1307->type == mcp794xx && + !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) { + regmap_write(ds1307->regmap, DS1307_REG_WDAY, + regs[DS1307_REG_WDAY] | + MCP794XX_BIT_VBATEN); } tmp = regs[DS1307_REG_HOUR]; diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index 5208da4cf94a..fa6de31d5793 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* rtc-ds1343.c * * Driver for Dallas Semiconductor DS1343 Low Current, SPI Compatible @@ -5,11 +6,6 @@ * * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com> * Ankur Srivastava <sankurece@gmail.com> : DS1343 Nvram Support - * - * 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/init.h> diff --git a/drivers/rtc/rtc-ds1347.c b/drivers/rtc/rtc-ds1347.c index 938512c676ee..d392a7bfdd1c 100644 --- a/drivers/rtc/rtc-ds1347.c +++ b/drivers/rtc/rtc-ds1347.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* rtc-ds1347.c * * Driver for Dallas Semiconductor DS1347 Low Current, SPI Compatible * Real Time Clock * * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com> - * - * 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/init.h> diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index 3b095401f848..66fc8617d07e 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * rtc-ds1390.c -- driver for the Dallas/Maxim DS1390/93/94 SPI RTC * * Copyright (C) 2008 Mercury IMC Ltd * Written by Mark Jackson <mpfj@mimc.co.uk> * - * 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. - * * NOTE: Currently this driver only supports the bare minimum for read * and write the RTC. The extra features provided by the chip family * (alarms, trickle charger, different control registers) are unavailable. diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index b8b6e51c0461..b6a477519280 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An rtc driver for the Dallas DS1511 * * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> * Copyright (C) 2007 Andrew Sharp <andy.sharp@lsi.com> * - * 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. - * * Real time clock driver for the Dallas 1511 chip, which also * contains a watchdog timer. There is a tiny amount of code that * platform code could use to mess with the watchdog device a little diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 34af7a802f43..219d6b520a69 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An rtc driver for the Dallas DS1553 * * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> - * - * 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/bcd.h> diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 5f4328524183..184e4a3e2bef 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An rtc driver for the Dallas/Maxim DS1685/DS1687 and related real-time * chips. @@ -10,10 +11,6 @@ * DS17x85/DS17x87 3V/5V Real-Time Clocks, 19-5222, Rev 4/10. * DS1689/DS1693 3V/5V Serialized Real-Time Clocks, Rev 112105. * Application Note 90, Using the Multiplex Bus RTC Extended Features. - * - * 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. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 5a4c2c5e86fe..2b949f0dbaa9 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An rtc driver for the Dallas DS1742 * * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> * - * 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. - * * Copyright (C) 2006 Torsten Ertbjerg Rasmussen <tr@newtec.dk> * - nvram size determined from resource * - this ds1742 driver now supports ds1743. diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c index 1e9f429ada64..9df0c44512b8 100644 --- a/drivers/rtc/rtc-ds2404.c +++ b/drivers/rtc/rtc-ds2404.c @@ -182,9 +182,10 @@ static void ds2404_enable_osc(struct device *dev) static int ds2404_read_time(struct device *dev, struct rtc_time *dt) { unsigned long time = 0; + __le32 hw_time = 0; - ds2404_read_memory(dev, 0x203, 4, (u8 *)&time); - time = le32_to_cpu(time); + ds2404_read_memory(dev, 0x203, 4, (u8 *)&hw_time); + time = le32_to_cpu(hw_time); rtc_time64_to_tm(time, dt); return 0; diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index b0ef8cfe742d..77cca1392253 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An rtc/i2c driver for the EM Microelectronic EM3027 * Copyright 2011 CompuLab, Ltd. @@ -5,10 +6,6 @@ * Author: Mike Rapoport <mike@compulab.co.il> * * Based on rtc-ds1672.c by Alessandro Zummo <a.zummo@towertech.it> - * - * 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/i2c.h> diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index e1137670d4d2..677ec2da13d8 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * rtc-fm3130.c - RTC driver for Ramtron FM3130 I2C chip. * * Copyright (C) 2008 Sergey Lapin * Based on ds1307 driver by James Chapman and 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/module.h> @@ -107,8 +104,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t) fm3130_rtc_mode(dev, FM3130_MODE_READ); /* read the RTC date and time registers all at once */ - tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), - fm3130->msg, 2); + tmp = i2c_transfer(fm3130->client->adapter, fm3130->msg, 2); if (tmp != 2) { dev_err(dev, "%s error %d\n", "read", tmp); return -EIO; @@ -200,8 +196,7 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) } /* read the RTC alarm registers all at once */ - tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), - &fm3130->msg[2], 2); + tmp = i2c_transfer(fm3130->client->adapter, &fm3130->msg[2], 2); if (tmp != 2) { dev_err(dev, "%s error %d\n", "read", tmp); return -EIO; @@ -351,7 +346,7 @@ static int fm3130_probe(struct i2c_client *client, struct fm3130 *fm3130; int err = -ENODEV; int tmp; - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) diff --git a/drivers/rtc/rtc-imx-sc.c b/drivers/rtc/rtc-imx-sc.c index 19642bfd913a..c933045fe04b 100644 --- a/drivers/rtc/rtc-imx-sc.c +++ b/drivers/rtc/rtc-imx-sc.c @@ -3,6 +3,7 @@ * Copyright 2018 NXP. */ +#include <dt-bindings/firmware/imx/rsrc.h> #include <linux/arm-smccc.h> #include <linux/firmware/imx/sci.h> #include <linux/module.h> @@ -11,11 +12,15 @@ #include <linux/rtc.h> #define IMX_SC_TIMER_FUNC_GET_RTC_SEC1970 9 +#define IMX_SC_TIMER_FUNC_SET_RTC_ALARM 8 #define IMX_SC_TIMER_FUNC_SET_RTC_TIME 6 #define IMX_SIP_SRTC 0xC2000002 #define IMX_SIP_SRTC_SET_TIME 0x0 +#define SC_IRQ_GROUP_RTC 2 +#define SC_IRQ_RTC 1 + static struct imx_sc_ipc *rtc_ipc_handle; static struct rtc_device *imx_sc_rtc; @@ -24,6 +29,16 @@ struct imx_sc_msg_timer_get_rtc_time { u32 time; } __packed; +struct imx_sc_msg_timer_rtc_set_alarm { + struct imx_sc_rpc_msg hdr; + u16 year; + u8 mon; + u8 day; + u8 hour; + u8 min; + u8 sec; +} __packed; + static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct imx_sc_msg_timer_get_rtc_time msg; @@ -60,9 +75,77 @@ static int imx_sc_rtc_set_time(struct device *dev, struct rtc_time *tm) return res.a0; } +static int imx_sc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) +{ + return imx_scu_irq_group_enable(SC_IRQ_GROUP_RTC, SC_IRQ_RTC, enable); +} + +static int imx_sc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + /* + * SCU firmware does NOT provide read alarm API, but .read_alarm + * callback is required by RTC framework to support alarm function, + * so just return here. + */ + return 0; +} + +static int imx_sc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct imx_sc_msg_timer_rtc_set_alarm msg; + struct imx_sc_rpc_msg *hdr = &msg.hdr; + int ret; + struct rtc_time *alrm_tm = &alrm->time; + + hdr->ver = IMX_SC_RPC_VERSION; + hdr->svc = IMX_SC_RPC_SVC_TIMER; + hdr->func = IMX_SC_TIMER_FUNC_SET_RTC_ALARM; + hdr->size = 3; + + msg.year = alrm_tm->tm_year + 1900; + msg.mon = alrm_tm->tm_mon + 1; + msg.day = alrm_tm->tm_mday; + msg.hour = alrm_tm->tm_hour; + msg.min = alrm_tm->tm_min; + msg.sec = alrm_tm->tm_sec; + + ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true); + if (ret) { + dev_err(dev, "set rtc alarm failed, ret %d\n", ret); + return ret; + } + + ret = imx_sc_rtc_alarm_irq_enable(dev, alrm->enabled); + if (ret) { + dev_err(dev, "enable rtc alarm failed, ret %d\n", ret); + return ret; + } + + return 0; +} + static const struct rtc_class_ops imx_sc_rtc_ops = { .read_time = imx_sc_rtc_read_time, .set_time = imx_sc_rtc_set_time, + .read_alarm = imx_sc_rtc_read_alarm, + .set_alarm = imx_sc_rtc_set_alarm, + .alarm_irq_enable = imx_sc_rtc_alarm_irq_enable, +}; + +static int imx_sc_rtc_alarm_notify(struct notifier_block *nb, + unsigned long event, void *group) +{ + /* ignore non-rtc irq */ + if (!((event & SC_IRQ_RTC) && (*(u8 *)group == SC_IRQ_GROUP_RTC))) + return 0; + + rtc_update_irq(imx_sc_rtc, 1, RTC_IRQF | RTC_AF); + + return 0; +} + +static struct notifier_block imx_sc_rtc_alarm_sc_notifier = { + .notifier_call = imx_sc_rtc_alarm_notify, }; static int imx_sc_rtc_probe(struct platform_device *pdev) @@ -73,6 +156,8 @@ static int imx_sc_rtc_probe(struct platform_device *pdev) if (ret) return ret; + device_init_wakeup(&pdev->dev, true); + imx_sc_rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(imx_sc_rtc)) return PTR_ERR(imx_sc_rtc); @@ -87,6 +172,8 @@ static int imx_sc_rtc_probe(struct platform_device *pdev) return ret; } + imx_scu_irq_register_notifier(&imx_sc_rtc_alarm_sc_notifier); + return 0; } diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 890ccfc9e5aa..961bd5d1d109 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An I2C driver for the Intersil ISL 12022 * @@ -5,10 +6,6 @@ * * Based on the Philips PCF8563 RTC * by Alessandro Zummo <a.zummo@towertech.it>. - * - * 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/i2c.h> diff --git a/drivers/rtc/rtc-lp8788.c b/drivers/rtc/rtc-lp8788.c index e20e7bd822e0..c0b8fbce1082 100644 --- a/drivers/rtc/rtc-lp8788.c +++ b/drivers/rtc/rtc-lp8788.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * TI LP8788 MFD - rtc driver * * Copyright 2012 Texas Instruments * * Author: Milo(Woogyom) Kim <milo.kim@ti.com> - * - * 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/err.h> diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index dd5a8991f75b..5f46f85f814b 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * I2C client/driver for the ST M41T80 family of i2c rtc chips. * @@ -6,11 +7,6 @@ * Based on m41t00.c by Mark A. Greer <mgreer@mvista.com> * * 2006 (c) mycable GmbH - * - * 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. - * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -876,7 +872,7 @@ static struct notifier_block wdt_notifier = { static int m41t80_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; int rc = 0; struct rtc_time tm; struct m41t80_data *m41t80_data = NULL; diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c index 4a08a9dabc82..9444cb5f5190 100644 --- a/drivers/rtc/rtc-m41t93.c +++ b/drivers/rtc/rtc-m41t93.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * * Driver for ST M41T93 SPI RTC * * (c) 2010 Nikolaus Voss, Weinmann Medical GmbH - * - * 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/bcd.h> diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c index bab82b4be356..6803b0273302 100644 --- a/drivers/rtc/rtc-m41t94.c +++ b/drivers/rtc/rtc-m41t94.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Driver for ST M41T94 SPI RTC * * Copyright (C) 2008 Kim B. Heino - * - * 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/module.h> diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 3c8ad1cdfd7c..67e218758a8b 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * ST M48T59 RTC driver * * Copyright (c) 2007 Wind River Systems, Inc. * * Author: Mark Zhan <rongkai.zhan@windriver.com> - * - * 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> diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index a9533535c3b7..59b54ed9b841 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * ST M48T86 / Dallas DS12887 RTC driver * Copyright (c) 2006 Tower Technologies * * Author: Alessandro Zummo <a.zummo@towertech.it> * - * 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. - * * This drivers only supports the clock running in BCD and 24H mode. * If it will be ever adapted to binary and 12H mode, care must be taken * to not introduce bugs. diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 745827463367..daaeb6fb6c2d 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* drivers/rtc/rtc-max6902.c * * Copyright (C) 2006 8D Technologies inc. * Copyright (C) 2004 Compulab Ltd. * - * 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. - * * Driver for MAX6902 spi RTC - * */ #include <linux/module.h> diff --git a/drivers/rtc/rtc-max6916.c b/drivers/rtc/rtc-max6916.c index 9d4b407cc4b8..e72e768ab8ff 100644 --- a/drivers/rtc/rtc-max6916.c +++ b/drivers/rtc/rtc-max6916.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* rtc-max6916.c * * Driver for MAXIM max6916 Low Current, SPI Compatible * Real Time Clock * * Author : Venkat Prashanth B U <venkat.prashanth2498@gmail.com> - * - * 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/init.h> diff --git a/drivers/rtc/rtc-max8907.c b/drivers/rtc/rtc-max8907.c index 19c29b72598d..db3495d10274 100644 --- a/drivers/rtc/rtc-max8907.c +++ b/drivers/rtc/rtc-max8907.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * RTC driver for Maxim MAX8907 * @@ -5,10 +6,6 @@ * * Based on drivers/rtc/rtc-max8925.c, * Copyright (C) 2009-2010 Marvell International Ltd. - * - * 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/bcd.h> diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c index 67d6fc2d23e6..64bb8ac6ef62 100644 --- a/drivers/rtc/rtc-max8925.c +++ b/drivers/rtc/rtc-max8925.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * RTC driver for Maxim MAX8925 * * Copyright (C) 2009-2010 Marvell International Ltd. * Haojian Zhuang <haojian.zhuang@marvell.com> - * - * 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/module.h> diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c index f22a945a3794..1660d5e79582 100644 --- a/drivers/rtc/rtc-mcp795.c +++ b/drivers/rtc/rtc-mcp795.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * SPI Driver for Microchip MCP795 RTC * @@ -7,11 +8,6 @@ * * Device datasheet: * http://ww1.microchip.com/downloads/en/DeviceDoc/22280A.pdf - * - * 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/module.h> diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index dd0364293bc0..15a9d0278778 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Real-time clock driver for MPC5121 * * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. * Copyright 2011, Dmitry Eremin-Solenikov - * - * 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/init.h> diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 39da8b214275..fb542a930bf0 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An SPI driver for the Philips PCF2123 RTC * Copyright 2009 Cyber Switching, Inc. @@ -10,10 +11,6 @@ * Thanks to Christian Pellegrin <chripell@fsfe.org> for * the sysfs contributions to this driver. * - * 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. - * * Please note that the CS is active high, so platform data * should look something like: * @@ -29,7 +26,6 @@ * }, * ... *}; - * */ #include <linux/bcd.h> @@ -44,7 +40,7 @@ #include <linux/rtc.h> #include <linux/spi/spi.h> #include <linux/module.h> -#include <linux/sysfs.h> +#include <linux/regmap.h> /* REGISTERS */ #define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */ @@ -99,6 +95,7 @@ #define OFFSET_SIGN_BIT 6 /* 2's complement sign bit */ #define OFFSET_COARSE BIT(7) /* Coarse mode offset */ #define OFFSET_STEP (2170) /* Offset step in parts per billion */ +#define OFFSET_MASK GENMASK(6, 0) /* Offset value */ /* READ/WRITE ADDRESS BITS */ #define PCF2123_WRITE BIT(4) @@ -107,120 +104,35 @@ static struct spi_driver pcf2123_driver; -struct pcf2123_sysfs_reg { - struct device_attribute attr; - char name[2]; -}; - struct pcf2123_plat_data { struct rtc_device *rtc; - struct pcf2123_sysfs_reg regs[16]; + struct regmap *map; }; -/* - * Causes a 30 nanosecond delay to ensure that the PCF2123 chip select - * is released properly after an SPI write. This function should be - * called after EVERY read/write call over SPI. - */ -static inline void pcf2123_delay_trec(void) -{ - ndelay(30); -} - -static int pcf2123_read(struct device *dev, u8 reg, u8 *rxbuf, size_t size) -{ - struct spi_device *spi = to_spi_device(dev); - int ret; - - reg |= PCF2123_READ; - ret = spi_write_then_read(spi, ®, 1, rxbuf, size); - pcf2123_delay_trec(); - - return ret; -} - -static int pcf2123_write(struct device *dev, u8 *txbuf, size_t size) -{ - struct spi_device *spi = to_spi_device(dev); - int ret; - - txbuf[0] |= PCF2123_WRITE; - ret = spi_write(spi, txbuf, size); - pcf2123_delay_trec(); - - return ret; -} - -static int pcf2123_write_reg(struct device *dev, u8 reg, u8 val) -{ - u8 txbuf[2]; - - txbuf[0] = reg; - txbuf[1] = val; - return pcf2123_write(dev, txbuf, sizeof(txbuf)); -} - -static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr, - char *buffer) -{ - struct pcf2123_sysfs_reg *r; - u8 rxbuf[1]; - unsigned long reg; - int ret; - - r = container_of(attr, struct pcf2123_sysfs_reg, attr); - - ret = kstrtoul(r->name, 16, ®); - if (ret) - return ret; - - ret = pcf2123_read(dev, reg, rxbuf, 1); - if (ret < 0) - return -EIO; - - return sprintf(buffer, "0x%x\n", rxbuf[0]); -} +static const struct regmap_config pcf2123_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = PCF2123_READ, + .write_flag_mask = PCF2123_WRITE, + .max_register = PCF2123_REG_CTDWN_TMR, +}; -static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, - const char *buffer, size_t count) +static int pcf2123_read_offset(struct device *dev, long *offset) { - struct pcf2123_sysfs_reg *r; - unsigned long reg; - unsigned long val; + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + int ret, val; + unsigned int reg; - int ret; - - r = container_of(attr, struct pcf2123_sysfs_reg, attr); - - ret = kstrtoul(r->name, 16, ®); + ret = regmap_read(pdata->map, PCF2123_REG_OFFSET, ®); if (ret) return ret; - ret = kstrtoul(buffer, 10, &val); - if (ret) - return ret; - - ret = pcf2123_write_reg(dev, reg, val); - if (ret < 0) - return -EIO; - return count; -} - -static int pcf2123_read_offset(struct device *dev, long *offset) -{ - int ret; - s8 reg; - - ret = pcf2123_read(dev, PCF2123_REG_OFFSET, ®, 1); - if (ret < 0) - return ret; + val = sign_extend32((reg & OFFSET_MASK), OFFSET_SIGN_BIT); if (reg & OFFSET_COARSE) - reg <<= 1; /* multiply by 2 and sign extend */ - else - reg = sign_extend32(reg, OFFSET_SIGN_BIT); + val *= 2; - *offset = ((long)reg) * OFFSET_STEP; + *offset = ((long)val) * OFFSET_STEP; return 0; } @@ -237,6 +149,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset) */ static int pcf2123_set_offset(struct device *dev, long offset) { + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); s8 reg; if (offset > OFFSET_STEP * 127) @@ -244,7 +157,7 @@ static int pcf2123_set_offset(struct device *dev, long offset) else if (offset < OFFSET_STEP * -128) reg = -128; else - reg = (s8)((offset + (OFFSET_STEP >> 1)) / OFFSET_STEP); + reg = DIV_ROUND_CLOSEST(offset, OFFSET_STEP); /* choose fine offset only for odd values in the normal range */ if (reg & 1 && reg <= 63 && reg >= -64) { @@ -256,16 +169,18 @@ static int pcf2123_set_offset(struct device *dev, long offset) reg |= OFFSET_COARSE; } - return pcf2123_write_reg(dev, PCF2123_REG_OFFSET, reg); + return regmap_write(pdata->map, PCF2123_REG_OFFSET, (unsigned int)reg); } static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); u8 rxbuf[7]; int ret; - ret = pcf2123_read(dev, PCF2123_REG_SC, rxbuf, sizeof(rxbuf)); - if (ret < 0) + ret = regmap_bulk_read(pdata->map, PCF2123_REG_SC, rxbuf, + sizeof(rxbuf)); + if (ret) return ret; if (rxbuf[0] & OSC_HAS_STOPPED) { @@ -283,82 +198,168 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) if (tm->tm_year < 70) tm->tm_year += 100; /* assume we are in 1970...2069 */ - dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " - "mday=%d, mon=%d, year=%d, wday=%d\n", - __func__, - tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm); return 0; } static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) { - u8 txbuf[8]; + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + u8 txbuf[7]; int ret; - dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " - "mday=%d, mon=%d, year=%d, wday=%d\n", - __func__, - tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm); /* Stop the counter first */ - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP); + if (ret) return ret; /* Set the new time */ - txbuf[0] = PCF2123_REG_SC; - txbuf[1] = bin2bcd(tm->tm_sec & 0x7F); - txbuf[2] = bin2bcd(tm->tm_min & 0x7F); - txbuf[3] = bin2bcd(tm->tm_hour & 0x3F); - txbuf[4] = bin2bcd(tm->tm_mday & 0x3F); - txbuf[5] = tm->tm_wday & 0x07; - txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */ - txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100); - - ret = pcf2123_write(dev, txbuf, sizeof(txbuf)); - if (ret < 0) + txbuf[0] = bin2bcd(tm->tm_sec & 0x7F); + txbuf[1] = bin2bcd(tm->tm_min & 0x7F); + txbuf[2] = bin2bcd(tm->tm_hour & 0x3F); + txbuf[3] = bin2bcd(tm->tm_mday & 0x3F); + txbuf[4] = tm->tm_wday & 0x07; + txbuf[5] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */ + txbuf[6] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100); + + ret = regmap_bulk_write(pdata->map, PCF2123_REG_SC, txbuf, + sizeof(txbuf)); + if (ret) return ret; /* Start the counter */ - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); + if (ret) + return ret; + + return 0; +} + +static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + u8 rxbuf[4]; + int ret; + unsigned int val = 0; + + ret = regmap_bulk_read(pdata->map, PCF2123_REG_ALRM_MN, rxbuf, + sizeof(rxbuf)); + if (ret) + return ret; + + alm->time.tm_min = bcd2bin(rxbuf[0] & 0x7F); + alm->time.tm_hour = bcd2bin(rxbuf[1] & 0x3F); + alm->time.tm_mday = bcd2bin(rxbuf[2] & 0x3F); + alm->time.tm_wday = bcd2bin(rxbuf[3] & 0x07); + + dev_dbg(dev, "%s: alm is %ptR\n", __func__, &alm->time); + + ret = regmap_read(pdata->map, PCF2123_REG_CTRL2, &val); + if (ret) + return ret; + + alm->enabled = !!(val & CTRL2_AIE); + + return 0; +} + +static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + u8 txbuf[4]; + int ret; + + dev_dbg(dev, "%s: alm is %ptR\n", __func__, &alm->time); + + /* Ensure alarm flag is clear */ + ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); + if (ret) return ret; + /* Disable alarm interrupt */ + ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0); + if (ret) + return ret; + + /* Set new alarm */ + txbuf[0] = bin2bcd(alm->time.tm_min & 0x7F); + txbuf[1] = bin2bcd(alm->time.tm_hour & 0x3F); + txbuf[2] = bin2bcd(alm->time.tm_mday & 0x3F); + txbuf[3] = bin2bcd(alm->time.tm_wday & 0x07); + + ret = regmap_bulk_write(pdata->map, PCF2123_REG_ALRM_MN, txbuf, + sizeof(txbuf)); + if (ret) + return ret; + + /* Enable alarm interrupt */ + if (alm->enabled) { + ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, + CTRL2_AIE, CTRL2_AIE); + if (ret) + return ret; + } + return 0; } +static irqreturn_t pcf2123_rtc_irq(int irq, void *dev) +{ + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct mutex *lock = &pdata->rtc->ops_lock; + unsigned int val = 0; + int ret = IRQ_NONE; + + mutex_lock(lock); + regmap_read(pdata->map, PCF2123_REG_CTRL2, &val); + + /* Alarm? */ + if (val & CTRL2_AF) { + ret = IRQ_HANDLED; + + /* Clear alarm flag */ + regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); + + rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); + } + + mutex_unlock(lock); + + return ret; +} + static int pcf2123_reset(struct device *dev) { + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); int ret; - u8 rxbuf[2]; + unsigned int val = 0; - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_SW_RESET); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_SW_RESET); + if (ret) return ret; /* Stop the counter */ dev_dbg(dev, "stopping RTC\n"); - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP); + if (ret) return ret; /* See if the counter was actually stopped */ dev_dbg(dev, "checking for presence of RTC\n"); - ret = pcf2123_read(dev, PCF2123_REG_CTRL1, rxbuf, sizeof(rxbuf)); - if (ret < 0) + ret = regmap_read(pdata->map, PCF2123_REG_CTRL1, &val); + if (ret) return ret; - dev_dbg(dev, "received data from RTC (0x%02X 0x%02X)\n", - rxbuf[0], rxbuf[1]); - if (!(rxbuf[0] & CTRL1_STOP)) + dev_dbg(dev, "received data from RTC (0x%08X)\n", val); + if (!(val & CTRL1_STOP)) return -ENODEV; /* Start the counter */ - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); + if (ret) return ret; return 0; @@ -369,7 +370,8 @@ static const struct rtc_class_ops pcf2123_rtc_ops = { .set_time = pcf2123_rtc_set_time, .read_offset = pcf2123_read_offset, .set_offset = pcf2123_set_offset, - + .read_alarm = pcf2123_rtc_read_alarm, + .set_alarm = pcf2123_rtc_set_alarm, }; static int pcf2123_probe(struct spi_device *spi) @@ -377,7 +379,7 @@ static int pcf2123_probe(struct spi_device *spi) struct rtc_device *rtc; struct rtc_time tm; struct pcf2123_plat_data *pdata; - int ret, i; + int ret = 0; pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data), GFP_KERNEL); @@ -385,6 +387,13 @@ static int pcf2123_probe(struct spi_device *spi) return -ENOMEM; spi->dev.platform_data = pdata; + pdata->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); + + if (IS_ERR(pdata->map)) { + dev_err(&spi->dev, "regmap init failed.\n"); + goto kfree_exit; + } + ret = pcf2123_rtc_read_time(&spi->dev, &tm); if (ret < 0) { ret = pcf2123_reset(&spi->dev); @@ -409,47 +418,31 @@ static int pcf2123_probe(struct spi_device *spi) pdata->rtc = rtc; - for (i = 0; i < 16; i++) { - sysfs_attr_init(&pdata->regs[i].attr.attr); - sprintf(pdata->regs[i].name, "%1x", i); - pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR; - pdata->regs[i].attr.attr.name = pdata->regs[i].name; - pdata->regs[i].attr.show = pcf2123_show; - pdata->regs[i].attr.store = pcf2123_store; - ret = device_create_file(&spi->dev, &pdata->regs[i].attr); - if (ret) { - dev_err(&spi->dev, "Unable to create sysfs %s\n", - pdata->regs[i].name); - goto sysfs_exit; - } + /* Register alarm irq */ + if (spi->irq > 0) { + ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, + pcf2123_rtc_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + pcf2123_driver.driver.name, &spi->dev); + if (!ret) + device_init_wakeup(&spi->dev, true); + else + dev_err(&spi->dev, "could not request irq.\n"); } - return 0; + /* The PCF2123's alarm only has minute accuracy. Must add timer + * support to this driver to generate interrupts more than once + * per minute. + */ + pdata->rtc->uie_unsupported = 1; -sysfs_exit: - for (i--; i >= 0; i--) - device_remove_file(&spi->dev, &pdata->regs[i].attr); + return 0; kfree_exit: spi->dev.platform_data = NULL; return ret; } -static int pcf2123_remove(struct spi_device *spi) -{ - struct pcf2123_plat_data *pdata = dev_get_platdata(&spi->dev); - int i; - - if (pdata) { - for (i = 0; i < 16; i++) - if (pdata->regs[i].name[0]) - device_remove_file(&spi->dev, - &pdata->regs[i].attr); - } - - return 0; -} - #ifdef CONFIG_OF static const struct of_device_id pcf2123_dt_ids[] = { { .compatible = "nxp,rtc-pcf2123", }, @@ -465,7 +458,6 @@ static struct spi_driver pcf2123_driver = { .of_match_table = of_match_ptr(pcf2123_dt_ids), }, .probe = pcf2123_probe, - .remove = pcf2123_remove, }; module_spi_driver(pcf2123_driver); diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 7cb786d76e3c..8632f58fed43 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An I2C and SPI driver for the NXP PCF2127/29 RTC * Copyright 2013 Til-Technologies @@ -7,10 +8,6 @@ * based on the other drivers in this same directory. * * Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf - * - * 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/i2c.h> diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index b5c61a70b5df..2f435e533b10 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -1,9 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2012 Avionic Design GmbH - * - * 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/bcd.h> diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 3efc86c25d27..ac159d24286d 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An I2C driver for the Philips PCF8563 RTC * Copyright 2005-06 Tower Technologies @@ -8,10 +9,6 @@ * based on the other drivers in this same directory. * * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf - * - * 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/clk-provider.h> @@ -563,7 +560,6 @@ static int pcf8563_probe(struct i2c_client *client, struct pcf8563 *pcf8563; int err; unsigned char buf; - unsigned char alm_pending; dev_dbg(&client->dev, "%s\n", __func__); @@ -587,13 +583,13 @@ static int pcf8563_probe(struct i2c_client *client, return err; } - err = pcf8563_get_alarm_mode(client, NULL, &alm_pending); - if (err) { - dev_err(&client->dev, "%s: read error\n", __func__); + /* Clear flags and disable interrupts */ + buf = 0; + err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf); + if (err < 0) { + dev_err(&client->dev, "%s: write error\n", __func__); return err; } - if (alm_pending) - pcf8563_set_alarm_mode(client, 0); pcf8563->rtc = devm_rtc_device_register(&client->dev, pcf8563_driver.driver.name, @@ -605,7 +601,7 @@ static int pcf8563_probe(struct i2c_client *client, if (client->irq > 0) { err = devm_request_threaded_irq(&client->dev, client->irq, NULL, pcf8563_irq, - IRQF_SHARED|IRQF_ONESHOT|IRQF_TRIGGER_FALLING, + IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW, pcf8563_driver.driver.name, client); if (err) { dev_err(&client->dev, "unable to request IRQ %d\n", diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 7ca9e8871d77..c80ca20e5d8d 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * drivers/rtc/rtc-pcf8583.c * * Copyright (C) 2000 Russell King * Copyright (C) 2008 Wolfram Sang & Juergen Beisert, Pengutronix * - * 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. - * * Driver for PCF8583 RTC & RAM chip * * Converted to the generic RTC susbsystem by G. Liakhovetski (2006) diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index 343bb6ed1783..d4a5f8afafbc 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/rtc/rtc-pl030.c * * Copyright (C) 2000-2001 Deep Blue Solutions Ltd. - * - * 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/module.h> #include <linux/rtc.h> diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c index f77ef282f013..63b9e73fb97d 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * RTC driver code specific to PKUnity SoC and UniCore ISA * * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn> * Copyright (C) 2001-2010 Guan Xuetao - * - * 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/module.h> diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index a39ccd1cf6e8..84f0d25259ae 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Driver for Epson RTC-9701JE * @@ -7,10 +8,6 @@ * * Copyright (C) 2006 8D Technologies inc. * Copyright (C) 2004 Compulab Ltd. - * - * 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/module.h> diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c index 2316b0343b03..c34540baa12a 100644 --- a/drivers/rtc/rtc-rk808.c +++ b/drivers/rtc/rtc-rk808.c @@ -42,9 +42,18 @@ #define NUM_TIME_REGS (RK808_WEEKS_REG - RK808_SECONDS_REG + 1) #define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1) +struct rk_rtc_compat_reg { + unsigned int ctrl_reg; + unsigned int status_reg; + unsigned int alarm_seconds_reg; + unsigned int int_reg; + unsigned int seconds_reg; +}; + struct rk808_rtc { struct rk808 *rk808; struct rtc_device *rtc; + struct rk_rtc_compat_reg *creg; int irq; }; @@ -93,7 +102,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) int ret; /* Force an update of the shadowed registers right now */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_RTC_GET_TIME, BIT_RTC_CTRL_REG_RTC_GET_TIME); if (ret) { @@ -107,7 +116,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) * 32khz. If we clear the GET_TIME bit here, the time of i2c transfer * certainly more than 31.25us: 16 * 2.5us at 400kHz bus frequency. */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_RTC_GET_TIME, 0); if (ret) { @@ -115,7 +124,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) return ret; } - ret = regmap_bulk_read(rk808->regmap, RK808_SECONDS_REG, + ret = regmap_bulk_read(rk808->regmap, rk808_rtc->creg->seconds_reg, rtc_data, NUM_TIME_REGS); if (ret) { dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret); @@ -154,7 +163,7 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) rtc_data[6] = bin2bcd(tm->tm_wday); /* Stop RTC while updating the RTC registers */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_STOP_RTC_M, BIT_RTC_CTRL_REG_STOP_RTC_M); if (ret) { @@ -162,14 +171,14 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) return ret; } - ret = regmap_bulk_write(rk808->regmap, RK808_SECONDS_REG, + ret = regmap_bulk_write(rk808->regmap, rk808_rtc->creg->seconds_reg, rtc_data, NUM_TIME_REGS); if (ret) { dev_err(dev, "Failed to bull write rtc_data: %d\n", ret); return ret; } /* Start RTC again */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_STOP_RTC_M, 0); if (ret) { dev_err(dev, "Failed to update RTC control: %d\n", ret); @@ -187,8 +196,13 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) uint32_t int_reg; int ret; - ret = regmap_bulk_read(rk808->regmap, RK808_ALARM_SECONDS_REG, + ret = regmap_bulk_read(rk808->regmap, + rk808_rtc->creg->alarm_seconds_reg, alrm_data, NUM_ALARM_REGS); + if (ret) { + dev_err(dev, "Failed to read RTC alarm date REG: %d\n", ret); + return ret; + } alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK); alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK); @@ -198,7 +212,7 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100; rockchip_to_gregorian(&alrm->time); - ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg); + ret = regmap_read(rk808->regmap, rk808_rtc->creg->int_reg, &int_reg); if (ret) { dev_err(dev, "Failed to read RTC INT REG: %d\n", ret); return ret; @@ -217,7 +231,7 @@ static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc) struct rk808 *rk808 = rk808_rtc->rk808; int ret; - ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->int_reg, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0); return ret; @@ -228,7 +242,7 @@ static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc) struct rk808 *rk808 = rk808_rtc->rk808; int ret; - ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->int_reg, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); @@ -258,7 +272,8 @@ static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1); alrm_data[5] = bin2bcd(alrm->time.tm_year - 100); - ret = regmap_bulk_write(rk808->regmap, RK808_ALARM_SECONDS_REG, + ret = regmap_bulk_write(rk808->regmap, + rk808_rtc->creg->alarm_seconds_reg, alrm_data, NUM_ALARM_REGS); if (ret) { dev_err(dev, "Failed to bulk write: %d\n", ret); @@ -302,7 +317,7 @@ static irqreturn_t rk808_alarm_irq(int irq, void *data) struct i2c_client *client = rk808->i2c; int ret; - ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG, + ret = regmap_write(rk808->regmap, rk808_rtc->creg->status_reg, RTC_STATUS_MASK); if (ret) { dev_err(&client->dev, @@ -353,6 +368,22 @@ static int rk808_rtc_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops, rk808_rtc_suspend, rk808_rtc_resume); +static struct rk_rtc_compat_reg rk808_creg = { + .ctrl_reg = RK808_RTC_CTRL_REG, + .status_reg = RK808_RTC_STATUS_REG, + .alarm_seconds_reg = RK808_ALARM_SECONDS_REG, + .int_reg = RK808_RTC_INT_REG, + .seconds_reg = RK808_SECONDS_REG, +}; + +static struct rk_rtc_compat_reg rk817_creg = { + .ctrl_reg = RK817_RTC_CTRL_REG, + .status_reg = RK817_RTC_STATUS_REG, + .alarm_seconds_reg = RK817_ALARM_SECONDS_REG, + .int_reg = RK817_RTC_INT_REG, + .seconds_reg = RK817_SECONDS_REG, +}; + static int rk808_rtc_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); @@ -363,11 +394,20 @@ static int rk808_rtc_probe(struct platform_device *pdev) if (rk808_rtc == NULL) return -ENOMEM; + switch (rk808->variant) { + case RK809_ID: + case RK817_ID: + rk808_rtc->creg = &rk817_creg; + break; + default: + rk808_rtc->creg = &rk808_creg; + break; + } platform_set_drvdata(pdev, rk808_rtc); rk808_rtc->rk808 = rk808; /* start rtc running by default, and use shadowed timer. */ - ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG, + ret = regmap_update_bits(rk808->regmap, rk808_rtc->creg->ctrl_reg, BIT_RTC_CTRL_REG_STOP_RTC_M | BIT_RTC_CTRL_REG_RTC_READSEL_M, BIT_RTC_CTRL_REG_RTC_READSEL_M); @@ -377,7 +417,7 @@ static int rk808_rtc_probe(struct platform_device *pdev) return ret; } - ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG, + ret = regmap_write(rk808->regmap, rk808_rtc->creg->status_reg, RTC_STATUS_MASK); if (ret) { dev_err(&pdev->dev, diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 6582be707bd0..47c13678449e 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * A SPI driver for the Ricoh RS5C348 RTC * * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> * - * 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. - * * The board specific init code should provide characteristics of this * device: * Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 66a473a3c3fe..3bd6eaa0dcf6 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An I2C driver for Ricoh RS5C372, R2025S/D and RV5C38[67] RTCs * * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> * Copyright (C) 2006 Tower Technologies * Copyright (C) 2008 Paul Mundt - * - * 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/i2c.h> diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 3d6174eb32f6..4a0e8ec015cc 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Micro Crystal RV-3029 / RV-3049 rtc class driver * @@ -5,11 +6,6 @@ * Michael Buesch <m@bues.ch> * * based on previously existing rtc class drivers - * - * 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/module.h> diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index 0b102c3cf5a4..fc5243400108 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -517,7 +517,7 @@ static int rx8900_trickle_charger_init(struct rv8803_data *rv8803) static int rv8803_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; struct rv8803_data *rv8803; int err, flags; struct nvmem_config nvmem_cfg = { diff --git a/drivers/rtc/rtc-rx4581.c b/drivers/rtc/rtc-rx4581.c index c59a218bdd87..c092e0452347 100644 --- a/drivers/rtc/rtc-rx4581.c +++ b/drivers/rtc/rtc-rx4581.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* drivers/rtc/rtc-rx4581.c * * written by Torben Hohn <torbenh@linutronix.de> @@ -8,10 +9,6 @@ * Copyright (C) 2006 8D Technologies inc. * Copyright (C) 2004 Compulab Ltd. * - * 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. - * * Driver for MAX6902 spi RTC * * and based on: @@ -22,13 +19,8 @@ * Author: Martyn Welch <martyn.welch@ge.com> * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. * - * 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. - * * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC) * Copyright 2005-06 Tower Technologies - * */ #include <linux/module.h> diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index 7ddc22eb5b0f..8102469e27c0 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Driver for the Epson RTC module RX-8010 SJ * * Copyright(C) Timesys Corporation 2015 * Copyright(C) General Electric Company 2015 - * - * 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/bcd.h> @@ -437,7 +433,7 @@ static struct rtc_class_ops rx8010_rtc_ops = { static int rx8010_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; struct rx8010_data *rx8010; int err = 0; diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index fddc996cb38d..b9bda10589e0 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Driver for Epson's RTC module RX-8025 SA/NB * @@ -13,10 +14,6 @@ * Code cleanup by Sergei Poselenov, <sposelenov@emcraft.com> * Converted to new style by Wolfgang Grandegger <wg@grandegger.com> * Alarm and periodic interrupt added by Dmitry Rakhchev <rda@emcraft.com> - * - * 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/bcd.h> #include <linux/bitops.h> @@ -504,7 +501,7 @@ static void rx8025_sysfs_unregister(struct device *dev) static int rx8025_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; struct rx8025_data *rx8025; int err = 0; diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 776e3a2b89e8..490f70f57636 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An I2C driver for the Epson RX8581 RTC * * Author: Martyn Welch <martyn.welch@ge.com> * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. * - * 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. - * * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC) * Copyright 2005-06 Tower Technologies */ diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 8c37acb4a007..84806ff763cf 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -32,21 +32,22 @@ #define S35390A_ALRM_BYTE_MINS 2 /* flags for STATUS1 */ -#define S35390A_FLAG_POC 0x01 -#define S35390A_FLAG_BLD 0x02 -#define S35390A_FLAG_INT2 0x04 -#define S35390A_FLAG_24H 0x40 -#define S35390A_FLAG_RESET 0x80 +#define S35390A_FLAG_POC BIT(0) +#define S35390A_FLAG_BLD BIT(1) +#define S35390A_FLAG_INT2 BIT(2) +#define S35390A_FLAG_24H BIT(6) +#define S35390A_FLAG_RESET BIT(7) /* flag for STATUS2 */ -#define S35390A_FLAG_TEST 0x01 - -#define S35390A_INT2_MODE_MASK 0xF0 +#define S35390A_FLAG_TEST BIT(0) +/* INT2 pin output mode */ +#define S35390A_INT2_MODE_MASK 0x0E #define S35390A_INT2_MODE_NOINTR 0x00 -#define S35390A_INT2_MODE_FREQ 0x10 -#define S35390A_INT2_MODE_ALARM 0x40 -#define S35390A_INT2_MODE_PMIN_EDG 0x20 +#define S35390A_INT2_MODE_ALARM BIT(1) /* INT2AE */ +#define S35390A_INT2_MODE_PMIN_EDG BIT(2) /* INT2ME */ +#define S35390A_INT2_MODE_FREQ BIT(3) /* INT2FE */ +#define S35390A_INT2_MODE_PMIN (BIT(3) | BIT(2)) /* INT2FE | INT2ME */ static const struct i2c_device_id s35390a_id[] = { { "s35390a", 0 }, @@ -284,6 +285,9 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); + if (alm->time.tm_sec != 0) + dev_warn(&client->dev, "Alarms are only supported on a per minute basis!\n"); + /* disable interrupt (which deasserts the irq line) */ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); if (err < 0) @@ -299,9 +303,6 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) else sts = S35390A_INT2_MODE_NOINTR; - /* This chip expects the bits of each byte to be in reverse order */ - sts = bitrev8(sts); - /* set interupt mode*/ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); if (err < 0) @@ -339,7 +340,7 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) if (err < 0) return err; - if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) { + if ((sts & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) { /* * When the alarm isn't enabled, the register to configure * the alarm time isn't accessible. @@ -431,14 +432,14 @@ static int s35390a_probe(struct i2c_client *client, unsigned int i; struct s35390a *s35390a; char buf, status1; + struct device *dev = &client->dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { err = -ENODEV; goto exit; } - s35390a = devm_kzalloc(&client->dev, sizeof(struct s35390a), - GFP_KERNEL); + s35390a = devm_kzalloc(dev, sizeof(struct s35390a), GFP_KERNEL); if (!s35390a) { err = -ENOMEM; goto exit; @@ -452,8 +453,8 @@ static int s35390a_probe(struct i2c_client *client, s35390a->client[i] = i2c_new_dummy(client->adapter, client->addr + i); if (!s35390a->client[i]) { - dev_err(&client->dev, "Address %02x unavailable\n", - client->addr + i); + dev_err(dev, "Address %02x unavailable\n", + client->addr + i); err = -EBUSY; goto exit_dummy; } @@ -462,7 +463,7 @@ static int s35390a_probe(struct i2c_client *client, err_read = s35390a_read_status(s35390a, &status1); if (err_read < 0) { err = err_read; - dev_err(&client->dev, "error resetting chip\n"); + dev_err(dev, "error resetting chip\n"); goto exit_dummy; } @@ -476,28 +477,30 @@ static int s35390a_probe(struct i2c_client *client, buf = 0; err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1); if (err < 0) { - dev_err(&client->dev, "error disabling alarm"); + dev_err(dev, "error disabling alarm"); goto exit_dummy; } } else { err = s35390a_disable_test_mode(s35390a); if (err < 0) { - dev_err(&client->dev, "error disabling test mode\n"); + dev_err(dev, "error disabling test mode\n"); goto exit_dummy; } } - device_set_wakeup_capable(&client->dev, 1); + device_set_wakeup_capable(dev, 1); - s35390a->rtc = devm_rtc_device_register(&client->dev, - s35390a_driver.driver.name, - &s35390a_rtc_ops, THIS_MODULE); + s35390a->rtc = devm_rtc_device_register(dev, s35390a_driver.driver.name, + &s35390a_rtc_ops, THIS_MODULE); if (IS_ERR(s35390a->rtc)) { err = PTR_ERR(s35390a->rtc); goto exit_dummy; } + /* supports per-minute alarms only, therefore set uie_unsupported */ + s35390a->rtc->uie_unsupported = 1; + if (status1 & S35390A_FLAG_INT2) rtc_update_irq(s35390a->rtc, 1, RTC_AF); diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index e81a2b22a5c3..74bf6473a05d 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* drivers/rtc/rtc-s3c.c * * Copyright (c) 2010 Samsung Electronics Co., Ltd. @@ -7,10 +8,6 @@ * Ben Dooks, <ben@simtec.co.uk> * http://armlinux.simtec.co.uk/ * - * 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. - * * S3C2410/S3C2440/S3C24XX Internal RTC Driver */ diff --git a/drivers/rtc/rtc-s3c.h b/drivers/rtc/rtc-s3c.h index 004b61a8343f..3552914aa611 100644 --- a/drivers/rtc/rtc-s3c.h +++ b/drivers/rtc/rtc-s3c.h @@ -1,11 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> * http://www.simtec.co.uk/products/SWLINUX/ * - * 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. - * * S3C2410 Internal RTC register definition */ diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c index 5fe021821831..49474a31c66d 100644 --- a/drivers/rtc/rtc-st-lpc.c +++ b/drivers/rtc/rtc-st-lpc.c @@ -162,10 +162,6 @@ static int st_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t) now_secs = rtc_tm_to_time64(&now); alarm_secs = rtc_tm_to_time64(&t->time); - /* Invalid alarm time */ - if (now_secs > alarm_secs) - return -EINVAL; - memcpy(&rtc->alarm, t, sizeof(struct rtc_wkalrm)); /* Now many secs to fire */ diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index fccbecbb2c98..a833ebc4ecb9 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * A RTC driver for the Simtek STK17TA8 * @@ -5,10 +6,6 @@ * * Based on the DS1553 driver from * Atsushi Nemoto <anemo@mba.ocn.ne.jp> - * - * 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/bcd.h> diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 8e6c9b3bcc29..773a1990b93f 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -519,11 +519,7 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) /* Write to Alarm register */ writel_relaxed(alrmar, rtc->base + regs->alrmar); - if (alrm->enabled) - stm32_rtc_alarm_irq_enable(dev, 1); - else - stm32_rtc_alarm_irq_enable(dev, 0); - + stm32_rtc_alarm_irq_enable(dev, alrm->enabled); end: stm32_rtc_wpr_lock(rtc); diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 8128ec200ba2..c0e75c373605 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -672,6 +672,7 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = { { .compatible = "allwinner,sun6i-a31-rtc" }, { .compatible = "allwinner,sun8i-a23-rtc" }, { .compatible = "allwinner,sun8i-h3-rtc" }, + { .compatible = "allwinner,sun8i-r40-rtc" }, { .compatible = "allwinner,sun8i-v3-rtc" }, { .compatible = "allwinner,sun50i-h5-rtc" }, { /* sentinel */ }, diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index f0ce76865434..8fa1b3febf69 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -2,7 +2,7 @@ /* * An RTC driver for the NVIDIA Tegra 200 series internal RTC. * - * Copyright (c) 2010, NVIDIA Corporation. + * Copyright (c) 2010-2019, NVIDIA Corporation. */ #include <linux/clk.h> @@ -18,10 +18,10 @@ #include <linux/rtc.h> #include <linux/slab.h> -/* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */ +/* Set to 1 = busy every eight 32 kHz clocks during copy of sec+msec to AHB. */ #define TEGRA_RTC_REG_BUSY 0x004 #define TEGRA_RTC_REG_SECONDS 0x008 -/* when msec is read, the seconds are buffered into shadow seconds. */ +/* When msec is read, the seconds are buffered into shadow seconds. */ #define TEGRA_RTC_REG_SHADOW_SECONDS 0x00c #define TEGRA_RTC_REG_MILLI_SECONDS 0x010 #define TEGRA_RTC_REG_SECONDS_ALARM0 0x014 @@ -46,44 +46,48 @@ #define TEGRA_RTC_INTR_STATUS_SEC_ALARM0 (1<<0) struct tegra_rtc_info { - struct platform_device *pdev; - struct rtc_device *rtc_dev; - void __iomem *rtc_base; /* NULL if not initialized. */ - struct clk *clk; - int tegra_rtc_irq; /* alarm and periodic irq */ - spinlock_t tegra_rtc_lock; + struct platform_device *pdev; + struct rtc_device *rtc; + void __iomem *base; /* NULL if not initialized */ + struct clk *clk; + int irq; /* alarm and periodic IRQ */ + spinlock_t lock; }; -/* RTC hardware is busy when it is updating its values over AHB once - * every eight 32kHz clocks (~250uS). - * outside of these updates the CPU is free to write. - * CPU is always free to read. +/* + * RTC hardware is busy when it is updating its values over AHB once every + * eight 32 kHz clocks (~250 us). Outside of these updates the CPU is free to + * write. CPU is always free to read. */ static inline u32 tegra_rtc_check_busy(struct tegra_rtc_info *info) { - return readl(info->rtc_base + TEGRA_RTC_REG_BUSY) & 1; + return readl(info->base + TEGRA_RTC_REG_BUSY) & 1; } -/* Wait for hardware to be ready for writing. - * This function tries to maximize the amount of time before the next update. - * It does this by waiting for the RTC to become busy with its periodic update, - * then returning once the RTC first becomes not busy. +/* + * Wait for hardware to be ready for writing. This function tries to maximize + * the amount of time before the next update. It does this by waiting for the + * RTC to become busy with its periodic update, then returning once the RTC + * first becomes not busy. + * * This periodic update (where the seconds and milliseconds are copied to the - * AHB side) occurs every eight 32kHz clocks (~250uS). - * The behavior of this function allows us to make some assumptions without - * introducing a race, because 250uS is plenty of time to read/write a value. + * AHB side) occurs every eight 32 kHz clocks (~250 us). The behavior of this + * function allows us to make some assumptions without introducing a race, + * because 250 us is plenty of time to read/write a value. */ static int tegra_rtc_wait_while_busy(struct device *dev) { struct tegra_rtc_info *info = dev_get_drvdata(dev); + int retries = 500; /* ~490 us is the worst case, ~250 us is best */ - int retries = 500; /* ~490 us is the worst case, ~250 us is best. */ - - /* first wait for the RTC to become busy. this is when it - * posts its updated seconds+msec registers to AHB side. */ + /* + * First wait for the RTC to become busy. This is when it posts its + * updated seconds+msec registers to AHB side. + */ while (tegra_rtc_check_busy(info)) { if (!retries--) goto retry_failed; + udelay(1); } @@ -91,28 +95,30 @@ static int tegra_rtc_wait_while_busy(struct device *dev) return 0; retry_failed: - dev_err(dev, "write failed:retry count exceeded.\n"); + dev_err(dev, "write failed: retry count exceeded\n"); return -ETIMEDOUT; } static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long sec, msec; - unsigned long sl_irq_flags; + unsigned long flags; + u32 sec, msec; - /* RTC hardware copies seconds to shadow seconds when a read - * of milliseconds occurs. use a lock to keep other threads out. */ - spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags); + /* + * RTC hardware copies seconds to shadow seconds when a read of + * milliseconds occurs. use a lock to keep other threads out. + */ + spin_lock_irqsave(&info->lock, flags); - msec = readl(info->rtc_base + TEGRA_RTC_REG_MILLI_SECONDS); - sec = readl(info->rtc_base + TEGRA_RTC_REG_SHADOW_SECONDS); + msec = readl(info->base + TEGRA_RTC_REG_MILLI_SECONDS); + sec = readl(info->base + TEGRA_RTC_REG_SHADOW_SECONDS); - spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags); + spin_unlock_irqrestore(&info->lock, flags); rtc_time64_to_tm(sec, tm); - dev_vdbg(dev, "time read as %lu. %ptR\n", sec, tm); + dev_vdbg(dev, "time read as %u, %ptR\n", sec, tm); return 0; } @@ -120,21 +126,21 @@ static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm) static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long sec; + u32 sec; int ret; - /* convert tm to seconds. */ + /* convert tm to seconds */ sec = rtc_tm_to_time64(tm); - dev_vdbg(dev, "time set to %lu. %ptR\n", sec, tm); + dev_vdbg(dev, "time set to %u, %ptR\n", sec, tm); - /* seconds only written if wait succeeded. */ + /* seconds only written if wait succeeded */ ret = tegra_rtc_wait_while_busy(dev); if (!ret) - writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS); + writel(sec, info->base + TEGRA_RTC_REG_SECONDS); dev_vdbg(dev, "time read back as %d\n", - readl(info->rtc_base + TEGRA_RTC_REG_SECONDS)); + readl(info->base + TEGRA_RTC_REG_SECONDS)); return ret; } @@ -142,22 +148,21 @@ static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm) static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long sec; - unsigned tmp; + u32 sec, value; - sec = readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0); + sec = readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0); if (sec == 0) { - /* alarm is disabled. */ + /* alarm is disabled */ alarm->enabled = 0; } else { - /* alarm is enabled. */ + /* alarm is enabled */ alarm->enabled = 1; rtc_time64_to_tm(sec, &alarm->time); } - tmp = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); - alarm->pending = (tmp & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) != 0; + value = readl(info->base + TEGRA_RTC_REG_INTR_STATUS); + alarm->pending = (value & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) != 0; return 0; } @@ -165,22 +170,22 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) static int tegra_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned status; - unsigned long sl_irq_flags; + unsigned long flags; + u32 status; tegra_rtc_wait_while_busy(dev); - spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags); + spin_lock_irqsave(&info->lock, flags); - /* read the original value, and OR in the flag. */ - status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_MASK); + /* read the original value, and OR in the flag */ + status = readl(info->base + TEGRA_RTC_REG_INTR_MASK); if (enabled) status |= TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* set it */ else status &= ~TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* clear it */ - writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_MASK); + writel(status, info->base + TEGRA_RTC_REG_INTR_MASK); - spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags); + spin_unlock_irqrestore(&info->lock, flags); return 0; } @@ -188,7 +193,7 @@ static int tegra_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long sec; + u32 sec; if (alarm->enabled) sec = rtc_tm_to_time64(&alarm->time); @@ -196,16 +201,16 @@ static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) sec = 0; tegra_rtc_wait_while_busy(dev); - writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0); + writel(sec, info->base + TEGRA_RTC_REG_SECONDS_ALARM0); dev_vdbg(dev, "alarm read back as %d\n", - readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0)); + readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0)); /* if successfully written and alarm is enabled ... */ if (sec) { tegra_rtc_alarm_irq_enable(dev, 1); - dev_vdbg(dev, "alarm set as %lu. %ptR\n", sec, &alarm->time); + dev_vdbg(dev, "alarm set as %u, %ptR\n", sec, &alarm->time); } else { - /* disable alarm if 0 or write error. */ + /* disable alarm if 0 or write error */ dev_vdbg(dev, "alarm disabled\n"); tegra_rtc_alarm_irq_enable(dev, 0); } @@ -227,39 +232,39 @@ static irqreturn_t tegra_rtc_irq_handler(int irq, void *data) { struct device *dev = data; struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long events = 0; - unsigned status; - unsigned long sl_irq_flags; + unsigned long events = 0, flags; + u32 status; - status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); + status = readl(info->base + TEGRA_RTC_REG_INTR_STATUS); if (status) { - /* clear the interrupt masks and status on any irq. */ + /* clear the interrupt masks and status on any IRQ */ tegra_rtc_wait_while_busy(dev); - spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags); - writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK); - writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); - spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags); + + spin_lock_irqsave(&info->lock, flags); + writel(0, info->base + TEGRA_RTC_REG_INTR_MASK); + writel(status, info->base + TEGRA_RTC_REG_INTR_STATUS); + spin_unlock_irqrestore(&info->lock, flags); } - /* check if Alarm */ - if ((status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0)) + /* check if alarm */ + if (status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) events |= RTC_IRQF | RTC_AF; - /* check if Periodic */ - if ((status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM)) + /* check if periodic */ + if (status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM) events |= RTC_IRQF | RTC_PF; - rtc_update_irq(info->rtc_dev, 1, events); + rtc_update_irq(info->rtc, 1, events); return IRQ_HANDLED; } static const struct rtc_class_ops tegra_rtc_ops = { - .read_time = tegra_rtc_read_time, - .set_time = tegra_rtc_set_time, - .read_alarm = tegra_rtc_read_alarm, - .set_alarm = tegra_rtc_set_alarm, - .proc = tegra_rtc_proc, + .read_time = tegra_rtc_read_time, + .set_time = tegra_rtc_set_time, + .read_alarm = tegra_rtc_read_alarm, + .set_alarm = tegra_rtc_set_alarm, + .proc = tegra_rtc_proc, .alarm_irq_enable = tegra_rtc_alarm_irq_enable, }; @@ -269,21 +274,20 @@ static const struct of_device_id tegra_rtc_dt_match[] = { }; MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match); -static int __init tegra_rtc_probe(struct platform_device *pdev) +static int tegra_rtc_probe(struct platform_device *pdev) { struct tegra_rtc_info *info; struct resource *res; int ret; - info = devm_kzalloc(&pdev->dev, sizeof(struct tegra_rtc_info), - GFP_KERNEL); + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - info->rtc_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(info->rtc_base)) - return PTR_ERR(info->rtc_base); + info->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(info->base)) + return PTR_ERR(info->base); ret = platform_get_irq(pdev, 0); if (ret <= 0) { @@ -291,14 +295,14 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) return ret; } - info->tegra_rtc_irq = ret; + info->irq = ret; - info->rtc_dev = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(info->rtc_dev)) - return PTR_ERR(info->rtc_dev); + info->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(info->rtc)) + return PTR_ERR(info->rtc); - info->rtc_dev->ops = &tegra_rtc_ops; - info->rtc_dev->range_max = U32_MAX; + info->rtc->ops = &tegra_rtc_ops; + info->rtc->range_max = U32_MAX; info->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(info->clk)) @@ -308,33 +312,30 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) if (ret < 0) return ret; - /* set context info. */ + /* set context info */ info->pdev = pdev; - spin_lock_init(&info->tegra_rtc_lock); + spin_lock_init(&info->lock); platform_set_drvdata(pdev, info); - /* clear out the hardware. */ - writel(0, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0); - writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); - writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK); + /* clear out the hardware */ + writel(0, info->base + TEGRA_RTC_REG_SECONDS_ALARM0); + writel(0xffffffff, info->base + TEGRA_RTC_REG_INTR_STATUS); + writel(0, info->base + TEGRA_RTC_REG_INTR_MASK); device_init_wakeup(&pdev->dev, 1); - ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq, - tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH, - dev_name(&pdev->dev), &pdev->dev); + ret = devm_request_irq(&pdev->dev, info->irq, tegra_rtc_irq_handler, + IRQF_TRIGGER_HIGH, dev_name(&pdev->dev), + &pdev->dev); if (ret) { - dev_err(&pdev->dev, - "Unable to request interrupt for device (err=%d).\n", - ret); + dev_err(&pdev->dev, "failed to request interrupt: %d\n", ret); goto disable_clk; } - ret = rtc_register_device(info->rtc_dev); + ret = rtc_register_device(info->rtc); if (ret) { - dev_err(&pdev->dev, "Unable to register device (err=%d).\n", - ret); + dev_err(&pdev->dev, "failed to register device: %d\n", ret); goto disable_clk; } @@ -363,20 +364,20 @@ static int tegra_rtc_suspend(struct device *dev) tegra_rtc_wait_while_busy(dev); - /* only use ALARM0 as a wake source. */ - writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); + /* only use ALARM0 as a wake source */ + writel(0xffffffff, info->base + TEGRA_RTC_REG_INTR_STATUS); writel(TEGRA_RTC_INTR_STATUS_SEC_ALARM0, - info->rtc_base + TEGRA_RTC_REG_INTR_MASK); + info->base + TEGRA_RTC_REG_INTR_MASK); dev_vdbg(dev, "alarm sec = %d\n", - readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0)); + readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0)); - dev_vdbg(dev, "Suspend (device_may_wakeup=%d) irq:%d\n", - device_may_wakeup(dev), info->tegra_rtc_irq); + dev_vdbg(dev, "Suspend (device_may_wakeup=%d) IRQ:%d\n", + device_may_wakeup(dev), info->irq); - /* leave the alarms on as a wake source. */ + /* leave the alarms on as a wake source */ if (device_may_wakeup(dev)) - enable_irq_wake(info->tegra_rtc_irq); + enable_irq_wake(info->irq); return 0; } @@ -386,10 +387,11 @@ static int tegra_rtc_resume(struct device *dev) struct tegra_rtc_info *info = dev_get_drvdata(dev); dev_vdbg(dev, "Resume (device_may_wakeup=%d)\n", - device_may_wakeup(dev)); - /* alarms were left on as a wake source, turn them off. */ + device_may_wakeup(dev)); + + /* alarms were left on as a wake source, turn them off */ if (device_may_wakeup(dev)) - disable_irq_wake(info->tegra_rtc_irq); + disable_irq_wake(info->irq); return 0; } @@ -399,22 +401,21 @@ static SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume); static void tegra_rtc_shutdown(struct platform_device *pdev) { - dev_vdbg(&pdev->dev, "disabling interrupts.\n"); + dev_vdbg(&pdev->dev, "disabling interrupts\n"); tegra_rtc_alarm_irq_enable(&pdev->dev, 0); } -MODULE_ALIAS("platform:tegra_rtc"); static struct platform_driver tegra_rtc_driver = { - .remove = tegra_rtc_remove, - .shutdown = tegra_rtc_shutdown, - .driver = { - .name = "tegra_rtc", + .probe = tegra_rtc_probe, + .remove = tegra_rtc_remove, + .shutdown = tegra_rtc_shutdown, + .driver = { + .name = "tegra_rtc", .of_match_table = tegra_rtc_dt_match, - .pm = &tegra_rtc_pm_ops, + .pm = &tegra_rtc_pm_ops, }, }; - -module_platform_driver_probe(tegra_rtc_driver, tegra_rtc_probe); +module_platform_driver(tegra_rtc_driver); MODULE_AUTHOR("Jon Mayo <jmayo@nvidia.com>"); MODULE_DESCRIPTION("driver for Tegra internal RTC"); diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index b298e9902f45..74b3a0603b73 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -133,6 +133,7 @@ static int test_probe(struct platform_device *plat_dev) break; default: rtd->rtc->ops = &test_rtc_ops; + device_init_wakeup(&plat_dev->dev, 1); } timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0); diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 8556d925e52a..7078f6da1cbc 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -143,7 +143,7 @@ static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) struct tps65910 *tps = dev_get_drvdata(dev->parent); int ret; - ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, alarm_data, + ret = regmap_bulk_read(tps->regmap, TPS65910_ALARM_SECONDS, alarm_data, NUM_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_read_alarm error %d\n", ret); diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index 1f3117b5a83c..63ffba21397b 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* drivers/rtc/rtc-v3020.c * * Copyright (C) 2006 8D Technologies inc. * Copyright (C) 2004 Compulab Ltd. * - * 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. - * * Driver for the V3020 RTC * * Changelog: @@ -17,7 +14,6 @@ * * ??-???-2004: Someone at Compulab * - Initial driver creation. - * */ #include <linux/platform_device.h> #include <linux/module.h> diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index d2e8b21c90c4..ccef887d2690 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -435,7 +435,8 @@ static int wm831x_rtc_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL, wm831x_alm_irq, - IRQF_TRIGGER_RISING, "RTC alarm", + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "RTC alarm", wm831x_rtc); if (ret != 0) { dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index ad2ae2f0536e..d1d5a44d9122 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * An i2c driver for the Xicor/Intersil X1205 RTC * Copyright 2004 Karen Spearel @@ -11,10 +12,6 @@ * * Information and datasheet: * http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html - * - * 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/i2c.h> |