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