summaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig41
-rw-r--r--drivers/rtc/Makefile3
-rw-r--r--drivers/rtc/rtc-amlogic-a4.c32
-rw-r--r--drivers/rtc/rtc-atcrtc100.c381
-rw-r--r--drivers/rtc/rtc-ds1685.c3
-rw-r--r--drivers/rtc/rtc-gamecube.c4
-rw-r--r--drivers/rtc/rtc-isl12026.c7
-rw-r--r--drivers/rtc/rtc-macsmc.c140
-rw-r--r--drivers/rtc/rtc-max31335.c6
-rw-r--r--drivers/rtc/rtc-nvidia-vrs10.c542
-rw-r--r--drivers/rtc/rtc-pic32.c2
-rw-r--r--drivers/rtc/rtc-renesas-rtca3.c3
-rw-r--r--drivers/rtc/rtc-rv3028.c2
-rw-r--r--drivers/rtc/rtc-rv3032.c2
-rw-r--r--drivers/rtc/rtc-rv8803.c2
-rw-r--r--drivers/rtc/rtc-rx6110.c2
-rw-r--r--drivers/rtc/rtc-rx8010.c1
-rw-r--r--drivers/rtc/rtc-rx8025.c2
-rw-r--r--drivers/rtc/rtc-s35390a.c18
-rw-r--r--drivers/rtc/rtc-sa1100.c3
-rw-r--r--drivers/rtc/rtc-sh.c1
-rw-r--r--drivers/rtc/rtc-tegra.c45
22 files changed, 1149 insertions, 93 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2933c41c77c8..50dc779f7f98 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -409,13 +409,22 @@ config RTC_DRV_MAX77686
config RTC_DRV_SPACEMIT_P1
tristate "SpacemiT P1 RTC"
depends on ARCH_SPACEMIT || COMPILE_TEST
- select MFD_SPACEMIT_P1
- default ARCH_SPACEMIT
+ depends on MFD_SPACEMIT_P1
+ default MFD_SPACEMIT_P1
help
Enable support for the RTC function in the SpacemiT P1 PMIC.
This driver can also be built as a module, which will be called
"spacemit-p1-rtc".
+config RTC_DRV_NVIDIA_VRS10
+ tristate "NVIDIA VRS10 RTC device"
+ help
+ If you say yes here you will get support for the battery backed RTC device
+ of NVIDIA VRS (Voltage Regulator Specification). The RTC is connected via
+ I2C interface and supports alarm functionality.
+ This driver can also be built as a module. If so, the module will be called
+ rtc-nvidia-vrs10.
+
config RTC_DRV_NCT3018Y
tristate "Nuvoton NCT3018Y"
depends on OF
@@ -1063,6 +1072,21 @@ config RTC_DRV_ALPHA
Direct support for the real-time clock found on every Alpha
system, specifically MC146818 compatibles. If in doubt, say Y.
+config RTC_DRV_ATCRTC100
+ tristate "Andes ATCRTC100"
+ depends on ARCH_ANDES || COMPILE_TEST
+ select REGMAP_MMIO
+ help
+ If you say yes here you will get support for the Andes ATCRTC100
+ RTC driver.
+
+ This driver provides support for the Andes ATCRTC100 real-time clock
+ device. It allows setting and retrieving the time and date, as well
+ as setting alarms.
+
+ To compile this driver as a module, choose M here: the module will
+ be called rtc-atcrtc100.
+
config RTC_DRV_DS1216
tristate "Dallas DS1216"
depends on SNI_RM
@@ -1749,7 +1773,7 @@ config RTC_DRV_MC13XXX
tristate "Freescale MC13xxx RTC"
help
This enables support for the RTCs found on Freescale's PMICs
- MC13783 and MC13892.
+ MC13783, MC13892 and MC34708.
config RTC_DRV_MPC5121
tristate "Freescale MPC5121 built-in RTC"
@@ -2074,6 +2098,17 @@ config RTC_DRV_WILCO_EC
This can also be built as a module. If so, the module will
be named "rtc_wilco_ec".
+config RTC_DRV_MACSMC
+ tristate "Apple Mac System Management Controller RTC"
+ depends on MFD_MACSMC
+ help
+ If you say yes here you get support for RTC functions
+ inside Apple SPMI PMUs accessed through the SoC's
+ System Management Controller
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-macsmc.
+
config RTC_DRV_MSC313
tristate "MStar MSC313 RTC"
depends on ARCH_MSTARV7 || COMPILE_TEST
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 8221bda6e6dc..6cf7e066314e 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o
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_ATCRTC100) += rtc-atcrtc100.o
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
obj-$(CONFIG_RTC_DRV_BBNSM) += rtc-nxp-bbnsm.o
obj-$(CONFIG_RTC_DRV_BD70528) += rtc-bd70528.o
@@ -93,6 +94,7 @@ obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_MA35D1) += rtc-ma35d1.o
+obj-$(CONFIG_RTC_DRV_MACSMC) += rtc-macsmc.o
obj-$(CONFIG_RTC_DRV_MAX31335) += rtc-max31335.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
@@ -121,6 +123,7 @@ obj-$(CONFIG_RTC_DRV_GAMECUBE) += rtc-gamecube.o
obj-$(CONFIG_RTC_DRV_NCT3018Y) += rtc-nct3018y.o
obj-$(CONFIG_RTC_DRV_NCT6694) += rtc-nct6694.o
obj-$(CONFIG_RTC_DRV_NTXEC) += rtc-ntxec.o
+obj-$(CONFIG_RTC_DRV_NVIDIA_VRS10)+= rtc-nvidia-vrs10.o
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o
obj-$(CONFIG_RTC_DRV_OPTEE) += rtc-optee.o
diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c
index 1928b29c1045..123fb372fc9f 100644
--- a/drivers/rtc/rtc-amlogic-a4.c
+++ b/drivers/rtc/rtc-amlogic-a4.c
@@ -361,39 +361,26 @@ static int aml_rtc_probe(struct platform_device *pdev)
"failed to get_enable rtc sys clk\n");
aml_rtc_init(rtc);
- device_init_wakeup(dev, true);
+ devm_device_init_wakeup(dev);
platform_set_drvdata(pdev, rtc);
rtc->rtc_dev = devm_rtc_allocate_device(dev);
- if (IS_ERR(rtc->rtc_dev)) {
- ret = PTR_ERR(rtc->rtc_dev);
- goto err_clk;
- }
+ if (IS_ERR(rtc->rtc_dev))
+ return PTR_ERR(rtc->rtc_dev);
ret = devm_request_irq(dev, rtc->irq, aml_rtc_handler,
IRQF_ONESHOT, "aml-rtc alarm", rtc);
if (ret) {
dev_err_probe(dev, ret, "IRQ%d request failed, ret = %d\n",
rtc->irq, ret);
- goto err_clk;
+ return ret;
}
rtc->rtc_dev->ops = &aml_rtc_ops;
rtc->rtc_dev->range_min = 0;
rtc->rtc_dev->range_max = U32_MAX;
- ret = devm_rtc_register_device(rtc->rtc_dev);
- if (ret) {
- dev_err_probe(&pdev->dev, ret, "Failed to register RTC device: %d\n", ret);
- goto err_clk;
- }
-
- return 0;
-err_clk:
- clk_disable_unprepare(rtc->sys_clk);
- device_init_wakeup(dev, false);
-
- return ret;
+ return devm_rtc_register_device(rtc->rtc_dev);
}
#ifdef CONFIG_PM_SLEEP
@@ -421,14 +408,6 @@ static int aml_rtc_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops,
aml_rtc_suspend, aml_rtc_resume);
-static void aml_rtc_remove(struct platform_device *pdev)
-{
- struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev);
-
- clk_disable_unprepare(rtc->sys_clk);
- device_init_wakeup(&pdev->dev, false);
-}
-
static const struct aml_rtc_config a5_rtc_config = {
};
@@ -451,7 +430,6 @@ MODULE_DEVICE_TABLE(of, aml_rtc_device_id);
static struct platform_driver aml_rtc_driver = {
.probe = aml_rtc_probe,
- .remove = aml_rtc_remove,
.driver = {
.name = "aml-rtc",
.pm = &aml_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-atcrtc100.c b/drivers/rtc/rtc-atcrtc100.c
new file mode 100644
index 000000000000..9808fc2c5a49
--- /dev/null
+++ b/drivers/rtc/rtc-atcrtc100.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for Andes ATCRTC100 real time clock.
+ *
+ * Copyright (C) 2025 Andes Technology Corporation
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/workqueue.h>
+
+/* Register Offsets */
+#define RTC_ID 0x00 /* ID and Revision Register */
+#define RTC_RSV 0x04 /* Reserved Register */
+#define RTC_CNT 0x10 /* Counter Register */
+#define RTC_ALM 0x14 /* Alarm Register */
+#define RTC_CR 0x18 /* Control Register */
+#define RTC_STA 0x1C /* Status Register */
+#define RTC_TRIM 0x20 /* Digital Trimming Register */
+
+/* RTC_ID Register */
+#define ID_MSK GENMASK(31, 8)
+#define ID_ATCRTC100 0x030110
+
+/* RTC_CNT and RTC_ALM Register Fields */
+#define SEC_MSK GENMASK(5, 0)
+#define MIN_MSK GENMASK(11, 6)
+#define HOUR_MSK GENMASK(16, 12)
+#define DAY_MSK GENMASK(31, 17)
+#define RTC_SEC_GET(x) FIELD_GET(SEC_MSK, x)
+#define RTC_MIN_GET(x) FIELD_GET(MIN_MSK, x)
+#define RTC_HOUR_GET(x) FIELD_GET(HOUR_MSK, x)
+#define RTC_DAY_GET(x) FIELD_GET(DAY_MSK, x)
+#define RTC_SEC_SET(x) FIELD_PREP(SEC_MSK, x)
+#define RTC_MIN_SET(x) FIELD_PREP(MIN_MSK, x)
+#define RTC_HOUR_SET(x) FIELD_PREP(HOUR_MSK, x)
+#define RTC_DAY_SET(x) FIELD_PREP(DAY_MSK, x)
+
+/* RTC_CR Register Bits */
+#define RTC_EN BIT(0) /* RTC Enable */
+#define ALARM_WAKEUP BIT(1) /* Alarm Wakeup Enable */
+#define ALARM_INT BIT(2) /* Alarm Interrupt Enable */
+#define DAY_INT BIT(3) /* Day Interrupt Enable */
+#define HOUR_INT BIT(4) /* Hour Interrupt Enable */
+#define MIN_INT BIT(5) /* Minute Interrupt Enable */
+#define SEC_INT BIT(6) /* Second Periodic Interrupt Enable */
+#define HSEC_INT BIT(7) /* Half-Second Periodic Interrupt Enable */
+
+/* RTC_STA Register Bits */
+#define WRITE_DONE BIT(16) /* Register write completion status */
+
+/* Time conversion macro */
+#define ATCRTC_TIME_TO_SEC(D, H, M, S) \
+ ((time64_t)(D) * 86400 + (H) * 3600 + (M) * 60 + (S))
+
+/* Timeout for waiting for the write_done bit */
+#define ATCRTC_TIMEOUT_US 1000000
+#define ATCRTC_TIMEOUT_USLEEP_MIN 20
+#define ATCRTC_TIMEOUT_USLEEP_MAX 30
+
+struct atcrtc_dev {
+ struct rtc_device *rtc_dev;
+ struct regmap *regmap;
+ struct work_struct rtc_work;
+ unsigned int alarm_irq;
+ bool alarm_en;
+};
+
+static const struct regmap_config atcrtc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = RTC_TRIM,
+ .cache_type = REGCACHE_NONE,
+};
+
+/**
+ * atcrtc_check_write_done - Wait for RTC registers to be synchronized.
+ * @rtc: Pointer to the atcrtc_dev structure.
+ *
+ * The WriteDone bit in the status register indicates the synchronization
+ * progress of RTC register updates. This bit is cleared to zero whenever
+ * any RTC control register (Counter, Alarm, Control, etc.) is written.
+ * It returns to one only after all previous updates have been fully
+ * synchronized to the RTC clock domain. This function polls the WriteDone
+ * bit with a timeout to ensure the device is ready for the next operation.
+ *
+ * Return: 0 on success, or -EBUSY on timeout.
+ */
+static int atcrtc_check_write_done(struct atcrtc_dev *rtc)
+{
+ unsigned int val;
+
+ /*
+ * Using read_poll_timeout is more efficient than a manual loop
+ * with usleep_range.
+ */
+ return regmap_read_poll_timeout(rtc->regmap, RTC_STA, val,
+ val & WRITE_DONE,
+ ATCRTC_TIMEOUT_USLEEP_MIN,
+ ATCRTC_TIMEOUT_US);
+}
+
+static irqreturn_t atcrtc_alarm_isr(int irq, void *dev)
+{
+ struct atcrtc_dev *rtc = dev;
+ unsigned int status;
+
+ regmap_read(rtc->regmap, RTC_STA, &status);
+ if (status & ALARM_INT) {
+ regmap_write(rtc->regmap, RTC_STA, ALARM_INT);
+ rtc->alarm_en = false;
+ schedule_work(&rtc->rtc_work);
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static int atcrtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+{
+ struct atcrtc_dev *rtc = dev_get_drvdata(dev);
+ unsigned int mask;
+ int ret;
+
+ ret = atcrtc_check_write_done(rtc);
+ if (ret)
+ return ret;
+
+ mask = ALARM_WAKEUP | ALARM_INT;
+ regmap_update_bits(rtc->regmap, RTC_CR, mask, enable ? mask : 0);
+
+ return 0;
+}
+
+static void atcrtc_alarm_clear(struct work_struct *work)
+{
+ struct atcrtc_dev *rtc =
+ container_of(work, struct atcrtc_dev, rtc_work);
+ int ret;
+
+ rtc_lock(rtc->rtc_dev);
+
+ if (!rtc->alarm_en) {
+ ret = atcrtc_check_write_done(rtc);
+ if (ret)
+ dev_info(&rtc->rtc_dev->dev,
+ "failed to sync before clearing alarm: %d\n",
+ ret);
+ else
+ regmap_update_bits(rtc->regmap, RTC_CR,
+ ALARM_WAKEUP | ALARM_INT, 0);
+ }
+ rtc_unlock(rtc->rtc_dev);
+}
+
+static int atcrtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct atcrtc_dev *rtc = dev_get_drvdata(dev);
+ time64_t time;
+ unsigned int rtc_cnt;
+
+ if (!regmap_test_bits(rtc->regmap, RTC_CR, RTC_EN))
+ return -EIO;
+
+ regmap_read(rtc->regmap, RTC_CNT, &rtc_cnt);
+ time = ATCRTC_TIME_TO_SEC(RTC_DAY_GET(rtc_cnt),
+ RTC_HOUR_GET(rtc_cnt),
+ RTC_MIN_GET(rtc_cnt),
+ RTC_SEC_GET(rtc_cnt));
+ rtc_time64_to_tm(time, tm);
+
+ return 0;
+}
+
+static int atcrtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct atcrtc_dev *rtc = dev_get_drvdata(dev);
+ time64_t time;
+ unsigned int counter;
+ unsigned int day;
+ int ret;
+
+ time = rtc_tm_to_time64(tm);
+ day = div_s64(time, 86400);
+ counter = RTC_DAY_SET(day) |
+ RTC_HOUR_SET(tm->tm_hour) |
+ RTC_MIN_SET(tm->tm_min) |
+ RTC_SEC_SET(tm->tm_sec);
+ ret = atcrtc_check_write_done(rtc);
+ if (ret)
+ return ret;
+ regmap_write(rtc->regmap, RTC_CNT, counter);
+
+ ret = atcrtc_check_write_done(rtc);
+ if (ret)
+ return ret;
+ regmap_update_bits(rtc->regmap, RTC_CR, RTC_EN, RTC_EN);
+
+ return 0;
+}
+
+static int atcrtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct atcrtc_dev *rtc = dev_get_drvdata(dev);
+ struct rtc_time *tm = &wkalrm->time;
+ unsigned int rtc_alarm;
+
+ wkalrm->enabled = regmap_test_bits(rtc->regmap, RTC_CR, ALARM_INT);
+ regmap_read(rtc->regmap, RTC_ALM, &rtc_alarm);
+ tm->tm_hour = RTC_HOUR_GET(rtc_alarm);
+ tm->tm_min = RTC_MIN_GET(rtc_alarm);
+ tm->tm_sec = RTC_SEC_GET(rtc_alarm);
+
+ /* The RTC alarm does not support day/month/year fields */
+ tm->tm_mday = -1;
+ tm->tm_mon = -1;
+ tm->tm_year = -1;
+
+ return 0;
+}
+
+static int atcrtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct atcrtc_dev *rtc = dev_get_drvdata(dev);
+ struct rtc_time *tm = &wkalrm->time;
+ unsigned int rtc_alarm;
+ int ret;
+
+ /* Disable alarm first before setting a new one */
+ ret = atcrtc_alarm_irq_enable(dev, 0);
+ if (ret)
+ return ret;
+
+ rtc->alarm_en = false;
+
+ rtc_alarm = RTC_SEC_SET(tm->tm_sec) |
+ RTC_MIN_SET(tm->tm_min) |
+ RTC_HOUR_SET(tm->tm_hour);
+
+ ret = atcrtc_check_write_done(rtc);
+ if (ret)
+ return ret;
+
+ regmap_write(rtc->regmap, RTC_ALM, rtc_alarm);
+
+ rtc->alarm_en = wkalrm->enabled;
+ ret = atcrtc_alarm_irq_enable(dev, wkalrm->enabled);
+
+ return ret;
+}
+
+static const struct rtc_class_ops rtc_ops = {
+ .read_time = atcrtc_read_time,
+ .set_time = atcrtc_set_time,
+ .read_alarm = atcrtc_read_alarm,
+ .set_alarm = atcrtc_set_alarm,
+ .alarm_irq_enable = atcrtc_alarm_irq_enable,
+};
+
+static int atcrtc_probe(struct platform_device *pdev)
+{
+ struct atcrtc_dev *atcrtc_dev;
+ void __iomem *reg_base;
+ unsigned int rtc_id;
+ int ret;
+
+ atcrtc_dev = devm_kzalloc(&pdev->dev, sizeof(*atcrtc_dev), GFP_KERNEL);
+ if (!atcrtc_dev)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, atcrtc_dev);
+
+ reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg_base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(reg_base),
+ "Failed to map I/O space\n");
+
+ atcrtc_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
+ reg_base,
+ &atcrtc_regmap_config);
+ if (IS_ERR(atcrtc_dev->regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(atcrtc_dev->regmap),
+ "Failed to initialize regmap\n");
+
+ regmap_read(atcrtc_dev->regmap, RTC_ID, &rtc_id);
+ if (FIELD_GET(ID_MSK, rtc_id) != ID_ATCRTC100)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "Failed to initialize RTC: unsupported hardware ID 0x%x\n",
+ rtc_id);
+
+ ret = platform_get_irq(pdev, 1);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to get IRQ for alarm\n");
+ atcrtc_dev->alarm_irq = ret;
+
+ ret = devm_request_irq(&pdev->dev,
+ atcrtc_dev->alarm_irq,
+ atcrtc_alarm_isr,
+ 0,
+ "atcrtc_alarm",
+ atcrtc_dev);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to request IRQ %d for alarm\n",
+ atcrtc_dev->alarm_irq);
+
+ atcrtc_dev->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(atcrtc_dev->rtc_dev))
+ return dev_err_probe(&pdev->dev, PTR_ERR(atcrtc_dev->rtc_dev),
+ "Failed to allocate RTC device\n");
+
+ set_bit(RTC_FEATURE_ALARM, atcrtc_dev->rtc_dev->features);
+ ret = device_init_wakeup(&pdev->dev, true);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to initialize wake capability\n");
+
+ ret = dev_pm_set_wake_irq(&pdev->dev, atcrtc_dev->alarm_irq);
+ if (ret) {
+ device_init_wakeup(&pdev->dev, false);
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to set wake IRQ\n");
+ }
+
+ atcrtc_dev->rtc_dev->ops = &rtc_ops;
+
+ INIT_WORK(&atcrtc_dev->rtc_work, atcrtc_alarm_clear);
+ return devm_rtc_register_device(atcrtc_dev->rtc_dev);
+}
+
+static int atcrtc_resume(struct device *dev)
+{
+ struct atcrtc_dev *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(rtc->alarm_irq);
+
+ return 0;
+}
+
+static int atcrtc_suspend(struct device *dev)
+{
+ struct atcrtc_dev *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(rtc->alarm_irq);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(atcrtc_pm_ops, atcrtc_suspend, atcrtc_resume);
+
+static const struct of_device_id atcrtc_dt_match[] = {
+ { .compatible = "andestech,atcrtc100" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, atcrtc_dt_match);
+
+static struct platform_driver atcrtc_platform_driver = {
+ .driver = {
+ .name = "atcrtc100",
+ .of_match_table = atcrtc_dt_match,
+ .pm = pm_sleep_ptr(&atcrtc_pm_ops),
+ },
+ .probe = atcrtc_probe,
+};
+
+module_platform_driver(atcrtc_platform_driver);
+
+MODULE_AUTHOR("CL Wang <cl634@andestech.com>");
+MODULE_DESCRIPTION("Andes ATCRTC100 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c
index 97423f1d0361..5fc8e36b1abf 100644
--- a/drivers/rtc/rtc-ds1685.c
+++ b/drivers/rtc/rtc-ds1685.c
@@ -1268,9 +1268,6 @@ ds1685_rtc_probe(struct platform_device *pdev)
rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
- /* Maximum periodic rate is 8192Hz (0.122070ms). */
- rtc_dev->max_user_freq = RTC_MAX_USER_FREQ;
-
/* See if the platform doesn't support UIE. */
if (pdata->uie_unsupported)
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc_dev->features);
diff --git a/drivers/rtc/rtc-gamecube.c b/drivers/rtc/rtc-gamecube.c
index c828bc8e05b9..045d5d45ab4b 100644
--- a/drivers/rtc/rtc-gamecube.c
+++ b/drivers/rtc/rtc-gamecube.c
@@ -242,6 +242,10 @@ static int gamecube_rtc_read_offset_from_sram(struct priv *d)
}
hw_srnprot = ioremap(res.start, resource_size(&res));
+ if (!hw_srnprot) {
+ pr_err("failed to ioremap hw_srnprot\n");
+ return -ENOMEM;
+ }
old = ioread32be(hw_srnprot);
/* TODO: figure out why we use this magic constant. I obtained it by
diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c
index 2aabb9151d4c..45a2c9f676c5 100644
--- a/drivers/rtc/rtc-isl12026.c
+++ b/drivers/rtc/rtc-isl12026.c
@@ -484,6 +484,12 @@ static const struct of_device_id isl12026_dt_match[] = {
};
MODULE_DEVICE_TABLE(of, isl12026_dt_match);
+static const struct i2c_device_id isl12026_id[] = {
+ { "isl12026" },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, isl12026_id);
+
static struct i2c_driver isl12026_driver = {
.driver = {
.name = "rtc-isl12026",
@@ -491,6 +497,7 @@ static struct i2c_driver isl12026_driver = {
},
.probe = isl12026_probe,
.remove = isl12026_remove,
+ .id_table = isl12026_id,
};
module_i2c_driver(isl12026_driver);
diff --git a/drivers/rtc/rtc-macsmc.c b/drivers/rtc/rtc-macsmc.c
new file mode 100644
index 000000000000..8fe883066956
--- /dev/null
+++ b/drivers/rtc/rtc-macsmc.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Apple SMC RTC driver
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <linux/bitops.h>
+#include <linux/mfd/macsmc.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+
+/* 48-bit RTC */
+#define RTC_BYTES 6
+#define RTC_BITS (8 * RTC_BYTES)
+
+/* 32768 Hz clock */
+#define RTC_SEC_SHIFT 15
+
+struct macsmc_rtc {
+ struct device *dev;
+ struct apple_smc *smc;
+ struct rtc_device *rtc_dev;
+ struct nvmem_cell *rtc_offset;
+};
+
+static int macsmc_rtc_get_time(struct device *dev, struct rtc_time *tm)
+{
+ struct macsmc_rtc *rtc = dev_get_drvdata(dev);
+ u64 ctr = 0, off = 0;
+ time64_t now;
+ void *p_off;
+ size_t len;
+ int ret;
+
+ ret = apple_smc_read(rtc->smc, SMC_KEY(CLKM), &ctr, RTC_BYTES);
+ if (ret < 0)
+ return ret;
+ if (ret != RTC_BYTES)
+ return -EIO;
+
+ p_off = nvmem_cell_read(rtc->rtc_offset, &len);
+ if (IS_ERR(p_off))
+ return PTR_ERR(p_off);
+ if (len < RTC_BYTES) {
+ kfree(p_off);
+ return -EIO;
+ }
+
+ memcpy(&off, p_off, RTC_BYTES);
+ kfree(p_off);
+
+ /* Sign extend from 48 to 64 bits, then arithmetic shift right 15 bits to get seconds */
+ now = sign_extend64(ctr + off, RTC_BITS - 1) >> RTC_SEC_SHIFT;
+ rtc_time64_to_tm(now, tm);
+
+ return ret;
+}
+
+static int macsmc_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct macsmc_rtc *rtc = dev_get_drvdata(dev);
+ u64 ctr = 0, off = 0;
+ int ret;
+
+ ret = apple_smc_read(rtc->smc, SMC_KEY(CLKM), &ctr, RTC_BYTES);
+ if (ret < 0)
+ return ret;
+ if (ret != RTC_BYTES)
+ return -EIO;
+
+ /* This sets the offset such that the set second begins now */
+ off = (rtc_tm_to_time64(tm) << RTC_SEC_SHIFT) - ctr;
+ return nvmem_cell_write(rtc->rtc_offset, &off, RTC_BYTES);
+}
+
+static const struct rtc_class_ops macsmc_rtc_ops = {
+ .read_time = macsmc_rtc_get_time,
+ .set_time = macsmc_rtc_set_time,
+};
+
+static int macsmc_rtc_probe(struct platform_device *pdev)
+{
+ struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent);
+ struct macsmc_rtc *rtc;
+
+ /*
+ * MFD will probe this device even without a node in the device tree,
+ * thus bail out early if the SMC on the current machines does not
+ * support RTC and has no node in the device tree.
+ */
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ rtc->dev = &pdev->dev;
+ rtc->smc = smc;
+
+ rtc->rtc_offset = devm_nvmem_cell_get(&pdev->dev, "rtc_offset");
+ if (IS_ERR(rtc->rtc_offset))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rtc->rtc_offset),
+ "Failed to get rtc_offset NVMEM cell\n");
+
+ rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(rtc->rtc_dev))
+ return PTR_ERR(rtc->rtc_dev);
+
+ rtc->rtc_dev->ops = &macsmc_rtc_ops;
+ rtc->rtc_dev->range_min = S64_MIN >> (RTC_SEC_SHIFT + (64 - RTC_BITS));
+ rtc->rtc_dev->range_max = S64_MAX >> (RTC_SEC_SHIFT + (64 - RTC_BITS));
+
+ platform_set_drvdata(pdev, rtc);
+
+ return devm_rtc_register_device(rtc->rtc_dev);
+}
+
+static const struct of_device_id macsmc_rtc_of_table[] = {
+ { .compatible = "apple,smc-rtc", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, macsmc_rtc_of_table);
+
+static struct platform_driver macsmc_rtc_driver = {
+ .driver = {
+ .name = "macsmc-rtc",
+ .of_match_table = macsmc_rtc_of_table,
+ },
+ .probe = macsmc_rtc_probe,
+};
+module_platform_driver(macsmc_rtc_driver);
+
+MODULE_LICENSE("Dual MIT/GPL");
+MODULE_DESCRIPTION("Apple SMC RTC driver");
+MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c
index dfb5bad3a369..23b7bf16b4cd 100644
--- a/drivers/rtc/rtc-max31335.c
+++ b/drivers/rtc/rtc-max31335.c
@@ -391,10 +391,8 @@ static int max31335_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (ret)
return ret;
- ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,
- MAX31335_STATUS1_A1F, 0);
-
- return 0;
+ return regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,
+ MAX31335_STATUS1_A1F, 0);
}
static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled)
diff --git a/drivers/rtc/rtc-nvidia-vrs10.c b/drivers/rtc/rtc-nvidia-vrs10.c
new file mode 100644
index 000000000000..b15796698558
--- /dev/null
+++ b/drivers/rtc/rtc-nvidia-vrs10.c
@@ -0,0 +1,542 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * NVIDIA Voltage Regulator Specification RTC
+ *
+ * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
+ * All rights reserved.
+ */
+
+#include <linux/bits.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+
+#define NVVRS_REG_VENDOR_ID 0x00
+#define NVVRS_REG_MODEL_REV 0x01
+
+/* Interrupts registers */
+#define NVVRS_REG_INT_SRC1 0x10
+#define NVVRS_REG_INT_SRC2 0x11
+#define NVVRS_REG_INT_VENDOR 0x12
+
+/* Control Registers */
+#define NVVRS_REG_CTL_1 0x28
+#define NVVRS_REG_CTL_2 0x29
+
+/* RTC Registers */
+#define NVVRS_REG_RTC_T3 0x70
+#define NVVRS_REG_RTC_T2 0x71
+#define NVVRS_REG_RTC_T1 0x72
+#define NVVRS_REG_RTC_T0 0x73
+#define NVVRS_REG_RTC_A3 0x74
+#define NVVRS_REG_RTC_A2 0x75
+#define NVVRS_REG_RTC_A1 0x76
+#define NVVRS_REG_RTC_A0 0x77
+
+/* Interrupt Mask */
+#define NVVRS_INT_SRC1_RSTIRQ_MASK BIT(0)
+#define NVVRS_INT_SRC1_OSC_MASK BIT(1)
+#define NVVRS_INT_SRC1_EN_MASK BIT(2)
+#define NVVRS_INT_SRC1_RTC_MASK BIT(3)
+#define NVVRS_INT_SRC1_PEC_MASK BIT(4)
+#define NVVRS_INT_SRC1_WDT_MASK BIT(5)
+#define NVVRS_INT_SRC1_EM_PD_MASK BIT(6)
+#define NVVRS_INT_SRC1_INTERNAL_MASK BIT(7)
+#define NVVRS_INT_SRC2_PBSP_MASK BIT(0)
+#define NVVRS_INT_SRC2_ECC_DED_MASK BIT(1)
+#define NVVRS_INT_SRC2_TSD_MASK BIT(2)
+#define NVVRS_INT_SRC2_LDO_MASK BIT(3)
+#define NVVRS_INT_SRC2_BIST_MASK BIT(4)
+#define NVVRS_INT_SRC2_RT_CRC_MASK BIT(5)
+#define NVVRS_INT_SRC2_VENDOR_MASK BIT(7)
+#define NVVRS_INT_VENDOR0_MASK BIT(0)
+#define NVVRS_INT_VENDOR1_MASK BIT(1)
+#define NVVRS_INT_VENDOR2_MASK BIT(2)
+#define NVVRS_INT_VENDOR3_MASK BIT(3)
+#define NVVRS_INT_VENDOR4_MASK BIT(4)
+#define NVVRS_INT_VENDOR5_MASK BIT(5)
+#define NVVRS_INT_VENDOR6_MASK BIT(6)
+#define NVVRS_INT_VENDOR7_MASK BIT(7)
+
+/* Controller Register Mask */
+#define NVVRS_REG_CTL_1_FORCE_SHDN (BIT(0) | BIT(1))
+#define NVVRS_REG_CTL_1_FORCE_ACT BIT(2)
+#define NVVRS_REG_CTL_1_FORCE_INT BIT(3)
+#define NVVRS_REG_CTL_2_EN_PEC BIT(0)
+#define NVVRS_REG_CTL_2_REQ_PEC BIT(1)
+#define NVVRS_REG_CTL_2_RTC_PU BIT(2)
+#define NVVRS_REG_CTL_2_RTC_WAKE BIT(3)
+#define NVVRS_REG_CTL_2_RST_DLY 0xF0
+
+#define ALARM_RESET_VAL 0xffffffff
+#define NVVRS_MIN_MODEL_REV 0x40
+
+enum nvvrs_irq_regs {
+ NVVRS_IRQ_REG_INT_SRC1 = 0,
+ NVVRS_IRQ_REG_INT_SRC2 = 1,
+ NVVRS_IRQ_REG_INT_VENDOR = 2,
+ NVVRS_IRQ_REG_COUNT = 3,
+};
+
+struct nvvrs_rtc_info {
+ struct device *dev;
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+ unsigned int irq;
+};
+
+static int nvvrs_update_bits(struct nvvrs_rtc_info *info, u8 reg,
+ u8 mask, u8 value)
+{
+ int ret;
+ u8 val;
+
+ ret = i2c_smbus_read_byte_data(info->client, reg);
+ if (ret < 0)
+ return ret;
+
+ val = (u8)ret;
+ val &= ~mask;
+ val |= (value & mask);
+
+ return i2c_smbus_write_byte_data(info->client, reg, val);
+}
+
+static int nvvrs_rtc_write_alarm(struct i2c_client *client, u8 *time)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A3, time[3]);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A2, time[2]);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A1, time[1]);
+ if (ret < 0)
+ return ret;
+
+ return i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A0, time[0]);
+}
+
+static int nvvrs_rtc_enable_alarm(struct nvvrs_rtc_info *info)
+{
+ int ret;
+
+ /* Set RTC_WAKE bit for autonomous wake from sleep */
+ ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_WAKE,
+ NVVRS_REG_CTL_2_RTC_WAKE);
+ if (ret < 0)
+ return ret;
+
+ /* Set RTC_PU bit for autonomous wake from shutdown */
+ ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_PU,
+ NVVRS_REG_CTL_2_RTC_PU);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int nvvrs_rtc_disable_alarm(struct nvvrs_rtc_info *info)
+{
+ struct i2c_client *client = info->client;
+ u8 val[4];
+ int ret;
+
+ /* Clear RTC_WAKE bit */
+ ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_WAKE,
+ 0);
+ if (ret < 0)
+ return ret;
+
+ /* Clear RTC_PU bit */
+ ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_PU,
+ 0);
+ if (ret < 0)
+ return ret;
+
+ /* Write ALARM_RESET_VAL in RTC Alarm register to disable alarm */
+ val[0] = 0xff;
+ val[1] = 0xff;
+ val[2] = 0xff;
+ val[3] = 0xff;
+
+ ret = nvvrs_rtc_write_alarm(client, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int nvvrs_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ time64_t secs = 0;
+ int ret;
+ u8 val;
+
+ /*
+ * Multi-byte transfers are not supported with PEC enabled
+ * Read MSB first to avoid coherency issues
+ */
+ ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T3);
+ if (ret < 0)
+ return ret;
+
+ val = (u8)ret;
+ secs |= (time64_t)val << 24;
+
+ ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T2);
+ if (ret < 0)
+ return ret;
+
+ val = (u8)ret;
+ secs |= (time64_t)val << 16;
+
+ ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T1);
+ if (ret < 0)
+ return ret;
+
+ val = (u8)ret;
+ secs |= (time64_t)val << 8;
+
+ ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T0);
+ if (ret < 0)
+ return ret;
+
+ val = (u8)ret;
+ secs |= val;
+
+ rtc_time64_to_tm(secs, tm);
+
+ return 0;
+}
+
+static int nvvrs_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ time64_t secs;
+ u8 time[4];
+ int ret;
+
+ secs = rtc_tm_to_time64(tm);
+ time[0] = secs & 0xff;
+ time[1] = (secs >> 8) & 0xff;
+ time[2] = (secs >> 16) & 0xff;
+ time[3] = (secs >> 24) & 0xff;
+
+ ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T3, time[3]);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T2, time[2]);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T1, time[1]);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T0, time[0]);
+
+ return ret;
+}
+
+static int nvvrs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ time64_t alarm_val = 0;
+ int ret;
+ u8 val;
+
+ /* Multi-byte transfers are not supported with PEC enabled */
+ ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A3);
+ if (ret < 0)
+ return ret;
+
+ val = (u8)ret;
+ alarm_val |= (time64_t)val << 24;
+
+ ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A2);
+ if (ret < 0)
+ return ret;
+
+ val = (u8)ret;
+ alarm_val |= (time64_t)val << 16;
+
+ ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A1);
+ if (ret < 0)
+ return ret;
+
+ val = (u8)ret;
+ alarm_val |= (time64_t)val << 8;
+
+ ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A0);
+ if (ret < 0)
+ return ret;
+
+ val = (u8)ret;
+ alarm_val |= val;
+
+ if (alarm_val == ALARM_RESET_VAL)
+ alrm->enabled = 0;
+ else
+ alrm->enabled = 1;
+
+ rtc_time64_to_tm(alarm_val, &alrm->time);
+
+ return 0;
+}
+
+static int nvvrs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ time64_t secs;
+ u8 time[4];
+ int ret;
+
+ if (!alrm->enabled) {
+ ret = nvvrs_rtc_disable_alarm(info);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = nvvrs_rtc_enable_alarm(info);
+ if (ret < 0)
+ return ret;
+
+ secs = rtc_tm_to_time64(&alrm->time);
+ time[0] = secs & 0xff;
+ time[1] = (secs >> 8) & 0xff;
+ time[2] = (secs >> 16) & 0xff;
+ time[3] = (secs >> 24) & 0xff;
+
+ ret = nvvrs_rtc_write_alarm(info->client, time);
+
+ return ret;
+}
+
+static int nvvrs_pseq_irq_clear(struct nvvrs_rtc_info *info)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < NVVRS_IRQ_REG_COUNT; i++) {
+ ret = i2c_smbus_read_byte_data(info->client,
+ NVVRS_REG_INT_SRC1 + i);
+ if (ret < 0) {
+ dev_err(info->dev, "Failed to read INT_SRC%d : %d\n",
+ i + 1, ret);
+ return ret;
+ }
+
+ ret = i2c_smbus_write_byte_data(info->client,
+ NVVRS_REG_INT_SRC1 + i,
+ (u8)ret);
+ if (ret < 0) {
+ dev_err(info->dev, "Failed to clear INT_SRC%d : %d\n",
+ i + 1, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static irqreturn_t nvvrs_rtc_irq_handler(int irq, void *data)
+{
+ struct nvvrs_rtc_info *info = data;
+ int ret;
+
+ /* Check for RTC alarm interrupt */
+ ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_INT_SRC1);
+ if (ret < 0)
+ return IRQ_NONE;
+
+ if (ret & NVVRS_INT_SRC1_RTC_MASK) {
+ rtc_lock(info->rtc);
+ rtc_update_irq(info->rtc, 1, RTC_IRQF | RTC_AF);
+ rtc_unlock(info->rtc);
+ }
+
+ /* Clear all interrupts */
+ if (nvvrs_pseq_irq_clear(info) < 0)
+ return IRQ_NONE;
+
+ return IRQ_HANDLED;
+}
+
+static int nvvrs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ /*
+ * This hardware does not support enabling/disabling the alarm IRQ
+ * independently. The alarm is disabled by clearing the alarm time
+ * via set_alarm().
+ */
+ return 0;
+}
+
+static const struct rtc_class_ops nvvrs_rtc_ops = {
+ .read_time = nvvrs_rtc_read_time,
+ .set_time = nvvrs_rtc_set_time,
+ .read_alarm = nvvrs_rtc_read_alarm,
+ .set_alarm = nvvrs_rtc_set_alarm,
+ .alarm_irq_enable = nvvrs_rtc_alarm_irq_enable,
+};
+
+static int nvvrs_pseq_vendor_info(struct nvvrs_rtc_info *info)
+{
+ struct i2c_client *client = info->client;
+ u8 vendor_id, model_rev;
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_REG_VENDOR_ID);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to read Vendor ID\n");
+
+ vendor_id = (u8)ret;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_REG_MODEL_REV);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to read Model Revision\n");
+
+ model_rev = (u8)ret;
+
+ if (model_rev < NVVRS_MIN_MODEL_REV) {
+ return dev_err_probe(&client->dev, -ENODEV,
+ "Chip revision 0x%02x is not supported!\n",
+ model_rev);
+ }
+
+ dev_dbg(&client->dev, "NVVRS Vendor ID: 0x%02x, Model Rev: 0x%02x\n",
+ vendor_id, model_rev);
+
+ return 0;
+}
+
+static int nvvrs_rtc_probe(struct i2c_client *client)
+{
+ struct nvvrs_rtc_info *info;
+ int ret;
+
+ info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ if (client->irq <= 0)
+ return dev_err_probe(&client->dev, -EINVAL, "No IRQ specified\n");
+
+ info->irq = client->irq;
+ info->dev = &client->dev;
+ client->flags |= I2C_CLIENT_PEC;
+ i2c_set_clientdata(client, info);
+ info->client = client;
+
+ /* Check vendor info */
+ if (nvvrs_pseq_vendor_info(info) < 0)
+ return dev_err_probe(&client->dev, -EINVAL,
+ "Failed to get vendor info\n");
+
+ /* Clear any pending IRQs before requesting IRQ handler */
+ if (nvvrs_pseq_irq_clear(info) < 0)
+ return dev_err_probe(&client->dev, -EINVAL,
+ "Failed to clear interrupts\n");
+
+ /* Allocate RTC device */
+ info->rtc = devm_rtc_allocate_device(info->dev);
+ if (IS_ERR(info->rtc))
+ return PTR_ERR(info->rtc);
+
+ info->rtc->ops = &nvvrs_rtc_ops;
+ info->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ info->rtc->range_max = RTC_TIMESTAMP_END_2099;
+
+ /* Request RTC IRQ */
+ ret = devm_request_threaded_irq(info->dev, info->irq, NULL,
+ nvvrs_rtc_irq_handler, IRQF_ONESHOT,
+ "nvvrs-rtc", info);
+ if (ret < 0) {
+ dev_err_probe(info->dev, ret, "Failed to request RTC IRQ\n");
+ return ret;
+ }
+
+ /* RTC as a wakeup source */
+ devm_device_init_wakeup(info->dev);
+
+ return devm_rtc_register_device(info->rtc);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int nvvrs_rtc_suspend(struct device *dev)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ int ret;
+
+ if (device_may_wakeup(dev)) {
+ /* Set RTC_WAKE bit for auto wake system from suspend state */
+ ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2,
+ NVVRS_REG_CTL_2_RTC_WAKE,
+ NVVRS_REG_CTL_2_RTC_WAKE);
+ if (ret < 0) {
+ dev_err(info->dev, "Failed to set RTC_WAKE bit (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return enable_irq_wake(info->irq);
+ }
+
+ return 0;
+}
+
+static int nvvrs_rtc_resume(struct device *dev)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ int ret;
+
+ if (device_may_wakeup(dev)) {
+ /* Clear FORCE_ACT bit */
+ ret = nvvrs_update_bits(info, NVVRS_REG_CTL_1,
+ NVVRS_REG_CTL_1_FORCE_ACT, 0);
+ if (ret < 0) {
+ dev_err(info->dev, "Failed to clear FORCE_ACT bit (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return disable_irq_wake(info->irq);
+ }
+
+ return 0;
+}
+
+#endif
+static SIMPLE_DEV_PM_OPS(nvvrs_rtc_pm_ops, nvvrs_rtc_suspend, nvvrs_rtc_resume);
+
+static const struct of_device_id nvvrs_rtc_of_match[] = {
+ { .compatible = "nvidia,vrs-10" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, nvvrs_rtc_of_match);
+
+static struct i2c_driver nvvrs_rtc_driver = {
+ .driver = {
+ .name = "rtc-nvidia-vrs10",
+ .pm = &nvvrs_rtc_pm_ops,
+ .of_match_table = nvvrs_rtc_of_match,
+ },
+ .probe = nvvrs_rtc_probe,
+};
+
+module_i2c_driver(nvvrs_rtc_driver);
+
+MODULE_AUTHOR("Shubhi Garg <shgarg@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Voltage Regulator Specification RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c
index 2812da2c50c5..52c11532bc3a 100644
--- a/drivers/rtc/rtc-pic32.c
+++ b/drivers/rtc/rtc-pic32.c
@@ -340,8 +340,6 @@ static int pic32_rtc_probe(struct platform_device *pdev)
if (ret)
goto err_nortc;
- pdata->rtc->max_user_freq = 128;
-
pic32_rtc_setfreq(&pdev->dev, 1);
ret = devm_request_irq(&pdev->dev, pdata->alarm_irq,
pic32_rtc_alarmirq, 0,
diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c
index ab816bdf0d77..cbabaa4dc96a 100644
--- a/drivers/rtc/rtc-renesas-rtca3.c
+++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -726,7 +726,7 @@ static int rtca3_probe(struct platform_device *pdev)
if (ret)
return ret;
- priv->rstc = devm_reset_control_get_shared(dev, NULL);
+ priv->rstc = devm_reset_control_array_get_shared(dev);
if (IS_ERR(priv->rstc))
return PTR_ERR(priv->rstc);
@@ -772,7 +772,6 @@ static int rtca3_probe(struct platform_device *pdev)
return PTR_ERR(priv->rtc_dev);
priv->rtc_dev->ops = &rtca3_ops;
- priv->rtc_dev->max_user_freq = 256;
priv->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
priv->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c
index c2a531f0e125..d96f6bb68850 100644
--- a/drivers/rtc/rtc-rv3028.c
+++ b/drivers/rtc/rtc-rv3028.c
@@ -1023,8 +1023,6 @@ static int rv3028_probe(struct i2c_client *client)
eeprom_cfg.priv = rv3028;
devm_rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
- rv3028->rtc->max_user_freq = 1;
-
#ifdef CONFIG_COMMON_CLK
rv3028_clkout_register_clk(rv3028, client);
#endif
diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c
index b8376bd1d905..6c09da7738e1 100644
--- a/drivers/rtc/rtc-rv3032.c
+++ b/drivers/rtc/rtc-rv3032.c
@@ -968,8 +968,6 @@ static int rv3032_probe(struct i2c_client *client)
eeprom_cfg.priv = rv3032;
devm_rtc_nvmem_register(rv3032->rtc, &eeprom_cfg);
- rv3032->rtc->max_user_freq = 1;
-
#ifdef CONFIG_COMMON_CLK
rv3032_clkout_register_clk(rv3032, client);
#endif
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 1327251e527c..4e9e04cbec89 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -738,8 +738,6 @@ static int rv8803_probe(struct i2c_client *client)
devm_rtc_nvmem_register(rv8803->rtc, &nvmem_cfg);
- rv8803->rtc->max_user_freq = 1;
-
return 0;
}
diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c
index 7c423d672adb..07bf35ac8d79 100644
--- a/drivers/rtc/rtc-rx6110.c
+++ b/drivers/rtc/rtc-rx6110.c
@@ -324,8 +324,6 @@ static int rx6110_probe(struct rx6110_data *rx6110, struct device *dev)
if (err)
return err;
- rx6110->rtc->max_user_freq = 1;
-
return 0;
}
diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c
index 2b6198d1cf81..171240e50f48 100644
--- a/drivers/rtc/rtc-rx8010.c
+++ b/drivers/rtc/rtc-rx8010.c
@@ -412,7 +412,6 @@ static int rx8010_probe(struct i2c_client *client)
}
rx8010->rtc->ops = &rx8010_rtc_ops;
- rx8010->rtc->max_user_freq = 1;
rx8010->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rx8010->rtc->range_max = RTC_TIMESTAMP_END_2099;
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 7e9f7cb90c28..ced6e7adfe8d 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -565,8 +565,6 @@ static int rx8025_probe(struct i2c_client *client)
clear_bit(RTC_FEATURE_ALARM, rx8025->rtc->features);
}
- rx8025->rtc->max_user_freq = 1;
-
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rx8025->rtc->features);
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rx8025->rtc->features);
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index 3408d2ab2741..07bd983b5692 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -66,7 +66,7 @@ struct s35390a {
int twentyfourhour;
};
-static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len)
+static int s35390a_set_reg(struct s35390a *s35390a, int reg, u8 *buf, int len)
{
struct i2c_client *client = s35390a->client[reg];
struct i2c_msg msg[] = {
@@ -83,7 +83,7 @@ static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len)
return 0;
}
-static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
+static int s35390a_get_reg(struct s35390a *s35390a, int reg, u8 *buf, int len)
{
struct i2c_client *client = s35390a->client[reg];
struct i2c_msg msg[] = {
@@ -168,7 +168,7 @@ static int s35390a_read_status(struct s35390a *s35390a, char *status1)
static int s35390a_disable_test_mode(struct s35390a *s35390a)
{
- char buf[1];
+ u8 buf[1];
if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0)
return -EIO;
@@ -210,7 +210,7 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
int i;
- char buf[7], status;
+ u8 buf[7], status;
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, "
"mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec,
@@ -239,7 +239,7 @@ static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
- char buf[7], status;
+ u8 buf[7], status;
int i, err;
if (s35390a_read_status(s35390a, &status) == 1)
@@ -273,7 +273,7 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
- char buf[3], sts = 0;
+ u8 buf[3], sts = 0;
int err, i;
dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\
@@ -326,7 +326,7 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
- char buf[3], sts;
+ u8 buf[3], sts;
int i, err;
err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
@@ -383,7 +383,7 @@ static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd,
{
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
- char sts;
+ u8 sts;
int err;
switch (cmd) {
@@ -422,7 +422,7 @@ static int s35390a_probe(struct i2c_client *client)
unsigned int i;
struct s35390a *s35390a;
struct rtc_device *rtc;
- char buf, status1;
+ u8 buf, status1;
struct device *dev = &client->dev;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 1ad93648d69c..26b2f4184ecc 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -40,8 +40,6 @@
#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
-#define RTC_FREQ 1024
-
static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
{
@@ -202,7 +200,6 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
}
info->rtc->ops = &sa1100_rtc_ops;
- info->rtc->max_user_freq = RTC_FREQ;
info->rtc->range_max = U32_MAX;
ret = devm_rtc_register_device(info->rtc);
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 619800a00479..0510dc64c3e2 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -423,7 +423,6 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
writeb(tmp, rtc->regbase + RCR1);
rtc->rtc_dev->ops = &sh_rtc_ops;
- rtc->rtc_dev->max_user_freq = 256;
if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index 46788db89953..528e32b7d101 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -274,6 +274,12 @@ static const struct of_device_id tegra_rtc_dt_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match);
+static const struct acpi_device_id tegra_rtc_acpi_match[] = {
+ { "NVDA0280" },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, tegra_rtc_acpi_match);
+
static int tegra_rtc_probe(struct platform_device *pdev)
{
struct tegra_rtc_info *info;
@@ -300,13 +306,11 @@ static int tegra_rtc_probe(struct platform_device *pdev)
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))
- return PTR_ERR(info->clk);
-
- ret = clk_prepare_enable(info->clk);
- if (ret < 0)
- return ret;
+ if (dev_of_node(&pdev->dev)) {
+ info->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(info->clk))
+ return PTR_ERR(info->clk);
+ }
/* set context info */
info->pdev = pdev;
@@ -324,32 +328,18 @@ static int tegra_rtc_probe(struct platform_device *pdev)
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, "failed to request interrupt: %d\n", ret);
- goto disable_clk;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to request interrupt\n");
ret = devm_rtc_register_device(info->rtc);
if (ret)
- goto disable_clk;
+ return ret;
dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
return 0;
-
-disable_clk:
- clk_disable_unprepare(info->clk);
- return ret;
-}
-
-static void tegra_rtc_remove(struct platform_device *pdev)
-{
- struct tegra_rtc_info *info = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(info->clk);
}
-#ifdef CONFIG_PM_SLEEP
static int tegra_rtc_suspend(struct device *dev)
{
struct tegra_rtc_info *info = dev_get_drvdata(dev);
@@ -387,9 +377,8 @@ static int tegra_rtc_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume);
static void tegra_rtc_shutdown(struct platform_device *pdev)
{
@@ -399,12 +388,12 @@ static void tegra_rtc_shutdown(struct platform_device *pdev)
static struct platform_driver tegra_rtc_driver = {
.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,
+ .acpi_match_table = tegra_rtc_acpi_match,
+ .pm = pm_sleep_ptr(&tegra_rtc_pm_ops),
},
};
module_platform_driver(tegra_rtc_driver);