Contributors: 1
Author Tokens Token Proportion Commits Commit Proportion
Shubhi Garg 2287 100.00% 1 100.00%
Total 2287 1


// 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");