usb: typec: add Qualcomm PMI8998 USB Type-C role-switch support
Subsystems (6)
cover usb: typec: add Qualcomm PMI8998 USB Type-C role-switch support
This series adds USB Type-C role-switch support for the PMI8998 PMIC used on SDM845 phones (OnePlus 6/6T, Xiaomi Poco F1, SHIFT 6mq), which have been locked to USB peripheral mode under mainline kernels until now.
The PMI8998 SMB2 charger block integrates a Type-C detection unit at SPMI offset 0x1300 that performs CC sensing, debounce and Rp/Rd resolution entirely in hardware. The state is exposed through the TYPE_C_STATUS_4 register and reported via a single consolidated "type-c-change" interrupt. The new driver reads that status on every interrupt and pushes the negotiated role to a usb_role_switch consumer (dwc3), enabling automatic peripheral/host switching on cable change. Because the hardware handles the Type-C state machine natively, no software TCPM port manager is required.
The Type-C block shares the SMB2 USBIN region with the already mainlined qcom_pmi8998-charger driver. The two coexist on the shared SPMI regmap without write conflict: the typec driver only reads TYPE_C_STATUS_* and touches the IRQ enable bits at offsets 0x130b-0x130f and 0x1367-0x1368.
The PMI8998 USB OTG VBUS boost converter at offset 0x1100 has the same CMD_OTG / OTG_CFG / OTG_CURRENT_LIMIT register layout as PM8150B, so the existing drivers/regulator/qcom_usb_vbus-regulator can drive it through a compatible cascade -- only the DT binding needs the new compatible string added.
Power Delivery is not implemented. The PMI8998 PDPHY block at offset 0x1700 is register-identical to PM8150B and could be wired through the existing drivers/usb/typec/tcpm/qcom code in a follow-up if PD negotiation becomes a requirement.
Tested-on: OnePlus 6T (sdm845-oneplus-fajita) running Mobian 6.12-sdm845. A USB flash drive, USB ethernet adapter, USB WiFi adapter (TP-Link Archer T2) and a self-powered USB-C dock with downstream ethernet all enumerate through xHCI after the role transitions from peripheral to host. Repeat plug/unplug cycles drive the role through device -> none -> host -> none -> device cleanly with no IRQ stalls or stale role-switch state.
Series mirror:
https://github.com/taygoth/linux/tree/pmi8998-typec
taygoth (6):
dt-bindings: regulator: qcom,usb-vbus-regulator: add PMI8998
dt-bindings: usb: add Qualcomm PMI8998 Type-C controller
usb: typec: add Qualcomm PMI8998 role-switch driver
arm64: dts: qcom: pmi8998: add USB Type-C and VBUS regulator nodes
arm64: dts: qcom: sdm845-oneplus-common: enable USB Type-C role
switching
MAINTAINERS: add entry for Qualcomm PMI8998 USB Type-C driver
.../regulator/qcom,usb-vbus-regulator.yaml | 1 + .../bindings/usb/qcom,pmi8998-typec.yaml | 97 ++++++++ MAINTAINERS | 8 + arch/arm64/boot/dts/qcom/pmi8998.dtsi | 19 ++ .../boot/dts/qcom/sdm845-oneplus-common.dtsi | 43 +++- drivers/usb/typec/Kconfig | 17 ++ drivers/usb/typec/Makefile | 1 + drivers/usb/typec/qcom_pmi8998_typec.c | 213 ++++++++++++++++++ 8 files changed, 392 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml create mode 100644 drivers/usb/typec/qcom_pmi8998_typec.c
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
Signature · 1 line
2.47.3
PATCH 1/6 dt-bindings: regulator: qcom,usb-vbus-regulator: add PMI8998
The Qualcomm PMI8998 PMIC integrates a USB OTG VBUS boost converter inside its SMB2 charger block at offset 0x1100. The OTG control register layout (CMD_OTG at +0x40, OTG_CURRENT_LIMIT_CFG at +0x52, OTG_CFG at +0x53) matches the PM8150B SMB5 block, so the existing qcom_usb_vbus-regulator driver can drive it without code changes via compatible cascade.
Verified by inspecting the downstream qpnp-smb2 driver and reading live register values on a OnePlus 6T (sdm845-oneplus-fajita) running mainline Linux.
--- .../devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml | 1 + 1 file changed, 1 insertion(+)
Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +1 -0
@@ -28,6 +28,7 @@ properties: - qcom,pm6150-vbus-reg - qcom,pm7250b-vbus-reg - qcom,pmi632-vbus-reg + - qcom,pmi8998-vbus-reg - const: qcom,pm8150b-vbus-reg reg:
Signature · 1 line
2.47.3
Re: [PATCH 1/6] dt-bindings: regulator: qcom,usb-vbus-regulator: add PMI8998
Quoted 21 lines · taygoth
The Qualcomm PMI8998 PMIC integrates a USB OTG VBUS boost converter inside its SMB2 charger block at offset
0x1100. The OTG control register layout (CMD_OTGat +0x40,OTG_CURRENT_LIMIT_CFGat +0x52,OTG_CFGat +0x53) matches the PM8150B SMB5 block, so the existing qcom_usb_vbus-regulator driver can drive it without code changes via compatible cascade.Verified by inspecting the downstream qpnp-smb2 driver and reading live register values on a OnePlus 6T (sdm845-oneplus-fajita) running mainline Linux.
Signed-off-by taygoth <[email protected]>--- .../devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml | 1 + 1 file changed, 1 insertion(+)Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +0
-0
Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml properties: · line 34
Quoted 7 lines
Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +1
-0@@ -28,6 +28,7 @@ properties: - qcom,pm6150-vbus-reg - qcom,pm7250b-vbus-reg - qcom,pmi632-vbus-reg + - qcom,pmi8998-vbus-reg - const: qcom,pm8150b-vbus-reg reg:
---
bod
Re: [PATCH 1/6] dt-bindings: regulator: qcom,usb-vbus-regulator: add PMI8998
In reply to taygothQuoted 7 lines · taygoth
The Qualcomm PMI8998 PMIC integrates a USB OTG VBUS boost converter inside its SMB2 charger block at offset
0x1100. The OTG control register layout (CMD_OTGat +0x40,OTG_CURRENT_LIMIT_CFGat +0x52,OTG_CFGat +0x53) matches the PM8150B SMB5 block, so the existing qcom_usb_vbus-regulator driver can drive it without code changes via compatible cascade.
Quoted 5 lines
Verified by inspecting the downstream qpnp-smb2 driver and reading live register values on a OnePlus 6T (sdm845-oneplus-fajita) running mainline Linux.
Signed-off-by taygoth <[email protected]>
Incomplete identity. Please use real names. We do not accept anonymous contributions.
Best regards,
Krzysztof
PATCH 2/6 dt-bindings: usb: add Qualcomm PMI8998 Type-C controller
In reply to taygothThe PMI8998 PMIC integrates a USB Type-C detection block in its SMB2 charger USBIN region at offset 0x1300. The block performs CC sensing, debounce and Rp/Rd resolution in hardware and reports role changes through a single consolidated "type-c-change" interrupt.
This is architecturally distinct from the qcom,pmic-typec binding (PM8150B / PMI632 family) which exposes a granular 8-16 IRQ topology fanned out per Type-C event for a software TCPM state machine. PMI8998 has neither the per-event IRQs nor a register layout compatible with the TCPM code path, so this binding describes a separate hardware- managed role-switch controller.
--- .../bindings/usb/qcom,pmi8998-typec.yaml | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml
Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml new file +97 -0
@@ -0,0 +1,97 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/qcom,pmi8998-typec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm PMI8998 USB Type-C role-switch controller + +maintainers: + - Maxim Furman <[email protected]> + +description: + The PMI8998 PMIC integrates a USB Type-C detection block inside its SMB2 + charger USBIN region at offset 0x1300. CC sensing, debounce and Rp/Rd + resolution are performed in hardware, and the negotiated role is reported + through a single consolidated "type-c-change" interrupt. + + This block is distinct from the TCPM-based qcom,pmic-typec controllers + (PM8150B, PMI632, etc.) — PMI8998 lacks the granular per-event interrupt + topology those parts expose and the driver therefore translates the + hardware-decided role directly into a usb_role_switch_set_role() call + rather than running a software TCPM state machine. Power Delivery is not + supported by this binding. + +properties: + compatible: + const: qcom,pmi8998-typec + + reg: + maxItems: 1 + description: Type-C SPMI register base offset (typically 0x1300). + + interrupts: + maxItems: 1 + + interrupt-names: + items: + - const: type-c-change + + vdd-vbus-supply: + description: + VBUS source regulator enabled when the controller transitions to + USB host mode so bus-powered downstream peripherals can be powered. + + connector: + type: object + $ref: /schemas/connector/usb-connector.yaml# + unevaluatedProperties: false + +required: + - compatible + - reg + - interrupts + - interrupt-names + - connector + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + typec@1300 { + compatible = "qcom,pmi8998-typec"; + reg = <0x1300>; + + interrupts = <0x2 0x13 0x7 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "type-c-change"; + + vdd-vbus-supply = <&pmi8998_vbus>; + + connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + pmi8998_hs_in: endpoint { + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + }; + }; + }; + }; +...
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 2/6] dt-bindings: usb: add Qualcomm PMI8998 Type-C controller
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] The `qcom,spmi-pmic.yaml` parent schema unconditionally enforces the old `qcom,pmic-typec.yaml`…
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The qcom,spmi-pmic.yaml parent schema unconditionally enforces the old qcom,pmic-typec.yaml on all typec@ nodes, which will cause dtbs_check validation failures for the newly introduced qcom,pmi8998-typec hardware node. --
commit 1c9db8c5249c49002058f3167b19c898d414957d
Author: taygoth <[email protected]>
dt-bindings: usb: add Qualcomm PMI8998 Type-C controller
This commit adds a new devicetree binding for the Qualcomm PMI8998 USB Type-C role-switch controller. It describes a hardware block distinct from the TCPM-based qcom,pmic-typec controllers, using a single consolidated interrupt instead of granular per-event IRQs.
Quoted 5 lines
Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml new file +0
-0
[ ... ]
Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml line 68
Quoted 10 lines
Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml new file +10
-0+examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + typec@1300 { + compatible = "qcom,pmi8998-typec";
Will this node cause dtbs_check validation failures when instantiated under the PMIC?
In Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml, the patternProperties rule for ^typec@[0-9a-f]+$ has a hardcoded reference to /schemas/usb/qcom,pmic-typec.yaml#.
Because this new qcom,pmi8998-typec schema defines only 1 interrupt instead of the 8 to 16 required by the older binding, it will fail validation against the parent PMIC schema.
Should the parent qcom,spmi-pmic.yaml schema be updated alongside this change to permit this new hardware block?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
Re: [PATCH 2/6] dt-bindings: usb: add Qualcomm PMI8998 Type-C controller
In reply to taygothQuoted 57 lines · taygoth
The PMI8998 PMIC integrates a USB Type-C detection block in its SMB2 charger USBIN region at offset
0x1300. The block performs CC sensing, debounce and Rp/Rd resolution in hardware and reports role changes through a single consolidated "type-c-change" interrupt.This is architecturally distinct from the qcom,pmic-typec binding (PM8150B / PMI632 family) which exposes a granular 8-16 IRQ topology fanned out per Type-C event for a software TCPM state machine. PMI8998 has neither the per-event IRQs nor a register layout compatible with the TCPM code path, so this binding describes a separate hardware- managed role-switch controller.
Signed-off-by taygoth <[email protected]>--- .../bindings/usb/qcom,pmi8998-typec.yaml | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yamlDocumentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml new file +33
-0@@ -0,0 +1,97 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/qcom,pmi8998-typec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm PMI8998 USB Type-C role-switch controller + +maintainers: + - Maxim Furman <[email protected]> + +description: + The PMI8998 PMIC integrates a USB Type-C detection block inside its SMB2 + charger USBIN region at offset 0x1300. CC sensing, debounce and Rp/Rd + resolution are performed in hardware, and the negotiated role is reported + through a single consolidated "type-c-change" interrupt. + + This block is distinct from the TCPM-based qcom,pmic-typec controllers + (PM8150B, PMI632, etc.) — PMI8998 lacks the granular per-event interrupt + topology those parts expose and the driver therefore translates the + hardware-decided role directly into a usb_role_switch_set_role() call + rather than running a software TCPM state machine. Power Delivery is not + supported by this binding. + +properties: + compatible: + const: qcom,pmi8998-typec + + reg: + maxItems: 1 + description: Type-C SPMI register base offset (typically 0x1300). + + interrupts:
Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml line 43
Quoted 10 lines
Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml new file +10
-0+ maxItems: 1 + + interrupt-names: + items: + - const: type-c-change + + vdd-vbus-supply: + description: + VBUS source regulator enabled when the controller transitions to + USB host mode so bus-powered downstream peripherals can be powered.
We probably need to fix this for PM8150B too... This should be connector's vbus-supply instead. I'll send a patch for the existing devices.
Quoted 57 lines
Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml new file +54
-0+ + connector: + type: object + $ref: /schemas/connector/usb-connector.yaml# + unevaluatedProperties: false + +required: + - compatible + - reg + - interrupts + - interrupt-names + - connector + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + typec@1300 { + compatible = "qcom,pmi8998-typec"; + reg = <0x1300>; + + interrupts = <0x2 0x13 0x7 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "type-c-change"; + + vdd-vbus-supply = <&pmi8998_vbus>; + + connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + pmi8998_hs_in: endpoint { + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + }; + }; + }; + }; +...Signature · 1 line
2.47.3
Signature · 2 lines
With best wishes Dmitry
PATCH 3/6 usb: typec: add Qualcomm PMI8998 role-switch driver
In reply to taygothThe Qualcomm PMI8998 PMIC integrates a USB Type-C detection block in its SMB2 charger USBIN region at offset 0x1300. The block performs CC sensing, debounce and Rp/Rd resolution in silicon and reports role changes through a single consolidated "type-c-change" interrupt.
This driver reads TYPE_C_STATUS_4 on probe and on every interrupt, decodes the hardware-detected role (host / device / none) and pushes it to a usb_role_switch consumer (typically dwc3) so the controller can flip between peripheral and host on cable orientation change. An optional VBUS supply regulator is toggled on USB_ROLE_HOST transitions so bus-powered downstream peripherals can be powered.
No software TCPM state machine is used because the hardware handles the Type-C protocol natively, and the PMI8998 interrupt topology does not expose the granular per-event signals the TCPM code path expects. Power Delivery is not implemented in this driver; the PMI8998 PDPHY block at offset 0x1700 (register-identical to PM8150B) can be wired up by a separate driver later if PD negotiation is required.
This enables USB host mode on the OnePlus 6 (enchilada), OnePlus 6T (fajita), Xiaomi Poco F1 (beryllium), SHIFT 6mq (axolotl) and other SDM845-based phones that use the PMI8998 as their second PMIC.
--- drivers/usb/typec/Kconfig | 17 ++ drivers/usb/typec/Makefile | 1 + drivers/usb/typec/qcom_pmi8998_typec.c | 213 +++++++++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 drivers/usb/typec/qcom_pmi8998_typec.c
drivers/usb/typec/Kconfig +17 -0
@@ -100,6 +100,23 @@ config TYPEC_STUSB160X If you choose to build this driver as a dynamically linked module, the module will be called stusb160x.ko. +config TYPEC_QCOM_PMI8998 + tristate "Qualcomm PMI8998 USB Type-C role-switch driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on SPMI + select USB_ROLE_SWITCH + help + Say Y or M here to enable the role-switch driver for the USB + Type-C detection block integrated in the Qualcomm PMI8998 PMIC. + This is the part used on SDM845 phones such as the OnePlus 6/6T, + Xiaomi Poco F1 and SHIFT 6mq. The driver reports the + hardware-detected role through the USB role switch class so the + USB DRD controller (e.g. dwc3) can flip between peripheral and + host on cable orientation change. + + If you choose to build this driver as a dynamically linked module, + the module will be called qcom_pmi8998_typec.ko. + config TYPEC_WUSB3801 tristate "Willsemi WUSB3801 Type-C port controller driver" depends on I2C
drivers/usb/typec/Makefile +1 -0
@@ -10,5 +10,6 @@ obj-$(CONFIG_TYPEC_ANX7411) += anx7411.o obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o obj-$(CONFIG_TYPEC_RT1719) += rt1719.o +obj-$(CONFIG_TYPEC_QCOM_PMI8998) += qcom_pmi8998_typec.o obj-$(CONFIG_TYPEC_WUSB3801) += wusb3801.o obj-$(CONFIG_TYPEC) += mux/
drivers/usb/typec/qcom_pmi8998_typec.c new file +213 -0
213 lines not on this page · raw message
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 3/6] usb: typec: add Qualcomm PMI8998 role-switch driver
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [High] Race condition and Use-After-Free during driver removal due to mixed devm and manual cleanup.…
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Race condition and Use-After-Free during driver removal due to mixed devm and manual cleanup.
- [Medium] VBUS regulator enable count leak on probe error path.
- [Medium] Silently ignored return value of hardware initialization in probe().
--
commit 2be57d2a22cd876c2f33d5adcda09af34cd9c497
Author: taygoth <[email protected]>
usb: typec: add Qualcomm PMI8998 role-switch driver
This commit introduces a new USB Type-C role-switch driver for the Qualcomm PMI8998 PMIC. It translates the hardware-detected role into a consumer switch state, and enables an optional VBUS supply regulator when acting as a USB host.
Quoted 5 lines
drivers/usb/typec/qcom_pmi8998_typec.c new file +0
-0
[ ... ]
Quoted 2 lines
drivers/usb/typec/qcom_pmi8998_typec.c new file +2
-0+static int pmi8998_typec_probe (struct platform_device *pdev) +{
[ ... ]
drivers/usb/typec/qcom_pmi8998_typec.c line 171
Quoted 3 lines
drivers/usb/typec/qcom_pmi8998_typec.c new file +3
-0+platform_set_drvdata (pdev, typec); + +pmi8998_typec_apply (typec);
Should the return value of pmi8998_typec_apply() be checked here?
If operations like regmap_read() or regulator_enable() fail inside apply(), the probe will silently succeed with an unsynchronized hardware state.
drivers/usb/typec/qcom_pmi8998_typec.c line 182
Quoted 11 lines
drivers/usb/typec/qcom_pmi8998_typec.c new file +11
-0+ + ret =devm_request_threaded_irq (dev, typec->irq,NULL , + pmi8998_typec_isr,IRQF_ONESHOT , +dev_name (dev), typec); +if (ret) + goto err_role_put; + +return 0 ; + +err_role_put: +usb_role_switch_put (typec->role_sw);
If pmi8998_typec_apply() above evaluates to USB_ROLE_HOST, it will enable the vbus regulator and set typec->vbus_enabled to true.
If the interrupt request then fails, does this error path leak the regulator enable count by missing a regulator_disable() call?
drivers/usb/typec/qcom_pmi8998_typec.c line 192
Quoted 10 lines
drivers/usb/typec/qcom_pmi8998_typec.c new file +10
-0+return ret; +} + +static void pmi8998_typec_remove (struct platform_device *pdev) +{ +struct pmi8998_typec *typec =platform_get_drvdata (pdev); + +if (typec->vbus_enabled) +regulator_disable (typec->vbus); +usb_role_switch_put (typec->role_sw);
Because the interrupt was requested using devm_request_threaded_irq(), it will not be freed until after pmi8998_typec_remove() returns.
If a hardware interrupt fires right after we disable the regulator and put the role switch:
pmi8998_typec_remove()
regulator_disable(typec->vbus);
usb_role_switch_put(typec->role_sw);-> interrupt firespmi8998_typec_isr()
pmi8998_typec_apply()
Could the ISR attempt to use the freed typec->role_sw or perform an unbalanced regulator_disable() since typec->vbus_enabled is never set to false in remove()?
Quoted 1 line
+}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
Re: [PATCH 3/6] usb: typec: add Qualcomm PMI8998 role-switch driver
In reply to taygothQuoted 11 lines · taygoth
The Qualcomm PMI8998 PMIC integrates a USB Type-C detection block in its SMB2 charger USBIN region at offset
0x1300. The block performs CC sensing, debounce and Rp/Rd resolution in silicon and reports role changes through a single consolidated "type-c-change" interrupt.This driver reads
TYPE_C_STATUS_4on probe and on every interrupt, decodes the hardware-detected role (host / device / none) and pushes it to ausb_role_switchconsumer (typically dwc3) so the controller can flip between peripheral and host on cable orientation change. An optional VBUS supply regulator is toggled onUSB_ROLE_HOSTtransitions so bus-powered downstream peripherals can be powered.
This is an interesting implementation, but...
Quoted 7 lines
No software TCPM state machine is used because the hardware handles the Type-C protocol natively, and the PMI8998 interrupt topology does not expose the granular per-event signals the TCPM code path expects. Power Delivery is not implemented in this driver; the PMI8998 PDPHY block at offset
0x1700(register-identical to PM8150B) can be wired up by a separate driver later if PD negotiation is required.
I think TCPM / PD-PHY is (more or less) a sensible requirement. Without it you can't negotiate higher power modes or AltModes support (which means no DP).
Also, this (read-only) implementation doesn't leave space for the active events, like role negotiation.
Anyway, could you please be more specific, which events or which controls do you need?
Quoted 6 lines
This enables USB host mode on the OnePlus 6 (enchilada), OnePlus 6T (fajita), Xiaomi Poco F1 (beryllium), SHIFT 6mq (axolotl) and other SDM845-based phones that use the PMI8998 as their second PMIC.
Signed-off-by taygoth <[email protected]>
Please correct your Git configuration to use your full name in the From metadata and in the SoB.
Quoted 8 lines
--- drivers/usb/typec/Kconfig | 17 ++ drivers/usb/typec/Makefile | 1 + drivers/usb/typec/qcom_pmi8998_typec.c | 213 +++++++++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 drivers/usb/typec/qcom_pmi8998_typec.c
Signature · 2 lines
With best wishes Dmitry
Re: [PATCH 3/6] usb: typec: add Qualcomm PMI8998 role-switch driver
Quoted 9 lines · Dmitry Baryshkov
Quoted 6 lines
No software TCPM state machine is used because the hardware handles the Type-C protocol natively, and the PMI8998 interrupt topology does not expose the granular per-event signals the TCPM code path expects. Power Delivery is not implemented in this driver; the PMI8998 PDPHY block at offset
0x1700(register-identical to PM8150B) can be wired up by a separate driver later if PD negotiation is required.I think TCPM / PD-PHY is (more or less) a sensible requirement. Without it you can't negotiate higher power modes or AltModes support (which means no DP).
If the PDPHY is register compatible as stated then the PD part is very close.
Looking at the pmi8998 STATUS_REG_4
- VBUS_STATUS
- ORIENTATION
- ATTACHED
are all driven. So I believe it would be possible to bring the pmi8998 into - along side the pmi8998 logic.
@Maxim have you looked at that as an option ?
I believe Casey and Luca? both worked on that.
For preference I think we should try to land pmi8998 into the existing TCPM logic though, as another TypeC port handler within the existing logic.
The important signals above, appear to be driven.
---
bod
Re: [PATCH 3/6] usb: typec: add Qualcomm PMI8998 role-switch driver
Quoted 1 line · Bryan O'Donoghue
along side the pmi8998 logic.
*pm8150b
---
bod
Re: [PATCH 3/6] usb: typec: add Qualcomm PMI8998 role-switch driver
In reply to taygothQuoted 19 lines · taygoth
The Qualcomm PMI8998 PMIC integrates a USB Type-C detection block in its SMB2 charger USBIN region at offset
0x1300. The block performs CC sensing, debounce and Rp/Rd resolution in silicon and reports role changes through a single consolidated "type-c-change" interrupt.This driver reads
TYPE_C_STATUS_4on probe and on every interrupt, decodes the hardware-detected role (host / device / none) and pushes it to ausb_role_switchconsumer (typically dwc3) so the controller can flip between peripheral and host on cable orientation change. An optional VBUS supply regulator is toggled onUSB_ROLE_HOSTtransitions so bus-powered downstream peripherals can be powered.No software TCPM state machine is used because the hardware handles the Type-C protocol natively, and the PMI8998 interrupt topology does not expose the granular per-event signals the TCPM code path expects. Power Delivery is not implemented in this driver; the PMI8998 PDPHY block at offset
0x1700(register-identical to PM8150B) can be wired up by a separate driver later if PD negotiation is required.
Quoted 5 lines
This enables USB host mode on the OnePlus 6 (enchilada), OnePlus 6T (fajita), Xiaomi Poco F1 (beryllium), SHIFT 6mq (axolotl) and other SDM845-based phones that use the PMI8998 as their second PMIC.
Signed-off-by taygoth <[email protected]>
Incomplete identity.
Quoted 6 lines
--- drivers/usb/typec/Kconfig | 17 ++ drivers/usb/typec/Makefile | 1 + drivers/usb/typec/qcom_pmi8998_typec.c | 213 +++++++++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 drivers/usb/typec/qcom_pmi8998_typec.c
Do not mix up subsystems which take entire sets in one patchset. USB patches should be split.
Best regards,
Krzysztof
PATCH 4/6 arm64: dts: qcom: pmi8998: add USB Type-C and VBUS regulator nodes
In reply to taygothThe PMI8998 PMIC includes a USB Type-C detection block at SPMI offset 0x1300 and a USB OTG VBUS boost converter at offset 0x1100. Both are left disabled here so that only boards which wire up the connector and USB role-switch enable them.
The VBUS regulator falls back to the qcom,pm8150b-vbus-reg compatible because the OTG register layout (CMD_OTG, OTG_CFG, OTG_CURRENT_LIMIT) is identical to the PM8150B SMB5 block.
--- arch/arm64/boot/dts/qcom/pmi8998.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
arch/arm64/boot/dts/qcom/pmi8998.dtsi +19 -0
@@ -29,6 +29,25 @@ pmi8998_charger: charger@1000 { status = "disabled"; }; + pmi8998_vbus: vbus-reg@1100 { + compatible = "qcom,pmi8998-vbus-reg", + "qcom,pm8150b-vbus-reg"; + reg = <0x1100>; + status = "disabled"; + }; + + pmi8998_typec: typec@1300 { + compatible = "qcom,pmi8998-typec"; + reg = <0x1300>; + + interrupts = <0x2 0x13 0x7 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "type-c-change"; + + vdd-vbus-supply = <&pmi8998_vbus>; + + status = "disabled"; + }; + pmi8998_gpios: gpio@c000 { compatible = "qcom,pmi8998-gpio", "qcom,spmi-gpio"; reg = <0xc000>;
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 4/6] arm64: dts: qcom: pmi8998: add USB Type-C and VBUS regulator nodes
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Medium] Devicetree schema validation failure for VBUS regulator node due to incorrect name and missing…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Devicetree schema validation failure for VBUS regulator node due to incorrect name and missing properties.
- [Medium] Devicetree schema validation failure for Type-C node due to schema routing conflict and missing required subnode. --
commit d114c820eb701d590cfd5b3e5e83a32def5c8605
Author: taygoth <[email protected]>
arm64: dts: qcom: pmi8998: add USB Type-C and VBUS regulator nodes
This commit adds disabled nodes for the PMI8998 PMIC USB Type-C detection block and the USB OTG VBUS boost converter. The VBUS regulator falls back to the pm8150b-vbus-reg compatible due to identical register layouts.
arch/arm64/boot/dts/qcom/pmi8998.dtsi pmi8998_charger: charger@1000 { · line 32
Quoted 7 lines
arch/arm64/boot/dts/qcom/pmi8998.dtsi +1
-0@@ -29,6 +29,25 @@ pmi8998_charger: charger@1000 { status = "disabled"; }; + pmi8998_vbus: vbus-reg@1100 {
Will this node name cause a devicetree schema validation failure during dtbs_check?
It looks like Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml enforces the node name pattern ^usb-vbus-regulator@[0-9a-f]+$ and has
additionalProperties: false.
arch/arm64/boot/dts/qcom/pmi8998.dtsi pmi8998_charger: charger@1000 { · line 35
Quoted 3 lines
arch/arm64/boot/dts/qcom/pmi8998.dtsi +3
-0+ compatible = "qcom,pmi8998-vbus-reg", + "qcom,pm8150b-vbus-reg"; + reg = <0x1100>;
Are we missing the regulator-min-microamp and regulator-max-microamp properties here?
The qcom,usb-vbus-regulator.yaml schema strictly requires them, which might trigger warnings for all boards including pmi8998.dtsi even if the status is disabled.
arch/arm64/boot/dts/qcom/pmi8998.dtsi pmi8998_charger: charger@1000 { · line 39
Quoted 4 lines
arch/arm64/boot/dts/qcom/pmi8998.dtsi +4
-0+ status = "disabled"; + }; + + pmi8998_typec: typec@1300 {
Does naming this node typec@1300 create a schema routing conflict?
The pattern ^typec@[0-9a-f]+$ in qcom,spmi-pmic.yaml hardcodes a reference to /schemas/usb/qcom,pmic-typec.yaml#. Since qcom,pmi8998-typec has its own binding and isn't permitted in qcom,pmic-typec.yaml, dtbs_check might evaluate it against the wrong schema and reject the compatible string.
arch/arm64/boot/dts/qcom/pmi8998.dtsi pmi8998_charger: charger@1000 { · line 46
Quoted 7 lines
arch/arm64/boot/dts/qcom/pmi8998.dtsi +7
-0+ compatible = "qcom,pmi8998-typec"; + reg = <0x1300>; + + interrupts = <0x2 0x13 0x7 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "type-c-change"; + + vdd-vbus-supply = <&pmi8998_vbus>;
Does this node also need the connector subnode? It appears to be explicitly listed as required in qcom,pmi8998-typec.yaml.
Quoted 3 lines
arch/arm64/boot/dts/qcom/pmi8998.dtsi +3
-0+ + status = "disabled"; + };
[ ... ]
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
PATCH 5/6 arm64: dts: qcom: sdm845-oneplus-common: enable USB Type-C role switching
In reply to taygothEnable the PMI8998 Type-C controller and USB OTG VBUS regulator so the OnePlus 6 and OnePlus 6T can dynamically switch between USB peripheral and host roles depending on the connected cable, instead of being locked to peripheral mode at boot.
The dwc3 controller is moved from dr_mode = "peripheral" to "otg" and gains a usb-role-switch property. The existing usb_1_dwc3_hs endpoint declared in sdm845.dtsi has its remote-endpoint pointed at the new pmi8998 Type-C connector subnode. The maximum-speed override is no longer required because role switching infrastructure handles speed negotiation through the usb-c-connector.
The VBUS regulator current limits (500 mA - 1.5 A) match the boost converter capability noted in the downstream qpnp-smb2 charger config.
--- .../boot/dts/qcom/sdm845-oneplus-common.dtsi | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-)
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +36 -7
@@ -606,6 +606,36 @@ &pmi8998_charger { status = "okay"; }; +&pmi8998_vbus { + regulator-min-microamp = <500000>; + regulator-max-microamp = <1500000>; + status = "okay"; +}; + +&pmi8998_typec { + status = "okay"; + + connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + pmi8998_hs_in: endpoint { + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + }; + }; +}; + &pmi8998_flash { status = "okay";
@@ -890,19 +920,18 @@ &usb_1 { }; &usb_1_dwc3 { - /* - * We don't have the capability to switch modes yet. - */ - dr_mode = "peripheral"; - - /* fastest mode for USB 2 */ - maximum-speed = "high-speed"; + dr_mode = "otg"; + usb-role-switch; /* Remove USB3 phy as it's unused on this device. */ phys = <&usb_1_hsphy>; phy-names = "usb2-phy"; }; +&usb_1_dwc3_hs { + remote-endpoint = <&pmi8998_hs_in>; +}; + &usb_1_hsphy { status = "okay";
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 5/6] arm64: dts: qcom: sdm845-oneplus-common: enable USB Type-C role switching
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] Removing `maximum-speed = "high-speed"` misconfigures the DWC3 controller to default to SuperSpeed…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Removing maximum-speed = "high-speed" misconfigures the DWC3 controller to default to SuperSpeed on a physically High-Speed-only board, leading to false capabilities advertisement and potential AXI bus hangs.
- [High] The vdd-vbus-supply property is missing from the &pmi8998_typec node, which completely breaks VBUS power delivery in USB host mode.
--
commit fd2e287ee85d01cae64bd27f78d0a7b1a4d6ea65
Author: taygoth <[email protected]>
arm64: dts: qcom: sdm845-oneplus-common: enable USB Type-C role switching
This commit enables the PMI8998 Type-C controller and configures the dwc3 controller for OTG mode on the OnePlus 6/6T. It removes the maximum-speed property and maps the USB endpoints for role switching.
Quoted 3 lines
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +0
-0
[ ... ]
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi &pmi8998_charger { · line 616
Quoted 8 lines
+&pmi8998_vbus {
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +7
-0+ regulator-min-microamp = <500000>; + regulator-max-microamp = <1500000>; + status = "okay"; +}; + +&pmi8998_typec { + status = "okay";
Does this node need a vdd-vbus-supply property?
The qcom,pmi8998-typec driver looks up the VBUS regulator using devm_regulator_get_optional(dev, "vdd-vbus"). Without a vdd-vbus-supply property pointing to &pmi8998_vbus, the lookup returns -ENODEV and the driver proceeds with a NULL vbus.
Will this result in the driver silently skipping the VBUS regulator enablement during USB_ROLE_HOST transitions, leaving bus-powered downstream peripherals without power?
Quoted 3 lines
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +3
-0+ + connector { + compatible = "usb-c-connector";
[ ... ]
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi &usb_1 { · line 924
Quoted 13 lines
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +2
-7@@ -890,19 +920,18 @@ &usb_1 { }; &usb_1_dwc3 { - /* - * We don't have the capability to switch modes yet. - */ - dr_mode = "peripheral"; - - /* fastest mode for USB 2 */ - maximum-speed = "high-speed"; + dr_mode = "otg"; + usb-role-switch;
Is it safe to remove the maximum-speed property here?
The commit message notes that the role switching infrastructure handles speed negotiation through the usb-c-connector. However, Type-C CC pins typically only negotiate power delivery and data roles, not the underlying USB protocol speed limits.
If maximum-speed is omitted, the DWC3 core driver falls back to reading the controller's internal hardware parameters (GHWPARAMS3). Since the SDM845 IP is SuperSpeed-capable, it will default to USB_SPEED_SUPER.
Because the board only wires High-Speed lines and drops the SuperSpeed PHY (phys = <&usb_1_hsphy>), will the xHCI driver register a SuperSpeed root hub and attempt Rx.Detect polling? Could attempting to access the PIPE interface of an unclocked QMP PHY trigger an AXI bus hang?
Quoted 3 lines
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +0
-0/* Remove USB3 phy as it's unused on this device. */ phys = <&usb_1_hsphy>;
[ ... ]
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
PATCH 6/6 MAINTAINERS: add entry for Qualcomm PMI8998 USB Type-C driver
In reply to taygothAdd a MAINTAINERS entry covering the new qcom_pmi8998_typec driver and its device-tree binding.
--- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+)
MAINTAINERS +8 -0
@@ -22120,6 +22120,14 @@ S: Maintained F: Documentation/devicetree/bindings/usb/qcom,pmic-*.yaml F: drivers/usb/typec/tcpm/qcom/ +QUALCOMM PMI8998 USB TYPE-C ROLE-SWITCH DRIVER +M: Maxim Furman <[email protected]> +L: [email protected] +L: [email protected] +S: Maintained +F: Documentation/devicetree/bindings/usb/qcom,pmi8998-typec.yaml +F: drivers/usb/typec/qcom_pmi8998_typec.c + QUALCOMM VENUS VIDEO ACCELERATOR DRIVER M: Vikash Garodia <[email protected]> M: Dikshita Agarwal <[email protected]>
Signature · 1 line
2.47.3
Quoted 4 lines · taygoth
Power Delivery is not implemented. The PMI8998 PDPHY block at offset
0x1700is register-identical to PM8150B and could be wired through the existingdrivers/usb/typec/tcpm/qcomcode in a follow-up if PD negotiation becomes a requirement.
So in this case why not implement your code as a new instance of of type-c phy in the existing TCPM driver ?
---
bod
A message that is not in the archive (sent off-list or not yet received): CAFPzRonyVt9Kd+Sc0ooNz8By6b-Zr_jHr0sBXv-M25dQ0w9Cjg@mail.gmail.com
Quoted 10 lines · Максим Фурман
Three shapes for adding a second port handler to the existing driver:
(a) extracted ops --pmic_typec_port_opswith chip-specificget_cc/get_vbus/set_mode/set_vconn/start_toggling, refactor PM8150B code into the ops, add parallel PMI8998 implementation
(b) parallel port file -- keep PM8150B code untouched, add a sibling source file with the sametcpc_devcallback surface
(c) per-chip register table + per-chip decode helpers in the same fileBryan, do you have a preference? I'd rather match your taste than guess, since you'll be maintaining the merged result.
Taste - loaded with honey, chilli and salt please chef and add the whole clove of garlic....
My feeling is sibling file but please use your own taste/discretion.
---
bod
Quoted 7 lines · Bryan O'Donoghue
Quoted 6 lines · Максим Фурман
Three shapes for adding a second port handler to the existing driver:
(a) extracted ops --pmic_typec_port_opswith chip-specificget_cc/get_vbus/set_mode/set_vconn/start_toggling, refactor PM8150B code into the ops, add parallel PMI8998 implementation
(b) parallel port file -- keep PM8150B code untouched, add a sibling source file with the sametcpc_devcallback surface
2c, my preference would be this option.
Quoted 12 lines
Quoted 4 lines
(c) per-chip register table + per-chip decode helpers in the same file
Bryan, do you have a preference? I'd rather match your taste than guess, since you'll be maintaining the merged result.
Taste - loaded with honey, chilli and salt please chef and add the whole clove of garlic....
My feeling is sibling file but please use your own taste/discretion.
---
bod
Signature · 2 lines
With best wishes Dmitry
Quoted 27 lines · taygoth
This series adds USB Type-C role-switch support for the PMI8998 PMIC used on SDM845 phones (OnePlus 6/6T, Xiaomi Poco F1, SHIFT 6mq), which have been locked to USB peripheral mode under mainline kernels until now.
The PMI8998 SMB2 charger block integrates a Type-C detection unit at SPMI offset
0x1300that performs CC sensing, debounce and Rp/Rd resolution entirely in hardware. The state is exposed through theTYPE_C_STATUS_4register and reported via a single consolidated "type-c-change" interrupt. The new driver reads that status on every interrupt and pushes the negotiated role to ausb_role_switchconsumer (dwc3), enabling automatic peripheral/host switching on cable change. Because the hardware handles the Type-C state machine natively, no software TCPM port manager is required.The Type-C block shares the SMB2 USBIN region with the already mainlined qcom_pmi8998-charger driver. The two coexist on the shared SPMI regmap without write conflict: the typec driver only reads TYPE_C_STATUS_* and touches the IRQ enable bits at offsets 0x130b-0x130f and 0x1367-0x1368.
The PMI8998 USB OTG VBUS boost converter at offset
0x1100has the sameCMD_OTG/OTG_CFG/OTG_CURRENT_LIMITregister layout as PM8150B, so the existingdrivers/regulator/qcom_usb_vbus-regulatorcan drive it through a compatible cascade -- only the DT binding needs the new compatible string added.
Quoted 7 lines
Power Delivery is not implemented. The PMI8998 PDPHY block at offset
0x1700is register-identical to PM8150B and could be wired through the existingdrivers/usb/typec/tcpm/qcomcode in a follow-up if PD negotiation becomes a requirement.Tested-on: OnePlus 6T (sdm845-oneplus-fajita) running Mobian 6.12-sdm845.
FWIW 6.12 has been released 2 years ago and the sdm845 fork contains a lot of unrelated changes. Please give this a test on linux-next/master
Konrad
Quoted 32 lines · taygoth
This series adds USB Type-C role-switch support for the PMI8998 PMIC used on SDM845 phones (OnePlus 6/6T, Xiaomi Poco F1, SHIFT 6mq), which have been locked to USB peripheral mode under mainline kernels until now.
The PMI8998 SMB2 charger block integrates a Type-C detection unit at SPMI offset
0x1300that performs CC sensing, debounce and Rp/Rd resolution entirely in hardware. The state is exposed through theTYPE_C_STATUS_4register and reported via a single consolidated "type-c-change" interrupt. The new driver reads that status on every interrupt and pushes the negotiated role to ausb_role_switchconsumer (dwc3), enabling automatic peripheral/host switching on cable change. Because the hardware handles the Type-C state machine natively, no software TCPM port manager is required.The Type-C block shares the SMB2 USBIN region with the already mainlined qcom_pmi8998-charger driver. The two coexist on the shared SPMI regmap without write conflict: the typec driver only reads TYPE_C_STATUS_* and touches the IRQ enable bits at offsets 0x130b-0x130f and 0x1367-0x1368.
The PMI8998 USB OTG VBUS boost converter at offset
0x1100has the sameCMD_OTG/OTG_CFG/OTG_CURRENT_LIMITregister layout as PM8150B, so the existingdrivers/regulator/qcom_usb_vbus-regulatorcan drive it through a compatible cascade -- only the DT binding needs the new compatible string added.Power Delivery is not implemented. The PMI8998 PDPHY block at offset
0x1700is register-identical to PM8150B and could be wired through the existingdrivers/usb/typec/tcpm/qcomcode in a follow-up if PD negotiation becomes a requirement.
Quoted 8 lines
Tested-on: OnePlus 6T (sdm845-oneplus-fajita) running Mobian 6.12-sdm845. A USB flash drive, USB ethernet adapter, USB WiFi adapter (TP-Link Archer T2) and a self-powered USB-C dock with downstream ethernet all enumerate through xHCI after the role transitions from peripheral to host. Repeat plug/unplug cycles drive the role through device -> none -> host -> none -> device cleanly with no IRQ stalls or stale role-switch state.
Hello Максим,
1st, let me say happy to hear about progress here, I missed this message - due to huge traffic in linux-arm-msm*.
2nd, I have locally version which does work with DisplayPort (SHIFT 6MQ), does work with dockstation USB (e.g. perperials are recognized and does work), but doesn't provide power to the usb devices (haven't figureout, and it's more clanker work than mine here).
3rd, added Sam into +Cc, as he's interested in the pmi8998 too, plus there are others doing some experiments with pmi8998 in Matrix room https://matrix.to/#/#sdm845:ixit.cz .
What's your current state? Would you be interested joining the room and chat? or
we can do some email exchange of trees and work done :)
David
* there is [email protected], where this type of contribution stand out a bit, possibly for next iteration
[...]