* [PATCH v2 0/4] Add UFS host controller support for NVIDIA Tegra264
@ 2026-09-29 9:45 Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 1/4] dt-bindings: ufs: Add nvidia,tegra264-ufs Kartik Rajput
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Kartik Rajput @ 2026-09-29 9:45 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, James E.J. Bottomley, Martin K. Petersen,
Philipp Zabel
Cc: Thierry Reding, linux-scsi, devicetree, linux-tegra,
linux-kernel, Kartik Rajput
Add UFS host controller support for NVIDIA Tegra264 SoCs. The controller
supports UFS 3.1 up to HS-G4B on two data lanes.
This series depends on the Tegra264 M-PHY series: the binding references
the M-PHY provider, and drivers/ufs/host/Kconfig selects PHY_TEGRA_MPHY.
The driver consumes the M-PHY through the generic PHY API.
Changes in v2:
- Rename the UFS functional clock to "core" and the host-consumed UPHY
PLL clock to "hs" in the binding and driver.
- Use raw M-PHY cell values in the binding example so it can be checked
independently of the prerequisite series.
- Drop the unnecessary mod_devicetable.h include and clean up the OF
match table initializers.
- Limit compile testing to 64-bit architectures because the high-speed
link clock rate exceeds the range of unsigned long on 32-bit systems.
- Tear down the M-PHY lanes in reverse initialization order.
- Link to v1: https://lore.kernel.org/r/20260909-tegra264-ufs-v1-0-e4a9831702a0@nvidia.com
Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
---
Kartik Rajput (4):
dt-bindings: ufs: Add nvidia,tegra264-ufs
scsi: ufs: Add UIC DEBUGSAVECONFIGTIME attribute and its field masks
scsi: ufs: hisi: Use VS_DEBUGSAVECONFIGTIME instead of a literal address
scsi: ufs: tegra: Add Tegra264 UFS host controller driver
.../bindings/ufs/nvidia,tegra264-ufs.yaml | 120 ++++
drivers/ufs/host/Kconfig | 14 +
drivers/ufs/host/Makefile | 1 +
drivers/ufs/host/ufs-hisi.c | 6 +-
drivers/ufs/host/ufs-tegra.c | 686 +++++++++++++++++++++
include/ufs/unipro.h | 6 +
6 files changed, 829 insertions(+), 4 deletions(-)
---
base-commit: 6375e61c01e93e35ee7acd336a689ac1fae4b509
change-id: 20260909-tegra264-ufs-92edda57c75a
prerequisite-change-id: 20260909-tegra264-mphy-f3edf6fa4321:v1
prerequisite-patch-id: 1c46e1bce9f6106dbabf81e50cd366d3d2da01fc
prerequisite-patch-id: d367971b99f7308cef032b436c054d005b94eded
Best regards,
--
Kartik Rajput <kkartik@nvidia.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/4] dt-bindings: ufs: Add nvidia,tegra264-ufs
2026-09-29 9:45 [PATCH v2 0/4] Add UFS host controller support for NVIDIA Tegra264 Kartik Rajput
@ 2026-09-29 9:45 ` Kartik Rajput
2026-09-30 10:43 ` Krzysztof Kozlowski
2026-09-29 9:45 ` [PATCH v2 2/4] scsi: ufs: Add UIC DEBUGSAVECONFIGTIME attribute and its field masks Kartik Rajput
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Kartik Rajput @ 2026-09-29 9:45 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, James E.J. Bottomley, Martin K. Petersen,
Philipp Zabel
Cc: Thierry Reding, linux-scsi, devicetree, linux-tegra,
linux-kernel, Kartik Rajput
Add binding for the UFS host controller on NVIDIA Tegra264 SoCs. The
controller supports UFS 3.1 up to HS-G4B on two data lanes.
Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
---
.../bindings/ufs/nvidia,tegra264-ufs.yaml | 120 +++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git a/Documentation/devicetree/bindings/ufs/nvidia,tegra264-ufs.yaml b/Documentation/devicetree/bindings/ufs/nvidia,tegra264-ufs.yaml
new file mode 100644
index 000000000000..a6f3abd10c0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/ufs/nvidia,tegra264-ufs.yaml
@@ -0,0 +1,120 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ufs/nvidia,tegra264-ufs.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra264 UFS Host Controller
+
+maintainers:
+ - Kartik Rajput <kkartik@nvidia.com>
+ - Thierry Reding <treding@nvidia.com>
+
+properties:
+ compatible:
+ const: nvidia,tegra264-ufs
+
+ reg:
+ items:
+ - description: UFS Host Controller registers
+ - description: UFS auxiliary registers
+
+ reg-names:
+ items:
+ - const: ufs
+ - const: aux
+
+ clocks:
+ items:
+ - description: UFS host controller core clock
+ - description: UFS host controller divider clock
+ - description: UFS reference clock (PLLREFUFS output)
+ - description: UFS device-side reference clock
+ - description: UFS high-speed link clock (UPHY0 PLL4 digital output)
+
+ clock-names:
+ items:
+ - const: core
+ - const: div
+ - const: ref
+ - const: ref-dev
+ - const: hs
+
+ resets:
+ items:
+ - description: UFS host controller reset
+ - description: UFS host controller AXI-master reset
+ - description: UFS host controller low-power sequencer reset
+
+ reset-names:
+ items:
+ - const: ufs
+ - const: axi
+ - const: lp
+
+ phys:
+ items:
+ - description: M-PHY lane 0 transmit
+ - description: M-PHY lane 0 receive
+ - description: M-PHY lane 1 transmit
+ - description: M-PHY lane 1 receive
+
+ phy-names:
+ items:
+ - const: mphy-l0-tx
+ - const: mphy-l0-rx
+ - const: mphy-l1-tx
+ - const: mphy-l1-rx
+
+ iommus:
+ maxItems: 1
+
+ dma-coherent: true
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - phys
+ - phy-names
+ - iommus
+ - dma-coherent
+
+allOf:
+ - $ref: ufs-common.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/nvidia,tegra264.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/reset/nvidia,tegra264.h>
+
+ ufs@b8d0000 {
+ compatible = "nvidia,tegra264-ufs";
+ reg = <0xb8d0000 0x10000>,
+ <0xb8e0000 0x8000>;
+ reg-names = "ufs", "aux";
+ interrupts = <GIC_SPI 951 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&bpmp TEGRA264_CLK_UFSHC_CG_SYS>,
+ <&bpmp TEGRA264_CLK_UFSHC_CG_SYS_DIV>,
+ <&bpmp TEGRA264_CLK_PLLREFUFS_CLKOUT624>,
+ <&bpmp TEGRA264_CLK_PLLREFUFS_UFSDEV_REFCLKOUT>,
+ <&bpmp TEGRA264_CLK_UPHY0_PLL4_XDIG>;
+ clock-names = "core", "div", "ref", "ref-dev", "hs";
+ resets = <&bpmp TEGRA264_RESET_UFSHC>,
+ <&bpmp TEGRA264_RESET_UFSHC_AXI_M>,
+ <&bpmp TEGRA264_RESET_UFSHC_LP_SEQ>;
+ reset-names = "ufs", "axi", "lp";
+ phys = <&mphy 0>, <&mphy 1>, <&mphy 2>, <&mphy 3>;
+ phy-names = "mphy-l0-tx", "mphy-l0-rx",
+ "mphy-l1-tx", "mphy-l1-rx";
+ iommus = <&smmu 0x20>;
+ dma-coherent;
+ };
+...
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/4] scsi: ufs: Add UIC DEBUGSAVECONFIGTIME attribute and its field masks
2026-09-29 9:45 [PATCH v2 0/4] Add UFS host controller support for NVIDIA Tegra264 Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 1/4] dt-bindings: ufs: Add nvidia,tegra264-ufs Kartik Rajput
@ 2026-09-29 9:45 ` Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 3/4] scsi: ufs: hisi: Use VS_DEBUGSAVECONFIGTIME instead of a literal address Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 4/4] scsi: ufs: tegra: Add Tegra264 UFS host controller driver Kartik Rajput
3 siblings, 0 replies; 9+ messages in thread
From: Kartik Rajput @ 2026-09-29 9:45 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, James E.J. Bottomley, Martin K. Petersen,
Philipp Zabel
Cc: Thierry Reding, linux-scsi, devicetree, linux-tegra,
linux-kernel, Kartik Rajput
Add the UniPro vendor-specific save-config-time attribute and masks for
the two fields within it:
VS_DEBUGSAVECONFIGTIME Save-config-time attribute (0xD0A0)
VS_DEBUGSAVECONFIGTIME_TREF Field masks within that attribute, for
VS_DEBUGSAVECONFIGTIME_SCT use with FIELD_PREP()
ufs-hisi already writes this attribute by its literal address, so name
it in the shared header rather than in the driver. Add it here in
preparation for the Tegra264 UFS host controller driver, which also
programs the two fields.
Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
---
include/ufs/unipro.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/ufs/unipro.h b/include/ufs/unipro.h
index 9c168703b104..f6d83878f2a6 100644
--- a/include/ufs/unipro.h
+++ b/include/ufs/unipro.h
@@ -6,6 +6,8 @@
#ifndef _UNIPRO_H_
#define _UNIPRO_H_
+#include <linux/bits.h>
+
/*
* M-TX Configuration Attributes
*/
@@ -232,8 +234,12 @@
#define VS_POWERSTATE 0xD083
#define VS_MPHYCFGUPDT 0xD085
#define VS_DEBUGOMC 0xD09E
+#define VS_DEBUGSAVECONFIGTIME 0xD0A0
#define VS_MPHYDISABLE 0xD0C1
+#define VS_DEBUGSAVECONFIGTIME_TREF GENMASK(4, 2)
+#define VS_DEBUGSAVECONFIGTIME_SCT GENMASK(1, 0)
+
#define PA_GRANULARITY_MIN_VAL 1
#define PA_GRANULARITY_MAX_VAL 6
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/4] scsi: ufs: hisi: Use VS_DEBUGSAVECONFIGTIME instead of a literal address
2026-09-29 9:45 [PATCH v2 0/4] Add UFS host controller support for NVIDIA Tegra264 Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 1/4] dt-bindings: ufs: Add nvidia,tegra264-ufs Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 2/4] scsi: ufs: Add UIC DEBUGSAVECONFIGTIME attribute and its field masks Kartik Rajput
@ 2026-09-29 9:45 ` Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 4/4] scsi: ufs: tegra: Add Tegra264 UFS host controller driver Kartik Rajput
3 siblings, 0 replies; 9+ messages in thread
From: Kartik Rajput @ 2026-09-29 9:45 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, James E.J. Bottomley, Martin K. Petersen,
Philipp Zabel
Cc: Thierry Reding, linux-scsi, devicetree, linux-tegra,
linux-kernel, Kartik Rajput
ufs-hisi writes the VS_DebugSaveConfigTime UIC attribute twice by its
literal address, with a comment naming it each time. The attribute now
has a name in the shared UniPro header, so use it and drop the comments
and the redundant (u32) cast.
No functional change.
Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
---
drivers/ufs/host/ufs-hisi.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/ufs/host/ufs-hisi.c b/drivers/ufs/host/ufs-hisi.c
index 993e20ac211d..79417c16c627 100644
--- a/drivers/ufs/host/ufs-hisi.c
+++ b/drivers/ufs/host/ufs-hisi.c
@@ -318,8 +318,7 @@ static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba)
* Boston platform need to set SaveConfigTime to 0x13,
* and change sync length to maximum value
*/
- /* VS_DebugSaveConfigTime */
- ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0xD0A0), 0x13);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGSAVECONFIGTIME), 0x13);
/* g1 sync length */
ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1552), 0x4f);
/* g2 sync length */
@@ -335,8 +334,7 @@ static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba)
if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME) {
pr_info("ufs flash device must set VS_DebugSaveConfigTime 0x10\n");
- /* VS_DebugSaveConfigTime */
- ufshcd_dme_set(hba, UIC_ARG_MIB(0xD0A0), 0x10);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGSAVECONFIGTIME), 0x10);
/* sync length */
ufshcd_dme_set(hba, UIC_ARG_MIB(0x1556), 0x48);
}
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 4/4] scsi: ufs: tegra: Add Tegra264 UFS host controller driver
2026-09-29 9:45 [PATCH v2 0/4] Add UFS host controller support for NVIDIA Tegra264 Kartik Rajput
` (2 preceding siblings ...)
2026-09-29 9:45 ` [PATCH v2 3/4] scsi: ufs: hisi: Use VS_DEBUGSAVECONFIGTIME instead of a literal address Kartik Rajput
@ 2026-09-29 9:45 ` Kartik Rajput
2026-09-30 10:44 ` Krzysztof Kozlowski
2026-09-30 11:34 ` Thierry Reding
3 siblings, 2 replies; 9+ messages in thread
From: Kartik Rajput @ 2026-09-29 9:45 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, James E.J. Bottomley, Martin K. Petersen,
Philipp Zabel
Cc: Thierry Reding, linux-scsi, devicetree, linux-tegra,
linux-kernel, Kartik Rajput
Add a driver for the UFS host controller found on NVIDIA Tegra264 SoCs.
The controller has Tegra-specific auxiliary registers, clocks and resets,
and it drives the four M-PHY lane directions exposed by the Tegra264
M-PHY driver.
Co-developed-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
---
drivers/ufs/host/Kconfig | 14 +
drivers/ufs/host/Makefile | 1 +
drivers/ufs/host/ufs-tegra.c | 686 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 701 insertions(+)
diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig
index ff170c0b6da0..7ca317d25251 100644
--- a/drivers/ufs/host/Kconfig
+++ b/drivers/ufs/host/Kconfig
@@ -168,3 +168,17 @@ config SCSI_UFS_AMD_VERSAL2
Select this if you have UFS controller on AMD Versal Gen 2 SoC.
If unsure, say N.
+
+config SCSI_UFS_TEGRA
+ tristate "NVIDIA Tegra264 UFS controller platform driver"
+ depends on SCSI_UFSHCD_PLATFORM
+ depends on ARCH_TEGRA_264_SOC || (COMPILE_TEST && 64BIT)
+ select PHY_TEGRA_MPHY
+ help
+ Enable support for the UFS host controller on NVIDIA Tegra264
+ SoCs. The driver relies on the Tegra264 M-PHY driver
+ (PHY_TEGRA_MPHY) for the two data lanes and implements the
+ vendor register programming required for HS-mode transitions
+ and system suspend/resume.
+
+ If unsure, say N.
diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile
index 7d8db67eb23c..1459a081cc9d 100644
--- a/drivers/ufs/host/Makefile
+++ b/drivers/ufs/host/Makefile
@@ -14,5 +14,6 @@ obj-$(CONFIG_SCSI_UFS_MEDIATEK) += ufs-mediatek.o
obj-$(CONFIG_SCSI_UFS_RENESAS) += ufs-renesas.o
obj-$(CONFIG_SCSI_UFS_ROCKCHIP) += ufs-rockchip.o
obj-$(CONFIG_SCSI_UFS_SPRD) += ufs-sprd.o
+obj-$(CONFIG_SCSI_UFS_TEGRA) += ufs-tegra.o ufshcd-dwc.o
obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o
obj-$(CONFIG_SCSI_UFS_AMD_VERSAL2) += ufs-amd-versal2.o ufshcd-dwc.o
diff --git a/drivers/ufs/host/ufs-tegra.c b/drivers/ufs/host/ufs-tegra.c
new file mode 100644
index 000000000000..f12265432592
--- /dev/null
+++ b/drivers/ufs/host/ufs-tegra.c
@@ -0,0 +1,686 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// NVIDIA Tegra264 UFS host controller driver.
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <ufs/ufshcd.h>
+#include <ufs/ufshci.h>
+#include <ufs/unipro.h>
+
+#include "ufshcd-dwc.h"
+#include "ufshcd-pltfrm.h"
+#include "ufshci-dwc.h"
+
+#define UFSHC_DWC_BLOCK_BUSTHRTL 0xc0
+#define MBL(x) (((x) & 0x7) << 13)
+#define MBL_MASK (0x7 << 13)
+
+#define HCLKDIV(x) ((x) & 0xff)
+
+#define UFSHC_AUX_SW_EN_CLK_SLCG 0x08
+#define CLK_OVR_ON BIT(0)
+
+#define UFSHC_AUX_DEV_CTRL 0x14
+#define DEV_CTRL_CLK_EN BIT(0)
+#define DEV_CTRL_RESET BIT(1)
+
+#define UFS_TEGRA_HS_CLK_RATE_HZ 5840000000UL
+
+/* DWC UFSHC BUSTHRTL max AXI burst length. */
+#define UFS_TEGRA_MBL_MAX 0x5
+
+/* DWC UniPro save-config-time reference and value fields. */
+#define UFS_TEGRA_SAVECONFIGTIME_TREF 0x6
+#define UFS_TEGRA_SAVECONFIGTIME_SCT 0x3
+
+/* HS G1..G4 sync burst length advertised to the peer. */
+#define UFS_TEGRA_HSG_SYNC_LEN 0x4f
+
+/* Local UniPro DME timeout values sent to the peer via PA_PWRMODEUSERDATA. */
+#define UFS_TEGRA_FC0_TIMEOUT 0x1fff
+#define UFS_TEGRA_TC0_TIMEOUT 0xffff
+#define UFS_TEGRA_AFC0_TIMEOUT 0x7fff
+
+struct ufs_tegra {
+ void __iomem *aux;
+
+ struct reset_control_bulk_data *resets;
+ unsigned int num_resets;
+
+ struct clk *core_clk;
+ struct clk *hs_clk;
+
+ struct phy *mphy_l0_rx;
+ struct phy *mphy_l0_tx;
+ struct phy *mphy_l1_rx;
+ struct phy *mphy_l1_tx;
+
+ bool mphy_on;
+
+ struct ufs_host_params host_params;
+};
+
+static int ufs_tegra_init_resources(struct ufs_hba *hba)
+{
+ struct platform_device *pdev = to_platform_device(hba->dev);
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+
+ ufs->aux = devm_platform_ioremap_resource_byname(pdev, "aux");
+ if (IS_ERR(ufs->aux))
+ return PTR_ERR(ufs->aux);
+
+ return 0;
+}
+
+static const struct reset_control_bulk_data ufs_tegra_resets[] = {
+ { .id = "ufs" },
+ { .id = "axi" },
+ { .id = "lp" },
+};
+
+static int ufs_tegra_parse_reset_info(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ struct device *dev = hba->dev;
+
+ ufs->num_resets = ARRAY_SIZE(ufs_tegra_resets);
+
+ ufs->resets = devm_kmemdup(dev, ufs_tegra_resets, sizeof(ufs_tegra_resets), GFP_KERNEL);
+ if (!ufs->resets)
+ return -ENOMEM;
+
+ return devm_reset_control_bulk_get_exclusive(dev, ufs->num_resets, ufs->resets);
+}
+
+static int ufs_tegra_parse_clock_info(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ struct ufs_clk_info *clki;
+
+ list_for_each_entry(clki, &hba->clk_list_head, list) {
+ if (!strcmp(clki->name, "core"))
+ ufs->core_clk = clki->clk;
+
+ if (!strcmp(clki->name, "hs"))
+ ufs->hs_clk = clki->clk;
+ }
+
+ if (!ufs->core_clk || !ufs->hs_clk)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int ufs_tegra_parse_phy_info(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ struct device *dev = hba->dev;
+
+ ufs->mphy_l0_rx = devm_phy_get(dev, "mphy-l0-rx");
+ if (IS_ERR(ufs->mphy_l0_rx))
+ return PTR_ERR(ufs->mphy_l0_rx);
+
+ ufs->mphy_l0_tx = devm_phy_get(dev, "mphy-l0-tx");
+ if (IS_ERR(ufs->mphy_l0_tx))
+ return PTR_ERR(ufs->mphy_l0_tx);
+
+ ufs->mphy_l1_rx = devm_phy_get(dev, "mphy-l1-rx");
+ if (IS_ERR(ufs->mphy_l1_rx))
+ return PTR_ERR(ufs->mphy_l1_rx);
+
+ ufs->mphy_l1_tx = devm_phy_get(dev, "mphy-l1-tx");
+ if (IS_ERR(ufs->mphy_l1_tx))
+ return PTR_ERR(ufs->mphy_l1_tx);
+
+ return 0;
+}
+
+static void ufs_tegra_set_caps(struct ufs_hba *hba)
+{
+ hba->caps |= UFSHCD_CAP_INTR_AGGR;
+ hba->caps |= UFSHCD_CAP_WB_EN;
+
+ hba->spm_lvl = UFS_PM_LVL_5;
+}
+
+static void ufs_tegra_configure_aux(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ u32 value;
+
+ value = readl(ufs->aux + UFSHC_AUX_DEV_CTRL);
+ value |= DEV_CTRL_CLK_EN;
+ writel(value, ufs->aux + UFSHC_AUX_DEV_CTRL);
+
+ /* Let the reference clock stabilise before deasserting device reset. */
+ usleep_range(1000, 2000);
+
+ value |= DEV_CTRL_RESET;
+ writel(value, ufs->aux + UFSHC_AUX_DEV_CTRL);
+}
+
+static void ufs_tegra_aux_init(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ u32 value;
+
+ value = readl(ufs->aux + UFSHC_AUX_DEV_CTRL);
+ value &= ~(DEV_CTRL_CLK_EN | DEV_CTRL_RESET);
+ writel(value, ufs->aux + UFSHC_AUX_DEV_CTRL);
+
+ /* Ensure the clear is observed before we re-enable. */
+ usleep_range(100, 200);
+
+ ufs_tegra_configure_aux(hba);
+}
+
+static void ufs_tegra_update_hclk_div(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ u32 core_clk_mhz;
+
+ core_clk_mhz = clk_get_rate(ufs->core_clk) / USEC_PER_SEC;
+ ufshcd_writel(hba, HCLKDIV(core_clk_mhz), DWC_UFS_REG_HCLKDIV);
+}
+
+static int ufs_tegra_init(struct ufs_hba *hba)
+{
+ struct platform_device *pdev = to_platform_device(hba->dev);
+ struct device *dev = &pdev->dev;
+ struct ufs_tegra *ufs;
+ int err;
+
+ ufs = devm_kzalloc(dev, sizeof(*ufs), GFP_KERNEL);
+ if (!ufs)
+ return -ENOMEM;
+
+ ufshcd_set_variant(hba, ufs);
+
+ err = ufs_tegra_init_resources(hba);
+ if (err)
+ return err;
+
+ err = ufs_tegra_parse_clock_info(hba);
+ if (err)
+ return err;
+
+ err = ufs_tegra_parse_reset_info(hba);
+ if (err)
+ return err;
+
+ err = ufs_tegra_parse_phy_info(hba);
+ if (err)
+ return err;
+
+ ufs_tegra_set_caps(hba);
+
+ ufshcd_init_host_params(&ufs->host_params);
+ ufs->host_params.hs_rx_gear = UFS_HS_G4;
+ ufs->host_params.hs_tx_gear = UFS_HS_G4;
+
+ err = reset_control_bulk_deassert(ufs->num_resets, ufs->resets);
+ if (err)
+ return err;
+
+ ufs_tegra_aux_init(hba);
+ ufs_tegra_update_hclk_div(hba);
+
+ return 0;
+}
+
+static int ufs_tegra_mphy_init(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ int err;
+
+ err = phy_init(ufs->mphy_l0_rx);
+ if (err) {
+ dev_err(hba->dev, "failed to initialize mphy-l0-rx\n");
+ return err;
+ }
+
+ err = phy_init(ufs->mphy_l0_tx);
+ if (err) {
+ dev_err(hba->dev, "failed to initialize mphy-l0-tx\n");
+ goto out_exit_l0_rx;
+ }
+
+ err = phy_init(ufs->mphy_l1_rx);
+ if (err) {
+ dev_err(hba->dev, "failed to initialize mphy-l1-rx\n");
+ goto out_exit_l0_tx;
+ }
+
+ err = phy_init(ufs->mphy_l1_tx);
+ if (err) {
+ dev_err(hba->dev, "failed to initialize mphy-l1-tx\n");
+ goto out_exit_l1_rx;
+ }
+
+ return 0;
+
+out_exit_l1_rx:
+ phy_exit(ufs->mphy_l1_rx);
+out_exit_l0_tx:
+ phy_exit(ufs->mphy_l0_tx);
+out_exit_l0_rx:
+ phy_exit(ufs->mphy_l0_rx);
+
+ return err;
+}
+
+static void ufs_tegra_mphy_exit(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+
+ phy_exit(ufs->mphy_l1_tx);
+ phy_exit(ufs->mphy_l1_rx);
+ phy_exit(ufs->mphy_l0_tx);
+ phy_exit(ufs->mphy_l0_rx);
+}
+
+static int ufs_tegra_mphy_power_on(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ int err;
+
+ err = phy_power_on(ufs->mphy_l0_rx);
+ if (err) {
+ dev_err(hba->dev, "failed to power on mphy-l0-rx\n");
+ return err;
+ }
+
+ err = phy_power_on(ufs->mphy_l0_tx);
+ if (err) {
+ dev_err(hba->dev, "failed to power on mphy-l0-tx\n");
+ goto out_power_off_l0_rx;
+ }
+
+ err = phy_power_on(ufs->mphy_l1_rx);
+ if (err) {
+ dev_err(hba->dev, "failed to power on mphy-l1-rx\n");
+ goto out_power_off_l0_tx;
+ }
+
+ err = phy_power_on(ufs->mphy_l1_tx);
+ if (err) {
+ dev_err(hba->dev, "failed to power on mphy-l1-tx\n");
+ goto out_power_off_l1_rx;
+ }
+
+ return 0;
+
+out_power_off_l1_rx:
+ phy_power_off(ufs->mphy_l1_rx);
+out_power_off_l0_tx:
+ phy_power_off(ufs->mphy_l0_tx);
+out_power_off_l0_rx:
+ phy_power_off(ufs->mphy_l0_rx);
+
+ return err;
+}
+
+static void ufs_tegra_mphy_power_off(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+
+ phy_power_off(ufs->mphy_l1_tx);
+ phy_power_off(ufs->mphy_l1_rx);
+ phy_power_off(ufs->mphy_l0_tx);
+ phy_power_off(ufs->mphy_l0_rx);
+}
+
+static int ufs_tegra_mphy_enable(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ int err;
+
+ if (ufs->mphy_on)
+ return 0;
+
+ err = ufs_tegra_mphy_init(hba);
+ if (err)
+ return err;
+
+ err = ufs_tegra_mphy_power_on(hba);
+ if (err) {
+ ufs_tegra_mphy_exit(hba);
+ return err;
+ }
+
+ ufs->mphy_on = true;
+
+ /* Allow M-PHY to settle after power-on. */
+ usleep_range(500, 600);
+
+ return 0;
+}
+
+static void ufs_tegra_mphy_disable(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+
+ if (!ufs->mphy_on)
+ return;
+
+ ufs_tegra_mphy_power_off(hba);
+ ufs_tegra_mphy_exit(hba);
+
+ ufs->mphy_on = false;
+}
+
+static int ufs_tegra_mphy_configure_tx(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ int err;
+
+ err = phy_configure(ufs->mphy_l0_tx, NULL);
+ if (err)
+ return err;
+
+ return phy_configure(ufs->mphy_l1_tx, NULL);
+}
+
+static int ufs_tegra_mphy_calibrate_tx(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ int err;
+
+ err = phy_calibrate(ufs->mphy_l0_tx);
+ if (err)
+ return err;
+
+ return phy_calibrate(ufs->mphy_l1_tx);
+}
+
+static int ufs_tegra_mphy_calibrate_rx(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ int err;
+
+ err = phy_configure(ufs->mphy_l1_rx, NULL);
+ if (err)
+ return err;
+
+ err = phy_configure(ufs->mphy_l0_rx, NULL);
+ if (err)
+ return err;
+
+ err = phy_calibrate(ufs->mphy_l1_rx);
+ if (err)
+ return err;
+
+ return phy_calibrate(ufs->mphy_l0_rx);
+}
+
+static void ufs_tegra_exit(struct ufs_hba *hba)
+{
+ ufs_tegra_mphy_disable(hba);
+}
+
+static int ufs_tegra_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
+ enum ufs_notify_change_status status)
+{
+ if (status == PRE_CHANGE)
+ return 0;
+
+ /* Runtime H8 park keeps the M-PHY powered; only tear it down
+ * on the full-teardown paths (system suspend, shutdown, or
+ * runtime PM with LINK_OFF).
+ */
+ if (pm_op == UFS_RUNTIME_PM && !ufshcd_is_link_off(hba))
+ return 0;
+
+ ufs_tegra_mphy_disable(hba);
+
+ if (pm_op != UFS_RUNTIME_PM)
+ ufshcd_set_link_off(hba);
+
+ return 0;
+}
+
+static int ufs_tegra_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+{
+ /* Skip when the M-PHY was left powered by the suspend path. */
+ if (ufshcd_is_link_active(hba) || ufshcd_is_link_hibern8(hba))
+ return 0;
+
+ return ufs_tegra_mphy_enable(hba);
+}
+
+static int ufs_tegra_reset(struct ufs_tegra *ufs)
+{
+ int err;
+
+ err = reset_control_bulk_assert(ufs->num_resets, ufs->resets);
+ if (err)
+ return err;
+
+ usleep_range(100, 200);
+
+ err = reset_control_bulk_deassert(ufs->num_resets, ufs->resets);
+ if (err)
+ return err;
+
+ usleep_range(500, 600);
+
+ return 0;
+}
+
+static int ufs_tegra_power_up_sequence(struct ufs_hba *hba)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ int err;
+
+ err = ufs_tegra_reset(ufs);
+ if (err)
+ return err;
+
+ return ufs_tegra_mphy_enable(hba);
+}
+
+static void ufs_tegra_setup(struct ufs_hba *hba)
+{
+ ufs_tegra_configure_aux(hba);
+ ufs_tegra_update_hclk_div(hba);
+ ufshcd_rmwl(hba, MBL_MASK, MBL(UFS_TEGRA_MBL_MAX), UFSHC_DWC_BLOCK_BUSTHRTL);
+}
+
+static int ufs_tegra_hce_enable_notify(struct ufs_hba *hba, enum ufs_notify_change_status status)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ u32 value;
+ int err;
+
+ switch (status) {
+ case PRE_CHANGE:
+ err = ufs_tegra_power_up_sequence(hba);
+ if (err)
+ return err;
+
+ /* Assert device reset; POST_CHANGE releases it via
+ * ufs_tegra_configure_aux() so the HCE toggle pulses it.
+ */
+ value = readl(ufs->aux + UFSHC_AUX_DEV_CTRL);
+ value &= ~DEV_CTRL_RESET;
+ writel(value, ufs->aux + UFSHC_AUX_DEV_CTRL);
+ break;
+ case POST_CHANGE:
+ value = readl(ufs->aux + UFSHC_AUX_SW_EN_CLK_SLCG);
+ value &= ~CLK_OVR_ON;
+ writel(value, ufs->aux + UFSHC_AUX_SW_EN_CLK_SLCG);
+
+ ufs_tegra_setup(hba);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ufs_tegra_link_startup_notify(struct ufs_hba *hba, enum ufs_notify_change_status status)
+{
+ static const struct ufshcd_dme_attr_val post_change_attrs[] = {
+ { UIC_ARG_MIB(T_CONNECTIONSTATE), 0x1, DME_LOCAL },
+ { UIC_ARG_MIB(PA_TXHSG1SYNCLENGTH), UFS_TEGRA_HSG_SYNC_LEN, DME_LOCAL },
+ { UIC_ARG_MIB(PA_TXHSG2SYNCLENGTH), UFS_TEGRA_HSG_SYNC_LEN, DME_LOCAL },
+ { UIC_ARG_MIB(PA_TXHSG3SYNCLENGTH), UFS_TEGRA_HSG_SYNC_LEN, DME_LOCAL },
+ { UIC_ARG_MIB(PA_TXHSG4SYNCLENGTH), UFS_TEGRA_HSG_SYNC_LEN, DME_LOCAL },
+ { UIC_ARG_MIB(DME_LocalFC0ProtectionTimeOutVal), UFS_TEGRA_FC0_TIMEOUT, DME_LOCAL },
+ { UIC_ARG_MIB(DME_LocalTC0ReplayTimeOutVal), UFS_TEGRA_TC0_TIMEOUT, DME_LOCAL },
+ { UIC_ARG_MIB(DME_LocalAFC0ReqTimeOutVal), UFS_TEGRA_AFC0_TIMEOUT, DME_LOCAL },
+ { UIC_ARG_MIB(PA_PWRMODEUSERDATA0), UFS_TEGRA_FC0_TIMEOUT, DME_LOCAL },
+ { UIC_ARG_MIB(PA_PWRMODEUSERDATA1), UFS_TEGRA_TC0_TIMEOUT, DME_LOCAL },
+ { UIC_ARG_MIB(PA_PWRMODEUSERDATA2), UFS_TEGRA_AFC0_TIMEOUT, DME_LOCAL },
+ };
+ int err;
+
+ switch (status) {
+ case PRE_CHANGE:
+ /* Arm TX calibration; RX capabilities are advertised in
+ * tegra_mphy_rx_power_on().
+ */
+ err = ufs_tegra_mphy_configure_tx(hba);
+ if (err)
+ return err;
+ break;
+
+ case POST_CHANGE:
+ err = ufs_tegra_mphy_calibrate_tx(hba);
+ if (err)
+ return err;
+
+ err = ufshcd_dwc_dme_set_attrs(hba, post_change_attrs,
+ ARRAY_SIZE(post_change_attrs));
+ if (err)
+ return err;
+
+ err = ufs_tegra_mphy_calibrate_rx(hba);
+ if (err)
+ return err;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ufs_tegra_negotiate_pwr_mode(struct ufs_hba *hba,
+ const struct ufs_pa_layer_attr *dev_max_params,
+ struct ufs_pa_layer_attr *dev_req_params)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+
+ return ufshcd_negotiate_pwr_params(&ufs->host_params, dev_max_params, dev_req_params);
+}
+
+static int ufs_tegra_pwr_change_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status,
+ struct ufs_pa_layer_attr *dev_req_params)
+{
+ struct ufs_tegra *ufs = ufshcd_get_variant(hba);
+ u32 value;
+ int err;
+
+ if (status != PRE_CHANGE)
+ return 0;
+
+ err = ufshcd_dme_get(hba, UIC_ARG_MIB(VS_DEBUGSAVECONFIGTIME), &value);
+ if (err)
+ return err;
+
+ value &= ~VS_DEBUGSAVECONFIGTIME_TREF;
+ value |= FIELD_PREP(VS_DEBUGSAVECONFIGTIME_TREF, UFS_TEGRA_SAVECONFIGTIME_TREF);
+ value &= ~VS_DEBUGSAVECONFIGTIME_SCT;
+ value |= FIELD_PREP(VS_DEBUGSAVECONFIGTIME_SCT, UFS_TEGRA_SAVECONFIGTIME_SCT);
+
+ err = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGSAVECONFIGTIME), value);
+ if (err)
+ return err;
+
+ if (dev_req_params->hs_rate == PA_HS_MODE_A ||
+ dev_req_params->hs_rate == PA_HS_MODE_B) {
+ err = clk_set_rate(ufs->hs_clk, UFS_TEGRA_HS_CLK_RATE_HZ);
+ if (err)
+ return err;
+ }
+
+ err = ufshcd_dme_configure_adapt(hba, dev_req_params->gear_tx, PA_INITIAL_ADAPT);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int ufs_tegra_set_dma_mask(struct ufs_hba *hba)
+{
+ return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32));
+}
+
+static const struct ufs_hba_variant_ops ufs_tegra_vops = {
+ .name = "ufs-tegra",
+ .init = ufs_tegra_init,
+ .exit = ufs_tegra_exit,
+ .suspend = ufs_tegra_suspend,
+ .resume = ufs_tegra_resume,
+ .hce_enable_notify = ufs_tegra_hce_enable_notify,
+ .negotiate_pwr_mode = ufs_tegra_negotiate_pwr_mode,
+ .pwr_change_notify = ufs_tegra_pwr_change_notify,
+ .link_startup_notify = ufs_tegra_link_startup_notify,
+ .set_dma_mask = ufs_tegra_set_dma_mask,
+};
+
+static int ufs_tegra_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ int err;
+
+ err = ufshcd_pltfrm_init(pdev, &ufs_tegra_vops);
+ if (err)
+ return dev_err_probe(dev, err, "ufshcd platform init failed\n");
+
+ return 0;
+}
+
+static void ufs_tegra_remove(struct platform_device *pdev)
+{
+ ufshcd_pltfrm_remove(pdev);
+}
+
+static const struct dev_pm_ops ufs_tegra_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+ SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
+};
+
+static const struct of_device_id ufs_tegra_of_match[] = {
+ { .compatible = "nvidia,tegra264-ufs" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ufs_tegra_of_match);
+
+static struct platform_driver ufs_tegra_driver = {
+ .probe = ufs_tegra_probe,
+ .remove = ufs_tegra_remove,
+ .driver = {
+ .name = "ufs-tegra",
+ .pm = &ufs_tegra_pm_ops,
+ .of_match_table = ufs_tegra_of_match,
+ },
+};
+module_platform_driver(ufs_tegra_driver);
+
+MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+MODULE_AUTHOR("Kartik Rajput <kkartik@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Tegra UFS host controller driver");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/4] dt-bindings: ufs: Add nvidia,tegra264-ufs
2026-09-29 9:45 ` [PATCH v2 1/4] dt-bindings: ufs: Add nvidia,tegra264-ufs Kartik Rajput
@ 2026-09-30 10:43 ` Krzysztof Kozlowski
2026-09-30 10:45 ` Krzysztof Kozlowski
0 siblings, 1 reply; 9+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-30 10:43 UTC (permalink / raw)
To: Kartik Rajput
Cc: Alim Akhtar, Avri Altman, Bart Van Assche, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, James E.J. Bottomley, Martin K. Petersen,
Philipp Zabel, Thierry Reding, linux-scsi, devicetree,
linux-tegra, linux-kernel
On Tue, Sep 29, 2026 at 03:15:07PM +0530, Kartik Rajput wrote:
> Add binding for the UFS host controller on NVIDIA Tegra264 SoCs. The
> controller supports UFS 3.1 up to HS-G4B on two data lanes.
>
> Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
I do not understand why you added dependency on the phy in this
patchset. Looks like fake/not real dependency, so you only stall your
work and raise questions.
Cover letter mentions "the binding references
the M-PHY provider" but this is simply NOT TRUE.
Patch itself is correct but I suggest to be careful what you send, to
avoid questions on trivial stuff.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 4/4] scsi: ufs: tegra: Add Tegra264 UFS host controller driver
2026-09-29 9:45 ` [PATCH v2 4/4] scsi: ufs: tegra: Add Tegra264 UFS host controller driver Kartik Rajput
@ 2026-09-30 10:44 ` Krzysztof Kozlowski
2026-09-30 11:34 ` Thierry Reding
1 sibling, 0 replies; 9+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-30 10:44 UTC (permalink / raw)
To: Kartik Rajput
Cc: Alim Akhtar, Avri Altman, Bart Van Assche, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, James E.J. Bottomley, Martin K. Petersen,
Philipp Zabel, Thierry Reding, linux-scsi, devicetree,
linux-tegra, linux-kernel
On Tue, Sep 29, 2026 at 03:15:10PM +0530, Kartik Rajput wrote:
> Add a driver for the UFS host controller found on NVIDIA Tegra264 SoCs.
> The controller has Tegra-specific auxiliary registers, clocks and resets,
> and it drives the four M-PHY lane directions exposed by the Tegra264
> M-PHY driver.
>
> Co-developed-by: Thierry Reding <treding@nvidia.com>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
> ---
> drivers/ufs/host/Kconfig | 14 +
> drivers/ufs/host/Makefile | 1 +
> drivers/ufs/host/ufs-tegra.c | 686 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 701 insertions(+)
>
> diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig
> index ff170c0b6da0..7ca317d25251 100644
> --- a/drivers/ufs/host/Kconfig
> +++ b/drivers/ufs/host/Kconfig
> @@ -168,3 +168,17 @@ config SCSI_UFS_AMD_VERSAL2
>
> Select this if you have UFS controller on AMD Versal Gen 2 SoC.
> If unsure, say N.
> +
> +config SCSI_UFS_TEGRA
> + tristate "NVIDIA Tegra264 UFS controller platform driver"
> + depends on SCSI_UFSHCD_PLATFORM
> + depends on ARCH_TEGRA_264_SOC || (COMPILE_TEST && 64BIT)
> + select PHY_TEGRA_MPHY
Nope.
There is nothing here which depends on the phy. If there is, you wrote
this wrong and did not use proper Linux interfaces (the Generic PHY).
Also, you must NOT select user-visible symbols, that's basic rules now.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/4] dt-bindings: ufs: Add nvidia,tegra264-ufs
2026-09-30 10:43 ` Krzysztof Kozlowski
@ 2026-09-30 10:45 ` Krzysztof Kozlowski
0 siblings, 0 replies; 9+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-30 10:45 UTC (permalink / raw)
To: Kartik Rajput
Cc: Alim Akhtar, Avri Altman, Bart Van Assche, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, James E.J. Bottomley, Martin K. Petersen,
Philipp Zabel, Thierry Reding, linux-scsi, devicetree,
linux-tegra, linux-kernel
On 30/09/2026 12:43, Krzysztof Kozlowski wrote:
> On Tue, Sep 29, 2026 at 03:15:07PM +0530, Kartik Rajput wrote:
>> Add binding for the UFS host controller on NVIDIA Tegra264 SoCs. The
>> controller supports UFS 3.1 up to HS-G4B on two data lanes.
>>
>> Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
>
> I do not understand why you added dependency on the phy in this
> patchset. Looks like fake/not real dependency, so you only stall your
> work and raise questions.
>
> Cover letter mentions "the binding references
> the M-PHY provider" but this is simply NOT TRUE.
>
> Patch itself is correct but I suggest to be careful what you send, to
> avoid questions on trivial stuff.
Forgot the tag:
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
But honestly, this fake dependency is a no-go and I commented on driver
patch regarding it.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 4/4] scsi: ufs: tegra: Add Tegra264 UFS host controller driver
2026-09-29 9:45 ` [PATCH v2 4/4] scsi: ufs: tegra: Add Tegra264 UFS host controller driver Kartik Rajput
2026-09-30 10:44 ` Krzysztof Kozlowski
@ 2026-09-30 11:34 ` Thierry Reding
1 sibling, 0 replies; 9+ messages in thread
From: Thierry Reding @ 2026-09-30 11:34 UTC (permalink / raw)
To: Kartik Rajput
Cc: Alim Akhtar, Avri Altman, Bart Van Assche, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jonathan Hunter,
James E.J. Bottomley, Martin K. Petersen, Philipp Zabel,
Thierry Reding, linux-scsi, devicetree, linux-tegra,
linux-kernel
[-- Attachment #1: Type: text/plain, Size: 6006 bytes --]
On Tue, Sep 29, 2026 at 03:15:10PM +0530, Kartik Rajput wrote:
> Add a driver for the UFS host controller found on NVIDIA Tegra264 SoCs.
> The controller has Tegra-specific auxiliary registers, clocks and resets,
> and it drives the four M-PHY lane directions exposed by the Tegra264
> M-PHY driver.
>
> Co-developed-by: Thierry Reding <treding@nvidia.com>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
> ---
> drivers/ufs/host/Kconfig | 14 +
> drivers/ufs/host/Makefile | 1 +
> drivers/ufs/host/ufs-tegra.c | 686 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 701 insertions(+)
>
> diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig
> index ff170c0b6da0..7ca317d25251 100644
> --- a/drivers/ufs/host/Kconfig
> +++ b/drivers/ufs/host/Kconfig
> @@ -168,3 +168,17 @@ config SCSI_UFS_AMD_VERSAL2
>
> Select this if you have UFS controller on AMD Versal Gen 2 SoC.
> If unsure, say N.
> +
> +config SCSI_UFS_TEGRA
> + tristate "NVIDIA Tegra264 UFS controller platform driver"
> + depends on SCSI_UFSHCD_PLATFORM
> + depends on ARCH_TEGRA_264_SOC || (COMPILE_TEST && 64BIT)
From a quick look I couldn't spot anything specific to 64-bit in the
driver. Did I miss anything?
Also, we really shouldn't depend on ARCH_TEGRA_264_SOC since this
controller exists on prior generations and we will eventually want to
support them, too.
> + select PHY_TEGRA_MPHY
Maybe to complement what Krzysztof already said: Kconfig dependencies
are primarily build-time dependencies. This driver uses the generic PHY
API to access the M-PHY functionality, so GENERIC_PHY is the correct
build-time dependency. The driver is purposefully agnostic to the
specific implementation of the PHYs that it uses so that it can work
with (potentially) many different PHY implementations.
We use device tree to hook up the runtime dependencies. If the M-PHY
driver is not enabled we get the probe deferred because the PHYs that
were hooked up in DT haven't been registered and hence can't be found
(by the generic PHY framework). On other devices the PHYs might end up
being backed by completely different implementations and they could
still work just fine.
> + help
> + Enable support for the UFS host controller on NVIDIA Tegra264
> + SoCs. The driver relies on the Tegra264 M-PHY driver
I would suggest dropping references to Tegra264 here. The driver is not
specific to Tegra264. There are older Tegra SoCs that have (earlier)
generations of this IP and that should still work with this driver
(maybe with some parameterization).
> diff --git a/drivers/ufs/host/ufs-tegra.c b/drivers/ufs/host/ufs-tegra.c
> new file mode 100644
> index 000000000000..f12265432592
> --- /dev/null
> +++ b/drivers/ufs/host/ufs-tegra.c
> @@ -0,0 +1,686 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
> +// NVIDIA Tegra264 UFS host controller driver.
Tegra264 can be dropped here as well.
[...]
> +#define UFS_TEGRA_HS_CLK_RATE_HZ 5840000000UL
Do we assume that this will always be the same value? Maybe this should
be turned into SoC data? We could always do that when necessary, of
course.
[...]
> +static int ufs_tegra_mphy_power_on(struct ufs_hba *hba)
> +{
> + struct ufs_tegra *ufs = ufshcd_get_variant(hba);
> + int err;
> +
> + err = phy_power_on(ufs->mphy_l0_rx);
> + if (err) {
> + dev_err(hba->dev, "failed to power on mphy-l0-rx\n");
> + return err;
> + }
> +
> + err = phy_power_on(ufs->mphy_l0_tx);
> + if (err) {
> + dev_err(hba->dev, "failed to power on mphy-l0-tx\n");
> + goto out_power_off_l0_rx;
> + }
> +
> + err = phy_power_on(ufs->mphy_l1_rx);
> + if (err) {
> + dev_err(hba->dev, "failed to power on mphy-l1-rx\n");
> + goto out_power_off_l0_tx;
> + }
> +
> + err = phy_power_on(ufs->mphy_l1_tx);
> + if (err) {
> + dev_err(hba->dev, "failed to power on mphy-l1-tx\n");
> + goto out_power_off_l1_rx;
> + }
> +
> + return 0;
> +
> +out_power_off_l1_rx:
> + phy_power_off(ufs->mphy_l1_rx);
> +out_power_off_l0_tx:
> + phy_power_off(ufs->mphy_l0_tx);
> +out_power_off_l0_rx:
> + phy_power_off(ufs->mphy_l0_rx);
> +
> + return err;
> +}
Almost seems like we need phy_bulk APIs. Again, doesn't need to be part
of this series, but maybe something to keep in mind.
[...]
> +static int ufs_tegra_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
> + enum ufs_notify_change_status status)
> +{
> + if (status == PRE_CHANGE)
> + return 0;
> +
> + /* Runtime H8 park keeps the M-PHY powered; only tear it down
> + * on the full-teardown paths (system suspend, shutdown, or
> + * runtime PM with LINK_OFF).
> + */
Comment style needs the first line to be /* on its own, except for the
net subsystem, if I recall correctly. There are other occurrences of
this elsewhere in the file.
Also, I read "H8" as "hate" at first and it took me a little bit to
realize it meant "hibernate" in this case. Looks like the rest of UFS
uses "hibern8". Maybe stick to the convention?
[...]
> +static int ufs_tegra_pwr_change_notify(struct ufs_hba *hba,
> + enum ufs_notify_change_status status,
> + struct ufs_pa_layer_attr *dev_req_params)
> +{
[...]
> + if (dev_req_params->hs_rate == PA_HS_MODE_A ||
> + dev_req_params->hs_rate == PA_HS_MODE_B) {
> + err = clk_set_rate(ufs->hs_clk, UFS_TEGRA_HS_CLK_RATE_HZ);
What if hs_rate != PA_HS_MODE_A or PA_HS_MODE_B?
> +static int ufs_tegra_set_dma_mask(struct ufs_hba *hba)
> +{
> + return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32));
> +}
I have a feeling like the 32 is here on purpose, but I can't fully
remember why it's not something like 40, which is the standard on recent
Tegra devices.
Maybe we should add a comment explaining why this needs to be so narrow.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-09-30 11:34 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-29 9:45 [PATCH v2 0/4] Add UFS host controller support for NVIDIA Tegra264 Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 1/4] dt-bindings: ufs: Add nvidia,tegra264-ufs Kartik Rajput
2026-09-30 10:43 ` Krzysztof Kozlowski
2026-09-30 10:45 ` Krzysztof Kozlowski
2026-09-29 9:45 ` [PATCH v2 2/4] scsi: ufs: Add UIC DEBUGSAVECONFIGTIME attribute and its field masks Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 3/4] scsi: ufs: hisi: Use VS_DEBUGSAVECONFIGTIME instead of a literal address Kartik Rajput
2026-09-29 9:45 ` [PATCH v2 4/4] scsi: ufs: tegra: Add Tegra264 UFS host controller driver Kartik Rajput
2026-09-30 10:44 ` Krzysztof Kozlowski
2026-09-30 11:34 ` Thierry Reding
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®