* [PATCH v2 0/3] Add StarFive JHB100 soc UFS platform driver
@ 2026-05-09 6:27 Minda Chen
2026-05-09 6:27 ` [PATCH v2 1/3] scsi: ufs: dt-bindings: starfive: Add UFS Host Controller for JHB100 soc Minda Chen
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Minda Chen @ 2026-05-09 6:27 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche, Sai Krishna Potthuri,
Ajay Neeli, James E . J . Bottomley, Martin K . Petersen,
Pedro Sousa, Arnd Bergmann, AngeloGioacchino Del Regno,
Conor Dooley, Rob Herring, Krzysztof Kozlowski, linux-scsi
Cc: linux-kernel, devicetree, Minda Chen
JHB100 is a Starfive new RISC-V SoC for datacenter BMC (BaseBoard
Managent Controller). Similar with Aspeed 27x0.
The JHB100 minimal system upstream is in progress:
https://patchwork.kernel.org/project/linux-riscv/cover/20260508053632.818548-1-changhuang.liang@starfivetech.com/
JHB100 contain 1 UFS 3.1 interface and using Synopsys designware
UFS controller/unipro/M-PHY. The ufs-starfive.c contain JHB100
UFS platform driver, unipro driver and M-PHY driver.
The patch base on kernel v7.1-rc2
previous link:
v1:
https://patchwork.kernel.org/project/linux-scsi/cover/20260421091215.120632-1-minda.chen@starfivetech.com/
changes:
v2:
patch1 rename dts binding doc from starfive,ufs to starfive,jhb100-ufs
Minda Chen (3):
scsi: ufs: dt-bindings: starfive: Add UFS Host Controller for JHB100
soc
scsi: ufs: dwc: Rename amd-versal2 read/write PHY API and move to dwc
common file
scsi: ufs: starfive: Add UFS support for StarFive JHB100 SoC
.../bindings/ufs/starfive,jhb100-ufs.yaml | 76 +++++
MAINTAINERS | 6 +
drivers/ufs/host/Kconfig | 13 +
drivers/ufs/host/Makefile | 1 +
drivers/ufs/host/ufs-amd-versal2.c | 85 ++----
drivers/ufs/host/ufs-starfive.c | 280 ++++++++++++++++++
drivers/ufs/host/ufshcd-dwc.c | 53 ++++
drivers/ufs/host/ufshcd-dwc.h | 20 ++
8 files changed, 466 insertions(+), 68 deletions(-)
create mode 100644 Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml
create mode 100644 drivers/ufs/host/ufs-starfive.c
base-commit: 74fe02ce122a6103f207d29fafc8b3a53de6abaf
--
2.17.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/3] scsi: ufs: dt-bindings: starfive: Add UFS Host Controller for JHB100 soc
2026-05-09 6:27 [PATCH v2 0/3] Add StarFive JHB100 soc UFS platform driver Minda Chen
@ 2026-05-09 6:27 ` Minda Chen
2026-05-09 6:38 ` sashiko-bot
2026-05-09 6:27 ` [PATCH v2 2/3] scsi: ufs: dwc: Rename amd-versal2 read/write PHY API and move to dwc common file Minda Chen
2026-05-09 6:27 ` [PATCH v2 3/3] scsi: ufs: starfive: Add UFS support for StarFive JHB100 SoC Minda Chen
2 siblings, 1 reply; 7+ messages in thread
From: Minda Chen @ 2026-05-09 6:27 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche, Sai Krishna Potthuri,
Ajay Neeli, James E . J . Bottomley, Martin K . Petersen,
Pedro Sousa, Arnd Bergmann, AngeloGioacchino Del Regno,
Conor Dooley, Rob Herring, Krzysztof Kozlowski, linux-scsi
Cc: linux-kernel, devicetree, Minda Chen
Add devicetree document for UFS Host Controller StarFive JHB100 SoC.
The UFS controller is based on the Synopsys DesignWare UFS controller.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
.../bindings/ufs/starfive,jhb100-ufs.yaml | 76 +++++++++++++++++++
MAINTAINERS | 5 ++
2 files changed, 81 insertions(+)
create mode 100644 Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml
diff --git a/Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml b/Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml
new file mode 100644
index 000000000000..4773f1c2670f
--- /dev/null
+++ b/Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ufs/starfive,jhb100-ufs.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Starfive Universal Flash Storage (UFS) Controller
+
+maintainers:
+ - Minda Chen <minda.chen@starfivetech.com>
+
+allOf:
+ - $ref: ufs-common.yaml
+
+properties:
+ compatible:
+ const: starfive,jhb100-ufs
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: UFS reference clock
+ - description: UFS main enable clock
+
+ clock-names:
+ items:
+ - const: ref_clk
+ - const: ufs
+
+ resets:
+ items:
+ - description: UFS main reset
+ - description: UFS PHY reset
+
+ reset-names:
+ items:
+ - const: main
+ - const: phy
+
+ interrupts:
+ maxItems: 1
+
+ starfive,syscon:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description:
+ The phandle to System Register Controller syscon node.
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+ - reset-names
+ - interrupts
+ - starfive,syscon
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ ufs@11b10000 {
+ compatible = "starfive,jhb100-ufs";
+ reg = <0x11b10000 0x20000>;
+ interrupts = <105>;
+ clocks = <&syscrg 4>,
+ <&syscrg 5>;
+ clock-names = "ref_clk", "ufs";
+ freq-table-hz = <26000000 26000000>,
+ <100000000 100000000>;
+ resets = <&syscrg 10>,
+ <&syscrg 7>;
+ reset-names = "main", "phy";
+ starfive,syscon = <&syscon>;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index b9a7c6ef4788..5d222150e015 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27478,6 +27478,11 @@ L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/ufs/host/ufs-renesas.c
+UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER STARFIVE
+M: Minda Chen <minda.chen@starfivetech.com>
+S: Maintained
+F: Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml
+
UNIWILL LAPTOP DRIVER
M: Armin Wolf <W_Armin@gmx.de>
L: platform-driver-x86@vger.kernel.org
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/3] scsi: ufs: dwc: Rename amd-versal2 read/write PHY API and move to dwc common file
2026-05-09 6:27 [PATCH v2 0/3] Add StarFive JHB100 soc UFS platform driver Minda Chen
2026-05-09 6:27 ` [PATCH v2 1/3] scsi: ufs: dt-bindings: starfive: Add UFS Host Controller for JHB100 soc Minda Chen
@ 2026-05-09 6:27 ` Minda Chen
2026-05-09 6:43 ` sashiko-bot
2026-05-09 6:27 ` [PATCH v2 3/3] scsi: ufs: starfive: Add UFS support for StarFive JHB100 SoC Minda Chen
2 siblings, 1 reply; 7+ messages in thread
From: Minda Chen @ 2026-05-09 6:27 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche, Sai Krishna Potthuri,
Ajay Neeli, James E . J . Bottomley, Martin K . Petersen,
Pedro Sousa, Arnd Bergmann, AngeloGioacchino Del Regno,
Conor Dooley, Rob Herring, Krzysztof Kozlowski, linux-scsi
Cc: linux-kernel, devicetree, Minda Chen
AMD versal2 UFS using designware ufs mipi PHY. The read/write PHY
register API are common functions for designware ufs PHY. For other
vendors reuse the code, move to common ufshcd-dwc.c file.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
drivers/ufs/host/ufs-amd-versal2.c | 85 ++++++------------------------
drivers/ufs/host/ufshcd-dwc.c | 53 +++++++++++++++++++
drivers/ufs/host/ufshcd-dwc.h | 2 +
3 files changed, 72 insertions(+), 68 deletions(-)
diff --git a/drivers/ufs/host/ufs-amd-versal2.c b/drivers/ufs/host/ufs-amd-versal2.c
index 2154d6286817..2e671881e7ae 100644
--- a/drivers/ufs/host/ufs-amd-versal2.c
+++ b/drivers/ufs/host/ufs-amd-versal2.c
@@ -43,57 +43,6 @@ struct ufs_versal2_host {
u8 ctlecompval1;
};
-static int ufs_versal2_phy_reg_write(struct ufs_hba *hba, u32 addr, u32 val)
-{
- static struct ufshcd_dme_attr_val phy_write_attrs[] = {
- { UIC_ARG_MIB(CBCREGADDRLSB), 0, DME_LOCAL },
- { UIC_ARG_MIB(CBCREGADDRMSB), 0, DME_LOCAL },
- { UIC_ARG_MIB(CBCREGWRLSB), 0, DME_LOCAL },
- { UIC_ARG_MIB(CBCREGWRMSB), 0, DME_LOCAL },
- { UIC_ARG_MIB(CBCREGRDWRSEL), 1, DME_LOCAL },
- { UIC_ARG_MIB(VS_MPHYCFGUPDT), 1, DME_LOCAL }
- };
-
- phy_write_attrs[0].mib_val = (u8)addr;
- phy_write_attrs[1].mib_val = (u8)(addr >> 8);
- phy_write_attrs[2].mib_val = (u8)val;
- phy_write_attrs[3].mib_val = (u8)(val >> 8);
-
- return ufshcd_dwc_dme_set_attrs(hba, phy_write_attrs, ARRAY_SIZE(phy_write_attrs));
-}
-
-static int ufs_versal2_phy_reg_read(struct ufs_hba *hba, u32 addr, u32 *val)
-{
- u32 mib_val;
- int ret;
- static struct ufshcd_dme_attr_val phy_read_attrs[] = {
- { UIC_ARG_MIB(CBCREGADDRLSB), 0, DME_LOCAL },
- { UIC_ARG_MIB(CBCREGADDRMSB), 0, DME_LOCAL },
- { UIC_ARG_MIB(CBCREGRDWRSEL), 0, DME_LOCAL },
- { UIC_ARG_MIB(VS_MPHYCFGUPDT), 1, DME_LOCAL }
- };
-
- phy_read_attrs[0].mib_val = (u8)addr;
- phy_read_attrs[1].mib_val = (u8)(addr >> 8);
-
- ret = ufshcd_dwc_dme_set_attrs(hba, phy_read_attrs, ARRAY_SIZE(phy_read_attrs));
- if (ret)
- return ret;
-
- ret = ufshcd_dme_get(hba, UIC_ARG_MIB(CBCREGRDLSB), &mib_val);
- if (ret)
- return ret;
-
- *val = mib_val;
- ret = ufshcd_dme_get(hba, UIC_ARG_MIB(CBCREGRDMSB), &mib_val);
- if (ret)
- return ret;
-
- *val |= (mib_val << 8);
-
- return 0;
-}
-
static int ufs_versal2_enable_phy(struct ufs_hba *hba)
{
u32 offset, reg;
@@ -162,64 +111,64 @@ static int ufs_versal2_setup_phy(struct ufs_hba *hba)
u32 reg;
/* Bypass RX-AFE offset calibrations (ATT/CTLE) */
- ret = ufs_versal2_phy_reg_read(hba, FAST_FLAGS(0), ®);
+ ret = ufs_dwc_phy_reg_read(hba, FAST_FLAGS(0), ®);
if (ret)
return ret;
reg |= MPHY_FAST_RX_AFE_CAL;
- ret = ufs_versal2_phy_reg_write(hba, FAST_FLAGS(0), reg);
+ ret = ufs_dwc_phy_reg_write(hba, FAST_FLAGS(0), reg);
if (ret)
return ret;
- ret = ufs_versal2_phy_reg_read(hba, FAST_FLAGS(1), ®);
+ ret = ufs_dwc_phy_reg_read(hba, FAST_FLAGS(1), ®);
if (ret)
return ret;
reg |= MPHY_FAST_RX_AFE_CAL;
- ret = ufs_versal2_phy_reg_write(hba, FAST_FLAGS(1), reg);
+ ret = ufs_dwc_phy_reg_write(hba, FAST_FLAGS(1), reg);
if (ret)
return ret;
/* Program ATT and CTLE compensation values */
if (host->attcompval0) {
- ret = ufs_versal2_phy_reg_write(hba, RX_AFE_ATT_IDAC(0), host->attcompval0);
+ ret = ufs_dwc_phy_reg_write(hba, RX_AFE_ATT_IDAC(0), host->attcompval0);
if (ret)
return ret;
}
if (host->attcompval1) {
- ret = ufs_versal2_phy_reg_write(hba, RX_AFE_ATT_IDAC(1), host->attcompval1);
+ ret = ufs_dwc_phy_reg_write(hba, RX_AFE_ATT_IDAC(1), host->attcompval1);
if (ret)
return ret;
}
if (host->ctlecompval0) {
- ret = ufs_versal2_phy_reg_write(hba, RX_AFE_CTLE_IDAC(0), host->ctlecompval0);
+ ret = ufs_dwc_phy_reg_write(hba, RX_AFE_CTLE_IDAC(0), host->ctlecompval0);
if (ret)
return ret;
}
if (host->ctlecompval1) {
- ret = ufs_versal2_phy_reg_write(hba, RX_AFE_CTLE_IDAC(1), host->ctlecompval1);
+ ret = ufs_dwc_phy_reg_write(hba, RX_AFE_CTLE_IDAC(1), host->ctlecompval1);
if (ret)
return ret;
}
- ret = ufs_versal2_phy_reg_read(hba, FW_CALIB_CCFG(0), ®);
+ ret = ufs_dwc_phy_reg_read(hba, FW_CALIB_CCFG(0), ®);
if (ret)
return ret;
reg |= MPHY_FW_CALIB_CFG_VAL;
- ret = ufs_versal2_phy_reg_write(hba, FW_CALIB_CCFG(0), reg);
+ ret = ufs_dwc_phy_reg_write(hba, FW_CALIB_CCFG(0), reg);
if (ret)
return ret;
- ret = ufs_versal2_phy_reg_read(hba, FW_CALIB_CCFG(1), ®);
+ ret = ufs_dwc_phy_reg_read(hba, FW_CALIB_CCFG(1), ®);
if (ret)
return ret;
reg |= MPHY_FW_CALIB_CFG_VAL;
- return ufs_versal2_phy_reg_write(hba, FW_CALIB_CCFG(1), reg);
+ return ufs_dwc_phy_reg_write(hba, FW_CALIB_CCFG(1), reg);
}
static int ufs_versal2_phy_init(struct ufs_hba *hba)
@@ -406,7 +355,7 @@ static int ufs_versal2_phy_ratesel(struct ufs_hba *hba, u32 activelanes, u32 rx_
for (lane = 0; lane < activelanes; lane++) {
time_left = TIMEOUT_MICROSEC;
- ret = ufs_versal2_phy_reg_read(hba, RX_OVRD_IN_1(lane), ®);
+ ret = ufs_dwc_phy_reg_read(hba, RX_OVRD_IN_1(lane), ®);
if (ret)
return ret;
@@ -416,12 +365,12 @@ static int ufs_versal2_phy_ratesel(struct ufs_hba *hba, u32 activelanes, u32 rx_
else
reg &= ~MPHY_RX_OVRD_VAL;
- ret = ufs_versal2_phy_reg_write(hba, RX_OVRD_IN_1(lane), reg);
+ ret = ufs_dwc_phy_reg_write(hba, RX_OVRD_IN_1(lane), reg);
if (ret)
return ret;
do {
- ret = ufs_versal2_phy_reg_read(hba, RX_PCS_OUT(lane), ®);
+ ret = ufs_dwc_phy_reg_read(hba, RX_PCS_OUT(lane), ®);
if (ret)
return ret;
@@ -483,12 +432,12 @@ static int ufs_versal2_pwr_change_notify(struct ufs_hba *hba, enum ufs_notify_ch
/* Remove rx_req override */
for (lane = 0; lane < dev_req_params->lane_tx; lane++) {
- ret = ufs_versal2_phy_reg_read(hba, RX_OVRD_IN_1(lane), ®);
+ ret = ufs_dwc_phy_reg_read(hba, RX_OVRD_IN_1(lane), ®);
if (ret)
return ret;
reg &= ~MPHY_RX_OVRD_EN;
- ret = ufs_versal2_phy_reg_write(hba, RX_OVRD_IN_1(lane), reg);
+ ret = ufs_dwc_phy_reg_write(hba, RX_OVRD_IN_1(lane), reg);
if (ret)
return ret;
}
diff --git a/drivers/ufs/host/ufshcd-dwc.c b/drivers/ufs/host/ufshcd-dwc.c
index 21b1cf912dcc..b057a78e151c 100644
--- a/drivers/ufs/host/ufshcd-dwc.c
+++ b/drivers/ufs/host/ufshcd-dwc.c
@@ -15,6 +15,59 @@
#include "ufshcd-dwc.h"
#include "ufshci-dwc.h"
+int ufs_dwc_phy_reg_write(struct ufs_hba *hba, u32 addr, u32 val)
+{
+ static struct ufshcd_dme_attr_val phy_write_attrs[] = {
+ { UIC_ARG_MIB(CBCREGADDRLSB), 0, DME_LOCAL },
+ { UIC_ARG_MIB(CBCREGADDRMSB), 0, DME_LOCAL },
+ { UIC_ARG_MIB(CBCREGWRLSB), 0, DME_LOCAL },
+ { UIC_ARG_MIB(CBCREGWRMSB), 0, DME_LOCAL },
+ { UIC_ARG_MIB(CBCREGRDWRSEL), 1, DME_LOCAL },
+ { UIC_ARG_MIB(VS_MPHYCFGUPDT), 1, DME_LOCAL }
+ };
+
+ phy_write_attrs[0].mib_val = (u8)addr;
+ phy_write_attrs[1].mib_val = (u8)(addr >> 8);
+ phy_write_attrs[2].mib_val = (u8)val;
+ phy_write_attrs[3].mib_val = (u8)(val >> 8);
+
+ return ufshcd_dwc_dme_set_attrs(hba, phy_write_attrs, ARRAY_SIZE(phy_write_attrs));
+}
+EXPORT_SYMBOL(ufs_dwc_phy_reg_write);
+
+int ufs_dwc_phy_reg_read(struct ufs_hba *hba, u32 addr, u32 *val)
+{
+ u32 mib_val;
+ int ret;
+ static struct ufshcd_dme_attr_val phy_read_attrs[] = {
+ { UIC_ARG_MIB(CBCREGADDRLSB), 0, DME_LOCAL },
+ { UIC_ARG_MIB(CBCREGADDRMSB), 0, DME_LOCAL },
+ { UIC_ARG_MIB(CBCREGRDWRSEL), 0, DME_LOCAL },
+ { UIC_ARG_MIB(VS_MPHYCFGUPDT), 1, DME_LOCAL }
+ };
+
+ phy_read_attrs[0].mib_val = (u8)addr;
+ phy_read_attrs[1].mib_val = (u8)(addr >> 8);
+
+ ret = ufshcd_dwc_dme_set_attrs(hba, phy_read_attrs, ARRAY_SIZE(phy_read_attrs));
+ if (ret)
+ return ret;
+
+ ret = ufshcd_dme_get(hba, UIC_ARG_MIB(CBCREGRDLSB), &mib_val);
+ if (ret)
+ return ret;
+
+ *val = mib_val;
+ ret = ufshcd_dme_get(hba, UIC_ARG_MIB(CBCREGRDMSB), &mib_val);
+ if (ret)
+ return ret;
+
+ *val |= (mib_val << 8);
+
+ return 0;
+}
+EXPORT_SYMBOL(ufs_dwc_phy_reg_read);
+
int ufshcd_dwc_dme_set_attrs(struct ufs_hba *hba,
const struct ufshcd_dme_attr_val *v, int n)
{
diff --git a/drivers/ufs/host/ufshcd-dwc.h b/drivers/ufs/host/ufshcd-dwc.h
index c618bb914904..8091f186a9b3 100644
--- a/drivers/ufs/host/ufshcd-dwc.h
+++ b/drivers/ufs/host/ufshcd-dwc.h
@@ -68,4 +68,6 @@ int ufshcd_dwc_link_startup_notify(struct ufs_hba *hba,
enum ufs_notify_change_status status);
int ufshcd_dwc_dme_set_attrs(struct ufs_hba *hba,
const struct ufshcd_dme_attr_val *v, int n);
+int ufs_dwc_phy_reg_write(struct ufs_hba *hba, u32 addr, u32 val);
+int ufs_dwc_phy_reg_read(struct ufs_hba *hba, u32 addr, u32 *val);
#endif /* End of Header */
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/3] scsi: ufs: starfive: Add UFS support for StarFive JHB100 SoC
2026-05-09 6:27 [PATCH v2 0/3] Add StarFive JHB100 soc UFS platform driver Minda Chen
2026-05-09 6:27 ` [PATCH v2 1/3] scsi: ufs: dt-bindings: starfive: Add UFS Host Controller for JHB100 soc Minda Chen
2026-05-09 6:27 ` [PATCH v2 2/3] scsi: ufs: dwc: Rename amd-versal2 read/write PHY API and move to dwc common file Minda Chen
@ 2026-05-09 6:27 ` Minda Chen
2026-05-09 7:07 ` sashiko-bot
2 siblings, 1 reply; 7+ messages in thread
From: Minda Chen @ 2026-05-09 6:27 UTC (permalink / raw)
To: Alim Akhtar, Avri Altman, Bart Van Assche, Sai Krishna Potthuri,
Ajay Neeli, James E . J . Bottomley, Martin K . Petersen,
Pedro Sousa, Arnd Bergmann, AngeloGioacchino Del Regno,
Conor Dooley, Rob Herring, Krzysztof Kozlowski, linux-scsi
Cc: linux-kernel, devicetree, Minda Chen
Add support for the UFS host controller on JHB100 SoC, built on
the Synopsys DWC UFS controller and using UFSHCD platform driver.
This controller requires specific configurations like
M-PHY/RMMI/UniPro
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
MAINTAINERS | 1 +
drivers/ufs/host/Kconfig | 13 ++
drivers/ufs/host/Makefile | 1 +
drivers/ufs/host/ufs-starfive.c | 280 ++++++++++++++++++++++++++++++++
drivers/ufs/host/ufshcd-dwc.h | 18 ++
5 files changed, 313 insertions(+)
create mode 100644 drivers/ufs/host/ufs-starfive.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 5d222150e015..8021fd8a3fe0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27482,6 +27482,7 @@ UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER STARFIVE
M: Minda Chen <minda.chen@starfivetech.com>
S: Maintained
F: Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml
+F: drivers/ufs/host/ufs-starfive.c
UNIWILL LAPTOP DRIVER
M: Armin Wolf <W_Armin@gmx.de>
diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig
index 964ae70e7390..b742f7a2b0b6 100644
--- a/drivers/ufs/host/Kconfig
+++ b/drivers/ufs/host/Kconfig
@@ -168,3 +168,16 @@ 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_STARFIVE
+ tristate "Starfive UFS controller platform driver"
+ depends on OF && SCSI_UFSHCD_PLATFORM
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ help
+ This selects the StarFive specific additions to UFSHCD platform driver.
+ UFS host on StarFive needs some vendor specific configuration before
+ accessing the hardware which includes PHY configuration and vendor
+ specific registers.
+
+ Select this if you have UFS controller on StarFive chipset.
+ If unsure, say N.
diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile
index 65d8bb23ab7b..adfee2ae3b48 100644
--- a/drivers/ufs/host/Makefile
+++ b/drivers/ufs/host/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_SCSI_UFS_ROCKCHIP) += ufs-rockchip.o
obj-$(CONFIG_SCSI_UFS_SPRD) += ufs-sprd.o
obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o
obj-$(CONFIG_SCSI_UFS_AMD_VERSAL2) += ufs-amd-versal2.o ufshcd-dwc.o
+obj-$(CONFIG_SCSI_UFS_STARFIVE) += ufs-starfive.o ufshcd-dwc.o
diff --git a/drivers/ufs/host/ufs-starfive.c b/drivers/ufs/host/ufs-starfive.c
new file mode 100644
index 000000000000..3e91461aef75
--- /dev/null
+++ b/drivers/ufs/host/ufs-starfive.c
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Starfive UFS host platform driver
+ *
+ * Copyright (C) 2026 Starfive, Inc.
+ *
+ * Authors: Minda Chen <minda.chen@starfivetech.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <ufs/unipro.h>
+
+#include "ufshcd-pltfrm.h"
+#include "ufshcd-dwc.h"
+#include "ufshci-dwc.h"
+
+struct ufs_starfive_host {
+ struct ufs_hba *hba;
+ struct regmap *syscon;
+ struct reset_control *core_reset;
+ struct reset_control *phy_reset;
+ struct clk *ufs_clk;
+};
+
+#define SRAM_STATUS 0x38
+#define SRAM_EXT_LD_DONE BIT(1)
+#define SRAM_INIT_DONE BIT(2)
+#define UFS_REFCLK 0x3c
+#define REFCLK_OEN BIT(8)
+#define RESET_I BIT(9)
+#define RESET_OEN BIT(10)
+
+#define MPHY_POLL_INTERVAL_US 100
+#define MPHY_POLL_TIMEOUT_US 10000
+
+static int ufs_starfive_phy_config(struct ufs_hba *hba, struct ufs_starfive_host *host)
+{
+ static struct ufs_dwc_phy_pair_data phy_data[] = {
+ { RAWAONLANEN_DIG_MPLLA_COARSE_TUNE, 0x51},
+ { MPLL_SKIPCAL_COARSE_TUNE, 0x51},
+ { RX_AFE_ATT_IDAC(0), 0x8a},
+ { RX_AFE_ATT_IDAC(1), 0xc2},
+ { RX_AFE_CTLE_IDAC(0), 0x8e},
+ { RX_AFE_CTLE_IDAC(1), 0x8b},
+ { FAST_FLAGS(0), 0x0004 },
+ { FAST_FLAGS(1), 0x0004 },
+ { RX_ADAPT_DFE(0), 0xa00},
+ { RX_ADAPT_DFE(1), 0xa00},
+ };
+ struct ufs_dwc_phy_pair_data *data;
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(phy_data); i++) {
+ data = &phy_data[i];
+ ret = ufs_dwc_phy_reg_write(hba, data->addr, data->value);
+ if (ret)
+ return ret;
+ }
+
+ ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYDISABLE), 0);
+ if (ret)
+ return ret;
+
+ ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ufs_starfive_phy_init(struct ufs_hba *hba)
+{
+ struct ufs_starfive_host *host = ufshcd_get_variant(hba);
+ static struct ufshcd_dme_attr_val rmmi_config[] = {
+ { UIC_ARG_MIB(CBRATESEL), 0x1,
+ DME_LOCAL },
+ { UIC_ARG_MIB(CBREFCLKCTRL2), CBREFREFCLK_GATE_OVR_EN,
+ DME_LOCAL },
+ { UIC_ARG_MIB_SEL(RXSQCONTROL, SELIND_LN0_RX), 0x01,
+ DME_LOCAL },
+ { UIC_ARG_MIB_SEL(RXRHOLDCTRLOPT, SELIND_LN0_RX), 0x02,
+ DME_LOCAL },
+ { UIC_ARG_MIB_SEL(RXSQCONTROL, SELIND_LN1_RX), 0x01,
+ DME_LOCAL },
+ { UIC_ARG_MIB_SEL(RXRHOLDCTRLOPT, SELIND_LN1_RX), 0x02,
+ DME_LOCAL },
+ { UIC_ARG_MIB(EXT_COARSE_TUNE_RATEA), 0x25,
+ DME_LOCAL },
+ { UIC_ARG_MIB(EXT_COARSE_TUNE_RATEB), 0x51,
+ DME_LOCAL },
+ { UIC_ARG_MIB(CBCRCTRL), 0x01, DME_LOCAL },
+ { UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x1,
+ DME_LOCAL },
+ };
+ int ret, val;
+
+ ret = ufshcd_dwc_dme_set_attrs(hba, rmmi_config,
+ ARRAY_SIZE(rmmi_config));
+ if (ret) {
+ dev_err(hba->dev, "set rmmi config failed\n");
+ return ret;
+ }
+
+ ret = reset_control_deassert(host->phy_reset);
+ if (ret) {
+ dev_err(hba->dev, "Failed to reset phy\n");
+ return ret;
+ }
+
+ ret = regmap_read_poll_timeout(host->syscon,
+ SRAM_STATUS, val,
+ (val & SRAM_INIT_DONE),
+ MPHY_POLL_INTERVAL_US,
+ MPHY_POLL_TIMEOUT_US);
+ if (ret) {
+ dev_err(hba->dev, "wait sram init done timeout\n");
+ return ret;
+ }
+
+ regmap_update_bits(host->syscon, SRAM_STATUS,
+ SRAM_EXT_LD_DONE, SRAM_EXT_LD_DONE);
+
+ ret = ufs_starfive_phy_config(hba, host);
+ if (ret) {
+ dev_err(hba->dev, "configure phy failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ufs_starfive_init(struct ufs_hba *hba)
+{
+ struct ufs_starfive_host *host;
+ struct device *dev = hba->dev;
+ struct platform_device *pdev;
+ int ret;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
+ if (!host)
+ return dev_err_probe(dev, -ENOMEM,
+ "no memory for starfive ufs host\n");
+
+ host->syscon = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "starfive,syscon");
+
+ if (IS_ERR(host->syscon))
+ return dev_err_probe(dev, PTR_ERR(host->syscon), "getting the regmap failed\n");
+
+ host->core_reset = devm_reset_control_get_exclusive(hba->dev, "main");
+ if (IS_ERR(host->core_reset))
+ return dev_err_probe(dev, PTR_ERR(host->core_reset),
+ "Failed to get core clock resets");
+
+ host->phy_reset = devm_reset_control_get_exclusive(hba->dev, "phy");
+ if (IS_ERR(host->phy_reset))
+ return dev_err_probe(dev, PTR_ERR(host->phy_reset),
+ "Failed to get phy clk reset\n");
+
+ host->ufs_clk = devm_clk_get_enabled(&pdev->dev, "ufs");
+ if (IS_ERR(host->ufs_clk))
+ return dev_err_probe(dev, PTR_ERR(host->ufs_clk),
+ "Failed to get ufs clock\n");
+
+ regmap_update_bits(host->syscon, UFS_REFCLK,
+ REFCLK_OEN | RESET_OEN, 0);
+ usleep_range(2, 3);
+ regmap_update_bits(host->syscon, UFS_REFCLK, RESET_I, RESET_I);
+
+ ret = reset_control_deassert(host->core_reset);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to reset core clock");
+
+ host->hba = hba;
+ ufshcd_set_variant(hba, host);
+ hba->caps |= UFSHCD_CAP_WB_EN;
+
+ return 0;
+}
+
+static int ufs_starfive_link_startup_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status)
+{
+ int ret;
+
+ if (status == PRE_CHANGE) {
+ ret = ufshcd_vops_phy_initialization(hba);
+ if (ret) {
+ dev_err(hba->dev, "Phy setup failed (%d)\n", ret);
+ return ret;
+ }
+ } else { /* POST_CHANGE */
+ return ufshcd_dwc_link_startup_notify(hba, status);
+ }
+
+ return 0;
+}
+
+static int ufs_starfive_hce_enable_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status)
+{
+ u32 val;
+
+ if (status != POST_CHANGE)
+ return 0;
+
+ /* Disable Gating clock. Auto hibernation quirk */
+ val = ufshcd_readl(hba, REG_BUSTHRTL);
+ val &= ~(LP_AH8_POWER_GATING_EN
+ | LP_POWER_GATING_EN
+ | CLK_GATING_EN);
+ ufshcd_writel(hba, val, REG_BUSTHRTL);
+
+ return 0;
+}
+
+static struct ufs_hba_variant_ops ufs_hba_vops = {
+ .name = "ufs_starfive_platform",
+ .init = ufs_starfive_init,
+ .link_startup_notify = ufs_starfive_link_startup_notify,
+ .phy_initialization = ufs_starfive_phy_init,
+ .hce_enable_notify = ufs_starfive_hce_enable_notify,
+};
+
+static int ufs_starfive_probe(struct platform_device *pdev)
+{
+ int err;
+
+ /* Perform generic probe */
+ err = ufshcd_pltfrm_init(pdev, &ufs_hba_vops);
+ if (err)
+ dev_err(&pdev->dev, "ufshcd_pltfrm_init() failed %d\n", err);
+
+ return err;
+}
+
+static void ufs_starfive_remove(struct platform_device *pdev)
+{
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ pm_runtime_get_sync(&(pdev)->dev);
+ ufshcd_remove(hba);
+}
+
+static const struct dev_pm_ops ufs_starfive_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_starfive_pltfm_match[] = {
+ { .compatible = "starfive,jhb100-ufs", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ufs_starfive_pltfm_match);
+
+static struct platform_driver ufs_starfive_driver = {
+ .probe = ufs_starfive_probe,
+ .remove = ufs_starfive_remove,
+ .driver = {
+ .name = "ufs-starfive",
+ .pm = &ufs_starfive_pm_ops,
+ .of_match_table = of_match_ptr(ufs_starfive_pltfm_match),
+ },
+};
+
+module_platform_driver(ufs_starfive_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ufs-starfive");
+MODULE_DESCRIPTION("Starfive UFS host platform glue driver");
diff --git a/drivers/ufs/host/ufshcd-dwc.h b/drivers/ufs/host/ufshcd-dwc.h
index 8091f186a9b3..71a60ede6805 100644
--- a/drivers/ufs/host/ufshcd-dwc.h
+++ b/drivers/ufs/host/ufshcd-dwc.h
@@ -12,7 +12,15 @@
#include <ufs/ufshcd.h>
+/* ufshcd vendor specific register */
+#define REG_BUSTHRTL 0xc0
+#define LP_AH8_POWER_GATING_EN BIT(17)
+#define LP_POWER_GATING_EN BIT(16)
+#define CLK_GATING_EN BIT(12)
+
/* RMMI Attributes */
+#define RXSQCONTROL 0x8009
+#define RXRHOLDCTRLOPT 0x8013
#define CBREFCLKCTRL2 0x8132
#define CBCRCTRL 0x811F
#define CBC10DIRECTCONF2 0x810E
@@ -24,6 +32,8 @@
#define CBCREGRDLSB 0x811A
#define CBCREGRDMSB 0x811B
#define CBCREGRDWRSEL 0x811C
+#define EXT_COARSE_TUNE_RATEA 0x814D
+#define EXT_COARSE_TUNE_RATEB 0x814E
#define CBREFREFCLK_GATE_OVR_EN BIT(7)
@@ -32,12 +42,15 @@
#define MRX_FSM_STATE 0xC1
/* M-PHY registers */
+#define MPLL_SKIPCAL_COARSE_TUNE 0x28
#define RX_OVRD_IN_1(n) (0x3006 + ((n) * 0x100))
#define RX_PCS_OUT(n) (0x300F + ((n) * 0x100))
#define FAST_FLAGS(n) (0x401C + ((n) * 0x100))
+#define RX_ADAPT_DFE(n) (0x401E + ((n) * 0x100))
#define RX_AFE_ATT_IDAC(n) (0x4000 + ((n) * 0x100))
#define RX_AFE_CTLE_IDAC(n) (0x4001 + ((n) * 0x100))
#define FW_CALIB_CCFG(n) (0x404D + ((n) * 0x100))
+#define RAWAONLANEN_DIG_MPLLA_COARSE_TUNE 0x7014
/* Tx/Rx FSM state */
enum rx_fsm_state {
@@ -64,6 +77,11 @@ struct ufshcd_dme_attr_val {
u8 peer;
};
+struct ufs_dwc_phy_pair_data {
+ u32 addr;
+ u32 value;
+};
+
int ufshcd_dwc_link_startup_notify(struct ufs_hba *hba,
enum ufs_notify_change_status status);
int ufshcd_dwc_dme_set_attrs(struct ufs_hba *hba,
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/3] scsi: ufs: dt-bindings: starfive: Add UFS Host Controller for JHB100 soc
2026-05-09 6:27 ` [PATCH v2 1/3] scsi: ufs: dt-bindings: starfive: Add UFS Host Controller for JHB100 soc Minda Chen
@ 2026-05-09 6:38 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-05-09 6:38 UTC (permalink / raw)
To: Minda Chen; +Cc: krzk+dt, robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] Missing `clock-names` in the `required` list.
- [Low] Unconstrained `starfive,syscon` property allows invalid array lengths and arguments.
- [Low] The example section uses the deprecated `freq-table-hz` property.
--
commit dcb3253ccedb17e87bb1f204ca98535c01e219f6
Author: Minda Chen <minda.chen@starfivetech.com>
scsi: ufs: dt-bindings: starfive: Add UFS Host Controller for JHB100 soc
This commit adds the devicetree binding documentation for the StarFive JHB100
SoC UFS Host Controller, based on the Synopsys DesignWare IP.
> diff --git a/Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml b/Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml
> new file mode 100644
> index 0000000000000..4773f1c2670f8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/ufs/starfive,jhb100-ufs.yaml
[ ... ]
> + starfive,syscon:
> + $ref: /schemas/types.yaml#/definitions/phandle-array
> + description:
> + The phandle to System Register Controller syscon node.
The starfive,syscon property is defined as a phandle-array, but should this
include an items or maxItems constraint? Since the example uses a bare
phandle, would it be better typed as just
/schemas/types.yaml#/definitions/phandle to prevent passing arrays of
arbitrary lengths during schema validation?
> +required:
> + - compatible
> + - reg
> + - clocks
> + - resets
> + - reset-names
> + - interrupts
> + - starfive,syscon
Is there a missing entry for clock-names in this list? The binding
mandates the clocks property and defines 'ref_clk' and 'ufs', so omitting
clock-names here allows device trees to define clocks without names and
still pass validation, potentially failing during driver lookup.
[ ... ]
> +examples:
> + - |
> + ufs@11b10000 {
> + compatible = "starfive,jhb100-ufs";
> + reg = <0x11b10000 0x20000>;
> + interrupts = <105>;
> + clocks = <&syscrg 4>,
> + <&syscrg 5>;
> + clock-names = "ref_clk", "ufs";
> + freq-table-hz = <26000000 26000000>,
> + <100000000 100000000>;
This isn't a bug, but does this example need to use freq-table-hz? The
common schema ufs-common.yaml included via $ref marks this property as
deprecated in favor of operating-points-v2. Using it in a new example
might encourage copying deprecated patterns into downstream device trees.
> + resets = <&syscrg 10>,
> + <&syscrg 7>;
> + reset-names = "main", "phy";
> + starfive,syscon = <&syscon>;
> + };
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260509062759.125472-1-minda.chen@starfivetech.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/3] scsi: ufs: dwc: Rename amd-versal2 read/write PHY API and move to dwc common file
2026-05-09 6:27 ` [PATCH v2 2/3] scsi: ufs: dwc: Rename amd-versal2 read/write PHY API and move to dwc common file Minda Chen
@ 2026-05-09 6:43 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-05-09 6:43 UTC (permalink / raw)
To: Minda Chen; +Cc: krzk+dt, devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The functions `ufs_dwc_phy_reg_write` and `ufs_dwc_phy_reg_read` use `static` local arrays (`phy_write_attrs` and `phy_read_attrs`) which are modified on every call, creating a severe data race.
--
commit b544cff60ab1cb7a813f07b65debab2ffee3a426
Author: Minda Chen <minda.chen@starfivetech.com>
scsi: ufs: dwc: Rename amd-versal2 read/write PHY API and move to dwc common file
This commit moves the read/write PHY register APIs from the AMD versal2
driver to a common file. This allows other vendors using the designware
UFS MIPI PHY to reuse the code.
> diff --git a/drivers/ufs/host/ufshcd-dwc.c b/drivers/ufs/host/ufshcd-dwc.c
> index 21b1cf912dcc6..b057a78e151c4 100644
> --- a/drivers/ufs/host/ufshcd-dwc.c
> +++ b/drivers/ufs/host/ufshcd-dwc.c
> @@ -15,6 +15,59 @@
> #include "ufshcd-dwc.h"
> #include "ufshci-dwc.h"
>
> +int ufs_dwc_phy_reg_write(struct ufs_hba *hba, u32 addr, u32 val)
> +{
> + static struct ufshcd_dme_attr_val phy_write_attrs[] = {
> + { UIC_ARG_MIB(CBCREGADDRLSB), 0, DME_LOCAL },
> + { UIC_ARG_MIB(CBCREGADDRMSB), 0, DME_LOCAL },
> + { UIC_ARG_MIB(CBCREGWRLSB), 0, DME_LOCAL },
> + { UIC_ARG_MIB(CBCREGWRMSB), 0, DME_LOCAL },
> + { UIC_ARG_MIB(CBCREGRDWRSEL), 1, DME_LOCAL },
> + { UIC_ARG_MIB(VS_MPHYCFGUPDT), 1, DME_LOCAL }
> + };
> +
> + phy_write_attrs[0].mib_val = (u8)addr;
> + phy_write_attrs[1].mib_val = (u8)(addr >> 8);
> + phy_write_attrs[2].mib_val = (u8)val;
> + phy_write_attrs[3].mib_val = (u8)(val >> 8);
Could moving this function into common code expose a data race regression?
Since phy_write_attrs is declared static, it is allocated in global memory and
shared across all threads and UFS device instances.
If multiple host controllers probe asynchronously or undergo concurrent power
state changes, will they clobber each other's register addresses and values
here before calling ufshcd_dwc_dme_set_attrs?
Would it be safer to remove the static keyword so this structure is safely
allocated on the stack per-invocation?
[ ... ]
> +int ufs_dwc_phy_reg_read(struct ufs_hba *hba, u32 addr, u32 *val)
> +{
> + u32 mib_val;
> + int ret;
> + static struct ufshcd_dme_attr_val phy_read_attrs[] = {
> + { UIC_ARG_MIB(CBCREGADDRLSB), 0, DME_LOCAL },
> + { UIC_ARG_MIB(CBCREGADDRMSB), 0, DME_LOCAL },
> + { UIC_ARG_MIB(CBCREGRDWRSEL), 0, DME_LOCAL },
> + { UIC_ARG_MIB(VS_MPHYCFGUPDT), 1, DME_LOCAL }
> + };
> +
> + phy_read_attrs[0].mib_val = (u8)addr;
> + phy_read_attrs[1].mib_val = (u8)(addr >> 8);
Does this static array have the same concurrency issue as phy_write_attrs
above?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260509062759.125472-1-minda.chen@starfivetech.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 3/3] scsi: ufs: starfive: Add UFS support for StarFive JHB100 SoC
2026-05-09 6:27 ` [PATCH v2 3/3] scsi: ufs: starfive: Add UFS support for StarFive JHB100 SoC Minda Chen
@ 2026-05-09 7:07 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-05-09 7:07 UTC (permalink / raw)
To: Minda Chen; +Cc: devicetree, robh, conor+dt, krzk+dt
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Missing PM runtime cleanup in the driver's remove callback.
- [Medium] Unconditional assignment of `dev_pm_ops` structure without `pm_ptr()` wrapper.
- [Medium] Hardware reset lines are deasserted during probe but never asserted on removal.
- [Low] Inappropriate delay function used for microsecond delay.
- [Low] Shared DWC library directly appended to multiple host drivers' Kbuild targets.
--
commit 7c7e2d539310c77f484d7f514058888be54a8ddf
Author: Minda Chen <minda.chen@starfivetech.com>
scsi: ufs: starfive: Add UFS support for StarFive JHB100 SoC
This commit adds support for the UFS host controller on JHB100 SoC, built on
the Synopsys DWC UFS controller and using the UFSHCD platform driver.
> diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile
> index 65d8bb23ab7b3..adfee2ae3b486 100644
> --- a/drivers/ufs/host/Makefile
> +++ b/drivers/ufs/host/Makefile
> @@ -14,3 +14,4 @@ obj-$(CONFIG_SCSI_UFS_ROCKCHIP) += ufs-rockchip.o
> obj-$(CONFIG_SCSI_UFS_SPRD) += ufs-sprd.o
> obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o
> obj-$(CONFIG_SCSI_UFS_AMD_VERSAL2) += ufs-amd-versal2.o ufshcd-dwc.o
> +obj-$(CONFIG_SCSI_UFS_STARFIVE) += ufs-starfive.o ufshcd-dwc.o
This isn't a bug, but is it safe to append ufshcd-dwc.o directly to multiple
independent Kconfig targets?
If one driver is configured as =y and another as =m, could this cause
unexpected linking behavior for the exported symbols in ufshcd-dwc.c?
Would a dedicated Kconfig symbol to manage the shared DWC library be safer?
> diff --git a/drivers/ufs/host/ufs-starfive.c b/drivers/ufs/host/ufs-starfive.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/ufs/host/ufs-starfive.c
[ ... ]
> +static int ufs_starfive_init(struct ufs_hba *hba)
> +{
[ ... ]
> + regmap_update_bits(host->syscon, UFS_REFCLK,
> + REFCLK_OEN | RESET_OEN, 0);
> + usleep_range(2, 3);
This isn't a bug, but should udelay(2) be used here instead? For delays
shorter than 10us, the context switching and timer setup overhead for
usleep_range() usually heavily outweighs the tiny interval.
> + regmap_update_bits(host->syscon, UFS_REFCLK, RESET_I, RESET_I);
> +
> + ret = reset_control_deassert(host->core_reset);
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Failed to reset core clock");
[ ... ]
> +static void ufs_starfive_remove(struct platform_device *pdev)
> +{
> + struct ufs_hba *hba = platform_get_drvdata(pdev);
> +
> + pm_runtime_get_sync(&(pdev)->dev);
> + ufshcd_remove(hba);
> +}
Does this code leak the PM runtime usage counter?
The driver calls pm_runtime_get_sync() to wake the device before calling
ufshcd_remove(), but fails to subsequently call pm_runtime_put_noidle() or
pm_runtime_disable(). Could this permanently leak the usage counter and leave
PM runtime active after the device is unbound?
Additionally, should the hardware reset lines (core_reset and phy_reset)
be asserted here during removal?
While devm_reset_control_get_exclusive() frees the handles on unbind, it
does not automatically assert the hardware reset lines, which might leave the
hardware permanently active after the driver is unloaded.
[ ... ]
> +static struct platform_driver ufs_starfive_driver = {
> + .probe = ufs_starfive_probe,
> + .remove = ufs_starfive_remove,
> + .driver = {
> + .name = "ufs-starfive",
> + .pm = &ufs_starfive_pm_ops,
Should ufs_starfive_pm_ops be wrapped with the pm_ptr() macro?
Assigning it unconditionally forces the dev_pm_ops structure and its referenced
callbacks to be compiled into the binary as dead code when CONFIG_PM is
disabled.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260509062759.125472-1-minda.chen@starfivetech.com?part=3
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-09 7:07 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-09 6:27 [PATCH v2 0/3] Add StarFive JHB100 soc UFS platform driver Minda Chen
2026-05-09 6:27 ` [PATCH v2 1/3] scsi: ufs: dt-bindings: starfive: Add UFS Host Controller for JHB100 soc Minda Chen
2026-05-09 6:38 ` sashiko-bot
2026-05-09 6:27 ` [PATCH v2 2/3] scsi: ufs: dwc: Rename amd-versal2 read/write PHY API and move to dwc common file Minda Chen
2026-05-09 6:43 ` sashiko-bot
2026-05-09 6:27 ` [PATCH v2 3/3] scsi: ufs: starfive: Add UFS support for StarFive JHB100 SoC Minda Chen
2026-05-09 7:07 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox