* [PATCH V2 1/6] dt-bindings: mfd: add bindings for NVIDIA VRS PSEQ
2025-05-20 9:08 [PATCH V2 0/6] Add NVIDIA VRS PSEQ support Shubhi Garg
@ 2025-05-20 9:08 ` Shubhi Garg
2025-05-21 9:09 ` Krzysztof Kozlowski
2025-05-20 9:08 ` [PATCH V2 2/6] arm64: tegra: Add device-tree node for NVVRS PSEQ Shubhi Garg
` (4 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Shubhi Garg @ 2025-05-20 9:08 UTC (permalink / raw)
To: jonathanh, lee, robh, krzk, alexandre.belloni, thierry.reding,
devicetree, linux-tegra, linux-kernel
Cc: Shubhi Garg
Add bindings for NVIDIA VRS (Voltage Regulator Specification) power
sequencer device. NVIDIA VRS PSEQ controls ON/OFF and suspend/resume
power sequencing of system power rails on Tegra234 SoC. This device
also provides 32kHz RTC support with backup battery for system timing.
Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
---
v2:
- fixed copyrights
- updated description with RTC information
- added status node in dtb node example
.../bindings/mfd/nvidia,vrs-pseq.yaml | 60 +++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/nvidia,vrs-pseq.yaml
diff --git a/Documentation/devicetree/bindings/mfd/nvidia,vrs-pseq.yaml b/Documentation/devicetree/bindings/mfd/nvidia,vrs-pseq.yaml
new file mode 100644
index 000000000000..676a29d4e1fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/nvidia,vrs-pseq.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/nvidia,vrs-pseq.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Voltage Regulator Specification Power Sequencer
+
+maintainers:
+ - Shubhi Garg <shgarg@nvidia.com>
+
+description:
+ NVIDIA Voltage Regulator Specification Power Sequencer device controls
+ ON/OFF and suspend/resume power sequencing of system power rails for NVIDIA
+ SoCs. It provides 32kHz RTC clock support with backup battery for system
+ timing. The device also acts as an interrupt controller for managing
+ interrupts from the VRS power sequencer.
+
+properties:
+ compatible:
+ const: nvidia,vrs-pseq
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+ description:
+ The first cell is the IRQ number, the second cell is the trigger type.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-controller
+ - "#interrupt-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vrs@3c {
+ compatible = "nvidia,vrs-pseq";
+ reg = <0x3c>;
+ interrupt-parent = <&pmc>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH V2 1/6] dt-bindings: mfd: add bindings for NVIDIA VRS PSEQ
2025-05-20 9:08 ` [PATCH V2 1/6] dt-bindings: mfd: add bindings for NVIDIA VRS PSEQ Shubhi Garg
@ 2025-05-21 9:09 ` Krzysztof Kozlowski
0 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-21 9:09 UTC (permalink / raw)
To: Shubhi Garg
Cc: jonathanh, lee, robh, alexandre.belloni, thierry.reding,
devicetree, linux-tegra, linux-kernel
On Tue, May 20, 2025 at 09:08:27AM GMT, Shubhi Garg wrote:
> Add bindings for NVIDIA VRS (Voltage Regulator Specification) power
> sequencer device. NVIDIA VRS PSEQ controls ON/OFF and suspend/resume
> power sequencing of system power rails on Tegra234 SoC. This device
> also provides 32kHz RTC support with backup battery for system timing.
>
A nit, subject: drop second/last, redundant "bindings for". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v6.7-rc8/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
> Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
> ---
>
> v2:
> - fixed copyrights
> - updated description with RTC information
> - added status node in dtb node example
>
> .../bindings/mfd/nvidia,vrs-pseq.yaml | 60 +++++++++++++++++++
> 1 file changed, 60 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/nvidia,vrs-pseq.yaml
>
> diff --git a/Documentation/devicetree/bindings/mfd/nvidia,vrs-pseq.yaml b/Documentation/devicetree/bindings/mfd/nvidia,vrs-pseq.yaml
> new file mode 100644
> index 000000000000..676a29d4e1fa
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/nvidia,vrs-pseq.yaml
> @@ -0,0 +1,60 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/nvidia,vrs-pseq.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NVIDIA Voltage Regulator Specification Power Sequencer
> +
> +maintainers:
> + - Shubhi Garg <shgarg@nvidia.com>
> +
> +description:
> + NVIDIA Voltage Regulator Specification Power Sequencer device controls
> + ON/OFF and suspend/resume power sequencing of system power rails for NVIDIA
> + SoCs. It provides 32kHz RTC clock support with backup battery for system
> + timing. The device also acts as an interrupt controller for managing
> + interrupts from the VRS power sequencer.
> +
> +properties:
> + compatible:
> + const: nvidia,vrs-pseq
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + interrupt-controller: true
> +
> + '#interrupt-cells':
Use consistent quotes, either ' or "
> + const: 2
> + description:
> + The first cell is the IRQ number, the second cell is the trigger type.
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - interrupt-controller
> + - "#interrupt-cells"
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/irq.h>
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + vrs@3c {
Node names should be generic. See also an explanation and list of
examples (not exhaustive) in DT specification:
https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
e.g. pmic@ or something appropriate.
> + compatible = "nvidia,vrs-pseq";
> + reg = <0x3c>;
> + interrupt-parent = <&pmc>;
> + interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
> + interrupt-controller;
> + #interrupt-cells = <2>;
> + };
Mixed up indentation.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 2/6] arm64: tegra: Add device-tree node for NVVRS PSEQ
2025-05-20 9:08 [PATCH V2 0/6] Add NVIDIA VRS PSEQ support Shubhi Garg
2025-05-20 9:08 ` [PATCH V2 1/6] dt-bindings: mfd: add bindings for NVIDIA VRS PSEQ Shubhi Garg
@ 2025-05-20 9:08 ` Shubhi Garg
2025-05-20 9:08 ` [PATCH V2 3/6] mfd: nvvrs: add NVVRS PSEQ MFD driver Shubhi Garg
` (3 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Shubhi Garg @ 2025-05-20 9:08 UTC (permalink / raw)
To: jonathanh, lee, robh, krzk, alexandre.belloni, thierry.reding,
devicetree, linux-tegra, linux-kernel
Cc: Shubhi Garg
Add NVIDIA VRS Power Sequencer device tree node for Tegra234 P3701 and
P3767 platforms. Assign VRS RTC as primary RTC (rtc0).
Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
---
v2:
- added alias to assign VRS RTC to rtc0
- removed status node from VRS DTB node
arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi | 11 +++++++++++
arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi | 15 +++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi
index 9086a0d010e5..b36df0c0c498 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi
@@ -8,6 +8,7 @@ / {
aliases {
mmc0 = "/bus@0/mmc@3460000";
mmc1 = "/bus@0/mmc@3400000";
+ rtc0 = "/bpmp/i2c/vrs@3c";
};
bus@0 {
@@ -170,6 +171,16 @@ bpmp {
i2c {
status = "okay";
+ vrs@3c {
+ compatible = "nvidia,vrs-pseq";
+ reg = <0x3c>;
+ interrupt-parent = <&pmc>;
+ /* VRS Wake ID is 24 */
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
thermal-sensor@4c {
compatible = "ti,tmp451";
status = "okay";
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi
index 84db7132e8fc..feae098033fc 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3767.dtsi
@@ -7,6 +7,7 @@ / {
aliases {
mmc0 = "/bus@0/mmc@3400000";
+ rtc0 = "/bpmp/i2c/vrs@3c";
};
bus@0 {
@@ -121,6 +122,20 @@ pmc@c360000 {
};
};
+ bpmp {
+ i2c {
+ vrs@3c {
+ compatible = "nvidia,vrs-pseq";
+ reg = <0x3c>;
+ interrupt-parent = <&pmc>;
+ /* VRS Wake ID is 24 */
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+ };
+
vdd_5v0_sys: regulator-vdd-5v0-sys {
compatible = "regulator-fixed";
regulator-name = "VDD_5V0_SYS";
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V2 3/6] mfd: nvvrs: add NVVRS PSEQ MFD driver
2025-05-20 9:08 [PATCH V2 0/6] Add NVIDIA VRS PSEQ support Shubhi Garg
2025-05-20 9:08 ` [PATCH V2 1/6] dt-bindings: mfd: add bindings for NVIDIA VRS PSEQ Shubhi Garg
2025-05-20 9:08 ` [PATCH V2 2/6] arm64: tegra: Add device-tree node for NVVRS PSEQ Shubhi Garg
@ 2025-05-20 9:08 ` Shubhi Garg
2025-05-21 9:12 ` Krzysztof Kozlowski
2025-05-20 9:08 ` [PATCH V2 4/6] rtc: nvvrs: add NVIDIA VRS PSEQ RTC device driver Shubhi Garg
` (2 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Shubhi Garg @ 2025-05-20 9:08 UTC (permalink / raw)
To: jonathanh, lee, robh, krzk, alexandre.belloni, thierry.reding,
devicetree, linux-tegra, linux-kernel
Cc: Shubhi Garg
Add support for NVIDIA VRS (Voltage Regulator Specification) power
sequencer device driver. This driver manages ON/OFF and suspend/resume
power sequencing of system power rails for NVIDIA Tegra234 SoC. It also
provides 32kHz RTC clock support with backup battery for system timing.
Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
---
v2:
- removed unnecessary error logs
- changed dev_info to dev_dbg
- changed dev_err to dev_err_probe
- fixed "of_match_table" assignment
drivers/mfd/Kconfig | 12 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/nvidia-vrs-pseq.c | 270 ++++++++++++++++++++++++++++
include/linux/mfd/nvidia-vrs-pseq.h | 127 +++++++++++++
4 files changed, 410 insertions(+)
create mode 100644 drivers/mfd/nvidia-vrs-pseq.c
create mode 100644 include/linux/mfd/nvidia-vrs-pseq.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6fb3768e3d71..3144b8f3eb9b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1437,6 +1437,18 @@ config MFD_SC27XX_PMIC
This driver provides common support for accessing the SC27xx PMICs,
and it also adds the irq_chip parts for handling the PMIC chip events.
+config MFD_NVVRS_PSEQ
+ tristate "NVIDIA Voltage Regulator Specification Power Sequencer"
+ depends on I2C=y
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ Say Y here to add support for NVIDIA Voltage Regulator Specification
+ Power Sequencer. NVVRS_PSEQ supports ON/OFF, suspend/resume sequence of
+ system power rails. It provides 32kHz RTC clock support with backup
+ battery for system timing.
+
config RZ_MTU3
tristate "Renesas RZ/G2L MTU3a core driver"
depends on (ARCH_RZG2L && OF) || COMPILE_TEST
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 79495f9f3457..9b07289985b5 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -183,6 +183,7 @@ obj-$(CONFIG_MFD_MT6360) += mt6360-core.o
obj-$(CONFIG_MFD_MT6370) += mt6370.o
mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o
obj-$(CONFIG_MFD_MT6397) += mt6397.o
+obj-$(CONFIG_MFD_NVVRS_PSEQ) += nvidia-vrs-pseq.o
obj-$(CONFIG_RZ_MTU3) += rz-mtu3.o
obj-$(CONFIG_ABX500_CORE) += abx500-core.o
diff --git a/drivers/mfd/nvidia-vrs-pseq.c b/drivers/mfd/nvidia-vrs-pseq.c
new file mode 100644
index 000000000000..e81c84b7811e
--- /dev/null
+++ b/drivers/mfd/nvidia-vrs-pseq.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// NVIDIA VRS Power Sequencer driver.
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/nvidia-vrs-pseq.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+static const struct resource rtc_resources[] = {
+ DEFINE_RES_IRQ(NVVRS_PSEQ_INT_SRC1_RTC),
+};
+
+static const struct regmap_irq nvvrs_pseq_irqs[] = {
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC1_RSTIRQ, 0, NVVRS_PSEQ_INT_SRC1_RSTIRQ_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC1_OSC, 0, NVVRS_PSEQ_INT_SRC1_OSC_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC1_EN, 0, NVVRS_PSEQ_INT_SRC1_EN_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC1_RTC, 0, NVVRS_PSEQ_INT_SRC1_RTC_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC1_PEC, 0, NVVRS_PSEQ_INT_SRC1_PEC_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC1_WDT, 0, NVVRS_PSEQ_INT_SRC1_WDT_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC1_EM_PD, 0, NVVRS_PSEQ_INT_SRC1_EM_PD_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC1_INTERNAL, 0, NVVRS_PSEQ_INT_SRC1_INTERNAL_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC2_PBSP, 1, NVVRS_PSEQ_INT_SRC2_PBSP_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC2_ECC_DED, 1, NVVRS_PSEQ_INT_SRC2_ECC_DED_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC2_TSD, 1, NVVRS_PSEQ_INT_SRC2_TSD_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC2_LDO, 1, NVVRS_PSEQ_INT_SRC2_LDO_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC2_BIST, 1, NVVRS_PSEQ_INT_SRC2_BIST_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC2_RT_CRC, 1, NVVRS_PSEQ_INT_SRC2_RT_CRC_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_SRC2_VENDOR, 1, NVVRS_PSEQ_INT_SRC2_VENDOR_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_VENDOR0, 2, NVVRS_PSEQ_INT_VENDOR0_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_VENDOR1, 2, NVVRS_PSEQ_INT_VENDOR1_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_VENDOR2, 2, NVVRS_PSEQ_INT_VENDOR2_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_VENDOR3, 2, NVVRS_PSEQ_INT_VENDOR3_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_VENDOR4, 2, NVVRS_PSEQ_INT_VENDOR4_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_VENDOR5, 2, NVVRS_PSEQ_INT_VENDOR5_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_VENDOR6, 2, NVVRS_PSEQ_INT_VENDOR6_MASK),
+ REGMAP_IRQ_REG(NVVRS_PSEQ_INT_VENDOR7, 2, NVVRS_PSEQ_INT_VENDOR7_MASK),
+};
+
+static const struct mfd_cell nvvrs_pseq_children[] = {
+ {
+ .name = "nvvrs-pseq-rtc",
+ .resources = rtc_resources,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ },
+};
+
+static const struct regmap_range nvvrs_pseq_readable_ranges[] = {
+ regmap_reg_range(NVVRS_PSEQ_REG_VENDOR_ID, NVVRS_PSEQ_REG_MODEL_REV),
+ regmap_reg_range(NVVRS_PSEQ_REG_INT_SRC1, NVVRS_PSEQ_REG_LAST_RST),
+ regmap_reg_range(NVVRS_PSEQ_REG_EN_ALT_F, NVVRS_PSEQ_REG_IEN_VENDOR),
+ regmap_reg_range(NVVRS_PSEQ_REG_RTC_T3, NVVRS_PSEQ_REG_RTC_A0),
+ regmap_reg_range(NVVRS_PSEQ_REG_WDT_CFG, NVVRS_PSEQ_REG_WDTKEY),
+};
+
+static const struct regmap_access_table nvvrs_pseq_readable_table = {
+ .yes_ranges = nvvrs_pseq_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(nvvrs_pseq_readable_ranges),
+};
+
+static const struct regmap_range nvvrs_pseq_writable_ranges[] = {
+ regmap_reg_range(NVVRS_PSEQ_REG_INT_SRC1, NVVRS_PSEQ_REG_INT_VENDOR),
+ regmap_reg_range(NVVRS_PSEQ_REG_GP_OUT, NVVRS_PSEQ_REG_IEN_VENDOR),
+ regmap_reg_range(NVVRS_PSEQ_REG_RTC_T3, NVVRS_PSEQ_REG_RTC_A0),
+ regmap_reg_range(NVVRS_PSEQ_REG_WDT_CFG, NVVRS_PSEQ_REG_WDTKEY),
+};
+
+static const struct regmap_access_table nvvrs_pseq_writable_table = {
+ .yes_ranges = nvvrs_pseq_writable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(nvvrs_pseq_writable_ranges),
+};
+
+static const struct regmap_config nvvrs_pseq_regmap_config = {
+ .name = "nvvrs-pseq",
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = NVVRS_PSEQ_REG_WDTKEY + 1,
+ .cache_type = REGCACHE_RBTREE,
+ .rd_table = &nvvrs_pseq_readable_table,
+ .wr_table = &nvvrs_pseq_writable_table,
+};
+
+static int nvvrs_pseq_irq_clear(void *irq_drv_data)
+{
+ struct nvvrs_pseq_chip *chip = (struct nvvrs_pseq_chip *)irq_drv_data;
+ struct i2c_client *client = chip->client;
+ u8 reg, val;
+ unsigned int i;
+ int ret = 0;
+
+ /* Write 1 to clear the interrupt bit in the Interrupt
+ * Source Register, writing 0 has no effect, writing 1 to a bit
+ * which is already at 0 has no effect
+ */
+
+ for (i = 0; i < chip->irq_chip->num_regs; i++) {
+ reg = (u8)(chip->irq_chip->status_base + i);
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret) {
+ val = (u8)ret;
+ dev_dbg(chip->dev, "Clearing interrupts! Interrupt status reg 0x%02x = 0x%02x\n",
+ reg, val);
+
+ ret = i2c_smbus_write_byte_data(client, reg, val);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static struct regmap_irq_chip nvvrs_pseq_irq_chip = {
+ .name = "nvvrs-pseq-irq",
+ .irqs = nvvrs_pseq_irqs,
+ .num_irqs = ARRAY_SIZE(nvvrs_pseq_irqs),
+ .num_regs = 3,
+ .status_base = NVVRS_PSEQ_REG_INT_SRC1,
+ .handle_post_irq = nvvrs_pseq_irq_clear,
+};
+
+static int nvvrs_pseq_vendor_info(struct nvvrs_pseq_chip *chip)
+{
+ struct i2c_client *client = chip->client;
+ u8 vendor_id, model_rev;
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_VENDOR_ID);
+ if (ret < 0) {
+ return dev_err_probe(chip->dev, ret,
+ "Failed to read Vendor ID\n");
+ }
+
+ vendor_id = (u8)ret;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_MODEL_REV);
+ if (ret < 0) {
+ return dev_err_probe(chip->dev, ret,
+ "Failed to read Model Rev\n");
+ }
+
+ model_rev = (u8)ret;
+
+ if (model_rev < 0x40) {
+ dev_err(chip->dev, "Chip revision 0x%02x is not supported!\n",
+ model_rev);
+ return -ENODEV;
+ }
+
+ dev_dbg(chip->dev, "NVVRS Vendor ID: 0x%02x, Model Rev: 0x%02x\n",
+ vendor_id, model_rev);
+
+ return 0;
+}
+
+static int nvvrs_pseq_probe(struct i2c_client *client)
+{
+ const struct regmap_config *rmap_config;
+ struct nvvrs_pseq_chip *nvvrs_chip;
+ const struct mfd_cell *mfd_cells;
+ int n_mfd_cells;
+ int ret;
+
+ nvvrs_chip = devm_kzalloc(&client->dev, sizeof(*nvvrs_chip), GFP_KERNEL);
+ if (!nvvrs_chip)
+ return -ENOMEM;
+
+ /* Set PEC flag for SMBUS transfer with PEC enabled */
+ client->flags |= I2C_CLIENT_PEC;
+
+ i2c_set_clientdata(client, nvvrs_chip);
+ nvvrs_chip->client = client;
+ nvvrs_chip->dev = &client->dev;
+ nvvrs_chip->chip_irq = client->irq;
+ mfd_cells = nvvrs_pseq_children;
+ n_mfd_cells = ARRAY_SIZE(nvvrs_pseq_children);
+ rmap_config = &nvvrs_pseq_regmap_config;
+ nvvrs_chip->irq_chip = &nvvrs_pseq_irq_chip;
+
+ nvvrs_chip->rmap = devm_regmap_init_i2c(client, rmap_config);
+ if (IS_ERR(nvvrs_chip->rmap)) {
+ ret = PTR_ERR(nvvrs_chip->rmap);
+ return dev_err_probe(nvvrs_chip->dev, ret,
+ "Failed to initialise regmap\n");
+ }
+
+ ret = nvvrs_pseq_vendor_info(nvvrs_chip);
+ if (ret < 0)
+ return ret;
+
+ nvvrs_pseq_irq_chip.irq_drv_data = nvvrs_chip;
+ ret = devm_regmap_add_irq_chip(nvvrs_chip->dev, nvvrs_chip->rmap, client->irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ &nvvrs_pseq_irq_chip,
+ &nvvrs_chip->irq_data);
+ if (ret < 0) {
+ return dev_err_probe(nvvrs_chip->dev, ret,
+ "Failed to add regmap irq\n");
+ }
+
+ ret = devm_mfd_add_devices(nvvrs_chip->dev, PLATFORM_DEVID_NONE,
+ mfd_cells, n_mfd_cells, NULL, 0,
+ regmap_irq_get_domain(nvvrs_chip->irq_data));
+ if (ret < 0) {
+ return dev_err_probe(nvvrs_chip->dev, ret,
+ "Failed to add MFD children\n");
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int nvvrs_pseq_i2c_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ /*
+ * IRQ must be disabled during suspend because if it happens
+ * while suspended it will be handled before resuming I2C.
+ *
+ * When device is woken up from suspend (e.g. by RTC wake alarm),
+ * an interrupt occurs before resuming I2C bus controller.
+ * Interrupt handler tries to read registers but this read
+ * will fail because I2C is still suspended.
+ */
+ disable_irq(client->irq);
+
+ return 0;
+}
+
+static int nvvrs_pseq_i2c_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ enable_irq(client->irq);
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops nvvrs_pseq_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(nvvrs_pseq_i2c_suspend, nvvrs_pseq_i2c_resume)
+};
+
+static const struct of_device_id nvvrs_dt_match[] = {
+ { .compatible = "nvidia,vrs-pseq" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, nvvrs_dt_match);
+
+static struct i2c_driver nvvrs_pseq_driver = {
+ .driver = {
+ .name = "nvvrs_pseq",
+ .pm = &nvvrs_pseq_pm_ops,
+ .of_match_table = nvvrs_dt_match,
+ },
+ .probe = nvvrs_pseq_probe,
+};
+
+module_i2c_driver(nvvrs_pseq_driver);
+
+MODULE_AUTHOR("Shubhi Garg <shgarg@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Voltage Regulator Specification Power Sequencer Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/nvidia-vrs-pseq.h b/include/linux/mfd/nvidia-vrs-pseq.h
new file mode 100644
index 000000000000..7e6f3aa940e7
--- /dev/null
+++ b/include/linux/mfd/nvidia-vrs-pseq.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved
+
+#ifndef _MFD_NVIDIA_VRS_PSEQ_H_
+#define _MFD_NVIDIA_VRS_PSEQ_H_
+
+#include <linux/types.h>
+
+/* Vendor ID */
+#define NVVRS_PSEQ_REG_VENDOR_ID 0x00
+#define NVVRS_PSEQ_REG_MODEL_REV 0x01
+
+/* Interrupts and Status registers */
+#define NVVRS_PSEQ_REG_INT_SRC1 0x10
+#define NVVRS_PSEQ_REG_INT_SRC2 0x11
+#define NVVRS_PSEQ_REG_INT_VENDOR 0x12
+#define NVVRS_PSEQ_REG_CTL_STAT 0x13
+#define NVVRS_PSEQ_REG_EN_STDR1 0x14
+#define NVVRS_PSEQ_REG_EN_STDR2 0x15
+#define NVVRS_PSEQ_REG_EN_STRD1 0x16
+#define NVVRS_PSEQ_REG_EN_STRD2 0x17
+#define NVVRS_PSEQ_REG_WDT_STAT 0x18
+#define NVVRS_PSEQ_REG_TEST_STAT 0x19
+#define NVVRS_PSEQ_REG_LAST_RST 0x1A
+
+/* Configuration Registers */
+#define NVVRS_PSEQ_REG_EN_ALT_F 0x20
+#define NVVRS_PSEQ_REG_AF_IN_OUT 0x21
+#define NVVRS_PSEQ_REG_EN_CFG1 0x22
+#define NVVRS_PSEQ_REG_EN_CFG2 0x23
+#define NVVRS_PSEQ_REG_CLK_CFG 0x24
+#define NVVRS_PSEQ_REG_GP_OUT 0x25
+#define NVVRS_PSEQ_REG_DEB_IN 0x26
+#define NVVRS_PSEQ_REG_LP_TTSHLD 0x27
+#define NVVRS_PSEQ_REG_CTL_1 0x28
+#define NVVRS_PSEQ_REG_CTL_2 0x29
+#define NVVRS_PSEQ_REG_TEST_CFG 0x2A
+#define NVVRS_PSEQ_REG_IEN_VENDOR 0x2B
+
+/* RTC */
+#define NVVRS_PSEQ_REG_RTC_T3 0x70
+#define NVVRS_PSEQ_REG_RTC_T2 0x71
+#define NVVRS_PSEQ_REG_RTC_T1 0x72
+#define NVVRS_PSEQ_REG_RTC_T0 0x73
+#define NVVRS_PSEQ_REG_RTC_A3 0x74
+#define NVVRS_PSEQ_REG_RTC_A2 0x75
+#define NVVRS_PSEQ_REG_RTC_A1 0x76
+#define NVVRS_PSEQ_REG_RTC_A0 0x77
+
+/* WDT */
+#define NVVRS_PSEQ_REG_WDT_CFG 0x80
+#define NVVRS_PSEQ_REG_WDT_CLOSE 0x81
+#define NVVRS_PSEQ_REG_WDT_OPEN 0x82
+#define NVVRS_PSEQ_REG_WDTKEY 0x83
+
+/* Interrupt Mask */
+#define NVVRS_PSEQ_INT_SRC1_RSTIRQ_MASK BIT(0)
+#define NVVRS_PSEQ_INT_SRC1_OSC_MASK BIT(1)
+#define NVVRS_PSEQ_INT_SRC1_EN_MASK BIT(2)
+#define NVVRS_PSEQ_INT_SRC1_RTC_MASK BIT(3)
+#define NVVRS_PSEQ_INT_SRC1_PEC_MASK BIT(4)
+#define NVVRS_PSEQ_INT_SRC1_WDT_MASK BIT(5)
+#define NVVRS_PSEQ_INT_SRC1_EM_PD_MASK BIT(6)
+#define NVVRS_PSEQ_INT_SRC1_INTERNAL_MASK BIT(7)
+#define NVVRS_PSEQ_INT_SRC2_PBSP_MASK BIT(0)
+#define NVVRS_PSEQ_INT_SRC2_ECC_DED_MASK BIT(1)
+#define NVVRS_PSEQ_INT_SRC2_TSD_MASK BIT(2)
+#define NVVRS_PSEQ_INT_SRC2_LDO_MASK BIT(3)
+#define NVVRS_PSEQ_INT_SRC2_BIST_MASK BIT(4)
+#define NVVRS_PSEQ_INT_SRC2_RT_CRC_MASK BIT(5)
+#define NVVRS_PSEQ_INT_SRC2_VENDOR_MASK BIT(7)
+#define NVVRS_PSEQ_INT_VENDOR0_MASK BIT(0)
+#define NVVRS_PSEQ_INT_VENDOR1_MASK BIT(1)
+#define NVVRS_PSEQ_INT_VENDOR2_MASK BIT(2)
+#define NVVRS_PSEQ_INT_VENDOR3_MASK BIT(3)
+#define NVVRS_PSEQ_INT_VENDOR4_MASK BIT(4)
+#define NVVRS_PSEQ_INT_VENDOR5_MASK BIT(5)
+#define NVVRS_PSEQ_INT_VENDOR6_MASK BIT(6)
+#define NVVRS_PSEQ_INT_VENDOR7_MASK BIT(7)
+
+/* Controller Register Mask */
+#define NVVRS_PSEQ_REG_CTL_1_FORCE_SHDN (BIT(0) | BIT(1))
+#define NVVRS_PSEQ_REG_CTL_1_FORCE_ACT BIT(2)
+#define NVVRS_PSEQ_REG_CTL_1_FORCE_INT BIT(3)
+#define NVVRS_PSEQ_REG_CTL_2_EN_PEC BIT(0)
+#define NVVRS_PSEQ_REG_CTL_2_REQ_PEC BIT(1)
+#define NVVRS_PSEQ_REG_CTL_2_RTC_PU BIT(2)
+#define NVVRS_PSEQ_REG_CTL_2_RTC_WAKE BIT(3)
+#define NVVRS_PSEQ_REG_CTL_2_RST_DLY 0xF0
+
+enum {
+ NVVRS_PSEQ_INT_SRC1_RSTIRQ, /* Reset or Interrupt Pin Fault */
+ NVVRS_PSEQ_INT_SRC1_OSC, /* Crystal Oscillator Fault */
+ NVVRS_PSEQ_INT_SRC1_EN, /* Enable Output Pin Fault */
+ NVVRS_PSEQ_INT_SRC1_RTC, /* RTC Alarm */
+ NVVRS_PSEQ_INT_SRC1_PEC, /* Packet Error Checking */
+ NVVRS_PSEQ_INT_SRC1_WDT, /* Watchdog Violation */
+ NVVRS_PSEQ_INT_SRC1_EM_PD, /* Emergency Power Down */
+ NVVRS_PSEQ_INT_SRC1_INTERNAL, /* Internal Fault*/
+ NVVRS_PSEQ_INT_SRC2_PBSP, /* PWR_BTN Short Pulse Detection */
+ NVVRS_PSEQ_INT_SRC2_ECC_DED, /* ECC Double-Error Detection */
+ NVVRS_PSEQ_INT_SRC2_TSD, /* Thermal Shutdown */
+ NVVRS_PSEQ_INT_SRC2_LDO, /* LDO Fault */
+ NVVRS_PSEQ_INT_SRC2_BIST, /* Built-In Self Test Fault */
+ NVVRS_PSEQ_INT_SRC2_RT_CRC, /* Runtime Register CRC Fault */
+ NVVRS_PSEQ_INT_SRC2_VENDOR, /* Vendor Specific Internal Fault */
+ NVVRS_PSEQ_INT_VENDOR0, /* Vendor Internal Fault Bit 0 */
+ NVVRS_PSEQ_INT_VENDOR1, /* Vendor Internal Fault Bit 1 */
+ NVVRS_PSEQ_INT_VENDOR2, /* Vendor Internal Fault Bit 2 */
+ NVVRS_PSEQ_INT_VENDOR3, /* Vendor Internal Fault Bit 3 */
+ NVVRS_PSEQ_INT_VENDOR4, /* Vendor Internal Fault Bit 4 */
+ NVVRS_PSEQ_INT_VENDOR5, /* Vendor Internal Fault Bit 5 */
+ NVVRS_PSEQ_INT_VENDOR6, /* Vendor Internal Fault Bit 6 */
+ NVVRS_PSEQ_INT_VENDOR7, /* Vendor Internal Fault Bit 7 */
+};
+
+struct nvvrs_pseq_chip {
+ struct device *dev;
+ struct regmap *rmap;
+ int chip_irq;
+ struct i2c_client *client;
+ struct regmap_irq_chip_data *irq_data;
+ const struct regmap_irq_chip *irq_chip;
+ void *irq_drv_data;
+};
+
+#endif /* _MFD_NVIDIA_VRS_PSEQ_H_ */
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH V2 3/6] mfd: nvvrs: add NVVRS PSEQ MFD driver
2025-05-20 9:08 ` [PATCH V2 3/6] mfd: nvvrs: add NVVRS PSEQ MFD driver Shubhi Garg
@ 2025-05-21 9:12 ` Krzysztof Kozlowski
0 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-21 9:12 UTC (permalink / raw)
To: Shubhi Garg
Cc: jonathanh, lee, robh, alexandre.belloni, thierry.reding,
devicetree, linux-tegra, linux-kernel
On Tue, May 20, 2025 at 09:08:29AM GMT, Shubhi Garg wrote:
> Add support for NVIDIA VRS (Voltage Regulator Specification) power
> sequencer device driver. This driver manages ON/OFF and suspend/resume
> power sequencing of system power rails for NVIDIA Tegra234 SoC. It also
> provides 32kHz RTC clock support with backup battery for system timing.
>
> Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
> ---
>
> v2:
> - removed unnecessary error logs
> - changed dev_info to dev_dbg
> - changed dev_err to dev_err_probe
> - fixed "of_match_table" assignment
>
> drivers/mfd/Kconfig | 12 ++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/nvidia-vrs-pseq.c | 270 ++++++++++++++++++++++++++++
> include/linux/mfd/nvidia-vrs-pseq.h | 127 +++++++++++++
> 4 files changed, 410 insertions(+)
> create mode 100644 drivers/mfd/nvidia-vrs-pseq.c
> create mode 100644 include/linux/mfd/nvidia-vrs-pseq.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 6fb3768e3d71..3144b8f3eb9b 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1437,6 +1437,18 @@ config MFD_SC27XX_PMIC
> This driver provides common support for accessing the SC27xx PMICs,
> and it also adds the irq_chip parts for handling the PMIC chip events.
>
> +config MFD_NVVRS_PSEQ
> + tristate "NVIDIA Voltage Regulator Specification Power Sequencer"
> + depends on I2C=y
Why I2C cannot be a module? This is a module.
> + select MFD_CORE
> + select REGMAP_I2C
> + select REGMAP_IRQ
> + help
> + Say Y here to add support for NVIDIA Voltage Regulator Specification
> + Power Sequencer. NVVRS_PSEQ supports ON/OFF, suspend/resume sequence of
> + system power rails. It provides 32kHz RTC clock support with backup
> + battery for system timing.
> +
...
> +static int nvvrs_pseq_irq_clear(void *irq_drv_data)
> +{
> + struct nvvrs_pseq_chip *chip = (struct nvvrs_pseq_chip *)irq_drv_data;
> + struct i2c_client *client = chip->client;
> + u8 reg, val;
> + unsigned int i;
> + int ret = 0;
> +
> + /* Write 1 to clear the interrupt bit in the Interrupt
> + * Source Register, writing 0 has no effect, writing 1 to a bit
> + * which is already at 0 has no effect
> + */
> +
> + for (i = 0; i < chip->irq_chip->num_regs; i++) {
> + reg = (u8)(chip->irq_chip->status_base + i);
> + ret = i2c_smbus_read_byte_data(client, reg);
> + if (ret) {
> + val = (u8)ret;
> + dev_dbg(chip->dev, "Clearing interrupts! Interrupt status reg 0x%02x = 0x%02x\n",
> + reg, val);
ratelimit
...
> +
> +static int nvvrs_pseq_probe(struct i2c_client *client)
> +{
> + const struct regmap_config *rmap_config;
> + struct nvvrs_pseq_chip *nvvrs_chip;
> + const struct mfd_cell *mfd_cells;
> + int n_mfd_cells;
> + int ret;
> +
> + nvvrs_chip = devm_kzalloc(&client->dev, sizeof(*nvvrs_chip), GFP_KERNEL);
> + if (!nvvrs_chip)
> + return -ENOMEM;
> +
> + /* Set PEC flag for SMBUS transfer with PEC enabled */
> + client->flags |= I2C_CLIENT_PEC;
> +
> + i2c_set_clientdata(client, nvvrs_chip);
> + nvvrs_chip->client = client;
> + nvvrs_chip->dev = &client->dev;
> + nvvrs_chip->chip_irq = client->irq;
> + mfd_cells = nvvrs_pseq_children;
> + n_mfd_cells = ARRAY_SIZE(nvvrs_pseq_children);
> + rmap_config = &nvvrs_pseq_regmap_config;
> + nvvrs_chip->irq_chip = &nvvrs_pseq_irq_chip;
> +
> + nvvrs_chip->rmap = devm_regmap_init_i2c(client, rmap_config);
> + if (IS_ERR(nvvrs_chip->rmap)) {
> + ret = PTR_ERR(nvvrs_chip->rmap);
Useless assignment
> + return dev_err_probe(nvvrs_chip->dev, ret,
> + "Failed to initialise regmap\n");
> + }
Drop }
> +
> + ret = nvvrs_pseq_vendor_info(nvvrs_chip);
> + if (ret < 0)
> + return ret;
> +
> + nvvrs_pseq_irq_chip.irq_drv_data = nvvrs_chip;
> + ret = devm_regmap_add_irq_chip(nvvrs_chip->dev, nvvrs_chip->rmap, client->irq,
> + IRQF_ONESHOT | IRQF_SHARED, 0,
> + &nvvrs_pseq_irq_chip,
> + &nvvrs_chip->irq_data);
> + if (ret < 0) {
> + return dev_err_probe(nvvrs_chip->dev, ret,
> + "Failed to add regmap irq\n");
> + }
Drop }
Your entire code is full of that.
Please run scripts/checkpatch.pl on the patches and fix reported
warnings. After that, run also 'scripts/checkpatch.pl --strict' on the
patches and (probably) fix more warnings. Some warnings can be ignored,
especially from --strict run, but the code here looks like it needs a
fix. Feel free to get in touch if the warning is not clear.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 4/6] rtc: nvvrs: add NVIDIA VRS PSEQ RTC device driver
2025-05-20 9:08 [PATCH V2 0/6] Add NVIDIA VRS PSEQ support Shubhi Garg
` (2 preceding siblings ...)
2025-05-20 9:08 ` [PATCH V2 3/6] mfd: nvvrs: add NVVRS PSEQ MFD driver Shubhi Garg
@ 2025-05-20 9:08 ` Shubhi Garg
2025-05-21 9:14 ` Krzysztof Kozlowski
2025-05-20 9:08 ` [PATCH V2 5/6] arm64: defconfig: enable NVIDIA VRS PSEQ Shubhi Garg
2025-05-20 9:08 ` [PATCH V2 6/6] MAINTAINERS: Add NVIDIA VRS PSEQ driver entry Shubhi Garg
5 siblings, 1 reply; 12+ messages in thread
From: Shubhi Garg @ 2025-05-20 9:08 UTC (permalink / raw)
To: jonathanh, lee, robh, krzk, alexandre.belloni, thierry.reding,
devicetree, linux-tegra, linux-kernel
Cc: Shubhi Garg
Add support for NVIDIA VRS (Voltage Regulator Specification) Power
Sequencer RTC device driver. This RTC can be used to get/set system
time, retain system time across boot, wake system from suspend and
shutdown state.
Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
---
v2:
- removed regmap struct since it is not required
- removed rtc_map definition to directly use register definition
- removed unnecessary dev_err logs
- fixed dev_err logs to dev_dbg
- used rtc_lock/unlock in irq handler
- changed RTC allocation and register APIs as per latest kernel
- removed nvvrs_rtc_remove function since it's not required
drivers/rtc/Kconfig | 10 +
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-nvidia-vrs-pseq.c | 456 ++++++++++++++++++++++++++++++
3 files changed, 467 insertions(+)
create mode 100644 drivers/rtc/rtc-nvidia-vrs-pseq.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 838bdc138ffe..3b6dc27a50af 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -406,6 +406,16 @@ config RTC_DRV_MAX77686
This driver can also be built as a module. If so, the module
will be called rtc-max77686.
+config RTC_DRV_NVVRS_PSEQ
+ tristate "NVIDIA VRS Power Sequencer RTC device"
+ depends on MFD_NVVRS_PSEQ
+ help
+ If you say yes here you will get support for the battery backed RTC device
+ of NVIDIA VRS Power Sequencer. 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-vrs-pseq.
+
config RTC_DRV_NCT3018Y
tristate "Nuvoton NCT3018Y"
depends on OF
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 31473b3276d9..543c5a9fe851 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -119,6 +119,7 @@ obj-$(CONFIG_RTC_DRV_MXC_V2) += rtc-mxc_v2.o
obj-$(CONFIG_RTC_DRV_GAMECUBE) += rtc-gamecube.o
obj-$(CONFIG_RTC_DRV_NCT3018Y) += rtc-nct3018y.o
obj-$(CONFIG_RTC_DRV_NTXEC) += rtc-ntxec.o
+obj-$(CONFIG_RTC_DRV_NVVRS_PSEQ)+= rtc-nvidia-vrs-pseq.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-vrs-pseq.c b/drivers/rtc/rtc-nvidia-vrs-pseq.c
new file mode 100644
index 000000000000..1379e8c64e94
--- /dev/null
+++ b/drivers/rtc/rtc-nvidia-vrs-pseq.c
@@ -0,0 +1,456 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ *
+ * RTC driver for NVIDIA Voltage Regulator Power Sequencer
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/rtc.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/mfd/nvidia-vrs-pseq.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+#include <linux/bits.h>
+
+#define ALARM_RESET_VAL 0xffffffff /* Alarm reset/disable value */
+#define NVVRS_INT_RTC_INDEX 0 /* Only one RTC interrupt register */
+
+struct nvvrs_rtc_info {
+ struct device *dev;
+ struct i2c_client *client;
+ struct rtc_device *rtc_dev;
+ unsigned int rtc_irq;
+ const struct regmap_irq_chip *rtc_irq_chip;
+ struct regmap_irq_chip_data *rtc_irq_data;
+ /* Mutex to protect RTC operations */
+ struct mutex lock;
+};
+
+static const struct regmap_irq nvvrs_rtc_irq[] = {
+ REGMAP_IRQ_REG(NVVRS_INT_RTC_INDEX, 0, NVVRS_PSEQ_INT_SRC1_RTC_MASK),
+};
+
+static const struct regmap_irq_chip nvvrs_rtc_irq_chip = {
+ .name = "nvvrs-rtc",
+ .status_base = NVVRS_PSEQ_REG_INT_SRC1,
+ .num_regs = 1,
+ .irqs = nvvrs_rtc_irq,
+ .num_irqs = ARRAY_SIZE(nvvrs_rtc_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_update_alarm_reg(struct i2c_client *client,
+ struct nvvrs_rtc_info *info, u8 *time)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, NVVRS_PSEQ_REG_RTC_A3, time[3]);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(client, NVVRS_PSEQ_REG_RTC_A2, time[2]);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(client, NVVRS_PSEQ_REG_RTC_A1, time[1]);
+ if (ret < 0)
+ return ret;
+
+ return i2c_smbus_write_byte_data(client, NVVRS_PSEQ_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_PSEQ_REG_CTL_2,
+ NVVRS_PSEQ_REG_CTL_2_RTC_WAKE,
+ NVVRS_PSEQ_REG_CTL_2_RTC_WAKE);
+ if (ret < 0) {
+ dev_dbg(info->dev, "Failed to set RTC_WAKE bit (%d)\n", ret);
+ return ret;
+ }
+
+ /* Set RTC_PU bit for autonomous wake from shutdown */
+ ret = nvvrs_update_bits(info, NVVRS_PSEQ_REG_CTL_2,
+ NVVRS_PSEQ_REG_CTL_2_RTC_PU,
+ NVVRS_PSEQ_REG_CTL_2_RTC_PU);
+ if (ret < 0) {
+ dev_dbg(info->dev, "Failed to set RTC_PU bit (%d)\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+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_PSEQ_REG_CTL_2,
+ NVVRS_PSEQ_REG_CTL_2_RTC_WAKE, 0);
+ if (ret < 0) {
+ dev_dbg(info->dev, "Failed to clear RTC_WAKE bit (%d)\n", ret);
+ return ret;
+ }
+
+ /* Clear RTC_PU bit */
+ ret = nvvrs_update_bits(info, NVVRS_PSEQ_REG_CTL_2,
+ NVVRS_PSEQ_REG_CTL_2_RTC_PU, 0);
+ if (ret < 0) {
+ dev_dbg(info->dev, "Failed to clear RTC_PU bit (%d)\n", ret);
+ 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_update_alarm_reg(client, info, val);
+ if (ret < 0)
+ dev_dbg(info->dev, "Failed to disable Alarm (%d)\n", ret);
+
+ return ret;
+}
+
+static irqreturn_t nvvrs_rtc_irq_handler(int irq, void *data)
+{
+ struct nvvrs_rtc_info *info = data;
+
+ dev_dbg(info->dev, "RTC alarm IRQ: %d\n", irq);
+
+ rtc_lock(info->rtc_dev);
+ rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
+ rtc_unlock(info->rtc_dev);
+
+ return IRQ_HANDLED;
+}
+
+static int nvvrs_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ struct i2c_client *client = info->client;
+ time64_t secs = 0;
+ int ret;
+ u8 val;
+
+ mutex_lock(&info->lock);
+
+ /* Multi-byte transfers are not supported with PEC enabled */
+ /* Read MSB first to avoid coherency issues */
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_RTC_T3);
+ if (ret < 0)
+ goto out;
+
+ val = (u8)ret;
+ secs |= (time64_t)val << 24;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_RTC_T2);
+ if (ret < 0)
+ goto out;
+
+ val = (u8)ret;
+ secs |= (time64_t)val << 16;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_RTC_T1);
+ if (ret < 0)
+ goto out;
+
+ val = (u8)ret;
+ secs |= (time64_t)val << 8;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_RTC_T0);
+ if (ret < 0)
+ goto out;
+
+ val = (u8)ret;
+ secs |= val;
+
+ rtc_time64_to_tm(secs, tm);
+out:
+ mutex_unlock(&info->lock);
+ return ret;
+}
+
+static int nvvrs_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ struct i2c_client *client = info->client;
+ u8 time[4];
+ time64_t secs;
+ int ret;
+
+ mutex_lock(&info->lock);
+
+ 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(client, NVVRS_PSEQ_REG_RTC_T3, time[3]);
+ if (ret < 0)
+ goto out;
+
+ ret = i2c_smbus_write_byte_data(client, NVVRS_PSEQ_REG_RTC_T2, time[2]);
+ if (ret < 0)
+ goto out;
+
+ ret = i2c_smbus_write_byte_data(client, NVVRS_PSEQ_REG_RTC_T1, time[1]);
+ if (ret < 0)
+ goto out;
+
+ ret = i2c_smbus_write_byte_data(client, NVVRS_PSEQ_REG_RTC_T0, time[0]);
+
+out:
+ mutex_unlock(&info->lock);
+ return ret;
+}
+
+static int nvvrs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ struct i2c_client *client = info->client;
+ time64_t alarm_val = 0;
+ int ret;
+ u8 val;
+
+ mutex_lock(&info->lock);
+
+ /* Multi-byte transfers are not supported with PEC enabled */
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_RTC_A3);
+ if (ret < 0)
+ goto out;
+
+ val = (u8)ret;
+ alarm_val |= (time64_t)val << 24;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_RTC_A2);
+ if (ret < 0)
+ goto out;
+
+ val = (u8)ret;
+ alarm_val |= (time64_t)val << 16;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_RTC_A1);
+ if (ret < 0)
+ goto out;
+
+ val = (u8)ret;
+ alarm_val |= (time64_t)val << 8;
+
+ ret = i2c_smbus_read_byte_data(client, NVVRS_PSEQ_REG_RTC_A0);
+ if (ret < 0)
+ goto out;
+
+ 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);
+out:
+ mutex_unlock(&info->lock);
+ return ret;
+}
+
+static int nvvrs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ struct i2c_client *client = info->client;
+ u8 time[4];
+ time64_t secs;
+ int ret;
+
+ mutex_lock(&info->lock);
+
+ ret = nvvrs_rtc_enable_alarm(info);
+ if (ret < 0) {
+ dev_err(info->dev, "Failed to enable alarm! (%d)\n", ret);
+ goto out;
+ }
+
+ 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_update_alarm_reg(client, info, time);
+
+ alrm->enabled = 1;
+out:
+ mutex_unlock(&info->lock);
+ return ret;
+}
+
+static int nvvrs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ int ret = 0;
+
+ mutex_lock(&info->lock);
+ if (enabled)
+ ret = nvvrs_rtc_enable_alarm(info);
+ else
+ ret = nvvrs_rtc_disable_alarm(info);
+
+ mutex_unlock(&info->lock);
+ return ret;
+}
+
+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_rtc_probe(struct platform_device *pdev)
+{
+ struct nvvrs_rtc_info *info;
+ struct device *parent;
+ struct i2c_client *client;
+ int ret;
+
+ info = devm_kzalloc(&pdev->dev, sizeof(struct nvvrs_rtc_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ mutex_init(&info->lock);
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get irq\n");
+ return ret;
+ }
+ info->rtc_irq = ret;
+
+ info->dev = &pdev->dev;
+ parent = info->dev->parent;
+ client = to_i2c_client(parent);
+ client->flags |= I2C_CLIENT_PEC;
+ i2c_set_clientdata(client, info);
+ info->client = client;
+ info->rtc_irq_chip = &nvvrs_rtc_irq_chip;
+ platform_set_drvdata(pdev, info);
+
+ /* Allocate RTC device */
+ info->rtc_dev = devm_rtc_allocate_device(info->dev);
+ if (IS_ERR(info->rtc_dev))
+ return PTR_ERR(info->rtc_dev);
+
+ info->rtc_dev->ops = &nvvrs_rtc_ops;
+ info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
+
+ ret = devm_request_threaded_irq(info->dev, info->rtc_irq, NULL,
+ nvvrs_rtc_irq_handler, 0, "rtc-alarm", info);
+ if (ret < 0)
+ dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
+ info->rtc_irq, ret);
+
+ /* RTC as a wakeup source */
+ device_init_wakeup(info->dev, true);
+
+ return devm_rtc_register_device(info->rtc_dev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int nvvrs_rtc_suspend(struct device *dev)
+{
+ struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (device_may_wakeup(dev)) {
+ /* Set RTC_WAKE bit for auto wake system from suspend state */
+ ret = nvvrs_update_bits(info, NVVRS_PSEQ_REG_CTL_2,
+ NVVRS_PSEQ_REG_CTL_2_RTC_WAKE,
+ NVVRS_PSEQ_REG_CTL_2_RTC_WAKE);
+ if (ret < 0) {
+ dev_err(info->dev, "Failed to set RTC_WAKE bit (%d)\n", ret);
+ return ret;
+ }
+
+ ret = enable_irq_wake(info->rtc_irq);
+ }
+
+ return ret;
+}
+
+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_PSEQ_REG_CTL_1,
+ NVVRS_PSEQ_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->rtc_irq);
+ }
+
+ return 0;
+}
+
+#endif
+static SIMPLE_DEV_PM_OPS(nvvrs_rtc_pm_ops, nvvrs_rtc_suspend, nvvrs_rtc_resume);
+
+static const struct platform_device_id nvvrs_rtc_id[] = {
+ { "nvvrs-pseq-rtc", },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, nvvrs_rtc_id);
+
+static struct platform_driver nvvrs_rtc_driver = {
+ .driver = {
+ .name = "nvvrs-pseq-rtc",
+ .pm = &nvvrs_rtc_pm_ops,
+ },
+ .probe = nvvrs_rtc_probe,
+ .id_table = nvvrs_rtc_id,
+};
+
+module_platform_driver(nvvrs_rtc_driver);
+
+MODULE_AUTHOR("Shubhi Garg <shgarg@nvidia.com>");
+MODULE_DESCRIPTION("NVVRS PSEQ RTC driver");
+MODULE_LICENSE("GPL");
\ No newline at end of file
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH V2 4/6] rtc: nvvrs: add NVIDIA VRS PSEQ RTC device driver
2025-05-20 9:08 ` [PATCH V2 4/6] rtc: nvvrs: add NVIDIA VRS PSEQ RTC device driver Shubhi Garg
@ 2025-05-21 9:14 ` Krzysztof Kozlowski
2025-06-02 14:47 ` Jon Hunter
0 siblings, 1 reply; 12+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-21 9:14 UTC (permalink / raw)
To: Shubhi Garg
Cc: jonathanh, lee, robh, alexandre.belloni, thierry.reding,
devicetree, linux-tegra, linux-kernel
On Tue, May 20, 2025 at 09:08:30AM GMT, Shubhi Garg wrote:
> Add support for NVIDIA VRS (Voltage Regulator Specification) Power
> Sequencer RTC device driver. This RTC can be used to get/set system
> time, retain system time across boot, wake system from suspend and
> shutdown state.
>
> Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
> ---
>
> v2:
> - removed regmap struct since it is not required
> - removed rtc_map definition to directly use register definition
> - removed unnecessary dev_err logs
> - fixed dev_err logs to dev_dbg
> - used rtc_lock/unlock in irq handler
> - changed RTC allocation and register APIs as per latest kernel
> - removed nvvrs_rtc_remove function since it's not required
>
> drivers/rtc/Kconfig | 10 +
> drivers/rtc/Makefile | 1 +
> drivers/rtc/rtc-nvidia-vrs-pseq.c | 456 ++++++++++++++++++++++++++++++
> 3 files changed, 467 insertions(+)
> create mode 100644 drivers/rtc/rtc-nvidia-vrs-pseq.c
>
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 838bdc138ffe..3b6dc27a50af 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -406,6 +406,16 @@ config RTC_DRV_MAX77686
> This driver can also be built as a module. If so, the module
> will be called rtc-max77686.
>
> +config RTC_DRV_NVVRS_PSEQ
> + tristate "NVIDIA VRS Power Sequencer RTC device"
> + depends on MFD_NVVRS_PSEQ
I bet this fails when MFD_NVVRS_PSEQ is a module.
> + help
> + If you say yes here you will get support for the battery backed RTC device
> + of NVIDIA VRS Power Sequencer. 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-vrs-pseq.
> +
...
> +static int nvvrs_rtc_probe(struct platform_device *pdev)
> +{
> + struct nvvrs_rtc_info *info;
> + struct device *parent;
> + struct i2c_client *client;
> + int ret;
> +
> + info = devm_kzalloc(&pdev->dev, sizeof(struct nvvrs_rtc_info), GFP_KERNEL);
sizeof(*)
> + if (!info)
> + return -ENOMEM;
> +
> + mutex_init(&info->lock);
> +
> + ret = platform_get_irq(pdev, 0);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "Failed to get irq\n");
return dev_err_probe
> + return ret;
> + }
> + info->rtc_irq = ret;
> +
> + info->dev = &pdev->dev;
> + parent = info->dev->parent;
> + client = to_i2c_client(parent);
> + client->flags |= I2C_CLIENT_PEC;
> + i2c_set_clientdata(client, info);
> + info->client = client;
> + info->rtc_irq_chip = &nvvrs_rtc_irq_chip;
> + platform_set_drvdata(pdev, info);
> +
> + /* Allocate RTC device */
> + info->rtc_dev = devm_rtc_allocate_device(info->dev);
> + if (IS_ERR(info->rtc_dev))
> + return PTR_ERR(info->rtc_dev);
> +
> + info->rtc_dev->ops = &nvvrs_rtc_ops;
> + info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
> + info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
> +
> + ret = devm_request_threaded_irq(info->dev, info->rtc_irq, NULL,
> + nvvrs_rtc_irq_handler, 0, "rtc-alarm", info);
> + if (ret < 0)
> + dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
> + info->rtc_irq, ret);
> +
> + /* RTC as a wakeup source */
> + device_init_wakeup(info->dev, true);
You leak wakeup.
> +
> + return devm_rtc_register_device(info->rtc_dev);
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int nvvrs_rtc_suspend(struct device *dev)
> +{
> + struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
> + int ret = 0;
> +
> + if (device_may_wakeup(dev)) {
> + /* Set RTC_WAKE bit for auto wake system from suspend state */
> + ret = nvvrs_update_bits(info, NVVRS_PSEQ_REG_CTL_2,
> + NVVRS_PSEQ_REG_CTL_2_RTC_WAKE,
> + NVVRS_PSEQ_REG_CTL_2_RTC_WAKE);
> + if (ret < 0) {
> + dev_err(info->dev, "Failed to set RTC_WAKE bit (%d)\n", ret);
> + return ret;
> + }
> +
> + ret = enable_irq_wake(info->rtc_irq);
> + }
> +
> + return ret;
> +}
> +
> +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_PSEQ_REG_CTL_1,
> + NVVRS_PSEQ_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->rtc_irq);
> + }
> +
> + return 0;
> +}
> +
> +#endif
> +static SIMPLE_DEV_PM_OPS(nvvrs_rtc_pm_ops, nvvrs_rtc_suspend, nvvrs_rtc_resume);
> +
> +static const struct platform_device_id nvvrs_rtc_id[] = {
> + { "nvvrs-pseq-rtc", },
> + { },
> +};
> +MODULE_DEVICE_TABLE(platform, nvvrs_rtc_id);
> +
> +static struct platform_driver nvvrs_rtc_driver = {
> + .driver = {
> + .name = "nvvrs-pseq-rtc",
> + .pm = &nvvrs_rtc_pm_ops,
> + },
> + .probe = nvvrs_rtc_probe,
> + .id_table = nvvrs_rtc_id,
> +};
> +
> +module_platform_driver(nvvrs_rtc_driver);
> +
> +MODULE_AUTHOR("Shubhi Garg <shgarg@nvidia.com>");
> +MODULE_DESCRIPTION("NVVRS PSEQ RTC driver");
> +MODULE_LICENSE("GPL");
> \ No newline at end of file
You have patch warnings.
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V2 4/6] rtc: nvvrs: add NVIDIA VRS PSEQ RTC device driver
2025-05-21 9:14 ` Krzysztof Kozlowski
@ 2025-06-02 14:47 ` Jon Hunter
0 siblings, 0 replies; 12+ messages in thread
From: Jon Hunter @ 2025-06-02 14:47 UTC (permalink / raw)
To: Krzysztof Kozlowski, Shubhi Garg
Cc: lee, robh, alexandre.belloni, thierry.reding, devicetree,
linux-tegra, linux-kernel
On 21/05/2025 10:14, Krzysztof Kozlowski wrote:
> On Tue, May 20, 2025 at 09:08:30AM GMT, Shubhi Garg wrote:
>> Add support for NVIDIA VRS (Voltage Regulator Specification) Power
>> Sequencer RTC device driver. This RTC can be used to get/set system
>> time, retain system time across boot, wake system from suspend and
>> shutdown state.
>>
>> Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
>> ---
>>
>> v2:
>> - removed regmap struct since it is not required
>> - removed rtc_map definition to directly use register definition
>> - removed unnecessary dev_err logs
>> - fixed dev_err logs to dev_dbg
>> - used rtc_lock/unlock in irq handler
>> - changed RTC allocation and register APIs as per latest kernel
>> - removed nvvrs_rtc_remove function since it's not required
>>
>> drivers/rtc/Kconfig | 10 +
>> drivers/rtc/Makefile | 1 +
>> drivers/rtc/rtc-nvidia-vrs-pseq.c | 456 ++++++++++++++++++++++++++++++
>> 3 files changed, 467 insertions(+)
>> create mode 100644 drivers/rtc/rtc-nvidia-vrs-pseq.c
>>
>> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
>> index 838bdc138ffe..3b6dc27a50af 100644
>> --- a/drivers/rtc/Kconfig
>> +++ b/drivers/rtc/Kconfig
>> @@ -406,6 +406,16 @@ config RTC_DRV_MAX77686
>> This driver can also be built as a module. If so, the module
>> will be called rtc-max77686.
>>
>> +config RTC_DRV_NVVRS_PSEQ
>> + tristate "NVIDIA VRS Power Sequencer RTC device"
>> + depends on MFD_NVVRS_PSEQ
>
> I bet this fails when MFD_NVVRS_PSEQ is a module.
This is building fine for me when MFD_NVVRS_PSEQ is a module.
The 'depends on I2C=y' in patch 3/6 definitely needs correcting as you
highlighted and will be fixed in the next version of this series.
Cheers
Jon
--
nvpublic
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 5/6] arm64: defconfig: enable NVIDIA VRS PSEQ
2025-05-20 9:08 [PATCH V2 0/6] Add NVIDIA VRS PSEQ support Shubhi Garg
` (3 preceding siblings ...)
2025-05-20 9:08 ` [PATCH V2 4/6] rtc: nvvrs: add NVIDIA VRS PSEQ RTC device driver Shubhi Garg
@ 2025-05-20 9:08 ` Shubhi Garg
2025-05-20 9:12 ` Krzysztof Kozlowski
2025-05-20 9:08 ` [PATCH V2 6/6] MAINTAINERS: Add NVIDIA VRS PSEQ driver entry Shubhi Garg
5 siblings, 1 reply; 12+ messages in thread
From: Shubhi Garg @ 2025-05-20 9:08 UTC (permalink / raw)
To: jonathanh, lee, robh, krzk, alexandre.belloni, thierry.reding,
devicetree, linux-tegra, linux-kernel
Cc: Shubhi Garg
Enable NVIDIA VRS (Voltage Regulator Specification) power sequencer
device modules. NVIDIA VRS PSEQ controls ON/OFF and suspend/resume
power sequencing of system power rails on Tegra234 SoC. This device
also provides 32kHz RTC support with backup battery for system timing.
Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
---
v2:
- moved VRS RTC config to correct place
arch/arm64/configs/defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1f3fd474911b..11b64ac4bb59 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -785,6 +785,7 @@ CONFIG_MFD_ROHM_BD718XX=y
CONFIG_MFD_STM32_LPTIMER=m
CONFIG_MFD_WCD934X=m
CONFIG_MFD_KHADAS_MCU=m
+CONFIG_MFD_NVVRS_PSEQ=m
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_BD718XX=y
@@ -1259,6 +1260,7 @@ CONFIG_RTC_DRV_MT6397=m
CONFIG_RTC_DRV_XGENE=y
CONFIG_RTC_DRV_TI_K3=m
CONFIG_RTC_DRV_RENESAS_RTCA3=m
+CONFIG_RTC_DRV_NVVRS_PSEQ=m
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2835=y
CONFIG_DMA_SUN6I=m
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH V2 5/6] arm64: defconfig: enable NVIDIA VRS PSEQ
2025-05-20 9:08 ` [PATCH V2 5/6] arm64: defconfig: enable NVIDIA VRS PSEQ Shubhi Garg
@ 2025-05-20 9:12 ` Krzysztof Kozlowski
0 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-20 9:12 UTC (permalink / raw)
To: Shubhi Garg, jonathanh, lee, robh, alexandre.belloni,
thierry.reding, devicetree, linux-tegra, linux-kernel
On 20/05/2025 11:08, Shubhi Garg wrote:
> Enable NVIDIA VRS (Voltage Regulator Specification) power sequencer
> device modules. NVIDIA VRS PSEQ controls ON/OFF and suspend/resume
> power sequencing of system power rails on Tegra234 SoC. This device
> also provides 32kHz RTC support with backup battery for system timing.
Nothing improved in the commit msg.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 6/6] MAINTAINERS: Add NVIDIA VRS PSEQ driver entry
2025-05-20 9:08 [PATCH V2 0/6] Add NVIDIA VRS PSEQ support Shubhi Garg
` (4 preceding siblings ...)
2025-05-20 9:08 ` [PATCH V2 5/6] arm64: defconfig: enable NVIDIA VRS PSEQ Shubhi Garg
@ 2025-05-20 9:08 ` Shubhi Garg
5 siblings, 0 replies; 12+ messages in thread
From: Shubhi Garg @ 2025-05-20 9:08 UTC (permalink / raw)
To: jonathanh, lee, robh, krzk, alexandre.belloni, thierry.reding,
devicetree, linux-tegra, linux-kernel
Cc: Shubhi Garg
Add NVIDIA VRS (Voltage Regulator Specification) power sequencer driver
entry in MAINTAINERS.
Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
---
v2:
- this is a new patch in V2
MAINTAINERS | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 20e07e61a148..aff6a915d5a2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17707,6 +17707,15 @@ S: Maintained
F: drivers/video/fbdev/nvidia/
F: drivers/video/fbdev/riva/
+NVIDIA VRS POWER SEQUENCER
+M: Shubhi Garg <shgarg@nvidia.com>
+L: linux-tegra@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/mfd/nvidia,vrs-pseq.yaml
+F: drivers/mfd/nvidia-vrs-pseq.c
+F: drivers/rtc/rtc-nvidia-vrs-pseq.c
+F: include/linux/mfd/nvidia-vrs-pseq.h
+
NVIDIA WMI EC BACKLIGHT DRIVER
M: Daniel Dadap <ddadap@nvidia.com>
L: platform-driver-x86@vger.kernel.org
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread