root/drivers/rtc/rtc-nvidia-vrs10.c
// 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");