git: 973783515e7d - main - ufshci: fix the Snapdragon X Elite reference clock
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 02 Sep 2026 02:07:58 UTC
The branch main has been updated by jaeyoon:
URL: https://cgit.FreeBSD.org/src/commit/?id=973783515e7db6e19550c57c8f9d94d907e3bd0e
commit 973783515e7db6e19550c57c8f9d94d907e3bd0e
Author: Jaeyoon Choi <jaeyoon@FreeBSD.org>
AuthorDate: 2026-09-02 01:47:18 +0000
Commit: Jaeyoon Choi <jaeyoon@FreeBSD.org>
CommitDate: 2026-09-02 02:05:09 +0000
ufshci: fix the Snapdragon X Elite reference clock
The driver's ACPI table set bRefClkFreq to 19.2 MHz. The
Snapdragon X Elite feeds the device 38.4 MHz from its CXO. The
firmware has no property for it. The device ran its PLL from
the wrong base. Every HS mode failed. PWM still worked. The
attribute is persistent. The wrong value survived reboots.
Set 38.4 MHz in the table. Read the attribute first. Write it
only when the value differs or the read fails. Log a changed
value and a failed read. Verified on the Galaxy Book 4 Edge.
Reviewed by: imp (mentor)
Sponsored by: Samsung Electronics
Differential Revision: https://reviews.freebsd.org/D59297
---
sys/dev/ufshci/ufshci_acpi.c | 6 +++++-
sys/dev/ufshci/ufshci_dev.c | 17 +++++++++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/sys/dev/ufshci/ufshci_acpi.c b/sys/dev/ufshci/ufshci_acpi.c
index 94da0d3cb411..f96a4c29e15e 100644
--- a/sys/dev/ufshci/ufshci_acpi.c
+++ b/sys/dev/ufshci/ufshci_acpi.c
@@ -51,8 +51,12 @@ static struct ufshci_acpi_device {
uint32_t ref_clk;
uint32_t quirks;
} ufshci_acpi_devices[] = {
+ /*
+ * The SoC feeds the device 38.4 MHz from its CXO. The firmware
+ * has no property for it. Verified on the Galaxy Book 4 Edge.
+ */
{ "QCOM24A5", "Qualcomm Snapdragon X Elite UFS Host Controller",
- UFSHCI_REF_CLK_19_2MHz,
+ UFSHCI_REF_CLK_38_4MHz,
UFSHCI_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH |
UFSHCI_QUIRK_BROKEN_LSDBS_MCQS_CAP },
{ 0x00000000, NULL, 0, 0 }
diff --git a/sys/dev/ufshci/ufshci_dev.c b/sys/dev/ufshci/ufshci_dev.c
index 063b65aaf579..dd467f85c795 100644
--- a/sys/dev/ufshci/ufshci_dev.c
+++ b/sys/dev/ufshci/ufshci_dev.c
@@ -242,10 +242,27 @@ ufshci_dev_init_reference_clock(struct ufshci_controller *ctrlr)
{
int error;
uint8_t index, selector;
+ uint64_t value;
index = 0; /* bRefClkFreq is device type attribute */
selector = 0; /* bRefClkFreq is device type attribute */
+ /*
+ * bRefClkFreq is a persistent attribute. Skip the write when
+ * the device already holds the wanted value.
+ */
+ error = ufshci_dev_read_attribute(ctrlr, UFSHCI_ATTR_B_REF_CLK_FREQ,
+ index, selector, &value);
+ if (error != 0) {
+ ufshci_printf(ctrlr, "bRefClkFreq read failed, writing %u\n",
+ ctrlr->ref_clk);
+ } else if ((uint32_t)value == ctrlr->ref_clk) {
+ return (0);
+ } else {
+ ufshci_printf(ctrlr, "changing bRefClkFreq from %u to %u\n",
+ (uint32_t)value, ctrlr->ref_clk);
+ }
+
error = ufshci_dev_write_attribute(ctrlr, UFSHCI_ATTR_B_REF_CLK_FREQ,
index, selector, ctrlr->ref_clk);
if (error)