]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rtc: nvvrs: add NVIDIA VRS RTC device driver
authorShubhi Garg <shgarg@nvidia.com>
Tue, 7 Oct 2025 13:57:37 +0000 (13:57 +0000)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Thu, 6 Nov 2025 22:50:08 +0000 (23:50 +0100)
Add support for NVIDIA VRS (Voltage Regulator Specification) RTC device
driver. NVIDIA VRS is a Power Management IC (PMIC) that implements a
power sequencing solution with I2C interface. The device includes RTC
which provides functionality to get/set system time, retain system
time across boot, wake system from suspend and shutdown state.

Supported platforms:
- NVIDIA Jetson AGX Orin Developer Kit
- NVIDIA IGX Orin Development Kit
- NVIDIA Jetson Orin NX Developer Kit
- NVIDIA Jetson Orin Nano Developer Kit

Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Link: https://patch.msgid.link/20251007135738.487694-4-shgarg@nvidia.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
MAINTAINERS
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-nvidia-vrs10.c [new file with mode: 0644]

index da1e75d4cb9eeaa3f2e083e405841cd1fcdf9364..a3b87f2c9eb60cde45cbad0eaff269dbc1bcb1ea 100644 (file)
@@ -18428,6 +18428,14 @@ S:     Maintained
 F:     drivers/video/fbdev/nvidia/
 F:     drivers/video/fbdev/riva/
 
+NVIDIA VRS RTC DRIVER
+M:     Shubhi Garg <shgarg@nvidia.com>
+L:     linux-tegra@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/rtc/nvidia,vrs-10.yaml
+F:     drivers/rtc/rtc-nvidia-vrs10.c
+F:     include/linux/rtc/rtc-nvidia-vrs10.h
+
 NVIDIA WMI EC BACKLIGHT DRIVER
 M:     Daniel Dadap <ddadap@nvidia.com>
 L:     platform-driver-x86@vger.kernel.org
index 5d509254824ea2d257f7a4da461dbac52c5d852d..8154fd251c9f7f8293957c0464937fd1394d17a3 100644 (file)
@@ -416,6 +416,15 @@ config RTC_DRV_SPACEMIT_P1
          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
index f1b5c3d123c0bee7b6309b1d480e19758437b073..e464a90be323e0d6b7fa436fe4ada54a6b65bbed 100644 (file)
@@ -122,6 +122,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-nvidia-vrs10.c b/drivers/rtc/rtc-nvidia-vrs10.c
new file mode 100644 (file)
index 0000000..b157966
--- /dev/null
@@ -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");