[PATCH 0/4] Fix up QUSB2 PHY description for MSM8996/SM61[12]5
Konrad Dybcio
konrad.dybcio at oss.qualcomm.com
Thu Sep 3 07:18:52 PDT 2026
On 6/10/26 3:20 PM, Dmitry Baryshkov wrote:
> On Wed, Jun 10, 2026 at 03:13:01PM +0200, Konrad Dybcio wrote:
>> On 6/10/26 3:03 PM, Dmitry Baryshkov wrote:
>>> On Wed, Jun 10, 2026 at 02:49:31PM +0200, Konrad Dybcio wrote:
>>>> On 6/10/26 2:04 PM, Konrad Dybcio wrote:
>>>>> The MSM8996 QUSB2PHY was not being guaranteed a power source.
>>>>> The SM6125's QUSB2PHY was believed to be idential as the 96 one. It
>>>>> wasn't. This series tackles that, freeing us of some dt checker
>>>>> errors about vdd-supply not found on MSM8996 boards.
[...]
>> reg 96 pro
>> 0x80 0xF8 0xD0 [!] QUSB2PHY_PORT_TUNE1
>> 0x84 0xB3 0xB3
>> 0x88 0x83 0x83
>> 0x8C 0xC0 0xC0
>> 0x90 none 0x02 [!] QUSB2PHY_PORT_TUNE5
>> 0x08 0x30 0x30
>> 0x0C 0x79 0x79
>> 0x10 0x21 0x21
>> 0x9C 0x14 0x14
>> 0x1C 0x9F 0x9F
>> 0x18 0x00 0x00
>>
>> apparently this is indeed SoC-specific (via docs) but also apparently
>> may not be very important (although should be fixed regardless as
>> some designs may rely on this)
>
> Would you send a patch, please?
So the tuning differences may be taken care of through a separate table,
or by adding support for overriding parameters for the QUSB2PHYv1 (8996
-class) devices. Currently the overrides only really work as intended
for V2/V3 (SDM845-class) PHYs as the register layout changed majorly.
I think the real right solution here is to fix the overrides.
dt-bindings clearly created by an LLM :)
I implemented some of it, but I currently don't have the time
for finishing it up - feel free to take it further. It would also
help adjust the specific OnePlus init sequence that was originally
used for every SM6115 device (patch 2)
I also discovered that the interrupt mask is wrong for V1 PHYs.
At this point maybe it'd be easier to split off the v1 support to
a separate driver? Anyway, up to you.
I'll resend this series as-is as it fixes actual issues.
Konrad
commit 792eeeb5d43428cedc72c5778f664a33c4cf2b30
Author: Konrad Dybcio <konrad.dybcio at oss.qualcomm.com>
Date: Thu Sep 3 16:10:36 2026 +0200
[WIP] qusb2phy v1 overrides/tuning/fixups
Assisted-by: LLM
diff --git a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
index 39e796cd5dc6..13a5c08fdb8e 100644
--- a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
@@ -169,6 +169,22 @@ properties:
maximum: 3
default: 0
+ qcom,man-sqrx-dis-value:
+ description:
+ It is a 1 bit value that enables manual squelch receiver disable.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 1
+ default: 0
+
+ qcom,squelch-eop-delay-value:
+ description:
+ It is a 2 bit value that specifies the squelch end-of-packet delay.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 3
+ default: 0
+
required:
- compatible
- reg
@@ -182,10 +198,17 @@ required:
allOf:
- if:
not:
- properties:
- compatible:
- contains:
- const: qcom,qusb2-v2-phy
+ anyOf:
+ - properties:
+ compatible:
+ contains:
+ const: qcom,qusb2-v2-phy
+ - properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,msm8996-qusb2-phy
then:
properties:
qcom,imp-res-offset-value: false
@@ -196,6 +219,19 @@ allOf:
qcom,preemphasis-width: false
qcom,hsdisc-trim-value: false
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,msm8996-qusb2-phy
+ then:
+ properties:
+ qcom,man-sqrx-dis-value: false
+ qcom,squelch-eop-delay-value: false
+
# On MSM8996, VDD is supplied via the MX power domain
- if:
properties:
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index c34d847b123c..a9435b6e1637 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -51,7 +51,22 @@
#define PHY_CLK_SCHEME_SEL BIT(0)
+/* V1 (MSM8996) register fields */
+
+/* QUSB2PHY_PORT_TUNE2 register bits */
+#define UTM_HSTX_TRIM_V1 GENMASK(7, 4)
+
+/* QUSB2PHY_PORT_TUNE4 register bits */
+#define SQUELCH_EOP_DLY_V1 GENMASK(7, 6)
+#define MAN_SQRX_DIS_V1 BIT(4)
+#define PREEMPH_WIDTH_HALF_BIT_V1 BIT(3)
+#define PREEMPHASIS_EN_MASK_V1 GENMASK(2, 0)
+
+/* V2/V3 (SDM845) register fields */
/* QUSB2PHY_INTR_CTRL register bits */
+
+// v1: 4-chg 3-dmse_high 2-dmse 1-dpse_high 0-dpse
+// v3: 4- dmse_high 3-dpse_high 2-chg_det 1-dmse_intr 0-dpse_intr
#define DMSE_INTR_HIGH_SEL BIT(4)
#define DPSE_INTR_HIGH_SEL BIT(3)
#define CHG_DET_INTR_EN BIT(2)
@@ -443,14 +458,17 @@ struct override_param {
u8 value;
};
-/*struct override_params - structure holding qusb2 v2 phy overriding params
+/**
+ * struct override_params - structure holding QUSB2 PHY override parameters
* @imp_res_offset: rescode offset to be updated in IMP_CTRL1 register
- * @hstx_trim: HSTX_TRIM to be updated in TUNE1 register
- * @preemphasis: Amplitude Pre-Emphasis to be updated in TUNE1 register
- * @preemphasis_width: half/full-width Pre-Emphasis updated via TUNE1
- * @bias_ctrl: bias ctrl to be updated in BIAS_CONTROL_2 register
- * @charge_ctrl: charge ctrl to be updated in CHG_CTRL2 register
- * @hsdisc_trim: disconnect threshold to be updated in TUNE2 register
+ * @hstx_trim: High-Speed TX trim
+ * @preemphasis: Amplitude Pre-Emphasis
+ * @preemphasis_width: Pre-Emphasis width (half/full)
+ * @bias_ctrl: bias control value
+ * @charge_ctrl: charge control value
+ * @hsdisc_trim: High-Speed disconnect threshold
+ * @man_sqrx_dis: manual squelch receiver disable
+ * @squelch_eop_delay: squelch end-of-packet delay
*/
struct override_params {
struct override_param imp_res_offset;
@@ -460,6 +478,9 @@ struct override_params {
struct override_param bias_ctrl;
struct override_param charge_ctrl;
struct override_param hsdisc_trim;
+
+ struct override_param man_sqrx_dis;
+ struct override_param squelch_eop_delay;
};
/**
@@ -558,11 +579,48 @@ void qcom_qusb2_phy_configure(void __iomem *base,
}
}
-/*
- * Update board specific PHY tuning override values if specified from
- * device tree.
- */
-static void qusb2_phy_override_phy_params(struct qusb2_phy *qphy)
+static void qusb2_v1_phy_override_phy_params(struct qusb2_phy *qphy)
+{
+ const struct qusb2_phy_cfg *cfg = qphy->cfg;
+ struct override_params *or = &qphy->overrides;
+
+ if (or->hstx_trim.override) {
+ qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2],
+ FIELD_PREP(UTM_HSTX_TRIM_V1, or->hstx_trim.value),
+ UTM_HSTX_TRIM_V1);
+ }
+
+ if (or->squelch_eop_delay.override) {
+ qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE4],
+ FIELD_PREP(SQUELCH_EOP_DLY_V1, or->squelch_eop_delay.value),
+ SQUELCH_EOP_DLY_V1);
+ }
+
+ if (or->man_sqrx_dis.override) {
+ qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE4],
+ FIELD_PREP(MAN_SQRX_DIS_V1, or->man_sqrx_dis.value),
+ MAN_SQRX_DIS_V1);
+ }
+
+ if (or->preemphasis.override) {
+ qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE4],
+ FIELD_PREP(PREEMPHASIS_EN_MASK_V1, or->preemphasis.value),
+ PREEMPHASIS_EN_MASK_V1);
+ }
+
+ if (or->preemphasis_width.override) {
+ if (or->preemphasis_width.value == QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT)
+ qusb2_setbits(qphy->base,
+ cfg->regs[QUSB2PHY_PORT_TUNE4],
+ PREEMPH_WIDTH_HALF_BIT_V1);
+ else
+ qusb2_clrbits(qphy->base,
+ cfg->regs[QUSB2PHY_PORT_TUNE4],
+ PREEMPH_WIDTH_HALF_BIT_V1);
+ }
+}
+
+static void qusb2_v3_phy_override_phy_params(struct qusb2_phy *qphy)
{
const struct qusb2_phy_cfg *cfg = qphy->cfg;
struct override_params *or = &qphy->overrides;
@@ -840,7 +898,10 @@ static int qusb2_phy_init(struct phy *phy)
cfg->tbl_num);
/* Override board specific PHY tuning values */
- qusb2_phy_override_phy_params(qphy);
+ if (true /* TODO: */)
+ qusb2_v3_phy_override_phy_params(qphy);
+ else
+ qusb2_v1_phy_override_phy_params(qphy);
/* Set efuse value for tuning the PHY */
qusb2_phy_set_tune2_param(qphy);
@@ -1136,6 +1197,18 @@ static int qusb2_phy_probe(struct platform_device *pdev)
or->hsdisc_trim.override = true;
}
+ if (!of_property_read_u32(dev->of_node, "qcom,man-sqrx-dis-value",
+ &value)) {
+ or->man_sqrx_dis.value = (u8)value;
+ or->man_sqrx_dis.override = true;
+ }
+
+ if (!of_property_read_u32(dev->of_node,
+ "qcom,squelch-eop-delay-value", &value)) {
+ or->squelch_eop_delay.value = (u8)value;
+ or->squelch_eop_delay.override = true;
+ }
+
dev_set_drvdata(dev, qphy);
/*
More information about the linux-phy
mailing list