* [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
@ 2023-04-13 11:34 Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 01/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required Bryan O'Donoghue
` (15 more replies)
0 siblings, 16 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
V5:
- Amagamates into once device, Heikki, Rob
- Takes feedback on usage form Luka and Jianhua on VSafeV state transition detection
dev_err() -> dev_warn()
- Orientation graph example and general expected bindings
I discussed offline with Bjorn the conclusions of the glink/sbu model.
The expected orientation-switch path is
connector/port@0 <-> phy/port@X <-> dp/port@0
This can then be expanded to
connector/port@0 <-> redriver/port@0 <-> phy/port@X <-> dp/port@0
- Rob, Bjorn, Krzysztof
- Data role
The data-role path is
connector/port@0 <-> dwc3/port@Y
Previous set:
https://lore.kernel.org/linux-arm-msm/20230318121828.739424-1-bryan.odonoghue@linaro.org/
Bootable:
https://git.codelinaro.org/bryan.odonoghue/kernel/-/tree/linux-next-23-04-12-pm8150b-tcpm-qcom-wrapper-typec-mux
V4:
- Per Rob's input the pdphy and type-c appear as stadalone blocks
inside of the PMIC declaration which is a 1:1 mapping of PMIC hardware.
The TCPM virtual device is declared at the top-level.
https://lore.kernel.org/all/YY7p7jviA3ZG05gL@robh.at.kernel.org/
- Squashes the removal of the old driver with the addition of the new. - Heikki, Gunter
https://lore.kernel.org/all/YYVHcHC1Gm92VxEM@kuha.fi.intel.com/
- Reworked Dmitry's old patch for the QMP to account for file renames and
very minimal code-drift in the interregnum.
- New yaml checks drive update of PMIC VBUS yaml
- Some housekeeping on the sc7180 yaml side. sc7180 is not supported yet.
- Expands and fixes the examples being added in the PMIC tcpm examples.
Previous set:
https://lore.kernel.org/all/20211105033558.1573552-1-bryan.odonoghue@linaro.org/
Bootable:
https://git.codelinaro.org/bryan.odonoghue/kernel/-/commits/linux-next-23-03-18-pm8150b-tcpm-qcom-wrapper-typec-mux
V3:
Rob Herrings review
- Drops use of remote-endpoint and ports to bind
tcpm to pdphy and typec replacing with phandle
- Drops pmic-pdphy-* and pmic-typec-* from interrupt names
as suggested
- Passes make dt_binding_check DT_CHECKER_FLAGS=-m
BOD
- Noticed qcom_pmic_tcpm_pdphy_enable() was missing a
regulator_disable in case of an error, added.
- qcom_pmic_tcpm_pdphy_probe()
devm_regulator_get() should come before regmap_get()
as is the case in qcom_pmic_tcpm_typec_probe()
- Fixes compatible name in qcom,pmic-typec.yaml should
have read qcom,pm8150b-typec not qcom,pm8150b-usb-typec
- Makes sure compat for core is "qcom,pm8150b-tcpm" in
docs and driver
- Drops redundant return in void qcom_pmic_tcpm_pdphy_reset_off()
Kernel Robot
- Drops unused variable debounced in qcom_pmic_tcpm_typec_get_cc()
- Drops unsused variable orientation in qcom_pmic_tcpm_typec_set_cc()
Latest bootable series can be found here:
Link: https://git.linaro.org/people/bryan.odonoghue/kernel.git/log/?h=usb-next-04-11-21-pm8150b-tcpm-v3
git diff usb-next-27-10-21-pm8150b-tcpm-v2 -- drivers/usb/typec/tcpm/qcom/
git diff usb-next-27-10-21-pm8150b-tcpm-v2 -- Documentation/devicetree/bindings/usb/qcom,pmic*
Previous set:
Link: https://lore.kernel.org/linux-usb/20211028164941.831918-1-bryan.odonoghue@linaro.org/T/#t
V2 resend:
- Adding omitted devicetree mailing list
V2:
Guenter Roeck's review
- Converts suggested qcom_pmic_tcpm_core.c into one-liners
- Adds comment on how polarity is set in set_polarity()
- Removes optional set_current_limit()
- regmap_read/regmap_write
Reviwing other pm8150b/spmi drivers I then added in checks for all
reamap_read()/regmap_write() calls.
- Fixes (type == TCPC_TX_CABLE_RESET || TCPC_TX_HARD_RESET)
thanks I definitely had the blinkers on there and didn't see that at all
- qcom_pmic_tcpm_pdphy_pd_transmit_payload()
Treats regmap_read and read value as separate error paths
- qcom_pmic_tcpm_pdphy_set_pd_rx()
Replaces boolean if/else with !on as suggested
- Returns -ENODEV not -EINVAL on dev_get_regmap() error
- qcom_pmic_tcpm_pdphy_pd_receive()
Guenter asks: "No error return ?"
bod: No we are inside an ISR here if we read data we pass that off to TCPM
if somehow we don't read the data - it is "junk" there's no value IMO
in pushing an error upwards back to the handler.
Heikki Krogerus' review
- Includes Makefile I missed adding to my git index
- Removes old Kconfig entry for remove driver
Randy Dunlap's review
- Rewords drivers/usb/typec/tcpm/Kconfig
- Drops tautology "aggregates togther"
- Corrects spelling typos
BOD's own review
- Drops redundant include of regmap.h in qcom_pmic_tcpm_core.c
- Propogates qcom_pmic_tcpm_pdphy_disable() error upwards
- Propogates pmic_pdphy_reset() error upwards
- Drops error prints in qcom_pmic_tcpm_pdphy_pd_transmit_payload()
I had these in-place during development and don't recall them being
triggered even once, they are redundant, remove.
Differences between the two can be seen by
git diff usb-next-27-10-21-pm8150b-tcpm-v2..usb-next-25-10-21-pm8150b-tcpm -- drivers/usb/typec/tcpm
Latest bootable series can be found here:
Link: https://git.linaro.org/people/bryan.odonoghue/kernel.git/log/?h=usb-next-27-10-21-pm8150b-tcpm-v2
Previous set:
Link: https://lore.kernel.org/all/20211025150906.176686-1-bryan.odonoghue@linaro.org/T/#t
V1:
This series adds a set of yaml and a driver to bind together the type-c and
pdphy silicon in qcom's pm8150b block as a Linux type-c port manager.
As part of that we retire the existing qcom-pmic-typec driver and fully
replicate its functionality inside of the new block with the additional
pdphy stuff along with it.
An additional series will follow this one for the SoC and RB5 dtsi and dts
respectively.
A bootable series can be found here
Link: https://git.linaro.org/people/bryan.odonoghue/kernel.git/log/?h=usb-next-25-10-21-pm8150b-tcpm
Bryan O'Donoghue (13):
dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required
dt-bindings: regulator: qcom,usb-vbus-regulator: Mark
regulator-*-microamp required
dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add orientation-switch
as optional
dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an
optional
dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema
dt-bindings: mfd: qcom,spmi-pmic: Add typec to SPMI device types
arm64: dts: qcom: sm8250: Define ports for qmpphy
orientation-switching
arm64: dts: qcom: pm8150b: Add a TCPM description
arm64: dts: qcom: qrb5165-rb5: Switch on Type-C VBUS boost
arm64: dts: qcom: qrb5165-rb5: Switch on basic TCPM
arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for
usb_1
arm64: dts: qcom: qrb5165-rb5: Switch on TCPM orientation-switch for
usb_1_qmpphy
usb: typec: qcom: Add Qualcomm PMIC TCPM support
Dmitry Baryshkov (1):
phy: qcom-qmp: Register as a typec switch for orientation detection
.../bindings/mfd/qcom,spmi-pmic.yaml | 4 +
.../phy/qcom,sc7180-qmp-usb3-dp-phy.yaml | 40 ++
.../regulator/qcom,usb-vbus-regulator.yaml | 10 +-
.../bindings/usb/qcom,pmic-typec.yaml | 169 ++++++
MAINTAINERS | 10 +
arch/arm64/boot/dts/qcom/pm8150b.dtsi | 40 ++
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 57 +-
arch/arm64/boot/dts/qcom/sm8250.dtsi | 13 +
drivers/phy/qualcomm/Kconfig | 8 +
drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 80 ++-
drivers/usb/typec/Kconfig | 13 -
drivers/usb/typec/Makefile | 1 -
drivers/usb/typec/qcom-pmic-typec.c | 261 --------
drivers/usb/typec/tcpm/Kconfig | 11 +
drivers/usb/typec/tcpm/Makefile | 1 +
drivers/usb/typec/tcpm/qcom/Makefile | 6 +
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c | 362 +++++++++++
.../typec/tcpm/qcom/qcom_pmic_typec_pdphy.c | 528 +++++++++++++++++
.../typec/tcpm/qcom/qcom_pmic_typec_pdphy.h | 115 ++++
.../typec/tcpm/qcom/qcom_pmic_typec_port.c | 560 ++++++++++++++++++
.../typec/tcpm/qcom/qcom_pmic_typec_port.h | 194 ++++++
21 files changed, 2202 insertions(+), 281 deletions(-)
create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
delete mode 100644 drivers/usb/typec/qcom-pmic-typec.c
create mode 100644 drivers/usb/typec/tcpm/qcom/Makefile
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
--
2.39.2
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v5 01/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-16 17:43 ` Krzysztof Kozlowski
2023-04-13 11:34 ` [PATCH v5 02/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark regulator-*-microamp required Bryan O'Donoghue
` (14 subsequent siblings)
15 siblings, 1 reply; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
The regulator code needs to know the location of the register to write to
to switch on/off. Right now we have a driver that does this, a yaml that
partially describes it and no dts that uses it.
Switching on the VBUS for sm8250 shows that we haven't documented reg as a
required property, do so now.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
.../devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml
index b1cff3adb21b5..7a3b59f836092 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml
@@ -25,6 +25,7 @@ properties:
required:
- compatible
+ - reg
additionalProperties: false
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 02/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark regulator-*-microamp required
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 01/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 03/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add orientation-switch as optional Bryan O'Donoghue
` (13 subsequent siblings)
15 siblings, 0 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom, Krzysztof Kozlowski
The VBUS driver needs to know the regulator-min-microamp and
regulator-max-microamp so they should both be marked as required.
regulator.yaml defines those two dependencies so include regulator.yaml.
We need to change from additionalProperties: false to
unevaluatedProperties: false.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
.../bindings/regulator/qcom,usb-vbus-regulator.yaml | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml
index 7a3b59f836092..89c564dfa5db5 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml
@@ -14,6 +14,9 @@ description: |
regulator will be enabled in situations where the device is required to
provide power to the connected peripheral.
+allOf:
+ - $ref: regulator.yaml#
+
properties:
compatible:
enum:
@@ -26,8 +29,10 @@ properties:
required:
- compatible
- reg
+ - regulator-min-microamp
+ - regulator-max-microamp
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
@@ -37,6 +42,8 @@ examples:
pm8150b_vbus: usb-vbus-regulator@1100 {
compatible = "qcom,pm8150b-vbus-reg";
reg = <0x1100>;
+ regulator-min-microamp = <500000>;
+ regulator-max-microamp = <3000000>;
};
};
...
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 03/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add orientation-switch as optional
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 01/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 02/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark regulator-*-microamp required Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional Bryan O'Donoghue
` (12 subsequent siblings)
15 siblings, 0 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom, Krzysztof Kozlowski
orientation-switch it the standard declaration to inform the Type-C mux
layer that a remote-endpoint is capable of processing orientation change
messages.
Add as an optional since not all versions of the dp-phy currently support
the orientation-switch.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
.../bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
index 0ef2c9b9d4669..d307343388888 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
@@ -61,6 +61,10 @@ properties:
power-domains:
maxItems: 1
+ orientation-switch:
+ description: Flag the port as possible handler of orientation switching
+ type: boolean
+
resets:
items:
- description: reset of phy block.
@@ -251,6 +255,8 @@ examples:
vdda-phy-supply = <&vdda_usb2_ss_1p2>;
vdda-pll-supply = <&vdda_usb2_ss_core>;
+ orientation-switch;
+
usb3-phy@200 {
reg = <0x200 0x128>,
<0x400 0x200>,
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (2 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 03/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add orientation-switch as optional Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-14 7:23 ` Marijn Suijten
2023-04-16 17:47 ` Krzysztof Kozlowski
2023-04-13 11:34 ` [PATCH v5 05/14] dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema Bryan O'Donoghue
` (11 subsequent siblings)
15 siblings, 2 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
Add ports as an optional
port@0 to receive an orientation-switch message from the Type-C port or
redriver
port@1 to subsequently transmit the orientation-switch on once the PHY has
finished doing its orientation turn-around.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
.../phy/qcom,sc7180-qmp-usb3-dp-phy.yaml | 34 +++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
index d307343388888..9ef69ad12b74a 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
@@ -65,6 +65,22 @@ properties:
description: Flag the port as possible handler of orientation switching
type: boolean
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description: OF graph bindings that model incoming orientation-switch and
+ outgoing orientation-switch messages. An example of an incoming
+ orientation-switch message might come form a Type-C connector or a USB
+ redriver. An example of an output would be a DisplayPort controller.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Type-C mux orientation-switch input.
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: PHY orientation-siwtch output.
+
resets:
items:
- description: reset of phy block.
@@ -279,4 +295,22 @@ examples:
#clock-cells = <1>;
#phy-cells = <0>;
};
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ qmpphy_typec_mux_in: endpoint {
+ remote-endpoint = <&pmic_typec_mux_out>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ qmpphy_typec_mux_out: endpoint {
+ remote-endpoint = <&dp_typec_mux_in>;
+ };
+ };
+ };
};
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 05/14] dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (3 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-14 7:27 ` Marijn Suijten
2023-04-16 17:49 ` Krzysztof Kozlowski
2023-04-13 11:34 ` [PATCH v5 06/14] dt-bindings: mfd: qcom,spmi-pmic: Add typec to SPMI device types Bryan O'Donoghue
` (10 subsequent siblings)
15 siblings, 2 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom, Wesley Cheng
Add a YAML binding for the Type-C silicon interface inside Qualcomm's
pm8150b hardware block.
The Type-C driver operates with a pdphy driver inside of a high level
single TCPM device.
Based on original work by Wesley.
Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
.../bindings/usb/qcom,pmic-typec.yaml | 169 ++++++++++++++++++
1 file changed, 169 insertions(+)
create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
diff --git a/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
new file mode 100644
index 0000000000000..6d0f5d00305cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
@@ -0,0 +1,169 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/usb/qcom,pmic-typec.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Qualcomm PMIC based USB Type-C block
+
+maintainers:
+ - Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+
+description: |
+ Qualcomm PMIC Type-C block
+
+properties:
+ compatible:
+ enum:
+ - qcom,pm8150b-typec
+
+ connector:
+ type: object
+ $ref: /schemas/connector/usb-connector.yaml#
+ unevaluatedProperties: false
+
+ reg:
+ description: Type-C port and pdphy SPMI register base offsets
+ minItems: 2
+ maxItems: 2
+
+ interrupts:
+ items:
+ - description: Bitmask of CC attach, VBUS error, tCCDebounce done and more
+ - description: VCONN Powered Detection
+ - description: CC state change
+ - description: VCONN over-current condition
+ - description: VBUS state change
+ - description: Attach Deteach notification
+ - description: Legacy cable detect
+ - description: Try.Src Try.Snk state change
+ - description: Sig TX - transmitted reset signal
+ - description: Sig RX - received reset signal
+ - description: TX completion
+ - description: RX completion
+ - description: TX fail
+ - description: TX discgard
+ - description: RX discgard
+ - description: Fast Role Swap event
+
+ interrupt-names:
+ items:
+ - const: or-rid-detect-change
+ - const: vpd-detect
+ - const: cc-state-change
+ - const: vconn-oc
+ - const: vbus-change
+ - const: attach-detach
+ - const: legacy-cable-detect
+ - const: try-snk-src-detect
+ - const: sig-tx
+ - const: sig-rx
+ - const: msg-tx
+ - const: msg-rx
+ - const: msg-tx-failed
+ - const: msg-tx-discarded
+ - const: msg-rx-discarded
+ - const: fr-swap
+
+ vdd-vbus-supply:
+ description: VBUS power supply.
+
+ vdd-pdphy-supply:
+ description: VDD regulator supply to the PDPHY.
+
+ port:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Contains a port which produces data-role switching messages.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - vdd-vbus-supply
+ - vdd-pdphy-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/usb/pd.h>
+
+ pm8150b {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8150b_typec: typec@1500 {
+ compatible = "qcom,pm8150b-typec";
+ reg = <0x1500>,
+ <0x1700>;
+
+ interrupts = <0x2 0x15 0x00 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x01 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x02 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x03 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x04 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x05 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x06 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x07 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x00 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x01 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x02 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x03 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x04 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x05 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x06 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x07 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-names = "or-rid-detect-change",
+ "vpd-detect",
+ "cc-state-change",
+ "vconn-oc",
+ "vbus-change",
+ "attach-detach",
+ "legacy-cable-detect",
+ "try-snk-src-detect",
+ "sig-tx",
+ "sig-rx",
+ "msg-tx",
+ "msg-rx",
+ "msg-tx-failed",
+ "msg-tx-discarded",
+ "msg-rx-discarded",
+ "fr-swap";
+
+ vdd-vbus-supply = <&pm8150b_vbus>;
+ vdd-pdphy-supply = <&vreg_l2a_3p1>;
+ connector {
+ compatible = "usb-c-connector";
+
+ power-role = "source";
+ data-role = "dual";
+ self-powered;
+
+ source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_DUAL_ROLE |
+ PDO_FIXED_USB_COMM | PDO_FIXED_DATA_SWAP)>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ pm8150b_typec_mux_out: endpoint {
+ remote-endpoint = <&qmpphy_typec_mux_in>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ pm8150b_typec_role_switch_out: endpoint {
+ remote-endpoint = <&dwc3_role_switch_in>;
+ };
+ };
+ };
+ };
+ };
+ };
+...
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 06/14] dt-bindings: mfd: qcom,spmi-pmic: Add typec to SPMI device types
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (4 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 05/14] dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-16 17:50 ` Krzysztof Kozlowski
2023-04-13 11:34 ` [PATCH v5 07/14] arm64: dts: qcom: sm8250: Define ports for qmpphy orientation-switching Bryan O'Donoghue
` (9 subsequent siblings)
15 siblings, 1 reply; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
Add the PMIC Type-C port driver to the list of devices.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
index 84620ebc1efe8..a689e8d451f9c 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
@@ -154,6 +154,10 @@ patternProperties:
type: object
$ref: /schemas/thermal/qcom,spmi-temp-alarm.yaml#
+ "^typec@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/usb/qcom,pmic-typec.yaml#
+
"^usb-detect@[0-9a-f]+$":
type: object
$ref: /schemas/extcon/qcom,pm8941-misc.yaml#
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 07/14] arm64: dts: qcom: sm8250: Define ports for qmpphy orientation-switching
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (5 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 06/14] dt-bindings: mfd: qcom,spmi-pmic: Add typec to SPMI device types Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description Bryan O'Donoghue
` (8 subsequent siblings)
15 siblings, 0 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
ports for orientation switching input and output. The individual board dts
files will instantiate port@0 and port@1 depending on the supported
feature-set.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
arch/arm64/boot/dts/qcom/sm8250.dtsi | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index a91d1175255e8..af16d3ba76b8e 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -3581,6 +3581,19 @@ dp_phy: dp-phy@88ea200 {
#phy-cells = <0>;
#clock-cells = <1>;
};
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+
+ port@1 {
+ reg = <1>;
+ };
+ };
};
usb_2_qmpphy: phy@88eb000 {
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (6 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 07/14] arm64: dts: qcom: sm8250: Define ports for qmpphy orientation-switching Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-13 20:28 ` kernel test robot
2023-04-15 13:51 ` kernel test robot
2023-04-13 11:34 ` [PATCH v5 09/14] arm64: dts: qcom: qrb5165-rb5: Switch on Type-C VBUS boost Bryan O'Donoghue
` (7 subsequent siblings)
15 siblings, 2 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
Type-C port management functionality lives inside of the PMIC block on
pm8150b.
The Type-C port management logic controls orientation detection, vbus/vconn
sense and to send/receive Type-C Power Domain messages.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
arch/arm64/boot/dts/qcom/pm8150b.dtsi | 40 +++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index 66752cc063d60..ffec8cfbd82a2 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -59,6 +59,46 @@ pm8150b_vbus: usb-vbus-regulator@1100 {
reg = <0x1100>;
};
+ pm8150b_typec: typec@1500 {
+ compatible = "qcom,pm8150b-typec";
+ reg = <0x1500>,
+ <0x1700>;
+ interrupts = <0x2 0x15 0x00 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x01 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x02 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x03 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x04 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x05 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x06 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x07 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x00 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x01 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x02 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x03 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x04 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x05 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x06 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x17 0x07 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "or-rid-detect-change",
+ "vpd-detect",
+ "cc-state-change",
+ "vconn-oc",
+ "vbus-change",
+ "attach-detach",
+ "legacy-cable-detect",
+ "try-snk-src-detect",
+ "sig-tx",
+ "sig-rx",
+ "msg-tx",
+ "msg-rx",
+ "msg-tx-failed",
+ "msg-tx-discarded",
+ "msg-rx-discarded",
+ "fr-swap";
+ vdd-pdphy-supply = <&vreg_l2a_3p1>;
+ vdd-vbus-supply = <&pm8150b_vbus>;
+ };
+
pm8150b_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 09/14] arm64: dts: qcom: qrb5165-rb5: Switch on Type-C VBUS boost
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (7 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 10/14] arm64: dts: qcom: qrb5165-rb5: Switch on basic TCPM Bryan O'Donoghue
` (6 subsequent siblings)
15 siblings, 0 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
Switch on VBUS for the Type-C port. We need to support a higher amperage
than the bootloader set 2 Amps.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
index dd924331b0eea..b326bdeeb7742 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -1338,3 +1338,9 @@ &qup_spi0_data_clk {
drive-strength = <6>;
bias-disable;
};
+
+&pm8150b_vbus {
+ regulator-min-microamp = <500000>;
+ regulator-max-microamp = <3000000>;
+ status = "okay";
+};
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 10/14] arm64: dts: qcom: qrb5165-rb5: Switch on basic TCPM
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (8 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 09/14] arm64: dts: qcom: qrb5165-rb5: Switch on Type-C VBUS boost Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 11/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for usb_1 Bryan O'Donoghue
` (5 subsequent siblings)
15 siblings, 0 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
Switch on TCPM for the RB5. Here we declare as a source only not a sink
since qrb5165 doesn't support powering exclusively from the type-c port.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
index b326bdeeb7742..1e0b6fd59abc9 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -9,6 +9,7 @@
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/usb/pd.h>
#include "sm8250.dtsi"
#include "pm8150.dtsi"
#include "pm8150b.dtsi"
@@ -1344,3 +1345,19 @@ &pm8150b_vbus {
regulator-max-microamp = <3000000>;
status = "okay";
};
+
+&pm8150b_typec {
+ status = "okay";
+ connector {
+ compatible = "usb-c-connector";
+
+ power-role = "source";
+ data-role = "dual";
+ self-powered;
+
+ source-pdos = <PDO_FIXED(5000, 3000,
+ PDO_FIXED_DUAL_ROLE |
+ PDO_FIXED_USB_COMM |
+ PDO_FIXED_DATA_SWAP)>;
+ };
+};
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 11/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for usb_1
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (9 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 10/14] arm64: dts: qcom: qrb5165-rb5: Switch on basic TCPM Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-22 14:52 ` Konrad Dybcio
2023-04-13 11:34 ` [PATCH v5 12/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM orientation-switch for usb_1_qmpphy Bryan O'Donoghue
` (4 subsequent siblings)
15 siblings, 1 reply; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
Switch on usb-role-switching for usb_1 via TCPM. We need to declare
usb-role-switch in &usb_1 and associate with the remote-endpoint in TCPM
which provides the necessary signal.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
index 1e0b6fd59abc9..b5cc45358a474 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -1273,7 +1273,13 @@ &usb_1 {
};
&usb_1_dwc3 {
- dr_mode = "peripheral";
+ dr_mode = "otg";
+ usb-role-switch;
+ port {
+ dwc3_role_switch_in: endpoint {
+ remote-endpoint = <&pm8150b_role_switch_out>;
+ };
+ };
};
&usb_1_hsphy {
@@ -1359,5 +1365,16 @@ connector {
PDO_FIXED_DUAL_ROLE |
PDO_FIXED_USB_COMM |
PDO_FIXED_DATA_SWAP)>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ pm8150b_role_switch_out: endpoint {
+ remote-endpoint = <&dwc3_role_switch_in>;
+ };
+ };
+ };
};
};
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 12/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM orientation-switch for usb_1_qmpphy
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (10 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 11/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for usb_1 Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 13/14] usb: typec: qcom: Add Qualcomm PMIC TCPM support Bryan O'Donoghue
` (3 subsequent siblings)
15 siblings, 0 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
Switch on USB orientation-switching for usb_1_qmp via TCPM. Detecting the
orientation switch is required to get the PHY to reset and bring-up the PHY
with the CC lines set to the appropriate lane.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
index b5cc45358a474..8935a8e327904 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -1295,6 +1295,14 @@ &usb_1_qmpphy {
vdda-phy-supply = <&vreg_l9a_1p2>;
vdda-pll-supply = <&vreg_l18a_0p92>;
+ orientation-switch;
+ ports {
+ port@1 {
+ qmpphy_typec_mux_in: endpoint {
+ remote-endpoint = <&pm8150b_typec_mux_out>;
+ };
+ };
+ };
};
&usb_2 {
@@ -1375,6 +1383,12 @@ pm8150b_role_switch_out: endpoint {
remote-endpoint = <&dwc3_role_switch_in>;
};
};
+ port@1 {
+ reg = <1>;
+ pm8150b_typec_mux_out: endpoint {
+ remote-endpoint = <&qmpphy_typec_mux_in>;
+ };
+ };
};
};
};
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 13/14] usb: typec: qcom: Add Qualcomm PMIC TCPM support
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (11 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 12/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM orientation-switch for usb_1_qmpphy Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-24 13:11 ` Heikki Krogerus
2023-04-13 11:34 ` [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection Bryan O'Donoghue
` (2 subsequent siblings)
15 siblings, 1 reply; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom
This commit adds a QCOM PMIC TCPM driver with an initial pm8150b
block.
qcom_pmic_virt_tcpm.c : Responsible for registering with TCPM and
arbitrates access to the Type-C and PDPHY hardware
blocks in one place.
This driver presents a virtual device to the Linux
TCPM layer.
qcom_pmic_pdphy.c: Rsponsible for interfacing with the PDPHY hardware and
processing power-delivery related calls from TCPM.
This hardware binding can be extended to facilitate
similar hardware in different PMICs.
qcom_pmic_typec.c: Responsible for notifying and processing Type-C
related calls from TCPM.
This hardware binding can be extended to facilitate
similar hardware in different PMICs.
This code provides all of the same functionality as the existing
qcom typec driver plus power-delivery as well.
As a result commit 6c8cf3695176 ("usb: typec: Add QCOM PMIC typec detection
driver") can be deleted entirely.
References code from Jonathan Marek, Jack Pham, Wesley Cheng, Hemant Kumar,
Guru Das Srinagesh and Ashay Jaiswal.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
MAINTAINERS | 10 +
drivers/usb/typec/Kconfig | 13 -
drivers/usb/typec/Makefile | 1 -
drivers/usb/typec/qcom-pmic-typec.c | 261 --------
drivers/usb/typec/tcpm/Kconfig | 11 +
drivers/usb/typec/tcpm/Makefile | 1 +
drivers/usb/typec/tcpm/qcom/Makefile | 6 +
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c | 362 +++++++++++
.../typec/tcpm/qcom/qcom_pmic_typec_pdphy.c | 528 +++++++++++++++++
.../typec/tcpm/qcom/qcom_pmic_typec_pdphy.h | 115 ++++
.../typec/tcpm/qcom/qcom_pmic_typec_port.c | 560 ++++++++++++++++++
.../typec/tcpm/qcom/qcom_pmic_typec_port.h | 194 ++++++
12 files changed, 1787 insertions(+), 275 deletions(-)
delete mode 100644 drivers/usb/typec/qcom-pmic-typec.c
create mode 100644 drivers/usb/typec/tcpm/qcom/Makefile
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 14a825f2bfb23..35d71858e768b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17530,6 +17530,16 @@ S: Maintained
F: Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
F: drivers/thermal/qcom/
+QUALCOMM TYPEC PORT MANAGER DRIVER
+M: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+L: linux-arm-msm@vger.kernel.org
+L: linux-usb@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/usb/qcom,pmic-*.yaml
+F: drivers/usb/typec/tcpm/qcom/
+F: include/dt-bindings/usb/typec/qcom,pmic-pdphy.h
+F: include/dt-bindings/usb/typec/qcom,pmic-typec.h
+
QUALCOMM VENUS VIDEO ACCELERATOR DRIVER
M: Stanimir Varbanov <stanimir.k.varbanov@gmail.com>
M: Vikash Garodia <quic_vgarodia@quicinc.com>
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index 831e7049977df..2f80c2792dbda 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -100,19 +100,6 @@ 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_PMIC
- tristate "Qualcomm PMIC USB Type-C driver"
- depends on ARCH_QCOM || COMPILE_TEST
- depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
- help
- Driver for supporting role switch over the Qualcomm PMIC. This will
- handle the USB Type-C role and orientation detection reported by the
- QCOM PMIC if the PMIC has the capability to handle USB Type-C
- detection.
-
- It will also enable the VBUS output to connected devices when a
- DFP connection is made.
-
config TYPEC_WUSB3801
tristate "Willsemi WUSB3801 Type-C port controller driver"
depends on I2C
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index 4a83dad51a6cf..7a368fea61bc9 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_TYPEC_UCSI) += ucsi/
obj-$(CONFIG_TYPEC_TPS6598X) += tipd/
obj-$(CONFIG_TYPEC_ANX7411) += anx7411.o
obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o
-obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom-pmic-typec.o
obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o
obj-$(CONFIG_TYPEC_RT1719) += rt1719.o
obj-$(CONFIG_TYPEC_WUSB3801) += wusb3801.o
diff --git a/drivers/usb/typec/qcom-pmic-typec.c b/drivers/usb/typec/qcom-pmic-typec.c
deleted file mode 100644
index 432ea62f1bab6..0000000000000
--- a/drivers/usb/typec/qcom-pmic-typec.c
+++ /dev/null
@@ -1,261 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/usb/role.h>
-#include <linux/usb/typec_mux.h>
-
-#define TYPEC_MISC_STATUS 0xb
-#define CC_ATTACHED BIT(0)
-#define CC_ORIENTATION BIT(1)
-#define SNK_SRC_MODE BIT(6)
-#define TYPEC_MODE_CFG 0x44
-#define TYPEC_DISABLE_CMD BIT(0)
-#define EN_SNK_ONLY BIT(1)
-#define EN_SRC_ONLY BIT(2)
-#define TYPEC_VCONN_CONTROL 0x46
-#define VCONN_EN_SRC BIT(0)
-#define VCONN_EN_VAL BIT(1)
-#define TYPEC_EXIT_STATE_CFG 0x50
-#define SEL_SRC_UPPER_REF BIT(2)
-#define TYPEC_INTR_EN_CFG_1 0x5e
-#define TYPEC_INTR_EN_CFG_1_MASK GENMASK(7, 0)
-
-struct qcom_pmic_typec {
- struct device *dev;
- struct regmap *regmap;
- u32 base;
-
- struct typec_port *port;
- struct usb_role_switch *role_sw;
-
- struct regulator *vbus_reg;
- bool vbus_enabled;
-};
-
-static void qcom_pmic_typec_enable_vbus_regulator(struct qcom_pmic_typec
- *qcom_usb, bool enable)
-{
- int ret;
-
- if (enable == qcom_usb->vbus_enabled)
- return;
-
- if (enable) {
- ret = regulator_enable(qcom_usb->vbus_reg);
- if (ret)
- return;
- } else {
- ret = regulator_disable(qcom_usb->vbus_reg);
- if (ret)
- return;
- }
- qcom_usb->vbus_enabled = enable;
-}
-
-static void qcom_pmic_typec_check_connection(struct qcom_pmic_typec *qcom_usb)
-{
- enum typec_orientation orientation;
- enum usb_role role;
- unsigned int stat;
- bool enable_vbus;
-
- regmap_read(qcom_usb->regmap, qcom_usb->base + TYPEC_MISC_STATUS,
- &stat);
-
- if (stat & CC_ATTACHED) {
- orientation = (stat & CC_ORIENTATION) ?
- TYPEC_ORIENTATION_REVERSE :
- TYPEC_ORIENTATION_NORMAL;
- typec_set_orientation(qcom_usb->port, orientation);
-
- role = (stat & SNK_SRC_MODE) ? USB_ROLE_HOST : USB_ROLE_DEVICE;
- if (role == USB_ROLE_HOST)
- enable_vbus = true;
- else
- enable_vbus = false;
- } else {
- role = USB_ROLE_NONE;
- enable_vbus = false;
- }
-
- qcom_pmic_typec_enable_vbus_regulator(qcom_usb, enable_vbus);
- usb_role_switch_set_role(qcom_usb->role_sw, role);
-}
-
-static irqreturn_t qcom_pmic_typec_interrupt(int irq, void *_qcom_usb)
-{
- struct qcom_pmic_typec *qcom_usb = _qcom_usb;
-
- qcom_pmic_typec_check_connection(qcom_usb);
- return IRQ_HANDLED;
-}
-
-static void qcom_pmic_typec_typec_hw_init(struct qcom_pmic_typec *qcom_usb,
- enum typec_port_type type)
-{
- u8 mode = 0;
-
- regmap_update_bits(qcom_usb->regmap,
- qcom_usb->base + TYPEC_INTR_EN_CFG_1,
- TYPEC_INTR_EN_CFG_1_MASK, 0);
-
- if (type == TYPEC_PORT_SRC)
- mode = EN_SRC_ONLY;
- else if (type == TYPEC_PORT_SNK)
- mode = EN_SNK_ONLY;
-
- regmap_update_bits(qcom_usb->regmap, qcom_usb->base + TYPEC_MODE_CFG,
- EN_SNK_ONLY | EN_SRC_ONLY, mode);
-
- regmap_update_bits(qcom_usb->regmap,
- qcom_usb->base + TYPEC_VCONN_CONTROL,
- VCONN_EN_SRC | VCONN_EN_VAL, VCONN_EN_SRC);
- regmap_update_bits(qcom_usb->regmap,
- qcom_usb->base + TYPEC_EXIT_STATE_CFG,
- SEL_SRC_UPPER_REF, SEL_SRC_UPPER_REF);
-}
-
-static int qcom_pmic_typec_probe(struct platform_device *pdev)
-{
- struct qcom_pmic_typec *qcom_usb;
- struct device *dev = &pdev->dev;
- struct fwnode_handle *fwnode;
- struct typec_capability cap;
- const char *buf;
- int ret, irq, role;
- u32 reg;
-
- ret = device_property_read_u32(dev, "reg", ®);
- if (ret < 0) {
- dev_err(dev, "missing base address\n");
- return ret;
- }
-
- qcom_usb = devm_kzalloc(dev, sizeof(*qcom_usb), GFP_KERNEL);
- if (!qcom_usb)
- return -ENOMEM;
-
- qcom_usb->dev = dev;
- qcom_usb->base = reg;
-
- qcom_usb->regmap = dev_get_regmap(dev->parent, NULL);
- if (!qcom_usb->regmap) {
- dev_err(dev, "Failed to get regmap\n");
- return -EINVAL;
- }
-
- qcom_usb->vbus_reg = devm_regulator_get(qcom_usb->dev, "usb_vbus");
- if (IS_ERR(qcom_usb->vbus_reg))
- return PTR_ERR(qcom_usb->vbus_reg);
-
- fwnode = device_get_named_child_node(dev, "connector");
- if (!fwnode)
- return -EINVAL;
-
- ret = fwnode_property_read_string(fwnode, "power-role", &buf);
- if (!ret) {
- role = typec_find_port_power_role(buf);
- if (role < 0)
- role = TYPEC_PORT_SNK;
- } else {
- role = TYPEC_PORT_SNK;
- }
- cap.type = role;
-
- ret = fwnode_property_read_string(fwnode, "data-role", &buf);
- if (!ret) {
- role = typec_find_port_data_role(buf);
- if (role < 0)
- role = TYPEC_PORT_UFP;
- } else {
- role = TYPEC_PORT_UFP;
- }
- cap.data = role;
-
- cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
- cap.fwnode = fwnode;
- qcom_usb->port = typec_register_port(dev, &cap);
- if (IS_ERR(qcom_usb->port)) {
- ret = PTR_ERR(qcom_usb->port);
- dev_err(dev, "Failed to register type c port %d\n", ret);
- goto err_put_node;
- }
- fwnode_handle_put(fwnode);
-
- qcom_usb->role_sw = fwnode_usb_role_switch_get(dev_fwnode(qcom_usb->dev));
- if (IS_ERR(qcom_usb->role_sw)) {
- ret = dev_err_probe(dev, PTR_ERR(qcom_usb->role_sw),
- "failed to get role switch\n");
- goto err_typec_port;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- goto err_usb_role_sw;
-
- ret = devm_request_threaded_irq(qcom_usb->dev, irq, NULL,
- qcom_pmic_typec_interrupt, IRQF_ONESHOT,
- "qcom-pmic-typec", qcom_usb);
- if (ret) {
- dev_err(&pdev->dev, "Could not request IRQ\n");
- goto err_usb_role_sw;
- }
-
- platform_set_drvdata(pdev, qcom_usb);
- qcom_pmic_typec_typec_hw_init(qcom_usb, cap.type);
- qcom_pmic_typec_check_connection(qcom_usb);
-
- return 0;
-
-err_usb_role_sw:
- usb_role_switch_put(qcom_usb->role_sw);
-err_typec_port:
- typec_unregister_port(qcom_usb->port);
-err_put_node:
- fwnode_handle_put(fwnode);
-
- return ret;
-}
-
-static int qcom_pmic_typec_remove(struct platform_device *pdev)
-{
- struct qcom_pmic_typec *qcom_usb = platform_get_drvdata(pdev);
-
- usb_role_switch_set_role(qcom_usb->role_sw, USB_ROLE_NONE);
- qcom_pmic_typec_enable_vbus_regulator(qcom_usb, 0);
-
- typec_unregister_port(qcom_usb->port);
- usb_role_switch_put(qcom_usb->role_sw);
-
- return 0;
-}
-
-static const struct of_device_id qcom_pmic_typec_table[] = {
- { .compatible = "qcom,pm8150b-usb-typec" },
- { }
-};
-MODULE_DEVICE_TABLE(of, qcom_pmic_typec_table);
-
-static struct platform_driver qcom_pmic_typec = {
- .driver = {
- .name = "qcom,pmic-typec",
- .of_match_table = qcom_pmic_typec_table,
- },
- .probe = qcom_pmic_typec_probe,
- .remove = qcom_pmic_typec_remove,
-};
-module_platform_driver(qcom_pmic_typec);
-
-MODULE_DESCRIPTION("QCOM PMIC USB type C driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
index e6b88ca4a4b94..5d393f520fc2f 100644
--- a/drivers/usb/typec/tcpm/Kconfig
+++ b/drivers/usb/typec/tcpm/Kconfig
@@ -76,4 +76,15 @@ config TYPEC_WCOVE
To compile this driver as module, choose M here: the module will be
called typec_wcove.ko
+config TYPEC_QCOM_PMIC
+ tristate "Qualcomm PMIC USB Type-C Port Controller Manager driver"
+ depends on ARCH_QCOM || COMPILE_TEST
+ help
+ A Type-C port and Power Delivery driver which aggregates two
+ discrete pieces of silicon in the PM8150b PMIC block: the
+ Type-C port controller and the Power Delivery PHY.
+
+ This driver enables Type-C role switching, orientation, Alternate
+ mode and Power Delivery support both for VBUS and VCONN.
+
endif # TYPEC_TCPM
diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile
index 08e57bb499cbc..7a8cad0c0bdb4 100644
--- a/drivers/usb/typec/tcpm/Makefile
+++ b/drivers/usb/typec/tcpm/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_TYPEC_MT6360) += tcpci_mt6360.o
obj-$(CONFIG_TYPEC_TCPCI_MT6370) += tcpci_mt6370.o
obj-$(CONFIG_TYPEC_TCPCI_MAXIM) += tcpci_maxim.o
tcpci_maxim-y += tcpci_maxim_core.o maxim_contaminant.o
+obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom/
diff --git a/drivers/usb/typec/tcpm/qcom/Makefile b/drivers/usb/typec/tcpm/qcom/Makefile
new file mode 100644
index 0000000000000..dc1e8832e197a
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom_pmic_tcpm.o
+qcom_pmic_tcpm-y += qcom_pmic_typec.o \
+ qcom_pmic_typec_port.o \
+ qcom_pmic_typec_pdphy.o
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
new file mode 100644
index 0000000000000..1e663988535f4
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/role.h>
+#include <linux/usb/tcpm.h>
+#include <linux/usb/typec_mux.h>
+#include "qcom_pmic_typec_pdphy.h"
+#include "qcom_pmic_typec_port.h"
+
+struct pmic_typec_resources {
+ struct pmic_typec_pdphy_resources *pdphy_res;
+ struct pmic_typec_port_resources *port_res;
+};
+
+struct pmic_typec {
+ struct device *dev;
+ struct tcpm_port *tcpm_port;
+ struct tcpc_dev tcpc;
+ struct pmic_typec_pdphy *pmic_typec_pdphy;
+ struct pmic_typec_port *pmic_typec_port;
+ bool vbus_enabled;
+ struct mutex lock; /* VBUS state serialization */
+};
+
+#define tcpc_to_tcpm(_tcpc_) container_of(_tcpc_, struct pmic_typec, tcpc)
+
+static int qcom_pmic_typec_get_vbus(struct tcpc_dev *tcpc)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+ int ret;
+
+ mutex_lock(&tcpm->lock);
+ ret = tcpm->vbus_enabled || qcom_pmic_typec_port_get_vbus(tcpm->pmic_typec_port);
+ mutex_unlock(&tcpm->lock);
+
+ return ret;
+}
+
+static int qcom_pmic_typec_set_vbus(struct tcpc_dev *tcpc, bool on, bool sink)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+ int ret = 0;
+
+ mutex_lock(&tcpm->lock);
+ if (tcpm->vbus_enabled == on)
+ goto done;
+
+ ret = qcom_pmic_typec_port_set_vbus(tcpm->pmic_typec_port, on);
+ if (ret)
+ goto done;
+
+ tcpm->vbus_enabled = on;
+ tcpm_vbus_change(tcpm->tcpm_port);
+
+done:
+ dev_dbg(tcpm->dev, "set_vbus set: %d result %d\n", on, ret);
+ mutex_unlock(&tcpm->lock);
+
+ return ret;
+}
+
+static int qcom_pmic_typec_set_vconn(struct tcpc_dev *tcpc, bool on)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_port_set_vconn(tcpm->pmic_typec_port, on);
+}
+
+static int qcom_pmic_typec_get_cc(struct tcpc_dev *tcpc,
+ enum typec_cc_status *cc1,
+ enum typec_cc_status *cc2)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_port_get_cc(tcpm->pmic_typec_port, cc1, cc2);
+}
+
+static int qcom_pmic_typec_set_cc(struct tcpc_dev *tcpc,
+ enum typec_cc_status cc)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_port_set_cc(tcpm->pmic_typec_port, cc);
+}
+
+static int qcom_pmic_typec_set_polarity(struct tcpc_dev *tcpc,
+ enum typec_cc_polarity pol)
+{
+ /* Polarity is set separately by phy-qcom-qmp.c */
+ return 0;
+}
+
+static int qcom_pmic_typec_start_toggling(struct tcpc_dev *tcpc,
+ enum typec_port_type port_type,
+ enum typec_cc_status cc)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_port_start_toggling(tcpm->pmic_typec_port,
+ port_type, cc);
+}
+
+static int qcom_pmic_typec_set_roles(struct tcpc_dev *tcpc, bool attached,
+ enum typec_role power_role,
+ enum typec_data_role data_role)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_pdphy_set_roles(tcpm->pmic_typec_pdphy,
+ data_role, power_role);
+}
+
+static int qcom_pmic_typec_set_pd_rx(struct tcpc_dev *tcpc, bool on)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_pdphy_set_pd_rx(tcpm->pmic_typec_pdphy, on);
+}
+
+static int qcom_pmic_typec_pd_transmit(struct tcpc_dev *tcpc,
+ enum tcpm_transmit_type type,
+ const struct pd_message *msg,
+ unsigned int negotiated_rev)
+{
+ struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
+
+ return qcom_pmic_typec_pdphy_pd_transmit(tcpm->pmic_typec_pdphy, type,
+ msg, negotiated_rev);
+}
+
+static int qcom_pmic_typec_init(struct tcpc_dev *tcpc)
+{
+ return 0;
+}
+
+static int qcom_pmic_typec_probe(struct platform_device *pdev)
+{
+ struct pmic_typec *tcpm;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct pmic_typec_resources *res;
+ struct regmap *regmap;
+ u32 base[2];
+ int ret;
+
+ res = of_device_get_match_data(dev);
+ if (!res)
+ return -ENODEV;
+
+ tcpm = devm_kzalloc(dev, sizeof(*tcpm), GFP_KERNEL);
+ if (!tcpm)
+ return -ENOMEM;
+
+ tcpm->dev = dev;
+ tcpm->tcpc.init = qcom_pmic_typec_init;
+ tcpm->tcpc.get_vbus = qcom_pmic_typec_get_vbus;
+ tcpm->tcpc.set_vbus = qcom_pmic_typec_set_vbus;
+ tcpm->tcpc.set_cc = qcom_pmic_typec_set_cc;
+ tcpm->tcpc.get_cc = qcom_pmic_typec_get_cc;
+ tcpm->tcpc.set_polarity = qcom_pmic_typec_set_polarity;
+ tcpm->tcpc.set_vconn = qcom_pmic_typec_set_vconn;
+ tcpm->tcpc.start_toggling = qcom_pmic_typec_start_toggling;
+ tcpm->tcpc.set_pd_rx = qcom_pmic_typec_set_pd_rx;
+ tcpm->tcpc.set_roles = qcom_pmic_typec_set_roles;
+ tcpm->tcpc.pd_transmit = qcom_pmic_typec_pd_transmit;
+
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get regmap\n");
+ return -ENODEV;
+ }
+
+ ret = of_property_read_u32_array(np, "reg", base, 2);
+ if (ret)
+ return ret;
+
+ tcpm->pmic_typec_port = qcom_pmic_typec_port_alloc(dev);
+ if (IS_ERR(tcpm->pmic_typec_port))
+ return PTR_ERR(tcpm->pmic_typec_port);
+
+ tcpm->pmic_typec_pdphy = qcom_pmic_typec_pdphy_alloc(dev);
+ if (IS_ERR(tcpm->pmic_typec_pdphy))
+ return PTR_ERR(tcpm->pmic_typec_pdphy);
+
+ ret = qcom_pmic_typec_port_probe(pdev, tcpm->pmic_typec_port,
+ res->port_res, regmap, base[0]);
+ if (ret)
+ return ret;
+
+ ret = qcom_pmic_typec_pdphy_probe(pdev, tcpm->pmic_typec_pdphy,
+ res->pdphy_res, regmap, base[1]);
+ if (ret)
+ return ret;
+
+ mutex_init(&tcpm->lock);
+ platform_set_drvdata(pdev, tcpm);
+
+ tcpm->tcpc.fwnode = device_get_named_child_node(tcpm->dev, "connector");
+ if (IS_ERR(tcpm->tcpc.fwnode))
+ return PTR_ERR(tcpm->tcpc.fwnode);
+
+ tcpm->tcpm_port = tcpm_register_port(tcpm->dev, &tcpm->tcpc);
+ if (IS_ERR(tcpm->tcpm_port)) {
+ ret = PTR_ERR(tcpm->tcpm_port);
+ goto fwnode_remove;
+ }
+
+ ret = qcom_pmic_typec_port_start(tcpm->pmic_typec_port,
+ tcpm->tcpm_port);
+ if (ret)
+ goto fwnode_remove;
+
+ ret = qcom_pmic_typec_pdphy_start(tcpm->pmic_typec_pdphy,
+ tcpm->tcpm_port);
+ if (ret)
+ goto fwnode_remove;
+
+ return 0;
+
+fwnode_remove:
+ fwnode_remove_software_node(tcpm->tcpc.fwnode);
+
+ return ret;
+}
+
+static int qcom_pmic_typec_remove(struct platform_device *pdev)
+{
+ struct pmic_typec *tcpm = platform_get_drvdata(pdev);
+
+ qcom_pmic_typec_pdphy_stop(tcpm->pmic_typec_pdphy);
+ qcom_pmic_typec_port_stop(tcpm->pmic_typec_port);
+ tcpm_unregister_port(tcpm->tcpm_port);
+ fwnode_remove_software_node(tcpm->tcpc.fwnode);
+
+ return 0;
+}
+
+static struct pmic_typec_pdphy_resources pm8150b_pdphy_res = {
+ .irq_params = {
+ {
+ .virq = PMIC_PDPHY_SIG_TX_IRQ,
+ .irq_name = "sig-tx",
+ },
+ {
+ .virq = PMIC_PDPHY_SIG_RX_IRQ,
+ .irq_name = "sig-rx",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_TX_IRQ,
+ .irq_name = "msg-tx",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_RX_IRQ,
+ .irq_name = "msg-rx",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_TX_FAIL_IRQ,
+ .irq_name = "msg-tx-failed",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_TX_DISCARD_IRQ,
+ .irq_name = "msg-tx-discarded",
+ },
+ {
+ .virq = PMIC_PDPHY_MSG_RX_DISCARD_IRQ,
+ .irq_name = "msg-rx-discarded",
+ },
+ },
+ .nr_irqs = 7,
+};
+
+static struct pmic_typec_port_resources pm8150b_port_res = {
+ .irq_params = {
+ {
+ .irq_name = "vpd-detect",
+ .virq = PMIC_TYPEC_VPD_IRQ,
+ },
+
+ {
+ .irq_name = "cc-state-change",
+ .virq = PMIC_TYPEC_CC_STATE_IRQ,
+ },
+ {
+ .irq_name = "vconn-oc",
+ .virq = PMIC_TYPEC_VCONN_OC_IRQ,
+ },
+
+ {
+ .irq_name = "vbus-change",
+ .virq = PMIC_TYPEC_VBUS_IRQ,
+ },
+
+ {
+ .irq_name = "attach-detach",
+ .virq = PMIC_TYPEC_ATTACH_DETACH_IRQ,
+ },
+ {
+ .irq_name = "legacy-cable-detect",
+ .virq = PMIC_TYPEC_LEGACY_CABLE_IRQ,
+ },
+
+ {
+ .irq_name = "try-snk-src-detect",
+ .virq = PMIC_TYPEC_TRY_SNK_SRC_IRQ,
+ },
+ },
+ .nr_irqs = 7,
+};
+
+struct pmic_typec_resources pm8150b_typec_res = {
+ .pdphy_res = &pm8150b_pdphy_res,
+ .port_res = &pm8150b_port_res,
+};
+
+static const struct of_device_id qcom_pmic_typec_table[] = {
+ { .compatible = "qcom,pm8150b-typec", .data = &pm8150b_typec_res },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qcom_pmic_typec_table);
+
+static struct platform_driver qcom_pmic_typec_platform_driver = {
+ .driver = {
+ .name = "qcom,pmic-typec",
+ .of_match_table = qcom_pmic_typec_table,
+ },
+ .probe = qcom_pmic_typec_probe,
+ .remove = qcom_pmic_typec_remove,
+};
+
+static int __init qcom_pmic_typec_module_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&qcom_pmic_typec_platform_driver);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+module_init(qcom_pmic_typec_module_init);
+
+static void __exit qcom_pmic_typec_module_exit(void)
+{
+ platform_driver_unregister(&qcom_pmic_typec_platform_driver);
+}
+module_exit(qcom_pmic_typec_module_exit);
+
+MODULE_DESCRIPTION("QCOM PMIC USB Type-C Port Manager Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
new file mode 100644
index 0000000000000..02f437b068bea
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
@@ -0,0 +1,528 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/pd.h>
+#include <linux/usb/tcpm.h>
+#include "qcom_pmic_typec_pdphy.h"
+
+struct pmic_typec_pdphy_irq_data {
+ int virq;
+ int irq;
+ struct pmic_typec_pdphy *pmic_typec_pdphy;
+};
+
+struct pmic_typec_pdphy {
+ struct device *dev;
+ struct tcpm_port *tcpm_port;
+ struct regmap *regmap;
+ u32 base;
+
+ unsigned int nr_irqs;
+ struct pmic_typec_pdphy_irq_data *irq_data;
+
+ struct work_struct reset_work;
+ struct work_struct receive_work;
+ struct regulator *vdd_pdphy;
+ spinlock_t lock; /* Register atomicity */
+};
+
+static void qcom_pmic_typec_pdphy_reset_on(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ int ret;
+
+ /* Terminate TX */
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0);
+ if (ret)
+ goto err;
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG, 0);
+ if (ret)
+ goto err;
+
+ return;
+err:
+ dev_err(dev, "pd_reset_on error\n");
+}
+
+static void qcom_pmic_typec_pdphy_reset_off(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ int ret;
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG,
+ FRAME_FILTER_EN_SOP | FRAME_FILTER_EN_HARD_RESET);
+ if (ret)
+ dev_err(dev, "pd_reset_off error\n");
+}
+
+static void qcom_pmic_typec_pdphy_sig_reset_work(struct work_struct *work)
+{
+ struct pmic_typec_pdphy *pmic_typec_pdphy = container_of(work, struct pmic_typec_pdphy,
+ reset_work);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
+ qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
+
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ tcpm_pd_hard_reset(pmic_typec_pdphy->tcpm_port);
+}
+
+static int
+qcom_pmic_typec_pdphy_clear_tx_control_reg(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ unsigned int val;
+ int ret;
+
+ /* Clear TX control register */
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0);
+ if (ret)
+ goto done;
+
+ /* Perform readback to ensure sufficient delay for command to latch */
+ ret = regmap_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, &val);
+
+done:
+ if (ret)
+ dev_err(dev, "pd_clear_tx_control_reg: clear tx flag\n");
+
+ return ret;
+}
+
+static int
+qcom_pmic_typec_pdphy_pd_transmit_signal(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ enum tcpm_transmit_type type,
+ unsigned int negotiated_rev)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ unsigned int val;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ /* Clear TX control register */
+ ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
+ if (ret)
+ goto done;
+
+ val = TX_CONTROL_SEND_SIGNAL;
+ if (negotiated_rev == PD_REV30)
+ val |= TX_CONTROL_RETRY_COUNT(2);
+ else
+ val |= TX_CONTROL_RETRY_COUNT(3);
+
+ if (type == TCPC_TX_CABLE_RESET || type == TCPC_TX_HARD_RESET)
+ val |= TX_CONTROL_FRAME_TYPE(1);
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val);
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ dev_vdbg(dev, "pd_transmit_signal: type %d negotiate_rev %d send %d\n",
+ type, negotiated_rev, ret);
+
+ return ret;
+}
+
+static int
+qcom_pmic_typec_pdphy_pd_transmit_payload(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ enum tcpm_transmit_type type,
+ const struct pd_message *msg,
+ unsigned int negotiated_rev)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ unsigned int val, hdr_len, txbuf_len, txsize_len;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ ret = regmap_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG,
+ &val);
+ if (ret)
+ goto done;
+
+ if (val) {
+ dev_err(dev, "pd_transmit_payload: RX message pending\n");
+ ret = -EBUSY;
+ goto done;
+ }
+
+ /* Clear TX control register */
+ ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
+ if (ret)
+ goto done;
+
+ hdr_len = sizeof(msg->header);
+ txbuf_len = pd_header_cnt_le(msg->header) * 4;
+ txsize_len = hdr_len + txbuf_len - 1;
+
+ /* Write message header sizeof(u16) to USB_PDPHY_TX_BUFFER_HDR_REG */
+ ret = regmap_bulk_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_HDR_REG,
+ &msg->header, hdr_len);
+ if (ret)
+ goto done;
+
+ /* Write payload to USB_PDPHY_TX_BUFFER_DATA_REG for txbuf_len */
+ if (txbuf_len) {
+ ret = regmap_bulk_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_DATA_REG,
+ &msg->payload, txbuf_len);
+ if (ret)
+ goto done;
+ }
+
+ /* Write total length ((header + data) - 1) to USB_PDPHY_TX_SIZE_REG */
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_SIZE_REG,
+ txsize_len);
+ if (ret)
+ goto done;
+
+ /* Clear TX control register */
+ ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
+ if (ret)
+ goto done;
+
+ /* Initiate transmit with retry count as indicated by PD revision */
+ val = TX_CONTROL_FRAME_TYPE(type) | TX_CONTROL_SEND_MSG;
+ if (pd_header_rev(msg->header) == PD_REV30)
+ val |= TX_CONTROL_RETRY_COUNT(2);
+ else
+ val |= TX_CONTROL_RETRY_COUNT(3);
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val);
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ if (ret) {
+ dev_err(dev, "pd_transmit_payload: %d hdr %*ph data %*ph ret %d\n",
+ ret, hdr_len, &msg->header, txbuf_len, &msg->payload, ret);
+ }
+
+ return ret;
+}
+
+int qcom_pmic_typec_pdphy_pd_transmit(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ enum tcpm_transmit_type type,
+ const struct pd_message *msg,
+ unsigned int negotiated_rev)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ int ret;
+
+ if (msg) {
+ ret = qcom_pmic_typec_pdphy_pd_transmit_payload(pmic_typec_pdphy,
+ type, msg,
+ negotiated_rev);
+ } else {
+ ret = qcom_pmic_typec_pdphy_pd_transmit_signal(pmic_typec_pdphy,
+ type,
+ negotiated_rev);
+ }
+
+ if (ret)
+ dev_dbg(dev, "pd_transmit: type %x result %d\n", type, ret);
+
+ return ret;
+}
+
+static void qcom_pmic_typec_pdphy_pd_receive(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ struct pd_message msg;
+ unsigned int size, rx_status;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ ret = regmap_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_SIZE_REG, &size);
+ if (ret)
+ goto done;
+
+ /* If we received a subsequent RX sig this value can be zero */
+ if ((size < 1 || size > sizeof(msg.payload))) {
+ dev_dbg(dev, "pd_receive: invalid size %d\n", size);
+ goto done;
+ }
+
+ size += 1;
+ ret = regmap_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_STATUS_REG,
+ &rx_status);
+
+ if (ret)
+ goto done;
+
+ ret = regmap_bulk_read(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_BUFFER_REG,
+ (u8 *)&msg, size);
+ if (ret)
+ goto done;
+
+ /* Return ownership of RX buffer to hardware */
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, 0);
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ if (!ret) {
+ dev_vdbg(dev, "pd_receive: handing %d bytes to tcpm\n", size);
+ tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg);
+ }
+}
+
+static irqreturn_t qcom_pmic_typec_pdphy_isr(int irq, void *dev_id)
+{
+ struct pmic_typec_pdphy_irq_data *irq_data = dev_id;
+ struct pmic_typec_pdphy *pmic_typec_pdphy = irq_data->pmic_typec_pdphy;
+ struct device *dev = pmic_typec_pdphy->dev;
+
+ switch (irq_data->virq) {
+ case PMIC_PDPHY_SIG_TX_IRQ:
+ dev_err(dev, "isr: tx_sig\n");
+ break;
+ case PMIC_PDPHY_SIG_RX_IRQ:
+ schedule_work(&pmic_typec_pdphy->reset_work);
+ break;
+ case PMIC_PDPHY_MSG_TX_IRQ:
+ tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
+ TCPC_TX_SUCCESS);
+ break;
+ case PMIC_PDPHY_MSG_RX_IRQ:
+ qcom_pmic_typec_pdphy_pd_receive(pmic_typec_pdphy);
+ break;
+ case PMIC_PDPHY_MSG_TX_FAIL_IRQ:
+ tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
+ TCPC_TX_FAILED);
+ break;
+ case PMIC_PDPHY_MSG_TX_DISCARD_IRQ:
+ tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
+ TCPC_TX_DISCARDED);
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+int qcom_pmic_typec_pdphy_set_pd_rx(struct pmic_typec_pdphy *pmic_typec_pdphy, bool on)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, !on);
+
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ dev_dbg(pmic_typec_pdphy->dev, "set_pd_rx: %s\n", on ? "on" : "off");
+
+ return ret;
+}
+
+int qcom_pmic_typec_pdphy_set_roles(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ bool data_role_host, bool power_role_src)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
+
+ ret = regmap_update_bits(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG,
+ MSG_CONFIG_PORT_DATA_ROLE |
+ MSG_CONFIG_PORT_POWER_ROLE,
+ data_role_host << 3 | power_role_src << 2);
+
+ spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
+
+ dev_dbg(dev, "pdphy_set_roles: data_role_host=%d power_role_src=%d\n",
+ data_role_host, power_role_src);
+
+ return ret;
+}
+
+static int qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ struct device *dev = pmic_typec_pdphy->dev;
+ int ret;
+
+ ret = regulator_enable(pmic_typec_pdphy->vdd_pdphy);
+ if (ret)
+ return ret;
+
+ /* PD 2.0, DR=TYPEC_DEVICE, PR=TYPEC_SINK */
+ ret = regmap_update_bits(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG,
+ MSG_CONFIG_SPEC_REV_MASK, PD_REV20);
+ if (ret)
+ goto done;
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0);
+ if (ret)
+ goto done;
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG,
+ CONTROL_ENABLE);
+ if (ret)
+ goto done;
+
+ qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
+done:
+ if (ret) {
+ regulator_disable(pmic_typec_pdphy->vdd_pdphy);
+ dev_err(dev, "pdphy_enable fail %d\n", ret);
+ }
+
+ return ret;
+}
+
+static int qcom_pmic_typec_pdphy_disable(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ int ret;
+
+ qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
+
+ ret = regmap_write(pmic_typec_pdphy->regmap,
+ pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0);
+
+ regulator_disable(pmic_typec_pdphy->vdd_pdphy);
+
+ return ret;
+}
+
+static int pmic_typec_pdphy_reset(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ int ret;
+
+ ret = qcom_pmic_typec_pdphy_disable(pmic_typec_pdphy);
+ if (ret)
+ goto done;
+
+ usleep_range(400, 500);
+ ret = qcom_pmic_typec_pdphy_enable(pmic_typec_pdphy);
+done:
+ return ret;
+}
+
+int qcom_pmic_typec_pdphy_start(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ struct tcpm_port *tcpm_port)
+{
+ int i;
+ int ret;
+
+ pmic_typec_pdphy->tcpm_port = tcpm_port;
+
+ ret = pmic_typec_pdphy_reset(pmic_typec_pdphy);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
+ enable_irq(pmic_typec_pdphy->irq_data[i].irq);
+
+ return 0;
+}
+
+void qcom_pmic_typec_pdphy_stop(struct pmic_typec_pdphy *pmic_typec_pdphy)
+{
+ int i;
+
+ for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
+ disable_irq(pmic_typec_pdphy->irq_data[i].irq);
+
+ qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
+}
+
+struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev)
+{
+ return devm_kzalloc(dev, sizeof(struct pmic_typec_pdphy), GFP_KERNEL);
+}
+
+int qcom_pmic_typec_pdphy_probe(struct platform_device *pdev,
+ struct pmic_typec_pdphy *pmic_typec_pdphy,
+ struct pmic_typec_pdphy_resources *res,
+ struct regmap *regmap,
+ u32 base)
+{
+ struct device *dev = &pdev->dev;
+ struct pmic_typec_pdphy_irq_data *irq_data;
+ int i, ret, irq;
+
+ if (!res->nr_irqs || res->nr_irqs > PMIC_PDPHY_MAX_IRQS)
+ return -EINVAL;
+
+ irq_data = devm_kzalloc(dev, sizeof(*irq_data) * res->nr_irqs,
+ GFP_KERNEL);
+ if (!irq_data)
+ return -ENOMEM;
+
+ pmic_typec_pdphy->vdd_pdphy = devm_regulator_get(dev, "vdd-pdphy");
+ if (IS_ERR(pmic_typec_pdphy->vdd_pdphy))
+ return PTR_ERR(pmic_typec_pdphy->vdd_pdphy);
+
+ pmic_typec_pdphy->dev = dev;
+ pmic_typec_pdphy->base = base;
+ pmic_typec_pdphy->regmap = regmap;
+ pmic_typec_pdphy->nr_irqs = res->nr_irqs;
+ pmic_typec_pdphy->irq_data = irq_data;
+ spin_lock_init(&pmic_typec_pdphy->lock);
+ INIT_WORK(&pmic_typec_pdphy->reset_work, qcom_pmic_typec_pdphy_sig_reset_work);
+
+ for (i = 0; i < res->nr_irqs; i++, irq_data++) {
+ irq = platform_get_irq_byname(pdev, res->irq_params[i].irq_name);
+ if (irq < 0)
+ return irq;
+
+ irq_data->pmic_typec_pdphy = pmic_typec_pdphy;
+ irq_data->irq = irq;
+ irq_data->virq = res->irq_params[i].virq;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ qcom_pmic_typec_pdphy_isr,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
+ res->irq_params[i].irq_name,
+ irq_data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
new file mode 100644
index 0000000000000..ebd33c9ae0606
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+#ifndef __QCOM_PMIC_PDPHY_H__
+#define __QCOM_PMIC_PDPHY_H__
+
+#define USB_PDPHY_MAX_DATA_OBJ_LEN 28
+#define USB_PDPHY_MSG_HDR_LEN 2
+
+/* PD PHY register offsets and bit fields */
+#define USB_PDPHY_MSG_CONFIG_REG 0x40
+#define MSG_CONFIG_PORT_DATA_ROLE BIT(3)
+#define MSG_CONFIG_PORT_POWER_ROLE BIT(2)
+#define MSG_CONFIG_SPEC_REV_MASK (BIT(1) | BIT(0))
+
+#define USB_PDPHY_EN_CONTROL_REG 0x46
+#define CONTROL_ENABLE BIT(0)
+
+#define USB_PDPHY_RX_STATUS_REG 0x4A
+#define RX_FRAME_TYPE (BIT(0) | BIT(1) | BIT(2))
+
+#define USB_PDPHY_FRAME_FILTER_REG 0x4C
+#define FRAME_FILTER_EN_HARD_RESET BIT(5)
+#define FRAME_FILTER_EN_SOP BIT(0)
+
+#define USB_PDPHY_TX_SIZE_REG 0x42
+#define TX_SIZE_MASK 0xF
+
+#define USB_PDPHY_TX_CONTROL_REG 0x44
+#define TX_CONTROL_RETRY_COUNT(n) (((n) & 0x3) << 5)
+#define TX_CONTROL_FRAME_TYPE(n) (((n) & 0x7) << 2)
+#define TX_CONTROL_FRAME_TYPE_CABLE_RESET (0x1 << 2)
+#define TX_CONTROL_SEND_SIGNAL BIT(1)
+#define TX_CONTROL_SEND_MSG BIT(0)
+
+#define USB_PDPHY_RX_SIZE_REG 0x48
+
+#define USB_PDPHY_RX_ACKNOWLEDGE_REG 0x4B
+#define RX_BUFFER_TOKEN BIT(0)
+
+#define USB_PDPHY_BIST_MODE_REG 0x4E
+#define BIST_MODE_MASK 0xF
+#define BIST_ENABLE BIT(7)
+#define PD_MSG_BIST 0x3
+#define PD_BIST_TEST_DATA_MODE 0x8
+
+#define USB_PDPHY_TX_BUFFER_HDR_REG 0x60
+#define USB_PDPHY_TX_BUFFER_DATA_REG 0x62
+
+#define USB_PDPHY_RX_BUFFER_REG 0x80
+
+/* VDD regulator */
+#define VDD_PDPHY_VOL_MIN 2800000 /* uV */
+#define VDD_PDPHY_VOL_MAX 3300000 /* uV */
+#define VDD_PDPHY_HPM_LOAD 3000 /* uA */
+
+/* Message Spec Rev field */
+#define PD_MSG_HDR_REV(hdr) (((hdr) >> 6) & 3)
+
+/* timers */
+#define RECEIVER_RESPONSE_TIME 15 /* tReceiverResponse */
+#define HARD_RESET_COMPLETE_TIME 5 /* tHardResetComplete */
+
+/* Interrupt numbers */
+#define PMIC_PDPHY_SIG_TX_IRQ 0x0
+#define PMIC_PDPHY_SIG_RX_IRQ 0x1
+#define PMIC_PDPHY_MSG_TX_IRQ 0x2
+#define PMIC_PDPHY_MSG_RX_IRQ 0x3
+#define PMIC_PDPHY_MSG_TX_FAIL_IRQ 0x4
+#define PMIC_PDPHY_MSG_TX_DISCARD_IRQ 0x5
+#define PMIC_PDPHY_MSG_RX_DISCARD_IRQ 0x6
+#define PMIC_PDPHY_FR_SWAP_IRQ 0x7
+
+/* Resources */
+#define PMIC_PDPHY_MAX_IRQS 0x08
+
+struct pmic_typec_pdphy_irq_params {
+ int virq;
+ char *irq_name;
+};
+
+struct pmic_typec_pdphy_resources {
+ unsigned int nr_irqs;
+ struct pmic_typec_pdphy_irq_params irq_params[PMIC_PDPHY_MAX_IRQS];
+};
+
+/* API */
+struct pmic_typec_pdphy;
+
+struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev);
+
+int qcom_pmic_typec_pdphy_probe(struct platform_device *pdev,
+ struct pmic_typec_pdphy *pmic_typec_pdphy,
+ struct pmic_typec_pdphy_resources *res,
+ struct regmap *regmap,
+ u32 base);
+
+int qcom_pmic_typec_pdphy_start(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ struct tcpm_port *tcpm_port);
+
+void qcom_pmic_typec_pdphy_stop(struct pmic_typec_pdphy *pmic_typec_pdphy);
+
+int qcom_pmic_typec_pdphy_set_roles(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ bool power_role_src, bool data_role_host);
+
+int qcom_pmic_typec_pdphy_set_pd_rx(struct pmic_typec_pdphy *pmic_typec_pdphy, bool on);
+
+int qcom_pmic_typec_pdphy_pd_transmit(struct pmic_typec_pdphy *pmic_typec_pdphy,
+ enum tcpm_transmit_type type,
+ const struct pd_message *msg,
+ unsigned int negotiated_rev);
+
+#endif /* __QCOM_PMIC_TYPEC_PDPHY_H__ */
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
new file mode 100644
index 0000000000000..42c956b6a1a1d
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
@@ -0,0 +1,560 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/usb/tcpm.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/workqueue.h>
+#include "qcom_pmic_typec_port.h"
+
+struct pmic_typec_port_irq_data {
+ int virq;
+ int irq;
+ struct pmic_typec_port *pmic_typec_port;
+};
+
+struct pmic_typec_port {
+ struct device *dev;
+ struct tcpm_port *tcpm_port;
+ struct regmap *regmap;
+ u32 base;
+ unsigned int nr_irqs;
+ struct pmic_typec_port_irq_data *irq_data;
+
+ struct regulator *vdd_vbus;
+
+ int cc;
+ bool debouncing_cc;
+ struct delayed_work cc_debounce_dwork;
+
+ spinlock_t lock; /* Register atomicity */
+};
+
+static const char * const typec_cc_status_name[] = {
+ [TYPEC_CC_OPEN] = "Open",
+ [TYPEC_CC_RA] = "Ra",
+ [TYPEC_CC_RD] = "Rd",
+ [TYPEC_CC_RP_DEF] = "Rp-def",
+ [TYPEC_CC_RP_1_5] = "Rp-1.5",
+ [TYPEC_CC_RP_3_0] = "Rp-3.0",
+};
+
+static const char *rp_unknown = "unknown";
+
+static const char *cc_to_name(enum typec_cc_status cc)
+{
+ if (cc > TYPEC_CC_RP_3_0)
+ return rp_unknown;
+
+ return typec_cc_status_name[cc];
+}
+
+static const char * const rp_sel_name[] = {
+ [TYPEC_SRC_RP_SEL_80UA] = "Rp-def-80uA",
+ [TYPEC_SRC_RP_SEL_180UA] = "Rp-1.5-180uA",
+ [TYPEC_SRC_RP_SEL_330UA] = "Rp-3.0-330uA",
+};
+
+static const char *rp_sel_to_name(int rp_sel)
+{
+ if (rp_sel > TYPEC_SRC_RP_SEL_330UA)
+ return rp_unknown;
+
+ return rp_sel_name[rp_sel];
+}
+
+#define misc_to_cc(msic) !!(misc & CC_ORIENTATION) ? "cc1" : "cc2"
+#define misc_to_vconn(msic) !!(misc & CC_ORIENTATION) ? "cc2" : "cc1"
+
+static void qcom_pmic_typec_port_cc_debounce(struct work_struct *work)
+{
+ struct pmic_typec_port *pmic_typec_port =
+ container_of(work, struct pmic_typec_port, cc_debounce_dwork.work);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+ pmic_typec_port->debouncing_cc = false;
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ dev_dbg(pmic_typec_port->dev, "Debounce cc complete\n");
+}
+
+static irqreturn_t pmic_typec_port_isr(int irq, void *dev_id)
+{
+ struct pmic_typec_port_irq_data *irq_data = dev_id;
+ struct pmic_typec_port *pmic_typec_port = irq_data->pmic_typec_port;
+ u32 misc_stat;
+ bool vbus_change = false;
+ bool cc_change = false;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
+ &misc_stat);
+ if (ret)
+ goto done;
+
+ switch (irq_data->virq) {
+ case PMIC_TYPEC_VBUS_IRQ:
+ /* Incoming vbus assert/de-assert detect */
+ vbus_change = true;
+ break;
+ case PMIC_TYPEC_CC_STATE_IRQ:
+ if (!pmic_typec_port->debouncing_cc)
+ cc_change = true;
+ break;
+ case PMIC_TYPEC_ATTACH_DETACH_IRQ:
+ if (!pmic_typec_port->debouncing_cc)
+ cc_change = true;
+ break;
+ }
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ if (vbus_change)
+ tcpm_vbus_change(pmic_typec_port->tcpm_port);
+
+ if (cc_change)
+ tcpm_cc_change(pmic_typec_port->tcpm_port);
+
+ return IRQ_HANDLED;
+}
+
+int qcom_pmic_typec_port_get_vbus(struct pmic_typec_port *pmic_typec_port)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int misc;
+ int ret;
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
+ &misc);
+ if (ret)
+ misc = 0;
+
+ dev_dbg(dev, "get_vbus: 0x%08x detect %d\n", misc, !!(misc & TYPEC_VBUS_DETECT));
+
+ return !!(misc & TYPEC_VBUS_DETECT);
+}
+
+int qcom_pmic_typec_port_set_vbus(struct pmic_typec_port *pmic_typec_port, bool on)
+{
+ u32 sm_stat;
+ u32 val;
+ int ret;
+
+ if (on) {
+ ret = regulator_enable(pmic_typec_port->vdd_vbus);
+ if (ret)
+ return ret;
+
+ val = TYPEC_SM_VBUS_VSAFE5V;
+ } else {
+ ret = regulator_disable(pmic_typec_port->vdd_vbus);
+ if (ret)
+ return ret;
+
+ val = TYPEC_SM_VBUS_VSAFE0V;
+ }
+
+ /* Poll waiting for transition to required vSafe5V or vSafe0V */
+ ret = regmap_read_poll_timeout(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_SM_STATUS_REG,
+ sm_stat, sm_stat & val,
+ 100, 250000);
+ if (ret)
+ dev_warn(pmic_typec_port->dev, "vbus vsafe%dv fail\n", on ? 5 : 0);
+
+ return 0;
+}
+
+int qcom_pmic_typec_port_get_cc(struct pmic_typec_port *pmic_typec_port,
+ enum typec_cc_status *cc1,
+ enum typec_cc_status *cc2)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int misc, val;
+ bool attached;
+ int ret = 0;
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc);
+ if (ret)
+ goto done;
+
+ attached = !!(misc & CC_ATTACHED);
+
+ if (pmic_typec_port->debouncing_cc) {
+ ret = -EBUSY;
+ goto done;
+ }
+
+ *cc1 = TYPEC_CC_OPEN;
+ *cc2 = TYPEC_CC_OPEN;
+
+ if (!(attached))
+ goto done;
+
+ if (misc & SNK_SRC_MODE) {
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_SRC_STATUS_REG,
+ &val);
+ if (ret)
+ goto done;
+ switch (val & DETECTED_SRC_TYPE_MASK) {
+ case SRC_RD_OPEN:
+ val = TYPEC_CC_RD;
+ break;
+ case SRC_RD_RA_VCONN:
+ val = TYPEC_CC_RD;
+ *cc1 = TYPEC_CC_RA;
+ *cc2 = TYPEC_CC_RA;
+ break;
+ default:
+ dev_warn(dev, "unexpected src status %.2x\n", val);
+ val = TYPEC_CC_RD;
+ break;
+ }
+ } else {
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_SNK_STATUS_REG,
+ &val);
+ if (ret)
+ goto done;
+ switch (val & DETECTED_SNK_TYPE_MASK) {
+ case SNK_RP_STD:
+ val = TYPEC_CC_RP_DEF;
+ break;
+ case SNK_RP_1P5:
+ val = TYPEC_CC_RP_1_5;
+ break;
+ case SNK_RP_3P0:
+ val = TYPEC_CC_RP_3_0;
+ break;
+ default:
+ dev_warn(dev, "unexpected snk status %.2x\n", val);
+ val = TYPEC_CC_RP_DEF;
+ break;
+ }
+ val = TYPEC_CC_RP_DEF;
+ }
+
+ if (misc & CC_ORIENTATION)
+ *cc2 = val;
+ else
+ *cc1 = val;
+
+done:
+ dev_dbg(dev, "get_cc: misc 0x%08x cc1 0x%08x %s cc2 0x%08x %s attached %d cc=%s\n",
+ misc, *cc1, cc_to_name(*cc1), *cc2, cc_to_name(*cc2), attached,
+ misc_to_cc(misc));
+
+ return ret;
+}
+
+static void qcom_pmic_set_cc_debounce(struct pmic_typec_port *pmic_typec_port)
+{
+ pmic_typec_port->debouncing_cc = true;
+ schedule_delayed_work(&pmic_typec_port->cc_debounce_dwork,
+ msecs_to_jiffies(2));
+}
+
+int qcom_pmic_typec_port_set_cc(struct pmic_typec_port *pmic_typec_port,
+ enum typec_cc_status cc)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int mode, currsrc;
+ unsigned int misc;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
+ &misc);
+ if (ret)
+ goto done;
+
+ mode = EN_SRC_ONLY;
+
+ switch (cc) {
+ case TYPEC_CC_OPEN:
+ currsrc = TYPEC_SRC_RP_SEL_80UA;
+ break;
+ case TYPEC_CC_RP_DEF:
+ currsrc = TYPEC_SRC_RP_SEL_80UA;
+ break;
+ case TYPEC_CC_RP_1_5:
+ currsrc = TYPEC_SRC_RP_SEL_180UA;
+ break;
+ case TYPEC_CC_RP_3_0:
+ currsrc = TYPEC_SRC_RP_SEL_330UA;
+ break;
+ case TYPEC_CC_RD:
+ currsrc = TYPEC_SRC_RP_SEL_80UA;
+ mode = EN_SNK_ONLY;
+ break;
+ default:
+ dev_warn(dev, "unexpected set_cc %d\n", cc);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (mode == EN_SRC_ONLY) {
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_CURRSRC_CFG_REG,
+ currsrc);
+ if (ret)
+ goto done;
+ }
+
+ pmic_typec_port->cc = cc;
+ qcom_pmic_set_cc_debounce(pmic_typec_port);
+ ret = 0;
+
+done:
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ dev_dbg(dev, "set_cc: currsrc=%x %s mode %s debounce %d attached %d cc=%s\n",
+ currsrc, rp_sel_to_name(currsrc),
+ mode == EN_SRC_ONLY ? "EN_SRC_ONLY" : "EN_SNK_ONLY",
+ pmic_typec_port->debouncing_cc, !!(misc & CC_ATTACHED),
+ misc_to_cc(misc));
+
+ return ret;
+}
+
+int qcom_pmic_typec_port_set_vconn(struct pmic_typec_port *pmic_typec_port, bool on)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int orientation, misc, mask, value;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc);
+ if (ret)
+ goto done;
+
+ /* Set VCONN on the inversion of the active CC channel */
+ orientation = (misc & CC_ORIENTATION) ? 0 : VCONN_EN_ORIENTATION;
+ if (on) {
+ mask = VCONN_EN_ORIENTATION | VCONN_EN_VALUE;
+ value = orientation | VCONN_EN_VALUE | VCONN_EN_SRC;
+ } else {
+ mask = VCONN_EN_VALUE;
+ value = 0;
+ }
+
+ ret = regmap_update_bits(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_VCONN_CONTROL_REG,
+ mask, value);
+done:
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ dev_dbg(dev, "set_vconn: orientation %d control 0x%08x state %s cc %s vconn %s\n",
+ orientation, value, on ? "on" : "off", misc_to_vconn(misc), misc_to_cc(misc));
+
+ return ret;
+}
+
+int qcom_pmic_typec_port_start_toggling(struct pmic_typec_port *pmic_typec_port,
+ enum typec_port_type port_type,
+ enum typec_cc_status cc)
+{
+ struct device *dev = pmic_typec_port->dev;
+ unsigned int misc;
+ u8 mode = 0;
+ unsigned long flags;
+ int ret;
+
+ switch (port_type) {
+ case TYPEC_PORT_SRC:
+ mode = EN_SRC_ONLY;
+ break;
+ case TYPEC_PORT_SNK:
+ mode = EN_SNK_ONLY;
+ break;
+ case TYPEC_PORT_DRP:
+ mode = EN_TRY_SNK;
+ break;
+ }
+
+ spin_lock_irqsave(&pmic_typec_port->lock, flags);
+
+ ret = regmap_read(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc);
+ if (ret)
+ goto done;
+
+ dev_dbg(dev, "start_toggling: misc 0x%08x attached %d port_type %d current cc %d new %d\n",
+ misc, !!(misc & CC_ATTACHED), port_type, pmic_typec_port->cc, cc);
+
+ qcom_pmic_set_cc_debounce(pmic_typec_port);
+
+ /* force it to toggle at least once */
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MODE_CFG_REG,
+ TYPEC_DISABLE_CMD);
+ if (ret)
+ goto done;
+
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MODE_CFG_REG,
+ mode);
+done:
+ spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
+
+ return ret;
+}
+
+#define TYPEC_INTR_EN_CFG_1_MASK \
+ (TYPEC_LEGACY_CABLE_INT_EN | \
+ TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN | \
+ TYPEC_TRYSOURCE_DETECT_INT_EN | \
+ TYPEC_TRYSINK_DETECT_INT_EN | \
+ TYPEC_CCOUT_DETACH_INT_EN | \
+ TYPEC_CCOUT_ATTACH_INT_EN | \
+ TYPEC_VBUS_DEASSERT_INT_EN | \
+ TYPEC_VBUS_ASSERT_INT_EN)
+
+#define TYPEC_INTR_EN_CFG_2_MASK \
+ (TYPEC_STATE_MACHINE_CHANGE_INT_EN | TYPEC_VBUS_ERROR_INT_EN | \
+ TYPEC_DEBOUNCE_DONE_INT_EN)
+
+int qcom_pmic_typec_port_start(struct pmic_typec_port *pmic_typec_port,
+ struct tcpm_port *tcpm_port)
+{
+ int i;
+ int mask;
+ int ret;
+
+ /* Configure interrupt sources */
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_INTERRUPT_EN_CFG_1_REG,
+ TYPEC_INTR_EN_CFG_1_MASK);
+ if (ret)
+ goto done;
+
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_INTERRUPT_EN_CFG_2_REG,
+ TYPEC_INTR_EN_CFG_2_MASK);
+ if (ret)
+ goto done;
+
+ /* start in TRY_SNK mode */
+ ret = regmap_write(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_MODE_CFG_REG, EN_TRY_SNK);
+ if (ret)
+ goto done;
+
+ /* Configure VCONN for software control */
+ ret = regmap_update_bits(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_VCONN_CONTROL_REG,
+ VCONN_EN_SRC | VCONN_EN_VALUE, VCONN_EN_SRC);
+ if (ret)
+ goto done;
+
+ /* Set CC threshold to 1.6 Volts | tPDdebounce = 10-20ms */
+ mask = SEL_SRC_UPPER_REF | USE_TPD_FOR_EXITING_ATTACHSRC;
+ ret = regmap_update_bits(pmic_typec_port->regmap,
+ pmic_typec_port->base + TYPEC_EXIT_STATE_CFG_REG,
+ mask, mask);
+ if (ret)
+ goto done;
+
+ pmic_typec_port->tcpm_port = tcpm_port;
+
+ for (i = 0; i < pmic_typec_port->nr_irqs; i++)
+ enable_irq(pmic_typec_port->irq_data[i].irq);
+
+done:
+ return ret;
+}
+
+void qcom_pmic_typec_port_stop(struct pmic_typec_port *pmic_typec_port)
+{
+ int i;
+
+ for (i = 0; i < pmic_typec_port->nr_irqs; i++)
+ disable_irq(pmic_typec_port->irq_data[i].irq);
+}
+
+struct pmic_typec_port *qcom_pmic_typec_port_alloc(struct device *dev)
+{
+ return devm_kzalloc(dev, sizeof(struct pmic_typec_port), GFP_KERNEL);
+}
+
+int qcom_pmic_typec_port_probe(struct platform_device *pdev,
+ struct pmic_typec_port *pmic_typec_port,
+ struct pmic_typec_port_resources *res,
+ struct regmap *regmap,
+ u32 base)
+{
+ struct device *dev = &pdev->dev;
+ struct pmic_typec_port_irq_data *irq_data;
+ int i, ret, irq;
+
+ if (!res->nr_irqs || res->nr_irqs > PMIC_TYPEC_MAX_IRQS)
+ return -EINVAL;
+
+ irq_data = devm_kzalloc(dev, sizeof(*irq_data) * res->nr_irqs,
+ GFP_KERNEL);
+ if (!irq_data)
+ return -ENOMEM;
+
+ pmic_typec_port->vdd_vbus = devm_regulator_get(dev, "vdd-vbus");
+ if (IS_ERR(pmic_typec_port->vdd_vbus))
+ return PTR_ERR(pmic_typec_port->vdd_vbus);
+
+ pmic_typec_port->dev = dev;
+ pmic_typec_port->base = base;
+ pmic_typec_port->regmap = regmap;
+ pmic_typec_port->nr_irqs = res->nr_irqs;
+ pmic_typec_port->irq_data = irq_data;
+ spin_lock_init(&pmic_typec_port->lock);
+ INIT_DELAYED_WORK(&pmic_typec_port->cc_debounce_dwork,
+ qcom_pmic_typec_port_cc_debounce);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ for (i = 0; i < res->nr_irqs; i++, irq_data++) {
+ irq = platform_get_irq_byname(pdev,
+ res->irq_params[i].irq_name);
+ if (irq < 0)
+ return irq;
+
+ irq_data->pmic_typec_port = pmic_typec_port;
+ irq_data->irq = irq;
+ irq_data->virq = res->irq_params[i].virq;
+ ret = devm_request_threaded_irq(dev, irq, NULL, pmic_typec_port_isr,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
+ res->irq_params[i].irq_name,
+ irq_data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
new file mode 100644
index 0000000000000..5a9c47373c614
--- /dev/null
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
@@ -0,0 +1,194 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Ltd. All rights reserved.
+ */
+#ifndef __QCOM_PMIC_TYPEC_H__
+#define __QCOM_PMIC_TYPEC_H__
+
+#include <linux/usb/tcpm.h>
+
+#define TYPEC_SNK_STATUS_REG 0x06
+#define DETECTED_SNK_TYPE_MASK GENMASK(6, 0)
+#define SNK_DAM_MASK GENMASK(6, 4)
+#define SNK_DAM_500MA BIT(6)
+#define SNK_DAM_1500MA BIT(5)
+#define SNK_DAM_3000MA BIT(4)
+#define SNK_RP_STD BIT(3)
+#define SNK_RP_1P5 BIT(2)
+#define SNK_RP_3P0 BIT(1)
+#define SNK_RP_SHORT BIT(0)
+
+#define TYPEC_SRC_STATUS_REG 0x08
+#define DETECTED_SRC_TYPE_MASK GENMASK(4, 0)
+#define SRC_HIGH_BATT BIT(5)
+#define SRC_DEBUG_ACCESS BIT(4)
+#define SRC_RD_OPEN BIT(3)
+#define SRC_RD_RA_VCONN BIT(2)
+#define SRC_RA_OPEN BIT(1)
+#define AUDIO_ACCESS_RA_RA BIT(0)
+
+#define TYPEC_STATE_MACHINE_STATUS_REG 0x09
+#define TYPEC_ATTACH_DETACH_STATE BIT(5)
+
+#define TYPEC_SM_STATUS_REG 0x0A
+#define TYPEC_SM_VBUS_VSAFE5V BIT(5)
+#define TYPEC_SM_VBUS_VSAFE0V BIT(6)
+#define TYPEC_SM_USBIN_LT_LV BIT(7)
+
+#define TYPEC_MISC_STATUS_REG 0x0B
+#define TYPEC_WATER_DETECTION_STATUS BIT(7)
+#define SNK_SRC_MODE BIT(6)
+#define TYPEC_VBUS_DETECT BIT(5)
+#define TYPEC_VBUS_ERROR_STATUS BIT(4)
+#define TYPEC_DEBOUNCE_DONE BIT(3)
+#define CC_ORIENTATION BIT(1)
+#define CC_ATTACHED BIT(0)
+
+#define LEGACY_CABLE_STATUS_REG 0x0D
+#define TYPEC_LEGACY_CABLE_STATUS BIT(1)
+#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS BIT(0)
+
+#define TYPEC_U_USB_STATUS_REG 0x0F
+#define U_USB_GROUND_NOVBUS BIT(6)
+#define U_USB_GROUND BIT(4)
+#define U_USB_FMB1 BIT(3)
+#define U_USB_FLOAT1 BIT(2)
+#define U_USB_FMB2 BIT(1)
+#define U_USB_FLOAT2 BIT(0)
+
+#define TYPEC_MODE_CFG_REG 0x44
+#define TYPEC_TRY_MODE_MASK GENMASK(4, 3)
+#define EN_TRY_SNK BIT(4)
+#define EN_TRY_SRC BIT(3)
+#define TYPEC_POWER_ROLE_CMD_MASK GENMASK(2, 0)
+#define EN_SRC_ONLY BIT(2)
+#define EN_SNK_ONLY BIT(1)
+#define TYPEC_DISABLE_CMD BIT(0)
+
+#define TYPEC_VCONN_CONTROL_REG 0x46
+#define VCONN_EN_ORIENTATION BIT(2)
+#define VCONN_EN_VALUE BIT(1)
+#define VCONN_EN_SRC BIT(0)
+
+#define TYPEC_CCOUT_CONTROL_REG 0x48
+#define TYPEC_CCOUT_BUFFER_EN BIT(2)
+#define TYPEC_CCOUT_VALUE BIT(1)
+#define TYPEC_CCOUT_SRC BIT(0)
+
+#define DEBUG_ACCESS_SRC_CFG_REG 0x4C
+#define EN_UNORIENTED_DEBUG_ACCESS_SRC BIT(0)
+
+#define TYPE_C_CRUDE_SENSOR_CFG_REG 0x4e
+#define EN_SRC_CRUDE_SENSOR BIT(1)
+#define EN_SNK_CRUDE_SENSOR BIT(0)
+
+#define TYPEC_EXIT_STATE_CFG_REG 0x50
+#define BYPASS_VSAFE0V_DURING_ROLE_SWAP BIT(3)
+#define SEL_SRC_UPPER_REF BIT(2)
+#define USE_TPD_FOR_EXITING_ATTACHSRC BIT(1)
+#define EXIT_SNK_BASED_ON_CC BIT(0)
+
+#define TYPEC_CURRSRC_CFG_REG 0x52
+#define TYPEC_SRC_RP_SEL_330UA BIT(1)
+#define TYPEC_SRC_RP_SEL_180UA BIT(0)
+#define TYPEC_SRC_RP_SEL_80UA 0
+#define TYPEC_SRC_RP_SEL_MASK GENMASK(1, 0)
+
+#define TYPEC_INTERRUPT_EN_CFG_1_REG 0x5E
+#define TYPEC_LEGACY_CABLE_INT_EN BIT(7)
+#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN BIT(6)
+#define TYPEC_TRYSOURCE_DETECT_INT_EN BIT(5)
+#define TYPEC_TRYSINK_DETECT_INT_EN BIT(4)
+#define TYPEC_CCOUT_DETACH_INT_EN BIT(3)
+#define TYPEC_CCOUT_ATTACH_INT_EN BIT(2)
+#define TYPEC_VBUS_DEASSERT_INT_EN BIT(1)
+#define TYPEC_VBUS_ASSERT_INT_EN BIT(0)
+
+#define TYPEC_INTERRUPT_EN_CFG_2_REG 0x60
+#define TYPEC_SRC_BATT_HPWR_INT_EN BIT(6)
+#define MICRO_USB_STATE_CHANGE_INT_EN BIT(5)
+#define TYPEC_STATE_MACHINE_CHANGE_INT_EN BIT(4)
+#define TYPEC_DEBUG_ACCESS_DETECT_INT_EN BIT(3)
+#define TYPEC_WATER_DETECTION_INT_EN BIT(2)
+#define TYPEC_VBUS_ERROR_INT_EN BIT(1)
+#define TYPEC_DEBOUNCE_DONE_INT_EN BIT(0)
+
+#define TYPEC_DEBOUNCE_OPTION_REG 0x62
+#define REDUCE_TCCDEBOUNCE_TO_2MS BIT(2)
+
+#define TYPE_C_SBU_CFG_REG 0x6A
+#define SEL_SBU1_ISRC_VAL 0x04
+#define SEL_SBU2_ISRC_VAL 0x01
+
+#define TYPEC_U_USB_CFG_REG 0x70
+#define EN_MICRO_USB_FACTORY_MODE BIT(1)
+#define EN_MICRO_USB_MODE BIT(0)
+
+#define TYPEC_PMI632_U_USB_WATER_PROTECTION_CFG_REG 0x72
+
+#define TYPEC_U_USB_WATER_PROTECTION_CFG_REG 0x73
+#define EN_MICRO_USB_WATER_PROTECTION BIT(4)
+#define MICRO_USB_DETECTION_ON_TIME_CFG_MASK GENMASK(3, 2)
+#define MICRO_USB_DETECTION_PERIOD_CFG_MASK GENMASK(1, 0)
+
+#define TYPEC_PMI632_MICRO_USB_MODE_REG 0x73
+#define MICRO_USB_MODE_ONLY BIT(0)
+
+/* Interrupt numbers */
+#define PMIC_TYPEC_OR_RID_IRQ 0x0
+#define PMIC_TYPEC_VPD_IRQ 0x1
+#define PMIC_TYPEC_CC_STATE_IRQ 0x2
+#define PMIC_TYPEC_VCONN_OC_IRQ 0x3
+#define PMIC_TYPEC_VBUS_IRQ 0x4
+#define PMIC_TYPEC_ATTACH_DETACH_IRQ 0x5
+#define PMIC_TYPEC_LEGACY_CABLE_IRQ 0x6
+#define PMIC_TYPEC_TRY_SNK_SRC_IRQ 0x7
+
+/* Resources */
+#define PMIC_TYPEC_MAX_IRQS 0x08
+
+struct pmic_typec_port_irq_params {
+ int virq;
+ char *irq_name;
+};
+
+struct pmic_typec_port_resources {
+ unsigned int nr_irqs;
+ struct pmic_typec_port_irq_params irq_params[PMIC_TYPEC_MAX_IRQS];
+};
+
+/* API */
+struct pmic_typec;
+
+struct pmic_typec_port *qcom_pmic_typec_port_alloc(struct device *dev);
+
+int qcom_pmic_typec_port_probe(struct platform_device *pdev,
+ struct pmic_typec_port *pmic_typec_port,
+ struct pmic_typec_port_resources *res,
+ struct regmap *regmap,
+ u32 base);
+
+int qcom_pmic_typec_port_start(struct pmic_typec_port *pmic_typec_port,
+ struct tcpm_port *tcpm_port);
+
+void qcom_pmic_typec_port_stop(struct pmic_typec_port *pmic_typec_port);
+
+int qcom_pmic_typec_port_get_cc(struct pmic_typec_port *pmic_typec_port,
+ enum typec_cc_status *cc1,
+ enum typec_cc_status *cc2);
+
+int qcom_pmic_typec_port_set_cc(struct pmic_typec_port *pmic_typec_port,
+ enum typec_cc_status cc);
+
+int qcom_pmic_typec_port_get_vbus(struct pmic_typec_port *pmic_typec_port);
+
+int qcom_pmic_typec_port_set_vconn(struct pmic_typec_port *pmic_typec_port, bool on);
+
+int qcom_pmic_typec_port_start_toggling(struct pmic_typec_port *pmic_typec_port,
+ enum typec_port_type port_type,
+ enum typec_cc_status cc);
+
+int qcom_pmic_typec_port_set_vbus(struct pmic_typec_port *pmic_typec_port, bool on);
+
+#endif /* __QCOM_PMIC_TYPE_C_PORT_H__ */
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (12 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 13/14] usb: typec: qcom: Add Qualcomm PMIC TCPM support Bryan O'Donoghue
@ 2023-04-13 11:34 ` Bryan O'Donoghue
2023-04-13 13:34 ` kernel test robot
2023-04-18 12:57 ` Bjorn Andersson
2023-04-13 14:19 ` [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Luca Weiss
2023-09-20 2:13 ` Bjorn Andersson
15 siblings, 2 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 11:34 UTC (permalink / raw)
To: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, bryan.odonoghue, konrad.dybcio, subbaram, jackp,
robertom, Dmitry Baryshkov, Wesley Cheng
From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
The lane select switch for USB typec orientation is within the USB QMP PHY.
the current device. It could be connected through an endpoint, to an
independent device handling the typec detection, ie the QCOM SPMI typec
driver.
bod: Fixed the logic qcom_qmp_phy_typec_switch_set() to disable phy
on disconnect if and only if we have initialized the PHY.
Retained CC orientation logic in qcom_qmp_phy_com_init() to simplify
patch.
bod: Ported from earlier version of driver to phy-qcom-qmp-combo.c
Co-developed-by: Wesley Cheng <wcheng@codeaurora.org>
Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
Co-developed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
drivers/phy/qualcomm/Kconfig | 8 +++
drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 80 +++++++++++++++++++++--
2 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 4850d48f31fa1..8240fffdbed4e 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -101,6 +101,14 @@ config PHY_QCOM_QMP_USB
endif # PHY_QCOM_QMP
+config PHY_QCOM_QMP_TYPEC
+ def_bool PHY_QCOM_QMP=y && TYPEC=y || PHY_QCOM_QMP=m && TYPEC
+ help
+ Register a type C switch from the QMP PHY driver for type C
+ orientation support. This has dependencies with if the type C kernel
+ configuration is enabled or not. This support will not be present if
+ USB type C is disabled.
+
config PHY_QCOM_QUSB2
tristate "Qualcomm QUSB2 PHY Driver"
depends on OF && (ARCH_QCOM || COMPILE_TEST)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index 6850e04c329b8..b9a30c087423d 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -19,6 +19,7 @@
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/slab.h>
+#include <linux/usb/typec_mux.h>
#include <dt-bindings/phy/phy-qcom-qmp.h>
@@ -63,6 +64,10 @@
/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
+/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */
+#define SW_PORTSELECT_VAL BIT(0)
+#define SW_PORTSELECT_MUX BIT(1)
+
#define PHY_INIT_COMPLETE_TIMEOUT 10000
struct qmp_phy_init_tbl {
@@ -1323,6 +1328,9 @@ struct qmp_combo {
struct clk_fixed_rate pipe_clk_fixed;
struct clk_hw dp_link_hw;
struct clk_hw dp_pixel_hw;
+
+ struct typec_switch_dev *sw;
+ enum typec_orientation orientation;
};
static void qmp_v3_dp_aux_init(struct qmp_combo *qmp);
@@ -1955,7 +1963,8 @@ static void qmp_v3_configure_dp_tx(struct qmp_combo *qmp)
static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
{
u32 val;
- bool reverse = false;
+ bool reverse = qmp->orientation == TYPEC_ORIENTATION_REVERSE;
+ const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
@@ -1974,10 +1983,18 @@ static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
* if (orientation == ORIENTATION_CC2)
* writel(0x4c, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_MODE);
*/
+ if (dp_opts->lanes == 4 || reverse)
+ val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
+ if (dp_opts->lanes == 4 || !reverse)
+ val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
+
val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
- writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
+ if (reverse)
+ writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE);
+ else
+ writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE);
return reverse;
}
@@ -2461,6 +2478,7 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *com = qmp->com;
+ u32 val;
int ret;
mutex_lock(&qmp->phy_mutex);
@@ -2498,8 +2516,11 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
- /* Default type-c orientation, i.e CC1 */
- qphy_setbits(com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02);
+ /* Latch CC orientation based on reported state by TCPM */
+ val = SW_PORTSELECT_MUX;
+ if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
+ val |= SW_PORTSELECT_VAL;
+ qphy_setbits(com, QPHY_V3_DP_COM_TYPEC_CTRL, val);
qphy_setbits(com, QPHY_V3_DP_COM_PHY_MODE_CTRL, USB3_MODE | DP_MODE);
@@ -3338,6 +3359,53 @@ static struct phy *qmp_combo_phy_xlate(struct device *dev, struct of_phandle_arg
return ERR_PTR(-EINVAL);
}
+#if IS_ENABLED(CONFIG_PHY_QCOM_QMP_TYPEC)
+static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw,
+ enum typec_orientation orientation)
+{
+ struct qmp_combo *qmp = typec_switch_get_drvdata(sw);
+ struct phy *dp_phy = qmp->dp_phy;
+ int ret = 0;
+
+ dev_dbg(qmp->dev, "Toggling orientation current %d requested %d\n",
+ qmp->orientation, orientation);
+
+ qmp->orientation = orientation;
+
+ if (orientation == TYPEC_ORIENTATION_NONE) {
+ if (qmp->init_count)
+ ret = qmp_combo_dp_power_off(dp_phy);
+ } else {
+ if (!qmp->init_count)
+ ret = qmp_combo_dp_power_on(dp_phy);
+ }
+
+ return 0;
+}
+
+static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
+{
+ struct typec_switch_desc sw_desc;
+ struct device *dev = qmp->dev;
+
+ sw_desc.drvdata = qmp;
+ sw_desc.fwnode = dev->fwnode;
+ sw_desc.set = qmp_combo_typec_switch_set;
+ qmp->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(qmp->sw)) {
+ dev_err(dev, "Error registering typec switch: %ld\n",
+ PTR_ERR(qmp->sw));
+ }
+
+ return 0;
+}
+#else
+static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
+{
+ return 0;
+}
+#endif
+
static int qmp_combo_probe(struct platform_device *pdev)
{
struct qmp_combo *qmp;
@@ -3428,6 +3496,10 @@ static int qmp_combo_probe(struct platform_device *pdev)
else
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ ret = qmp_combo_typec_switch_register(qmp);
+ if (ret)
+ goto err_node_put;
+
of_node_put(usb_np);
of_node_put(dp_np);
--
2.39.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection
2023-04-13 11:34 ` [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection Bryan O'Donoghue
@ 2023-04-13 13:34 ` kernel test robot
2023-04-18 12:57 ` Bjorn Andersson
1 sibling, 0 replies; 43+ messages in thread
From: kernel test robot @ 2023-04-13 13:34 UTC (permalink / raw)
To: Bryan O'Donoghue; +Cc: oe-kbuild-all
Hi Bryan,
kernel test robot noticed the following build warnings:
[auto build test WARNING on usb/usb-testing]
[also build test WARNING on usb/usb-next usb/usb-linus robh/for-next broonie-regulator/for-next linus/master v6.3-rc6 next-20230412]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Bryan-O-Donoghue/dt-bindings-regulator-qcom-usb-vbus-regulator-Mark-reg-as-required/20230413-193753
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
patch link: https://lore.kernel.org/r/20230413113438.1577658-15-bryan.odonoghue%40linaro.org
patch subject: [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection
config: riscv-allmodconfig (https://download.01.org/0day-ci/archive/20230413/202304132100.DVPOVbGn-lkp@intel.com/config)
compiler: riscv64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/9ce533fddd1468cd6acf3abeae8c01d6d8a02d57
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Bryan-O-Donoghue/dt-bindings-regulator-qcom-usb-vbus-regulator-Mark-reg-as-required/20230413-193753
git checkout 9ce533fddd1468cd6acf3abeae8c01d6d8a02d57
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=riscv olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash drivers/phy/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304132100.DVPOVbGn-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/phy/qualcomm/phy-qcom-qmp-combo.c: In function 'qmp_combo_typec_switch_set':
>> drivers/phy/qualcomm/phy-qcom-qmp-combo.c:3383:13: warning: variable 'ret' set but not used [-Wunused-but-set-variable]
3383 | int ret = 0;
| ^~~
vim +/ret +3383 drivers/phy/qualcomm/phy-qcom-qmp-combo.c
3376
3377 #if IS_ENABLED(CONFIG_PHY_QCOM_QMP_TYPEC)
3378 static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw,
3379 enum typec_orientation orientation)
3380 {
3381 struct qmp_combo *qmp = typec_switch_get_drvdata(sw);
3382 struct phy *dp_phy = qmp->dp_phy;
> 3383 int ret = 0;
3384
3385 dev_dbg(qmp->dev, "Toggling orientation current %d requested %d\n",
3386 qmp->orientation, orientation);
3387
3388 qmp->orientation = orientation;
3389
3390 if (orientation == TYPEC_ORIENTATION_NONE) {
3391 if (qmp->init_count)
3392 ret = qmp_combo_dp_power_off(dp_phy);
3393 } else {
3394 if (!qmp->init_count)
3395 ret = qmp_combo_dp_power_on(dp_phy);
3396 }
3397
3398 return 0;
3399 }
3400
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (13 preceding siblings ...)
2023-04-13 11:34 ` [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection Bryan O'Donoghue
@ 2023-04-13 14:19 ` Luca Weiss
2023-04-13 15:08 ` Bryan O'Donoghue
2023-09-20 2:13 ` Bjorn Andersson
15 siblings, 1 reply; 43+ messages in thread
From: Luca Weiss @ 2023-04-13 14:19 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
Hi Bryan,
On Thu Apr 13, 2023 at 1:34 PM CEST, Bryan O'Donoghue wrote:
> V5:
> - Amagamates into once device, Heikki, Rob
>
> - Takes feedback on usage form Luka and Jianhua on VSafeV state transition detection
> dev_err() -> dev_warn()
>
> - Orientation graph example and general expected bindings
> I discussed offline with Bjorn the conclusions of the glink/sbu model.
> The expected orientation-switch path is
> connector/port@0 <-> phy/port@X <-> dp/port@0
> This can then be expanded to
> connector/port@0 <-> redriver/port@0 <-> phy/port@X <-> dp/port@0
>
> - Rob, Bjorn, Krzysztof
>
> - Data role
> The data-role path is
> connector/port@0 <-> dwc3/port@Y
I believe I have adjusted my dts correctly for v5 compared to v4 but now
the usb doesn't seem to work anymore in most cases.
Only when having the phone already plugged in during boot in one
orientation does USB come up, but also disappears once you replug the
cable. I still see the same (or at least visually similar) messages when
plugging in the USB cable or the USB stick but nothing more than that
happens.
Not that v4 worked perfectly on pm7250b+sm7225(/sm6350) but at least it
worked in most cases as described in the emails there. Since the driver
structure changed quite a bit, git diff isn't helpful here
unfortunately.
Don't think it matters but worth mentioning that sm6350 uses the new
qmpphy bindings as described in qcom,sc8280xp-qmp-usb43dp-phy.yaml (this
was also the case when testing v4 of this).
Any idea?
Regards
Luca
>
> Previous set:
> https://lore.kernel.org/linux-arm-msm/20230318121828.739424-1-bryan.odonoghue@linaro.org/
>
> Bootable:
> https://git.codelinaro.org/bryan.odonoghue/kernel/-/tree/linux-next-23-04-12-pm8150b-tcpm-qcom-wrapper-typec-mux
>
> V4:
> - Per Rob's input the pdphy and type-c appear as stadalone blocks
> inside of the PMIC declaration which is a 1:1 mapping of PMIC hardware.
> The TCPM virtual device is declared at the top-level.
> https://lore.kernel.org/all/YY7p7jviA3ZG05gL@robh.at.kernel.org/
>
> - Squashes the removal of the old driver with the addition of the new. - Heikki, Gunter
> https://lore.kernel.org/all/YYVHcHC1Gm92VxEM@kuha.fi.intel.com/
>
> - Reworked Dmitry's old patch for the QMP to account for file renames and
> very minimal code-drift in the interregnum.
>
> - New yaml checks drive update of PMIC VBUS yaml
>
> - Some housekeeping on the sc7180 yaml side. sc7180 is not supported yet.
>
> - Expands and fixes the examples being added in the PMIC tcpm examples.
>
> Previous set:
> https://lore.kernel.org/all/20211105033558.1573552-1-bryan.odonoghue@linaro.org/
>
> Bootable:
> https://git.codelinaro.org/bryan.odonoghue/kernel/-/commits/linux-next-23-03-18-pm8150b-tcpm-qcom-wrapper-typec-mux
>
> V3:
> Rob Herrings review
>
> - Drops use of remote-endpoint and ports to bind
> tcpm to pdphy and typec replacing with phandle
>
> - Drops pmic-pdphy-* and pmic-typec-* from interrupt names
> as suggested
>
> - Passes make dt_binding_check DT_CHECKER_FLAGS=-m
>
> BOD
> - Noticed qcom_pmic_tcpm_pdphy_enable() was missing a
> regulator_disable in case of an error, added.
>
> - qcom_pmic_tcpm_pdphy_probe()
> devm_regulator_get() should come before regmap_get()
> as is the case in qcom_pmic_tcpm_typec_probe()
>
> - Fixes compatible name in qcom,pmic-typec.yaml should
> have read qcom,pm8150b-typec not qcom,pm8150b-usb-typec
>
> - Makes sure compat for core is "qcom,pm8150b-tcpm" in
> docs and driver
>
> - Drops redundant return in void qcom_pmic_tcpm_pdphy_reset_off()
>
> Kernel Robot
> - Drops unused variable debounced in qcom_pmic_tcpm_typec_get_cc()
>
> - Drops unsused variable orientation in qcom_pmic_tcpm_typec_set_cc()
>
> Latest bootable series can be found here:
> Link: https://git.linaro.org/people/bryan.odonoghue/kernel.git/log/?h=usb-next-04-11-21-pm8150b-tcpm-v3
>
> git diff usb-next-27-10-21-pm8150b-tcpm-v2 -- drivers/usb/typec/tcpm/qcom/
> git diff usb-next-27-10-21-pm8150b-tcpm-v2 -- Documentation/devicetree/bindings/usb/qcom,pmic*
>
> Previous set:
> Link: https://lore.kernel.org/linux-usb/20211028164941.831918-1-bryan.odonoghue@linaro.org/T/#t
>
> V2 resend:
> - Adding omitted devicetree mailing list
>
> V2:
>
> Guenter Roeck's review
> - Converts suggested qcom_pmic_tcpm_core.c into one-liners
>
> - Adds comment on how polarity is set in set_polarity()
>
> - Removes optional set_current_limit()
>
> - regmap_read/regmap_write
> Reviwing other pm8150b/spmi drivers I then added in checks for all
> reamap_read()/regmap_write() calls.
>
> - Fixes (type == TCPC_TX_CABLE_RESET || TCPC_TX_HARD_RESET)
> thanks I definitely had the blinkers on there and didn't see that at all
>
> - qcom_pmic_tcpm_pdphy_pd_transmit_payload()
> Treats regmap_read and read value as separate error paths
>
> - qcom_pmic_tcpm_pdphy_set_pd_rx()
> Replaces boolean if/else with !on as suggested
>
> - Returns -ENODEV not -EINVAL on dev_get_regmap() error
>
> - qcom_pmic_tcpm_pdphy_pd_receive()
> Guenter asks: "No error return ?"
> bod: No we are inside an ISR here if we read data we pass that off to TCPM
> if somehow we don't read the data - it is "junk" there's no value IMO
> in pushing an error upwards back to the handler.
>
> Heikki Krogerus' review
> - Includes Makefile I missed adding to my git index
>
> - Removes old Kconfig entry for remove driver
>
> Randy Dunlap's review
> - Rewords drivers/usb/typec/tcpm/Kconfig
>
> - Drops tautology "aggregates togther"
>
> - Corrects spelling typos
>
> BOD's own review
> - Drops redundant include of regmap.h in qcom_pmic_tcpm_core.c
>
> - Propogates qcom_pmic_tcpm_pdphy_disable() error upwards
>
> - Propogates pmic_pdphy_reset() error upwards
>
> - Drops error prints in qcom_pmic_tcpm_pdphy_pd_transmit_payload()
> I had these in-place during development and don't recall them being
> triggered even once, they are redundant, remove.
>
> Differences between the two can be seen by
> git diff usb-next-27-10-21-pm8150b-tcpm-v2..usb-next-25-10-21-pm8150b-tcpm -- drivers/usb/typec/tcpm
>
> Latest bootable series can be found here:
> Link: https://git.linaro.org/people/bryan.odonoghue/kernel.git/log/?h=usb-next-27-10-21-pm8150b-tcpm-v2
>
> Previous set:
> Link: https://lore.kernel.org/all/20211025150906.176686-1-bryan.odonoghue@linaro.org/T/#t
>
> V1:
> This series adds a set of yaml and a driver to bind together the type-c and
> pdphy silicon in qcom's pm8150b block as a Linux type-c port manager.
>
> As part of that we retire the existing qcom-pmic-typec driver and fully
> replicate its functionality inside of the new block with the additional
> pdphy stuff along with it.
>
> An additional series will follow this one for the SoC and RB5 dtsi and dts
> respectively.
>
> A bootable series can be found here
>
> Link: https://git.linaro.org/people/bryan.odonoghue/kernel.git/log/?h=usb-next-25-10-21-pm8150b-tcpm
>
> Bryan O'Donoghue (13):
> dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required
> dt-bindings: regulator: qcom,usb-vbus-regulator: Mark
> regulator-*-microamp required
> dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add orientation-switch
> as optional
> dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an
> optional
> dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema
> dt-bindings: mfd: qcom,spmi-pmic: Add typec to SPMI device types
> arm64: dts: qcom: sm8250: Define ports for qmpphy
> orientation-switching
> arm64: dts: qcom: pm8150b: Add a TCPM description
> arm64: dts: qcom: qrb5165-rb5: Switch on Type-C VBUS boost
> arm64: dts: qcom: qrb5165-rb5: Switch on basic TCPM
> arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for
> usb_1
> arm64: dts: qcom: qrb5165-rb5: Switch on TCPM orientation-switch for
> usb_1_qmpphy
> usb: typec: qcom: Add Qualcomm PMIC TCPM support
>
> Dmitry Baryshkov (1):
> phy: qcom-qmp: Register as a typec switch for orientation detection
>
> .../bindings/mfd/qcom,spmi-pmic.yaml | 4 +
> .../phy/qcom,sc7180-qmp-usb3-dp-phy.yaml | 40 ++
> .../regulator/qcom,usb-vbus-regulator.yaml | 10 +-
> .../bindings/usb/qcom,pmic-typec.yaml | 169 ++++++
> MAINTAINERS | 10 +
> arch/arm64/boot/dts/qcom/pm8150b.dtsi | 40 ++
> arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 57 +-
> arch/arm64/boot/dts/qcom/sm8250.dtsi | 13 +
> drivers/phy/qualcomm/Kconfig | 8 +
> drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 80 ++-
> drivers/usb/typec/Kconfig | 13 -
> drivers/usb/typec/Makefile | 1 -
> drivers/usb/typec/qcom-pmic-typec.c | 261 --------
> drivers/usb/typec/tcpm/Kconfig | 11 +
> drivers/usb/typec/tcpm/Makefile | 1 +
> drivers/usb/typec/tcpm/qcom/Makefile | 6 +
> drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c | 362 +++++++++++
> .../typec/tcpm/qcom/qcom_pmic_typec_pdphy.c | 528 +++++++++++++++++
> .../typec/tcpm/qcom/qcom_pmic_typec_pdphy.h | 115 ++++
> .../typec/tcpm/qcom/qcom_pmic_typec_port.c | 560 ++++++++++++++++++
> .../typec/tcpm/qcom/qcom_pmic_typec_port.h | 194 ++++++
> 21 files changed, 2202 insertions(+), 281 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
> delete mode 100644 drivers/usb/typec/qcom-pmic-typec.c
> create mode 100644 drivers/usb/typec/tcpm/qcom/Makefile
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
>
> --
> 2.39.2
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-13 14:19 ` [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Luca Weiss
@ 2023-04-13 15:08 ` Bryan O'Donoghue
2023-04-14 6:51 ` Luca Weiss
0 siblings, 1 reply; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-13 15:08 UTC (permalink / raw)
To: Luca Weiss, linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 13/04/2023 15:19, Luca Weiss wrote:
> Hi Bryan,
>
> On Thu Apr 13, 2023 at 1:34 PM CEST, Bryan O'Donoghue wrote:
>> V5:
>> - Amagamates into once device, Heikki, Rob
>>
>> - Takes feedback on usage form Luka and Jianhua on VSafeV state transition detection
>> dev_err() -> dev_warn()
>>
>> - Orientation graph example and general expected bindings
>> I discussed offline with Bjorn the conclusions of the glink/sbu model.
>> The expected orientation-switch path is
>> connector/port@0 <-> phy/port@X <-> dp/port@0
>> This can then be expanded to
>> connector/port@0 <-> redriver/port@0 <-> phy/port@X <-> dp/port@0
>>
>> - Rob, Bjorn, Krzysztof
>>
>> - Data role
>> The data-role path is
>> connector/port@0 <-> dwc3/port@Y
>
> I believe I have adjusted my dts correctly for v5 compared to v4 but now
> the usb doesn't seem to work anymore in most cases.
>
> Only when having the phone already plugged in during boot in one
> orientation does USB come up, but also disappears once you replug the
> cable. I still see the same (or at least visually similar) messages when
> plugging in the USB cable or the USB stick but nothing more than that
> happens.
>
> Not that v4 worked perfectly on pm7250b+sm7225(/sm6350) but at least it
> worked in most cases as described in the emails there. Since the driver
> structure changed quite a bit, git diff isn't helpful here
> unfortunately.
>
> Don't think it matters but worth mentioning that sm6350 uses the new
> qmpphy bindings as described in qcom,sc8280xp-qmp-usb43dp-phy.yaml (this
> was also the case when testing v4 of this).
>
> Any idea?
Can you confirm the output of /sys/class/typec/port0/orientation in host
mode with the USB key / peripheral in both orientations ?
If that's still OK, then perhaps we can figure out the gap in the PHY
code for v3
@caleb is working on this code for sdm845 which is a v3 PHY
---
bod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description
2023-04-13 11:34 ` [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description Bryan O'Donoghue
@ 2023-04-13 20:28 ` kernel test robot
2023-04-15 13:51 ` kernel test robot
1 sibling, 0 replies; 43+ messages in thread
From: kernel test robot @ 2023-04-13 20:28 UTC (permalink / raw)
To: Bryan O'Donoghue; +Cc: llvm, oe-kbuild-all
Hi Bryan,
kernel test robot noticed the following build errors:
[auto build test ERROR on usb/usb-testing]
[also build test ERROR on usb/usb-next usb/usb-linus robh/for-next broonie-regulator/for-next linus/master v6.3-rc6 next-20230412]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Bryan-O-Donoghue/dt-bindings-regulator-qcom-usb-vbus-regulator-Mark-reg-as-required/20230413-193753
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
patch link: https://lore.kernel.org/r/20230413113438.1577658-9-bryan.odonoghue%40linaro.org
patch subject: [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description
config: arm-randconfig-r046-20230409 (https://download.01.org/0day-ci/archive/20230414/202304140402.JsxaGCU5-lkp@intel.com/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project 9638da200e00bd069e6dd63604e14cbafede9324)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install arm cross compiling tool for clang build
# apt-get install binutils-arm-linux-gnueabi
# https://github.com/intel-lab-lkp/linux/commit/f70460d49d6af0c5f743cf69873fbc60dbd2c4be
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Bryan-O-Donoghue/dt-bindings-regulator-qcom-usb-vbus-regulator-Mark-reg-as-required/20230413-193753
git checkout f70460d49d6af0c5f743cf69873fbc60dbd2c4be
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304140402.JsxaGCU5-lkp@intel.com/
All errors (new ones prefixed by >>):
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-13 15:08 ` Bryan O'Donoghue
@ 2023-04-14 6:51 ` Luca Weiss
2023-04-17 0:30 ` Bryan O'Donoghue
0 siblings, 1 reply; 43+ messages in thread
From: Luca Weiss @ 2023-04-14 6:51 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On Thu Apr 13, 2023 at 5:08 PM CEST, Bryan O'Donoghue wrote:
> On 13/04/2023 15:19, Luca Weiss wrote:
> > Hi Bryan,
> >
> > On Thu Apr 13, 2023 at 1:34 PM CEST, Bryan O'Donoghue wrote:
> >> V5:
> >> - Amagamates into once device, Heikki, Rob
> >>
> >> - Takes feedback on usage form Luka and Jianhua on VSafeV state transition detection
> >> dev_err() -> dev_warn()
> >>
> >> - Orientation graph example and general expected bindings
> >> I discussed offline with Bjorn the conclusions of the glink/sbu model.
> >> The expected orientation-switch path is
> >> connector/port@0 <-> phy/port@X <-> dp/port@0
> >> This can then be expanded to
> >> connector/port@0 <-> redriver/port@0 <-> phy/port@X <-> dp/port@0
> >>
> >> - Rob, Bjorn, Krzysztof
> >>
> >> - Data role
> >> The data-role path is
> >> connector/port@0 <-> dwc3/port@Y
> >
> > I believe I have adjusted my dts correctly for v5 compared to v4 but now
> > the usb doesn't seem to work anymore in most cases.
> >
> > Only when having the phone already plugged in during boot in one
> > orientation does USB come up, but also disappears once you replug the
> > cable. I still see the same (or at least visually similar) messages when
> > plugging in the USB cable or the USB stick but nothing more than that
> > happens.
> >
> > Not that v4 worked perfectly on pm7250b+sm7225(/sm6350) but at least it
> > worked in most cases as described in the emails there. Since the driver
> > structure changed quite a bit, git diff isn't helpful here
> > unfortunately.
> >
> > Don't think it matters but worth mentioning that sm6350 uses the new
> > qmpphy bindings as described in qcom,sc8280xp-qmp-usb43dp-phy.yaml (this
> > was also the case when testing v4 of this).
> >
> > Any idea?
>
> Can you confirm the output of /sys/class/typec/port0/orientation in host
> mode with the USB key / peripheral in both orientations ?
I see "reverse" and "normal" depending on the direction the USB stick is
plugged in. When unplugged but also when plugged into my PC it stays at
"unknown".
>
> If that's still OK, then perhaps we can figure out the gap in the PHY
> code for v3
>
> @caleb is working on this code for sdm845 which is a v3 PHY
Regards
Luca
>
> ---
> bod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional
2023-04-13 11:34 ` [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional Bryan O'Donoghue
@ 2023-04-14 7:23 ` Marijn Suijten
2023-04-16 17:47 ` Krzysztof Kozlowski
1 sibling, 0 replies; 43+ messages in thread
From: Marijn Suijten @ 2023-04-14 7:23 UTC (permalink / raw)
To: Bryan O'Donoghue
Cc: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree,
caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 2023-04-13 12:34:28, Bryan O'Donoghue wrote:
> Add ports as an optional
"Add the following ports as optional ...:"
>
> port@0 to receive an orientation-switch message from the Type-C port or
> redriver
>
> port@1 to subsequently transmit the orientation-switch on once the PHY has
> finished doing its orientation turn-around.
>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
> .../phy/qcom,sc7180-qmp-usb3-dp-phy.yaml | 34 +++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
> index d307343388888..9ef69ad12b74a 100644
> --- a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
> @@ -65,6 +65,22 @@ properties:
> description: Flag the port as possible handler of orientation switching
> type: boolean
>
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description: OF graph bindings that model incoming orientation-switch and
> + outgoing orientation-switch messages. An example of an incoming
> + orientation-switch message might come form a Type-C connector or a USB
Nit: form -> from
> + redriver. An example of an output would be a DisplayPort controller.
> +
> + properties:
> + port@0:
> + $ref: /schemas/graph.yaml#/properties/port
> + description: Type-C mux orientation-switch input.
> +
> + port@1:
> + $ref: /schemas/graph.yaml#/properties/port
> + description: PHY orientation-siwtch output.
> +
> resets:
> items:
> - description: reset of phy block.
> @@ -279,4 +295,22 @@ examples:
> #clock-cells = <1>;
> #phy-cells = <0>;
> };
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + qmpphy_typec_mux_in: endpoint {
> + remote-endpoint = <&pmic_typec_mux_out>;
> + };
> + };
Nit: space?
- Marijn
> + port@1 {
> + reg = <1>;
> + qmpphy_typec_mux_out: endpoint {
> + remote-endpoint = <&dp_typec_mux_in>;
> + };
> + };
> + };
> };
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 05/14] dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema
2023-04-13 11:34 ` [PATCH v5 05/14] dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema Bryan O'Donoghue
@ 2023-04-14 7:27 ` Marijn Suijten
2023-04-16 17:49 ` Krzysztof Kozlowski
1 sibling, 0 replies; 43+ messages in thread
From: Marijn Suijten @ 2023-04-14 7:27 UTC (permalink / raw)
To: Bryan O'Donoghue
Cc: linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree,
caleb.connolly, konrad.dybcio, subbaram, jackp, robertom,
Wesley Cheng
On 2023-04-13 12:34:29, Bryan O'Donoghue wrote:
> Add a YAML binding for the Type-C silicon interface inside Qualcomm's
> pm8150b hardware block.
>
> The Type-C driver operates with a pdphy driver inside of a high level
> single TCPM device.
>
> Based on original work by Wesley.
>
> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
> .../bindings/usb/qcom,pmic-typec.yaml | 169 ++++++++++++++++++
> 1 file changed, 169 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
>
> diff --git a/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
> new file mode 100644
> index 0000000000000..6d0f5d00305cf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
> @@ -0,0 +1,169 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: "http://devicetree.org/schemas/usb/qcom,pmic-typec.yaml#"
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#"
> +
> +title: Qualcomm PMIC based USB Type-C block
> +
> +maintainers:
> + - Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> +
> +description: |
> + Qualcomm PMIC Type-C block
> +
> +properties:
> + compatible:
> + enum:
> + - qcom,pm8150b-typec
> +
> + connector:
> + type: object
> + $ref: /schemas/connector/usb-connector.yaml#
> + unevaluatedProperties: false
> +
> + reg:
> + description: Type-C port and pdphy SPMI register base offsets
> + minItems: 2
> + maxItems: 2
> +
> + interrupts:
> + items:
> + - description: Bitmask of CC attach, VBUS error, tCCDebounce done and more
> + - description: VCONN Powered Detection
> + - description: CC state change
> + - description: VCONN over-current condition
> + - description: VBUS state change
> + - description: Attach Deteach notification
Deteach -> Detach
> + - description: Legacy cable detect
> + - description: Try.Src Try.Snk state change
> + - description: Sig TX - transmitted reset signal
> + - description: Sig RX - received reset signal
> + - description: TX completion
> + - description: RX completion
> + - description: TX fail
> + - description: TX discgard
> + - description: RX discgard
discgard (2x) -> discard
> + - description: Fast Role Swap event
None of these descriptions follow a similar pattern and are very hard to
read and understand. Can you rewrite them? For starters, think about
using the same wording and capitalization.
> +
> + interrupt-names:
> + items:
> + - const: or-rid-detect-change
> + - const: vpd-detect
> + - const: cc-state-change
> + - const: vconn-oc
> + - const: vbus-change
> + - const: attach-detach
> + - const: legacy-cable-detect
> + - const: try-snk-src-detect
> + - const: sig-tx
> + - const: sig-rx
> + - const: msg-tx
> + - const: msg-rx
> + - const: msg-tx-failed
> + - const: msg-tx-discarded
> + - const: msg-rx-discarded
> + - const: fr-swap
> +
> + vdd-vbus-supply:
> + description: VBUS power supply.
> +
> + vdd-pdphy-supply:
> + description: VDD regulator supply to the PDPHY.
> +
> + port:
> + $ref: /schemas/graph.yaml#/properties/port
> + description:
> + Contains a port which produces data-role switching messages.
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - interrupt-names
> + - vdd-vbus-supply
> + - vdd-pdphy-supply
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/usb/pd.h>
> +
> + pm8150b {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + pm8150b_typec: typec@1500 {
> + compatible = "qcom,pm8150b-typec";
> + reg = <0x1500>,
> + <0x1700>;
> +
> + interrupts = <0x2 0x15 0x00 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x15 0x01 IRQ_TYPE_EDGE_BOTH>,
> + <0x2 0x15 0x02 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x15 0x03 IRQ_TYPE_EDGE_BOTH>,
> + <0x2 0x15 0x04 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x15 0x05 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x15 0x06 IRQ_TYPE_EDGE_BOTH>,
> + <0x2 0x15 0x07 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x17 0x00 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x17 0x01 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x17 0x02 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x17 0x03 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x17 0x04 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x17 0x05 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x17 0x06 IRQ_TYPE_EDGE_RISING>,
> + <0x2 0x17 0x07 IRQ_TYPE_EDGE_RISING>;
> +
> + interrupt-names = "or-rid-detect-change",
> + "vpd-detect",
> + "cc-state-change",
> + "vconn-oc",
> + "vbus-change",
> + "attach-detach",
> + "legacy-cable-detect",
> + "try-snk-src-detect",
> + "sig-tx",
> + "sig-rx",
> + "msg-tx",
> + "msg-rx",
> + "msg-tx-failed",
> + "msg-tx-discarded",
> + "msg-rx-discarded",
> + "fr-swap";
> +
> + vdd-vbus-supply = <&pm8150b_vbus>;
> + vdd-pdphy-supply = <&vreg_l2a_3p1>;
> + connector {
> + compatible = "usb-c-connector";
> +
> + power-role = "source";
> + data-role = "dual";
> + self-powered;
> +
> + source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_DUAL_ROLE |
> + PDO_FIXED_USB_COMM | PDO_FIXED_DATA_SWAP)>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + pm8150b_typec_mux_out: endpoint {
> + remote-endpoint = <&qmpphy_typec_mux_in>;
> + };
> + };
Also a newline?
- Marijn
> + port@1 {
> + reg = <1>;
> + pm8150b_typec_role_switch_out: endpoint {
> + remote-endpoint = <&dwc3_role_switch_in>;
> + };
> + };
> + };
> + };
> + };
> + };
> +...
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description
2023-04-13 11:34 ` [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description Bryan O'Donoghue
2023-04-13 20:28 ` kernel test robot
@ 2023-04-15 13:51 ` kernel test robot
1 sibling, 0 replies; 43+ messages in thread
From: kernel test robot @ 2023-04-15 13:51 UTC (permalink / raw)
To: Bryan O'Donoghue; +Cc: oe-kbuild-all
Hi Bryan,
kernel test robot noticed the following build errors:
[auto build test ERROR on usb/usb-testing]
[also build test ERROR on usb/usb-next usb/usb-linus robh/for-next broonie-regulator/for-next linus/master v6.3-rc6]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Bryan-O-Donoghue/dt-bindings-regulator-qcom-usb-vbus-regulator-Mark-reg-as-required/20230413-193753
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
patch link: https://lore.kernel.org/r/20230413113438.1577658-9-bryan.odonoghue%40linaro.org
patch subject: [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description
config: arm-allyesconfig (https://download.01.org/0day-ci/archive/20230415/202304152117.Bbof9aHB-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/f70460d49d6af0c5f743cf69873fbc60dbd2c4be
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Bryan-O-Donoghue/dt-bindings-regulator-qcom-usb-vbus-regulator-Mark-reg-as-required/20230413-193753
git checkout f70460d49d6af0c5f743cf69873fbc60dbd2c4be
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304152117.Bbof9aHB-lkp@intel.com/
All errors (new ones prefixed by >>):
>> ERROR: Input tree has errors, aborting (use -f to force output)
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 01/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required
2023-04-13 11:34 ` [PATCH v5 01/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required Bryan O'Donoghue
@ 2023-04-16 17:43 ` Krzysztof Kozlowski
0 siblings, 0 replies; 43+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-16 17:43 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 13/04/2023 13:34, Bryan O'Donoghue wrote:
> The regulator code needs to know the location of the register to write to
> to switch on/off. Right now we have a driver that does this, a yaml that
> partially describes it and no dts that uses it.
>
> Switching on the VBUS for sm8250 shows that we haven't documented reg as a
> required property, do so now.
>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
> .../devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml | 1 +
> 1 file changed, 1 insertion(+)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional
2023-04-13 11:34 ` [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional Bryan O'Donoghue
2023-04-14 7:23 ` Marijn Suijten
@ 2023-04-16 17:47 ` Krzysztof Kozlowski
2023-04-17 0:09 ` Bryan O'Donoghue
1 sibling, 1 reply; 43+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-16 17:47 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 13/04/2023 13:34, Bryan O'Donoghue wrote:
> Add ports as an optional
>
> port@0 to receive an orientation-switch message from the Type-C port or
> redriver
>
> port@1 to subsequently transmit the orientation-switch on once the PHY has
> finished doing its orientation turn-around.
>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
> .../phy/qcom,sc7180-qmp-usb3-dp-phy.yaml | 34 +++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
> index d307343388888..9ef69ad12b74a 100644
> --- a/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml
> @@ -65,6 +65,22 @@ properties:
> description: Flag the port as possible handler of orientation switching
> type: boolean
>
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description: OF graph bindings that model incoming orientation-switch and
> + outgoing orientation-switch messages. An example of an incoming
> + orientation-switch message might come form a Type-C connector or a USB
> + redriver. An example of an output would be a DisplayPort controller.
> +
> + properties:
> + port@0:
> + $ref: /schemas/graph.yaml#/properties/port
> + description: Type-C mux orientation-switch input.
> +
> + port@1:
> + $ref: /schemas/graph.yaml#/properties/port
> + description: PHY orientation-siwtch output.
typo: switch
I assume both ports are required? Could it work without input or output?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 05/14] dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema
2023-04-13 11:34 ` [PATCH v5 05/14] dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema Bryan O'Donoghue
2023-04-14 7:27 ` Marijn Suijten
@ 2023-04-16 17:49 ` Krzysztof Kozlowski
1 sibling, 0 replies; 43+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-16 17:49 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom, Wesley Cheng
On 13/04/2023 13:34, Bryan O'Donoghue wrote:
> Add a YAML binding for the Type-C silicon interface inside Qualcomm's
> pm8150b hardware block.
>
> The Type-C driver operates with a pdphy driver inside of a high level
> single TCPM device.
Subject: drop second/last, redundant "YAML schema". The "dt-bindings"
prefix is already stating that these are bindings (and their format).
>
> Based on original work by Wesley.
>
> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
> .../bindings/usb/qcom,pmic-typec.yaml | 169 ++++++++++++++++++
> 1 file changed, 169 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
>
> diff --git a/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
> new file mode 100644
> index 0000000000000..6d0f5d00305cf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
> @@ -0,0 +1,169 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: "http://devicetree.org/schemas/usb/qcom,pmic-typec.yaml#"
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#"
Drop quotes from both.
> +
> +title: Qualcomm PMIC based USB Type-C block
> +
> +maintainers:
> + - Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> +
> +description: |
Do not need '|' unless you need to preserve formatting.
> + Qualcomm PMIC Type-C block
> +
> +properties:
> + compatible:
> + enum:
> + - qcom,pm8150b-typec
> +
> + connector:
> + type: object
> + $ref: /schemas/connector/usb-connector.yaml#
> + unevaluatedProperties: false
> +
> + reg:
> + description: Type-C port and pdphy SPMI register base offsets
> + minItems: 2
Drop minItems.
> + maxItems: 2
> +
> + interrupts:
> + items:
> + - description: Bitmask of CC attach, VBUS error, tCCDebounce done and more
> + - description: VCONN Powered Detection
> + - description: CC state change
> + - description: VCONN over-current condition
> + - description: VBUS state change
> + - description: Attach Deteach notification
> + - description: Legacy cable detect
> + - description: Try.Src Try.Snk state change
> + - description: Sig TX - transmitted reset signal
> + - description: Sig RX - received reset signal
> + - description: TX completion
> + - description: RX completion
> + - description: TX fail
> + - description: TX discgard
> + - description: RX discgard
> + - description: Fast Role Swap event
> +
> + interrupt-names:
> + items:
> + - const: or-rid-detect-change
> + - const: vpd-detect
> + - const: cc-state-change
> + - const: vconn-oc
> + - const: vbus-change
> + - const: attach-detach
> + - const: legacy-cable-detect
> + - const: try-snk-src-detect
> + - const: sig-tx
> + - const: sig-rx
> + - const: msg-tx
> + - const: msg-rx
> + - const: msg-tx-failed
> + - const: msg-tx-discarded
> + - const: msg-rx-discarded
> + - const: fr-swap
> +
> + vdd-vbus-supply:
> + description: VBUS power supply.
> +
> + vdd-pdphy-supply:
> + description: VDD regulator supply to the PDPHY.
> +
> + port:
> + $ref: /schemas/graph.yaml#/properties/port
> + description:
> + Contains a port which produces data-role switching messages.
I think Rob asked for example for this...
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - interrupt-names
> + - vdd-vbus-supply
> + - vdd-pdphy-supply
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/usb/pd.h>
> +
> + pm8150b {
pmic
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 06/14] dt-bindings: mfd: qcom,spmi-pmic: Add typec to SPMI device types
2023-04-13 11:34 ` [PATCH v5 06/14] dt-bindings: mfd: qcom,spmi-pmic: Add typec to SPMI device types Bryan O'Donoghue
@ 2023-04-16 17:50 ` Krzysztof Kozlowski
0 siblings, 0 replies; 43+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-16 17:50 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 13/04/2023 13:34, Bryan O'Donoghue wrote:
> Add the PMIC Type-C port driver to the list of devices.
>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
This depends on previous patch, so should go together. You should
clearly communicate dependencies/merging in cover letter. At the top of
it, so maintainers will know they *cannot* pick it up independently.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional
2023-04-16 17:47 ` Krzysztof Kozlowski
@ 2023-04-17 0:09 ` Bryan O'Donoghue
2023-04-17 6:16 ` Krzysztof Kozlowski
0 siblings, 1 reply; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-17 0:09 UTC (permalink / raw)
To: Krzysztof Kozlowski, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 16/04/2023 18:47, Krzysztof Kozlowski wrote:
> I assume both ports are required? Could it work without input or output?
It can work without an output because we might not have DP switched on
-> bog-standard USB orientation-switching in host-only, device-only or
dual-role modes.
---
bod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-14 6:51 ` Luca Weiss
@ 2023-04-17 0:30 ` Bryan O'Donoghue
2023-04-17 7:35 ` Luca Weiss
0 siblings, 1 reply; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-17 0:30 UTC (permalink / raw)
To: Luca Weiss, linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 14/04/2023 07:51, Luca Weiss wrote:
> I see "reverse" and "normal" depending on the direction the USB stick is
> plugged in. When unplugged but also when plugged into my PC it stays at
> "unknown".
Right so, this is down to bad behavior on the PHY patch, which is
resolved for me on sm8250 with the below.
Basically when you unplug a device you would transition back to
"TYPEC_ORIENTATION_NONE" but that would turn off the PHY, which is obs
not very useful if you want to subsequently be a gadget.
Anyway thanks for testing this - I'd missed the
host->device->host->device ping-pong breakage.
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index b9a30c087423d..edb788a71edeb 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -3372,12 +3372,13 @@ static int qmp_combo_typec_switch_set(struct
typec_switch_dev *sw,
qmp->orientation = orientation;
- if (orientation == TYPEC_ORIENTATION_NONE) {
- if (qmp->init_count)
- ret = qmp_combo_dp_power_off(dp_phy);
- } else {
- if (!qmp->init_count)
- ret = qmp_combo_dp_power_on(dp_phy);
+ if (orientation != TYPEC_ORIENTATION_NONE) {
+ ret = qmp_combo_dp_power_off(dp_phy);
+ if (ret)
+ return ret;
+ ret = qmp_combo_dp_power_on(dp_phy);
+ if (ret)
+ return ret;
}
---
bod
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional
2023-04-17 0:09 ` Bryan O'Donoghue
@ 2023-04-17 6:16 ` Krzysztof Kozlowski
0 siblings, 0 replies; 43+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-17 6:16 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 17/04/2023 02:09, Bryan O'Donoghue wrote:
> On 16/04/2023 18:47, Krzysztof Kozlowski wrote:
>> I assume both ports are required? Could it work without input or output?
>
> It can work without an output because we might not have DP switched on
> -> bog-standard USB orientation-switching in host-only, device-only or
> dual-role modes.
>
Then I guess:
required:
- port@0
(or whichever was input)
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-17 0:30 ` Bryan O'Donoghue
@ 2023-04-17 7:35 ` Luca Weiss
2023-04-17 10:04 ` Bryan O'Donoghue
0 siblings, 1 reply; 43+ messages in thread
From: Luca Weiss @ 2023-04-17 7:35 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On Mon Apr 17, 2023 at 2:30 AM CEST, Bryan O'Donoghue wrote:
> On 14/04/2023 07:51, Luca Weiss wrote:
> > I see "reverse" and "normal" depending on the direction the USB stick is
> > plugged in. When unplugged but also when plugged into my PC it stays at
> > "unknown".
>
> Right so, this is down to bad behavior on the PHY patch, which is
> resolved for me on sm8250 with the below.
>
> Basically when you unplug a device you would transition back to
> "TYPEC_ORIENTATION_NONE" but that would turn off the PHY, which is obs
> not very useful if you want to subsequently be a gadget.
>
> Anyway thanks for testing this - I'd missed the
> host->device->host->device ping-pong breakage.
Hm, unfortunately no improvement with this on my side.. No USB
connection pops up on the host, or USB messages regarding the USB stick
on the device.
Do you have an idea in which part of the code to start debugging this?
Since orientation detection is working is it maybe in the phy code and
not in the tcpm driver? Or does that also touch crucial stuff for USB
apart from telling phy which direction to use?
Regards
Luca
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index b9a30c087423d..edb788a71edeb 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -3372,12 +3372,13 @@ static int qmp_combo_typec_switch_set(struct
> typec_switch_dev *sw,
>
> qmp->orientation = orientation;
>
> - if (orientation == TYPEC_ORIENTATION_NONE) {
> - if (qmp->init_count)
> - ret = qmp_combo_dp_power_off(dp_phy);
> - } else {
> - if (!qmp->init_count)
> - ret = qmp_combo_dp_power_on(dp_phy);
> + if (orientation != TYPEC_ORIENTATION_NONE) {
> + ret = qmp_combo_dp_power_off(dp_phy);
> + if (ret)
> + return ret;
> + ret = qmp_combo_dp_power_on(dp_phy);
> + if (ret)
> + return ret;
> }
>
> ---
> bod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-17 7:35 ` Luca Weiss
@ 2023-04-17 10:04 ` Bryan O'Donoghue
2023-04-17 10:11 ` Bryan O'Donoghue
2023-04-21 10:26 ` Luca Weiss
0 siblings, 2 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-17 10:04 UTC (permalink / raw)
To: Luca Weiss, linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 17/04/2023 08:35, Luca Weiss wrote:
> Do you have an idea in which part of the code to start debugging this?
> Since orientation detection is working is it maybe in the phy code and
> not in the tcpm driver? Or does that also touch crucial stuff for USB
> apart from telling phy which direction to use?
PHY - I'd almost just do the following
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index edb788a71edeb..bbac82bd093f8 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -3369,7 +3369,7 @@ static int qmp_combo_typec_switch_set(struct
typec_switch_dev *sw,
dev_dbg(qmp->dev, "Toggling orientation current %d requested %d\n",
qmp->orientation, orientation);
-
+return 0;
In that case the PHY should "just work" for host or device in one
orientation.
The other possibility is that the data role message is not hitting dwc3
drd on your platform.
If you take the last commit on this branch - plus the updated PHY commit
Commit: 171d7f507511 ("usb: dwc3: drd: Enable user-space triggered
role-switching")
Commit: eb0daa19f3ad ("phy: qcom-qmp: Register as a typec switch for
orientation detection")
https://git.codelinaro.org/bryan.odonoghue/kernel/-/tree/linux-next-23-04-17-pm8150b-tcpm-qcom-wrapper-typec-mux
cat /sys/class/usb_role/a600000.usb-role-switch/role
On SM8250 it looks like this
- Attach TypeC accessory with USB key plugged in [1]
Mount USB key, read/write some data
Unmount USB key
cat /sys/class/usb_role/a600000.usb-role-switch/role
host
- Attach TypeC accessory in opposite orientation
Run same test
- Connect to PC via TypeC cable
Run usb-ecm-up.sh [2]
cat /sys/class/usb_role/a600000.usb-role-switch/role
device
PC : ifconfig enp49s0f3u2u4 192.168.8.1
SM8250 : ifconfig usb0 192.168.8.2
Then
PC : iperf -s
SM8250 : iperf -c 192.168.8.1 -t 10
[ 1] 0.0000-10.0706 sec 307 MBytes 256 Mbits/sec
- Unplug from PC - replug TypeC accessory
Rerun test in both orientations
- Replug target to PC
In this case we only have to reset the IP address
PC : ifconfig enp49s0f3u2u4 192.168.8.1
SM8250 : ifconfig usb0 192.168.8.2
Yep its worth checking out that the data-role switch is working, we
might be looking at the wrong thing for you on the PHY.
[1]
https://www.amazon.com/CableCreation-Multiport-Adapter-Gigabit-Ethernet/dp/B08FWMWGTD
[2] usb-ecm-up.sh
root@linaro-gnome:~# cat usb-ecm-up.sh
#!/usr/bin/env bash
# load libcomposite module
modprobe libcomposite
# ensure function is loaded
modprobe usb_f_ecm
modprobe usb_f_ncm
mount -t configfs none /sys/kernel/config/
# create a gadget
mkdir /sys/kernel/config/usb_gadget/g0
# cd to its configfs node
cd /sys/kernel/config/usb_gadget/g0
# configure it (vid/pid can be anything if USB Class is used for driver
compat)
echo 0x0525 > idVendor
echo 0xa4a4 > idProduct
# configure its serial/mfg/product
mkdir strings/0x409
echo 0xCAFEBABE > strings/0x409/serialnumber
echo Linaro > strings/0x409/manufacturer
echo qrb5165-rb5 > strings/0x409/product
# create configs
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
# create the function (name must match a usb_f_<name> module such as 'acm')
mkdir functions/ncm.0
echo "CDC ECM" > configs/c.1/strings/0x409/configuration
# associate function with config
ln -s functions/ncm.0 configs/c.1
# Set USB version 3.1
echo 0x0310 > bcdUSB
echo "super-speed-plus" > max_speed
# enable gadget by binding it to a UDC from /sys/class/udc
#echo a600000.dwc3 > UDC
echo a600000.usb > UDC
# to unbind it: echo "" > UDC; sleep 1; rm -rf
/sys/kernel/config/usb_gadget/g0
sleep 1
ifconfig usb0 192.168.8.2
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-17 10:04 ` Bryan O'Donoghue
@ 2023-04-17 10:11 ` Bryan O'Donoghue
2023-04-21 10:26 ` Luca Weiss
1 sibling, 0 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-17 10:11 UTC (permalink / raw)
To: Luca Weiss, linux, heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 17/04/2023 11:04, Bryan O'Donoghue wrote:
> Unmount USB key
>
> cat /sys/class/usb_role/a600000.usb-role-switch/role
> host
Sorry obviously confirm the data role before detaching the accessory :)
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection
2023-04-13 11:34 ` [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection Bryan O'Donoghue
2023-04-13 13:34 ` kernel test robot
@ 2023-04-18 12:57 ` Bjorn Andersson
2023-04-18 16:54 ` Bryan O'Donoghue
1 sibling, 1 reply; 43+ messages in thread
From: Bjorn Andersson @ 2023-04-18 12:57 UTC (permalink / raw)
To: Bryan O'Donoghue
Cc: linux, heikki.krogerus, gregkh, robh+dt, krzysztof.kozlowski+dt,
linux-usb, linux-arm-msm, devicetree, caleb.connolly,
konrad.dybcio, subbaram, jackp, robertom, Dmitry Baryshkov,
Wesley Cheng
On Thu, Apr 13, 2023 at 12:34:38PM +0100, Bryan O'Donoghue wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>
> The lane select switch for USB typec orientation is within the USB QMP PHY.
> the current device. It could be connected through an endpoint, to an
> independent device handling the typec detection, ie the QCOM SPMI typec
> driver.
>
> bod: Fixed the logic qcom_qmp_phy_typec_switch_set() to disable phy
> on disconnect if and only if we have initialized the PHY.
> Retained CC orientation logic in qcom_qmp_phy_com_init() to simplify
> patch.
>
> bod: Ported from earlier version of driver to phy-qcom-qmp-combo.c
>
> Co-developed-by: Wesley Cheng <wcheng@codeaurora.org>
> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
> Co-developed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Your s-o-b should be last here...
> ---
> drivers/phy/qualcomm/Kconfig | 8 +++
> drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 80 +++++++++++++++++++++--
> 2 files changed, 84 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
> index 4850d48f31fa1..8240fffdbed4e 100644
> --- a/drivers/phy/qualcomm/Kconfig
> +++ b/drivers/phy/qualcomm/Kconfig
> @@ -101,6 +101,14 @@ config PHY_QCOM_QMP_USB
>
> endif # PHY_QCOM_QMP
>
> +config PHY_QCOM_QMP_TYPEC
> + def_bool PHY_QCOM_QMP=y && TYPEC=y || PHY_QCOM_QMP=m && TYPEC
> + help
> + Register a type C switch from the QMP PHY driver for type C
> + orientation support. This has dependencies with if the type C kernel
> + configuration is enabled or not. This support will not be present if
> + USB type C is disabled.
> +
> config PHY_QCOM_QUSB2
> tristate "Qualcomm QUSB2 PHY Driver"
> depends on OF && (ARCH_QCOM || COMPILE_TEST)
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index 6850e04c329b8..b9a30c087423d 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -19,6 +19,7 @@
> #include <linux/regulator/consumer.h>
> #include <linux/reset.h>
> #include <linux/slab.h>
> +#include <linux/usb/typec_mux.h>
>
> #include <dt-bindings/phy/phy-qcom-qmp.h>
>
> @@ -63,6 +64,10 @@
> /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
> #define CLAMP_EN BIT(0) /* enables i/o clamp_n */
>
> +/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */
> +#define SW_PORTSELECT_VAL BIT(0)
> +#define SW_PORTSELECT_MUX BIT(1)
> +
> #define PHY_INIT_COMPLETE_TIMEOUT 10000
>
> struct qmp_phy_init_tbl {
> @@ -1323,6 +1328,9 @@ struct qmp_combo {
> struct clk_fixed_rate pipe_clk_fixed;
> struct clk_hw dp_link_hw;
> struct clk_hw dp_pixel_hw;
> +
> + struct typec_switch_dev *sw;
> + enum typec_orientation orientation;
> };
>
> static void qmp_v3_dp_aux_init(struct qmp_combo *qmp);
> @@ -1955,7 +1963,8 @@ static void qmp_v3_configure_dp_tx(struct qmp_combo *qmp)
> static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
> {
> u32 val;
> - bool reverse = false;
> + bool reverse = qmp->orientation == TYPEC_ORIENTATION_REVERSE;
> + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
>
> val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
> @@ -1974,10 +1983,18 @@ static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
> * if (orientation == ORIENTATION_CC2)
> * writel(0x4c, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_MODE);
> */
> + if (dp_opts->lanes == 4 || reverse)
> + val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
> + if (dp_opts->lanes == 4 || !reverse)
> + val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
> +
> val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
When "reverse" this implies 4 lanes, I think it's an accidental left
over from introducing the conditionals.
> writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
>
> - writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
> + if (reverse)
> + writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE);
> + else
> + writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE);
>
> return reverse;
> }
> @@ -2461,6 +2478,7 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
> {
> const struct qmp_phy_cfg *cfg = qmp->cfg;
> void __iomem *com = qmp->com;
> + u32 val;
> int ret;
>
> mutex_lock(&qmp->phy_mutex);
> @@ -2498,8 +2516,11 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
> SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
> SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
>
> - /* Default type-c orientation, i.e CC1 */
> - qphy_setbits(com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02);
> + /* Latch CC orientation based on reported state by TCPM */
> + val = SW_PORTSELECT_MUX;
> + if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
> + val |= SW_PORTSELECT_VAL;
> + qphy_setbits(com, QPHY_V3_DP_COM_TYPEC_CTRL, val);
>
> qphy_setbits(com, QPHY_V3_DP_COM_PHY_MODE_CTRL, USB3_MODE | DP_MODE);
>
> @@ -3338,6 +3359,53 @@ static struct phy *qmp_combo_phy_xlate(struct device *dev, struct of_phandle_arg
> return ERR_PTR(-EINVAL);
> }
>
> +#if IS_ENABLED(CONFIG_PHY_QCOM_QMP_TYPEC)
> +static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw,
> + enum typec_orientation orientation)
> +{
> + struct qmp_combo *qmp = typec_switch_get_drvdata(sw);
> + struct phy *dp_phy = qmp->dp_phy;
> + int ret = 0;
> +
> + dev_dbg(qmp->dev, "Toggling orientation current %d requested %d\n",
> + qmp->orientation, orientation);
> +
> + qmp->orientation = orientation;
> +
> + if (orientation == TYPEC_ORIENTATION_NONE) {
> + if (qmp->init_count)
> + ret = qmp_combo_dp_power_off(dp_phy);
> + } else {
> + if (!qmp->init_count)
> + ret = qmp_combo_dp_power_on(dp_phy);
> + }
This sequence is crashing my laptop, need some more time to debug the
actual cause.
Regards,
Bjorn
> +
> + return 0;
> +}
> +
> +static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
> +{
> + struct typec_switch_desc sw_desc;
> + struct device *dev = qmp->dev;
> +
> + sw_desc.drvdata = qmp;
> + sw_desc.fwnode = dev->fwnode;
> + sw_desc.set = qmp_combo_typec_switch_set;
> + qmp->sw = typec_switch_register(dev, &sw_desc);
> + if (IS_ERR(qmp->sw)) {
> + dev_err(dev, "Error registering typec switch: %ld\n",
> + PTR_ERR(qmp->sw));
> + }
> +
> + return 0;
> +}
> +#else
> +static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
> +{
> + return 0;
> +}
> +#endif
> +
> static int qmp_combo_probe(struct platform_device *pdev)
> {
> struct qmp_combo *qmp;
> @@ -3428,6 +3496,10 @@ static int qmp_combo_probe(struct platform_device *pdev)
> else
> phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
>
> + ret = qmp_combo_typec_switch_register(qmp);
> + if (ret)
> + goto err_node_put;
> +
> of_node_put(usb_np);
> of_node_put(dp_np);
>
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection
2023-04-18 12:57 ` Bjorn Andersson
@ 2023-04-18 16:54 ` Bryan O'Donoghue
0 siblings, 0 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-18 16:54 UTC (permalink / raw)
To: Bjorn Andersson
Cc: linux, heikki.krogerus, gregkh, robh+dt, krzysztof.kozlowski+dt,
linux-usb, linux-arm-msm, devicetree, caleb.connolly,
konrad.dybcio, subbaram, jackp, robertom, Dmitry Baryshkov,
Wesley Cheng
On 18/04/2023 13:57, Bjorn Andersson wrote:
>> + dev_dbg(qmp->dev, "Toggling orientation current %d requested %d\n",
>> + qmp->orientation, orientation);
>> +
>> + qmp->orientation = orientation;
>> +
>> + if (orientation == TYPEC_ORIENTATION_NONE) {
>> + if (qmp->init_count)
>> + ret = qmp_combo_dp_power_off(dp_phy);
>> + } else {
>> + if (!qmp->init_count)
>> + ret = qmp_combo_dp_power_on(dp_phy);
>> + }
> This sequence is crashing my laptop, need some more time to debug the
> actual cause.
>
> Regards,
> Bjorn
>
https://git.codelinaro.org/bryan.odonoghue/kernel/-/tree/linux-next-23-04-17-pm8150b-tcpm-qcom-wrapper-typec-mux
This works for me on sm8250 nicely - I can transition from device to
host and back again in both orientations - I'm about to send out V6 with
this contained, I haven't tried/enabled it on x13s yet though.
https://git.codelinaro.org/bryan.odonoghue/kernel/-/commit/2c80c630636f1739bde4c1aac2b20940b84daf71
---
bod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-17 10:04 ` Bryan O'Donoghue
2023-04-17 10:11 ` Bryan O'Donoghue
@ 2023-04-21 10:26 ` Luca Weiss
2023-04-22 22:16 ` Bryan O'Donoghue
1 sibling, 1 reply; 43+ messages in thread
From: Luca Weiss @ 2023-04-21 10:26 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
Hi Bryan,
On Mon Apr 17, 2023 at 12:04 PM CEST, Bryan O'Donoghue wrote:
> On 17/04/2023 08:35, Luca Weiss wrote:
> > Do you have an idea in which part of the code to start debugging this?
> > Since orientation detection is working is it maybe in the phy code and
> > not in the tcpm driver? Or does that also touch crucial stuff for USB
> > apart from telling phy which direction to use?
>
> PHY - I'd almost just do the following
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index edb788a71edeb..bbac82bd093f8 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -3369,7 +3369,7 @@ static int qmp_combo_typec_switch_set(struct
> typec_switch_dev *sw,
>
> dev_dbg(qmp->dev, "Toggling orientation current %d requested %d\n",
> qmp->orientation, orientation);
> -
> +return 0;
>
> In that case the PHY should "just work" for host or device in one
> orientation.
>
> The other possibility is that the data role message is not hitting dwc3
> drd on your platform.
>
> If you take the last commit on this branch - plus the updated PHY commit
>
> Commit: 171d7f507511 ("usb: dwc3: drd: Enable user-space triggered
> role-switching")
>
> Commit: eb0daa19f3ad ("phy: qcom-qmp: Register as a typec switch for
> orientation detection")
>
> https://git.codelinaro.org/bryan.odonoghue/kernel/-/tree/linux-next-23-04-17-pm8150b-tcpm-qcom-wrapper-typec-mux
>
> cat /sys/class/usb_role/a600000.usb-role-switch/role
>
> On SM8250 it looks like this
>
> - Attach TypeC accessory with USB key plugged in [1]
> Mount USB key, read/write some data
> Unmount USB key
>
> cat /sys/class/usb_role/a600000.usb-role-switch/role
> host
It feels like I spent way too much time now trying to understand the
current behavior across the different patch versions, it's a bit messy,
but in short:
With the "user-space triggered role-switching" patch I can see that
whatever scenario the USB-C port is in, the role is stuck on "device".
Nothing =
Role: device, Orientation: unknown
USB(-A) cable to laptop (either direction) =
Role: device, Orientation: unknown
USB stick up =
Role: device, Orientation: reverse
USB stick down =
Role: device, Orientation: normal
Sometimes/mostly when the USB cable is attached during boot I get USB
connection to the laptop until I unplug, then it won't reenable itself.
Also the early return in qmp_combo_typec_switch_set doesn't seem to
change much I believe? But for sure normally qmp_combo_dp_power_off/on
does not get called so I wouldn't be suprised if this reinit breaks
something in the phy.
> <snip>
>
> Yep its worth checking out that the data-role switch is working, we
> might be looking at the wrong thing for you on the PHY.
>
So this seems to be the case? If that's useful, I can also go back to
the previous (v4?) TCPM revision where the switching mostly worked fine.
(btw the subject has a typo, TPCM instead of TCPM :) )
Regards
Luca
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 11/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for usb_1
2023-04-13 11:34 ` [PATCH v5 11/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for usb_1 Bryan O'Donoghue
@ 2023-04-22 14:52 ` Konrad Dybcio
2023-04-22 14:53 ` Konrad Dybcio
0 siblings, 1 reply; 43+ messages in thread
From: Konrad Dybcio @ 2023-04-22 14:52 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, subbaram, jackp, robertom
On 13.04.2023 13:34, Bryan O'Donoghue wrote:
> Switch on usb-role-switching for usb_1 via TCPM. We need to declare
> usb-role-switch in &usb_1 and associate with the remote-endpoint in TCPM
> which provides the necessary signal.
>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
This belongs to the SoC DTSI as it describes the capabilities
of the USB controllers on the chip.
Also please add a newline before each subnode.
Konrad
> arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 19 ++++++++++++++++++-
> 1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
> index 1e0b6fd59abc9..b5cc45358a474 100644
> --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
> +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
> @@ -1273,7 +1273,13 @@ &usb_1 {
> };
>
> &usb_1_dwc3 {
> - dr_mode = "peripheral";
> + dr_mode = "otg";
> + usb-role-switch;
> + port {
> + dwc3_role_switch_in: endpoint {
> + remote-endpoint = <&pm8150b_role_switch_out>;
> + };
> + };
> };
>
> &usb_1_hsphy {
> @@ -1359,5 +1365,16 @@ connector {
> PDO_FIXED_DUAL_ROLE |
> PDO_FIXED_USB_COMM |
> PDO_FIXED_DATA_SWAP)>;
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + pm8150b_role_switch_out: endpoint {
> + remote-endpoint = <&dwc3_role_switch_in>;
> + };
> + };
> + };
> };
> };
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 11/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for usb_1
2023-04-22 14:52 ` Konrad Dybcio
@ 2023-04-22 14:53 ` Konrad Dybcio
0 siblings, 0 replies; 43+ messages in thread
From: Konrad Dybcio @ 2023-04-22 14:53 UTC (permalink / raw)
To: Bryan O'Donoghue, linux, heikki.krogerus, gregkh, andersson,
robh+dt, krzysztof.kozlowski+dt, linux-usb, linux-arm-msm,
devicetree
Cc: caleb.connolly, subbaram, jackp, robertom
On 22.04.2023 16:52, Konrad Dybcio wrote:
>
>
> On 13.04.2023 13:34, Bryan O'Donoghue wrote:
>> Switch on usb-role-switching for usb_1 via TCPM. We need to declare
>> usb-role-switch in &usb_1 and associate with the remote-endpoint in TCPM
>> which provides the necessary signal.
>>
>> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>> ---
> This belongs to the SoC DTSI as it describes the capabilities
> of the USB controllers on the chip.
>
> Also please add a newline before each subnode.
To be clear, I meant the port definitions and properties,
not the DWC<->PMIC_TCPM port assignments
Konrad
>
> Konrad
>> arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 19 ++++++++++++++++++-
>> 1 file changed, 18 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
>> index 1e0b6fd59abc9..b5cc45358a474 100644
>> --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
>> +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
>> @@ -1273,7 +1273,13 @@ &usb_1 {
>> };
>>
>> &usb_1_dwc3 {
>> - dr_mode = "peripheral";
>> + dr_mode = "otg";
>> + usb-role-switch;
>> + port {
>> + dwc3_role_switch_in: endpoint {
>> + remote-endpoint = <&pm8150b_role_switch_out>;
>> + };
>> + };
>> };
>>
>> &usb_1_hsphy {
>> @@ -1359,5 +1365,16 @@ connector {
>> PDO_FIXED_DUAL_ROLE |
>> PDO_FIXED_USB_COMM |
>> PDO_FIXED_DATA_SWAP)>;
>> + ports {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> +
>> + port@0 {
>> + reg = <0>;
>> + pm8150b_role_switch_out: endpoint {
>> + remote-endpoint = <&dwc3_role_switch_in>;
>> + };
>> + };
>> + };
>> };
>> };
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-21 10:26 ` Luca Weiss
@ 2023-04-22 22:16 ` Bryan O'Donoghue
2023-04-25 7:29 ` Luca Weiss
0 siblings, 1 reply; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-22 22:16 UTC (permalink / raw)
To: Luca Weiss, Bryan O'Donoghue, linux, heikki.krogerus, gregkh,
andersson, robh+dt, krzysztof.kozlowski+dt, linux-usb,
linux-arm-msm, devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On 21/04/2023 11:26, Luca Weiss wrote:
> With the "user-space triggered role-switching" patch I can see that
> whatever scenario the USB-C port is in, the role is stuck on "device".
Hmm.
Could you share a branch ?
---
bod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 13/14] usb: typec: qcom: Add Qualcomm PMIC TCPM support
2023-04-13 11:34 ` [PATCH v5 13/14] usb: typec: qcom: Add Qualcomm PMIC TCPM support Bryan O'Donoghue
@ 2023-04-24 13:11 ` Heikki Krogerus
2023-04-24 13:48 ` Bryan O'Donoghue
0 siblings, 1 reply; 43+ messages in thread
From: Heikki Krogerus @ 2023-04-24 13:11 UTC (permalink / raw)
To: Bryan O'Donoghue
Cc: linux, gregkh, andersson, robh+dt, krzysztof.kozlowski+dt,
linux-usb, linux-arm-msm, devicetree, caleb.connolly,
konrad.dybcio, subbaram, jackp, robertom
On Thu, Apr 13, 2023 at 12:34:37PM +0100, Bryan O'Donoghue wrote:
> This commit adds a QCOM PMIC TCPM driver with an initial pm8150b
> block.
>
> qcom_pmic_virt_tcpm.c : Responsible for registering with TCPM and
> arbitrates access to the Type-C and PDPHY hardware
> blocks in one place.
> This driver presents a virtual device to the Linux
> TCPM layer.
>
> qcom_pmic_pdphy.c: Rsponsible for interfacing with the PDPHY hardware and
> processing power-delivery related calls from TCPM.
> This hardware binding can be extended to facilitate
> similar hardware in different PMICs.
>
> qcom_pmic_typec.c: Responsible for notifying and processing Type-C
> related calls from TCPM.
> This hardware binding can be extended to facilitate
> similar hardware in different PMICs.
>
> This code provides all of the same functionality as the existing
> qcom typec driver plus power-delivery as well.
>
> As a result commit 6c8cf3695176 ("usb: typec: Add QCOM PMIC typec detection
> driver") can be deleted entirely.
>
> References code from Jonathan Marek, Jack Pham, Wesley Cheng, Hemant Kumar,
> Guru Das Srinagesh and Ashay Jaiswal.
>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
I think you need to rewrite the commit message - you still have that
third driver in there - but otherwise I don't have any more comments.
I hope Guenter has time to check this. In any case, FWIW:
Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
> MAINTAINERS | 10 +
> drivers/usb/typec/Kconfig | 13 -
> drivers/usb/typec/Makefile | 1 -
> drivers/usb/typec/qcom-pmic-typec.c | 261 --------
> drivers/usb/typec/tcpm/Kconfig | 11 +
> drivers/usb/typec/tcpm/Makefile | 1 +
> drivers/usb/typec/tcpm/qcom/Makefile | 6 +
> drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c | 362 +++++++++++
> .../typec/tcpm/qcom/qcom_pmic_typec_pdphy.c | 528 +++++++++++++++++
> .../typec/tcpm/qcom/qcom_pmic_typec_pdphy.h | 115 ++++
> .../typec/tcpm/qcom/qcom_pmic_typec_port.c | 560 ++++++++++++++++++
> .../typec/tcpm/qcom/qcom_pmic_typec_port.h | 194 ++++++
> 12 files changed, 1787 insertions(+), 275 deletions(-)
> delete mode 100644 drivers/usb/typec/qcom-pmic-typec.c
> create mode 100644 drivers/usb/typec/tcpm/qcom/Makefile
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
> create mode 100644 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 14a825f2bfb23..35d71858e768b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17530,6 +17530,16 @@ S: Maintained
> F: Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
> F: drivers/thermal/qcom/
>
> +QUALCOMM TYPEC PORT MANAGER DRIVER
> +M: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> +L: linux-arm-msm@vger.kernel.org
> +L: linux-usb@vger.kernel.org
> +S: Maintained
> +F: Documentation/devicetree/bindings/usb/qcom,pmic-*.yaml
> +F: drivers/usb/typec/tcpm/qcom/
> +F: include/dt-bindings/usb/typec/qcom,pmic-pdphy.h
> +F: include/dt-bindings/usb/typec/qcom,pmic-typec.h
> +
> QUALCOMM VENUS VIDEO ACCELERATOR DRIVER
> M: Stanimir Varbanov <stanimir.k.varbanov@gmail.com>
> M: Vikash Garodia <quic_vgarodia@quicinc.com>
> diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
> index 831e7049977df..2f80c2792dbda 100644
> --- a/drivers/usb/typec/Kconfig
> +++ b/drivers/usb/typec/Kconfig
> @@ -100,19 +100,6 @@ 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_PMIC
> - tristate "Qualcomm PMIC USB Type-C driver"
> - depends on ARCH_QCOM || COMPILE_TEST
> - depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
> - help
> - Driver for supporting role switch over the Qualcomm PMIC. This will
> - handle the USB Type-C role and orientation detection reported by the
> - QCOM PMIC if the PMIC has the capability to handle USB Type-C
> - detection.
> -
> - It will also enable the VBUS output to connected devices when a
> - DFP connection is made.
> -
> config TYPEC_WUSB3801
> tristate "Willsemi WUSB3801 Type-C port controller driver"
> depends on I2C
> diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
> index 4a83dad51a6cf..7a368fea61bc9 100644
> --- a/drivers/usb/typec/Makefile
> +++ b/drivers/usb/typec/Makefile
> @@ -8,7 +8,6 @@ obj-$(CONFIG_TYPEC_UCSI) += ucsi/
> obj-$(CONFIG_TYPEC_TPS6598X) += tipd/
> obj-$(CONFIG_TYPEC_ANX7411) += anx7411.o
> obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o
> -obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom-pmic-typec.o
> obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o
> obj-$(CONFIG_TYPEC_RT1719) += rt1719.o
> obj-$(CONFIG_TYPEC_WUSB3801) += wusb3801.o
> diff --git a/drivers/usb/typec/qcom-pmic-typec.c b/drivers/usb/typec/qcom-pmic-typec.c
> deleted file mode 100644
> index 432ea62f1bab6..0000000000000
> --- a/drivers/usb/typec/qcom-pmic-typec.c
> +++ /dev/null
> @@ -1,261 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * Copyright (c) 2020, The Linux Foundation. All rights reserved.
> - */
> -
> -#include <linux/err.h>
> -#include <linux/interrupt.h>
> -#include <linux/kernel.h>
> -#include <linux/mod_devicetable.h>
> -#include <linux/module.h>
> -#include <linux/platform_device.h>
> -#include <linux/regmap.h>
> -#include <linux/regulator/consumer.h>
> -#include <linux/slab.h>
> -#include <linux/usb/role.h>
> -#include <linux/usb/typec_mux.h>
> -
> -#define TYPEC_MISC_STATUS 0xb
> -#define CC_ATTACHED BIT(0)
> -#define CC_ORIENTATION BIT(1)
> -#define SNK_SRC_MODE BIT(6)
> -#define TYPEC_MODE_CFG 0x44
> -#define TYPEC_DISABLE_CMD BIT(0)
> -#define EN_SNK_ONLY BIT(1)
> -#define EN_SRC_ONLY BIT(2)
> -#define TYPEC_VCONN_CONTROL 0x46
> -#define VCONN_EN_SRC BIT(0)
> -#define VCONN_EN_VAL BIT(1)
> -#define TYPEC_EXIT_STATE_CFG 0x50
> -#define SEL_SRC_UPPER_REF BIT(2)
> -#define TYPEC_INTR_EN_CFG_1 0x5e
> -#define TYPEC_INTR_EN_CFG_1_MASK GENMASK(7, 0)
> -
> -struct qcom_pmic_typec {
> - struct device *dev;
> - struct regmap *regmap;
> - u32 base;
> -
> - struct typec_port *port;
> - struct usb_role_switch *role_sw;
> -
> - struct regulator *vbus_reg;
> - bool vbus_enabled;
> -};
> -
> -static void qcom_pmic_typec_enable_vbus_regulator(struct qcom_pmic_typec
> - *qcom_usb, bool enable)
> -{
> - int ret;
> -
> - if (enable == qcom_usb->vbus_enabled)
> - return;
> -
> - if (enable) {
> - ret = regulator_enable(qcom_usb->vbus_reg);
> - if (ret)
> - return;
> - } else {
> - ret = regulator_disable(qcom_usb->vbus_reg);
> - if (ret)
> - return;
> - }
> - qcom_usb->vbus_enabled = enable;
> -}
> -
> -static void qcom_pmic_typec_check_connection(struct qcom_pmic_typec *qcom_usb)
> -{
> - enum typec_orientation orientation;
> - enum usb_role role;
> - unsigned int stat;
> - bool enable_vbus;
> -
> - regmap_read(qcom_usb->regmap, qcom_usb->base + TYPEC_MISC_STATUS,
> - &stat);
> -
> - if (stat & CC_ATTACHED) {
> - orientation = (stat & CC_ORIENTATION) ?
> - TYPEC_ORIENTATION_REVERSE :
> - TYPEC_ORIENTATION_NORMAL;
> - typec_set_orientation(qcom_usb->port, orientation);
> -
> - role = (stat & SNK_SRC_MODE) ? USB_ROLE_HOST : USB_ROLE_DEVICE;
> - if (role == USB_ROLE_HOST)
> - enable_vbus = true;
> - else
> - enable_vbus = false;
> - } else {
> - role = USB_ROLE_NONE;
> - enable_vbus = false;
> - }
> -
> - qcom_pmic_typec_enable_vbus_regulator(qcom_usb, enable_vbus);
> - usb_role_switch_set_role(qcom_usb->role_sw, role);
> -}
> -
> -static irqreturn_t qcom_pmic_typec_interrupt(int irq, void *_qcom_usb)
> -{
> - struct qcom_pmic_typec *qcom_usb = _qcom_usb;
> -
> - qcom_pmic_typec_check_connection(qcom_usb);
> - return IRQ_HANDLED;
> -}
> -
> -static void qcom_pmic_typec_typec_hw_init(struct qcom_pmic_typec *qcom_usb,
> - enum typec_port_type type)
> -{
> - u8 mode = 0;
> -
> - regmap_update_bits(qcom_usb->regmap,
> - qcom_usb->base + TYPEC_INTR_EN_CFG_1,
> - TYPEC_INTR_EN_CFG_1_MASK, 0);
> -
> - if (type == TYPEC_PORT_SRC)
> - mode = EN_SRC_ONLY;
> - else if (type == TYPEC_PORT_SNK)
> - mode = EN_SNK_ONLY;
> -
> - regmap_update_bits(qcom_usb->regmap, qcom_usb->base + TYPEC_MODE_CFG,
> - EN_SNK_ONLY | EN_SRC_ONLY, mode);
> -
> - regmap_update_bits(qcom_usb->regmap,
> - qcom_usb->base + TYPEC_VCONN_CONTROL,
> - VCONN_EN_SRC | VCONN_EN_VAL, VCONN_EN_SRC);
> - regmap_update_bits(qcom_usb->regmap,
> - qcom_usb->base + TYPEC_EXIT_STATE_CFG,
> - SEL_SRC_UPPER_REF, SEL_SRC_UPPER_REF);
> -}
> -
> -static int qcom_pmic_typec_probe(struct platform_device *pdev)
> -{
> - struct qcom_pmic_typec *qcom_usb;
> - struct device *dev = &pdev->dev;
> - struct fwnode_handle *fwnode;
> - struct typec_capability cap;
> - const char *buf;
> - int ret, irq, role;
> - u32 reg;
> -
> - ret = device_property_read_u32(dev, "reg", ®);
> - if (ret < 0) {
> - dev_err(dev, "missing base address\n");
> - return ret;
> - }
> -
> - qcom_usb = devm_kzalloc(dev, sizeof(*qcom_usb), GFP_KERNEL);
> - if (!qcom_usb)
> - return -ENOMEM;
> -
> - qcom_usb->dev = dev;
> - qcom_usb->base = reg;
> -
> - qcom_usb->regmap = dev_get_regmap(dev->parent, NULL);
> - if (!qcom_usb->regmap) {
> - dev_err(dev, "Failed to get regmap\n");
> - return -EINVAL;
> - }
> -
> - qcom_usb->vbus_reg = devm_regulator_get(qcom_usb->dev, "usb_vbus");
> - if (IS_ERR(qcom_usb->vbus_reg))
> - return PTR_ERR(qcom_usb->vbus_reg);
> -
> - fwnode = device_get_named_child_node(dev, "connector");
> - if (!fwnode)
> - return -EINVAL;
> -
> - ret = fwnode_property_read_string(fwnode, "power-role", &buf);
> - if (!ret) {
> - role = typec_find_port_power_role(buf);
> - if (role < 0)
> - role = TYPEC_PORT_SNK;
> - } else {
> - role = TYPEC_PORT_SNK;
> - }
> - cap.type = role;
> -
> - ret = fwnode_property_read_string(fwnode, "data-role", &buf);
> - if (!ret) {
> - role = typec_find_port_data_role(buf);
> - if (role < 0)
> - role = TYPEC_PORT_UFP;
> - } else {
> - role = TYPEC_PORT_UFP;
> - }
> - cap.data = role;
> -
> - cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
> - cap.fwnode = fwnode;
> - qcom_usb->port = typec_register_port(dev, &cap);
> - if (IS_ERR(qcom_usb->port)) {
> - ret = PTR_ERR(qcom_usb->port);
> - dev_err(dev, "Failed to register type c port %d\n", ret);
> - goto err_put_node;
> - }
> - fwnode_handle_put(fwnode);
> -
> - qcom_usb->role_sw = fwnode_usb_role_switch_get(dev_fwnode(qcom_usb->dev));
> - if (IS_ERR(qcom_usb->role_sw)) {
> - ret = dev_err_probe(dev, PTR_ERR(qcom_usb->role_sw),
> - "failed to get role switch\n");
> - goto err_typec_port;
> - }
> -
> - irq = platform_get_irq(pdev, 0);
> - if (irq < 0)
> - goto err_usb_role_sw;
> -
> - ret = devm_request_threaded_irq(qcom_usb->dev, irq, NULL,
> - qcom_pmic_typec_interrupt, IRQF_ONESHOT,
> - "qcom-pmic-typec", qcom_usb);
> - if (ret) {
> - dev_err(&pdev->dev, "Could not request IRQ\n");
> - goto err_usb_role_sw;
> - }
> -
> - platform_set_drvdata(pdev, qcom_usb);
> - qcom_pmic_typec_typec_hw_init(qcom_usb, cap.type);
> - qcom_pmic_typec_check_connection(qcom_usb);
> -
> - return 0;
> -
> -err_usb_role_sw:
> - usb_role_switch_put(qcom_usb->role_sw);
> -err_typec_port:
> - typec_unregister_port(qcom_usb->port);
> -err_put_node:
> - fwnode_handle_put(fwnode);
> -
> - return ret;
> -}
> -
> -static int qcom_pmic_typec_remove(struct platform_device *pdev)
> -{
> - struct qcom_pmic_typec *qcom_usb = platform_get_drvdata(pdev);
> -
> - usb_role_switch_set_role(qcom_usb->role_sw, USB_ROLE_NONE);
> - qcom_pmic_typec_enable_vbus_regulator(qcom_usb, 0);
> -
> - typec_unregister_port(qcom_usb->port);
> - usb_role_switch_put(qcom_usb->role_sw);
> -
> - return 0;
> -}
> -
> -static const struct of_device_id qcom_pmic_typec_table[] = {
> - { .compatible = "qcom,pm8150b-usb-typec" },
> - { }
> -};
> -MODULE_DEVICE_TABLE(of, qcom_pmic_typec_table);
> -
> -static struct platform_driver qcom_pmic_typec = {
> - .driver = {
> - .name = "qcom,pmic-typec",
> - .of_match_table = qcom_pmic_typec_table,
> - },
> - .probe = qcom_pmic_typec_probe,
> - .remove = qcom_pmic_typec_remove,
> -};
> -module_platform_driver(qcom_pmic_typec);
> -
> -MODULE_DESCRIPTION("QCOM PMIC USB type C driver");
> -MODULE_LICENSE("GPL v2");
> diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
> index e6b88ca4a4b94..5d393f520fc2f 100644
> --- a/drivers/usb/typec/tcpm/Kconfig
> +++ b/drivers/usb/typec/tcpm/Kconfig
> @@ -76,4 +76,15 @@ config TYPEC_WCOVE
> To compile this driver as module, choose M here: the module will be
> called typec_wcove.ko
>
> +config TYPEC_QCOM_PMIC
> + tristate "Qualcomm PMIC USB Type-C Port Controller Manager driver"
> + depends on ARCH_QCOM || COMPILE_TEST
> + help
> + A Type-C port and Power Delivery driver which aggregates two
> + discrete pieces of silicon in the PM8150b PMIC block: the
> + Type-C port controller and the Power Delivery PHY.
> +
> + This driver enables Type-C role switching, orientation, Alternate
> + mode and Power Delivery support both for VBUS and VCONN.
> +
> endif # TYPEC_TCPM
> diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile
> index 08e57bb499cbc..7a8cad0c0bdb4 100644
> --- a/drivers/usb/typec/tcpm/Makefile
> +++ b/drivers/usb/typec/tcpm/Makefile
> @@ -9,3 +9,4 @@ obj-$(CONFIG_TYPEC_MT6360) += tcpci_mt6360.o
> obj-$(CONFIG_TYPEC_TCPCI_MT6370) += tcpci_mt6370.o
> obj-$(CONFIG_TYPEC_TCPCI_MAXIM) += tcpci_maxim.o
> tcpci_maxim-y += tcpci_maxim_core.o maxim_contaminant.o
> +obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom/
> diff --git a/drivers/usb/typec/tcpm/qcom/Makefile b/drivers/usb/typec/tcpm/qcom/Makefile
> new file mode 100644
> index 0000000000000..dc1e8832e197a
> --- /dev/null
> +++ b/drivers/usb/typec/tcpm/qcom/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom_pmic_tcpm.o
> +qcom_pmic_tcpm-y += qcom_pmic_typec.o \
> + qcom_pmic_typec_port.o \
> + qcom_pmic_typec_pdphy.o
> diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
> new file mode 100644
> index 0000000000000..1e663988535f4
> --- /dev/null
> +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
> @@ -0,0 +1,362 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2023, Linaro Ltd. All rights reserved.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/of_graph.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +#include <linux/usb/role.h>
> +#include <linux/usb/tcpm.h>
> +#include <linux/usb/typec_mux.h>
> +#include "qcom_pmic_typec_pdphy.h"
> +#include "qcom_pmic_typec_port.h"
> +
> +struct pmic_typec_resources {
> + struct pmic_typec_pdphy_resources *pdphy_res;
> + struct pmic_typec_port_resources *port_res;
> +};
> +
> +struct pmic_typec {
> + struct device *dev;
> + struct tcpm_port *tcpm_port;
> + struct tcpc_dev tcpc;
> + struct pmic_typec_pdphy *pmic_typec_pdphy;
> + struct pmic_typec_port *pmic_typec_port;
> + bool vbus_enabled;
> + struct mutex lock; /* VBUS state serialization */
> +};
> +
> +#define tcpc_to_tcpm(_tcpc_) container_of(_tcpc_, struct pmic_typec, tcpc)
> +
> +static int qcom_pmic_typec_get_vbus(struct tcpc_dev *tcpc)
> +{
> + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
> + int ret;
> +
> + mutex_lock(&tcpm->lock);
> + ret = tcpm->vbus_enabled || qcom_pmic_typec_port_get_vbus(tcpm->pmic_typec_port);
> + mutex_unlock(&tcpm->lock);
> +
> + return ret;
> +}
> +
> +static int qcom_pmic_typec_set_vbus(struct tcpc_dev *tcpc, bool on, bool sink)
> +{
> + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
> + int ret = 0;
> +
> + mutex_lock(&tcpm->lock);
> + if (tcpm->vbus_enabled == on)
> + goto done;
> +
> + ret = qcom_pmic_typec_port_set_vbus(tcpm->pmic_typec_port, on);
> + if (ret)
> + goto done;
> +
> + tcpm->vbus_enabled = on;
> + tcpm_vbus_change(tcpm->tcpm_port);
> +
> +done:
> + dev_dbg(tcpm->dev, "set_vbus set: %d result %d\n", on, ret);
> + mutex_unlock(&tcpm->lock);
> +
> + return ret;
> +}
> +
> +static int qcom_pmic_typec_set_vconn(struct tcpc_dev *tcpc, bool on)
> +{
> + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
> +
> + return qcom_pmic_typec_port_set_vconn(tcpm->pmic_typec_port, on);
> +}
> +
> +static int qcom_pmic_typec_get_cc(struct tcpc_dev *tcpc,
> + enum typec_cc_status *cc1,
> + enum typec_cc_status *cc2)
> +{
> + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
> +
> + return qcom_pmic_typec_port_get_cc(tcpm->pmic_typec_port, cc1, cc2);
> +}
> +
> +static int qcom_pmic_typec_set_cc(struct tcpc_dev *tcpc,
> + enum typec_cc_status cc)
> +{
> + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
> +
> + return qcom_pmic_typec_port_set_cc(tcpm->pmic_typec_port, cc);
> +}
> +
> +static int qcom_pmic_typec_set_polarity(struct tcpc_dev *tcpc,
> + enum typec_cc_polarity pol)
> +{
> + /* Polarity is set separately by phy-qcom-qmp.c */
> + return 0;
> +}
> +
> +static int qcom_pmic_typec_start_toggling(struct tcpc_dev *tcpc,
> + enum typec_port_type port_type,
> + enum typec_cc_status cc)
> +{
> + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
> +
> + return qcom_pmic_typec_port_start_toggling(tcpm->pmic_typec_port,
> + port_type, cc);
> +}
> +
> +static int qcom_pmic_typec_set_roles(struct tcpc_dev *tcpc, bool attached,
> + enum typec_role power_role,
> + enum typec_data_role data_role)
> +{
> + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
> +
> + return qcom_pmic_typec_pdphy_set_roles(tcpm->pmic_typec_pdphy,
> + data_role, power_role);
> +}
> +
> +static int qcom_pmic_typec_set_pd_rx(struct tcpc_dev *tcpc, bool on)
> +{
> + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
> +
> + return qcom_pmic_typec_pdphy_set_pd_rx(tcpm->pmic_typec_pdphy, on);
> +}
> +
> +static int qcom_pmic_typec_pd_transmit(struct tcpc_dev *tcpc,
> + enum tcpm_transmit_type type,
> + const struct pd_message *msg,
> + unsigned int negotiated_rev)
> +{
> + struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc);
> +
> + return qcom_pmic_typec_pdphy_pd_transmit(tcpm->pmic_typec_pdphy, type,
> + msg, negotiated_rev);
> +}
> +
> +static int qcom_pmic_typec_init(struct tcpc_dev *tcpc)
> +{
> + return 0;
> +}
> +
> +static int qcom_pmic_typec_probe(struct platform_device *pdev)
> +{
> + struct pmic_typec *tcpm;
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + const struct pmic_typec_resources *res;
> + struct regmap *regmap;
> + u32 base[2];
> + int ret;
> +
> + res = of_device_get_match_data(dev);
> + if (!res)
> + return -ENODEV;
> +
> + tcpm = devm_kzalloc(dev, sizeof(*tcpm), GFP_KERNEL);
> + if (!tcpm)
> + return -ENOMEM;
> +
> + tcpm->dev = dev;
> + tcpm->tcpc.init = qcom_pmic_typec_init;
> + tcpm->tcpc.get_vbus = qcom_pmic_typec_get_vbus;
> + tcpm->tcpc.set_vbus = qcom_pmic_typec_set_vbus;
> + tcpm->tcpc.set_cc = qcom_pmic_typec_set_cc;
> + tcpm->tcpc.get_cc = qcom_pmic_typec_get_cc;
> + tcpm->tcpc.set_polarity = qcom_pmic_typec_set_polarity;
> + tcpm->tcpc.set_vconn = qcom_pmic_typec_set_vconn;
> + tcpm->tcpc.start_toggling = qcom_pmic_typec_start_toggling;
> + tcpm->tcpc.set_pd_rx = qcom_pmic_typec_set_pd_rx;
> + tcpm->tcpc.set_roles = qcom_pmic_typec_set_roles;
> + tcpm->tcpc.pd_transmit = qcom_pmic_typec_pd_transmit;
> +
> + regmap = dev_get_regmap(dev->parent, NULL);
> + if (!regmap) {
> + dev_err(dev, "Failed to get regmap\n");
> + return -ENODEV;
> + }
> +
> + ret = of_property_read_u32_array(np, "reg", base, 2);
> + if (ret)
> + return ret;
> +
> + tcpm->pmic_typec_port = qcom_pmic_typec_port_alloc(dev);
> + if (IS_ERR(tcpm->pmic_typec_port))
> + return PTR_ERR(tcpm->pmic_typec_port);
> +
> + tcpm->pmic_typec_pdphy = qcom_pmic_typec_pdphy_alloc(dev);
> + if (IS_ERR(tcpm->pmic_typec_pdphy))
> + return PTR_ERR(tcpm->pmic_typec_pdphy);
> +
> + ret = qcom_pmic_typec_port_probe(pdev, tcpm->pmic_typec_port,
> + res->port_res, regmap, base[0]);
> + if (ret)
> + return ret;
> +
> + ret = qcom_pmic_typec_pdphy_probe(pdev, tcpm->pmic_typec_pdphy,
> + res->pdphy_res, regmap, base[1]);
> + if (ret)
> + return ret;
> +
> + mutex_init(&tcpm->lock);
> + platform_set_drvdata(pdev, tcpm);
> +
> + tcpm->tcpc.fwnode = device_get_named_child_node(tcpm->dev, "connector");
> + if (IS_ERR(tcpm->tcpc.fwnode))
> + return PTR_ERR(tcpm->tcpc.fwnode);
> +
> + tcpm->tcpm_port = tcpm_register_port(tcpm->dev, &tcpm->tcpc);
> + if (IS_ERR(tcpm->tcpm_port)) {
> + ret = PTR_ERR(tcpm->tcpm_port);
> + goto fwnode_remove;
> + }
> +
> + ret = qcom_pmic_typec_port_start(tcpm->pmic_typec_port,
> + tcpm->tcpm_port);
> + if (ret)
> + goto fwnode_remove;
> +
> + ret = qcom_pmic_typec_pdphy_start(tcpm->pmic_typec_pdphy,
> + tcpm->tcpm_port);
> + if (ret)
> + goto fwnode_remove;
> +
> + return 0;
> +
> +fwnode_remove:
> + fwnode_remove_software_node(tcpm->tcpc.fwnode);
> +
> + return ret;
> +}
> +
> +static int qcom_pmic_typec_remove(struct platform_device *pdev)
> +{
> + struct pmic_typec *tcpm = platform_get_drvdata(pdev);
> +
> + qcom_pmic_typec_pdphy_stop(tcpm->pmic_typec_pdphy);
> + qcom_pmic_typec_port_stop(tcpm->pmic_typec_port);
> + tcpm_unregister_port(tcpm->tcpm_port);
> + fwnode_remove_software_node(tcpm->tcpc.fwnode);
> +
> + return 0;
> +}
> +
> +static struct pmic_typec_pdphy_resources pm8150b_pdphy_res = {
> + .irq_params = {
> + {
> + .virq = PMIC_PDPHY_SIG_TX_IRQ,
> + .irq_name = "sig-tx",
> + },
> + {
> + .virq = PMIC_PDPHY_SIG_RX_IRQ,
> + .irq_name = "sig-rx",
> + },
> + {
> + .virq = PMIC_PDPHY_MSG_TX_IRQ,
> + .irq_name = "msg-tx",
> + },
> + {
> + .virq = PMIC_PDPHY_MSG_RX_IRQ,
> + .irq_name = "msg-rx",
> + },
> + {
> + .virq = PMIC_PDPHY_MSG_TX_FAIL_IRQ,
> + .irq_name = "msg-tx-failed",
> + },
> + {
> + .virq = PMIC_PDPHY_MSG_TX_DISCARD_IRQ,
> + .irq_name = "msg-tx-discarded",
> + },
> + {
> + .virq = PMIC_PDPHY_MSG_RX_DISCARD_IRQ,
> + .irq_name = "msg-rx-discarded",
> + },
> + },
> + .nr_irqs = 7,
> +};
> +
> +static struct pmic_typec_port_resources pm8150b_port_res = {
> + .irq_params = {
> + {
> + .irq_name = "vpd-detect",
> + .virq = PMIC_TYPEC_VPD_IRQ,
> + },
> +
> + {
> + .irq_name = "cc-state-change",
> + .virq = PMIC_TYPEC_CC_STATE_IRQ,
> + },
> + {
> + .irq_name = "vconn-oc",
> + .virq = PMIC_TYPEC_VCONN_OC_IRQ,
> + },
> +
> + {
> + .irq_name = "vbus-change",
> + .virq = PMIC_TYPEC_VBUS_IRQ,
> + },
> +
> + {
> + .irq_name = "attach-detach",
> + .virq = PMIC_TYPEC_ATTACH_DETACH_IRQ,
> + },
> + {
> + .irq_name = "legacy-cable-detect",
> + .virq = PMIC_TYPEC_LEGACY_CABLE_IRQ,
> + },
> +
> + {
> + .irq_name = "try-snk-src-detect",
> + .virq = PMIC_TYPEC_TRY_SNK_SRC_IRQ,
> + },
> + },
> + .nr_irqs = 7,
> +};
> +
> +struct pmic_typec_resources pm8150b_typec_res = {
> + .pdphy_res = &pm8150b_pdphy_res,
> + .port_res = &pm8150b_port_res,
> +};
> +
> +static const struct of_device_id qcom_pmic_typec_table[] = {
> + { .compatible = "qcom,pm8150b-typec", .data = &pm8150b_typec_res },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, qcom_pmic_typec_table);
> +
> +static struct platform_driver qcom_pmic_typec_platform_driver = {
> + .driver = {
> + .name = "qcom,pmic-typec",
> + .of_match_table = qcom_pmic_typec_table,
> + },
> + .probe = qcom_pmic_typec_probe,
> + .remove = qcom_pmic_typec_remove,
> +};
> +
> +static int __init qcom_pmic_typec_module_init(void)
> +{
> + int ret;
> +
> + ret = platform_driver_register(&qcom_pmic_typec_platform_driver);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +module_init(qcom_pmic_typec_module_init);
> +
> +static void __exit qcom_pmic_typec_module_exit(void)
> +{
> + platform_driver_unregister(&qcom_pmic_typec_platform_driver);
> +}
> +module_exit(qcom_pmic_typec_module_exit);
> +
> +MODULE_DESCRIPTION("QCOM PMIC USB Type-C Port Manager Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
> new file mode 100644
> index 0000000000000..02f437b068bea
> --- /dev/null
> +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
> @@ -0,0 +1,528 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2023, Linaro Ltd. All rights reserved.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +#include <linux/usb/pd.h>
> +#include <linux/usb/tcpm.h>
> +#include "qcom_pmic_typec_pdphy.h"
> +
> +struct pmic_typec_pdphy_irq_data {
> + int virq;
> + int irq;
> + struct pmic_typec_pdphy *pmic_typec_pdphy;
> +};
> +
> +struct pmic_typec_pdphy {
> + struct device *dev;
> + struct tcpm_port *tcpm_port;
> + struct regmap *regmap;
> + u32 base;
> +
> + unsigned int nr_irqs;
> + struct pmic_typec_pdphy_irq_data *irq_data;
> +
> + struct work_struct reset_work;
> + struct work_struct receive_work;
> + struct regulator *vdd_pdphy;
> + spinlock_t lock; /* Register atomicity */
> +};
> +
> +static void qcom_pmic_typec_pdphy_reset_on(struct pmic_typec_pdphy *pmic_typec_pdphy)
> +{
> + struct device *dev = pmic_typec_pdphy->dev;
> + int ret;
> +
> + /* Terminate TX */
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0);
> + if (ret)
> + goto err;
> +
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG, 0);
> + if (ret)
> + goto err;
> +
> + return;
> +err:
> + dev_err(dev, "pd_reset_on error\n");
> +}
> +
> +static void qcom_pmic_typec_pdphy_reset_off(struct pmic_typec_pdphy *pmic_typec_pdphy)
> +{
> + struct device *dev = pmic_typec_pdphy->dev;
> + int ret;
> +
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_FRAME_FILTER_REG,
> + FRAME_FILTER_EN_SOP | FRAME_FILTER_EN_HARD_RESET);
> + if (ret)
> + dev_err(dev, "pd_reset_off error\n");
> +}
> +
> +static void qcom_pmic_typec_pdphy_sig_reset_work(struct work_struct *work)
> +{
> + struct pmic_typec_pdphy *pmic_typec_pdphy = container_of(work, struct pmic_typec_pdphy,
> + reset_work);
> + unsigned long flags;
> +
> + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
> +
> + qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
> + qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
> +
> + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
> +
> + tcpm_pd_hard_reset(pmic_typec_pdphy->tcpm_port);
> +}
> +
> +static int
> +qcom_pmic_typec_pdphy_clear_tx_control_reg(struct pmic_typec_pdphy *pmic_typec_pdphy)
> +{
> + struct device *dev = pmic_typec_pdphy->dev;
> + unsigned int val;
> + int ret;
> +
> + /* Clear TX control register */
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, 0);
> + if (ret)
> + goto done;
> +
> + /* Perform readback to ensure sufficient delay for command to latch */
> + ret = regmap_read(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, &val);
> +
> +done:
> + if (ret)
> + dev_err(dev, "pd_clear_tx_control_reg: clear tx flag\n");
> +
> + return ret;
> +}
> +
> +static int
> +qcom_pmic_typec_pdphy_pd_transmit_signal(struct pmic_typec_pdphy *pmic_typec_pdphy,
> + enum tcpm_transmit_type type,
> + unsigned int negotiated_rev)
> +{
> + struct device *dev = pmic_typec_pdphy->dev;
> + unsigned int val;
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
> +
> + /* Clear TX control register */
> + ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
> + if (ret)
> + goto done;
> +
> + val = TX_CONTROL_SEND_SIGNAL;
> + if (negotiated_rev == PD_REV30)
> + val |= TX_CONTROL_RETRY_COUNT(2);
> + else
> + val |= TX_CONTROL_RETRY_COUNT(3);
> +
> + if (type == TCPC_TX_CABLE_RESET || type == TCPC_TX_HARD_RESET)
> + val |= TX_CONTROL_FRAME_TYPE(1);
> +
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val);
> +
> +done:
> + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
> +
> + dev_vdbg(dev, "pd_transmit_signal: type %d negotiate_rev %d send %d\n",
> + type, negotiated_rev, ret);
> +
> + return ret;
> +}
> +
> +static int
> +qcom_pmic_typec_pdphy_pd_transmit_payload(struct pmic_typec_pdphy *pmic_typec_pdphy,
> + enum tcpm_transmit_type type,
> + const struct pd_message *msg,
> + unsigned int negotiated_rev)
> +{
> + struct device *dev = pmic_typec_pdphy->dev;
> + unsigned int val, hdr_len, txbuf_len, txsize_len;
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
> +
> + ret = regmap_read(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG,
> + &val);
> + if (ret)
> + goto done;
> +
> + if (val) {
> + dev_err(dev, "pd_transmit_payload: RX message pending\n");
> + ret = -EBUSY;
> + goto done;
> + }
> +
> + /* Clear TX control register */
> + ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
> + if (ret)
> + goto done;
> +
> + hdr_len = sizeof(msg->header);
> + txbuf_len = pd_header_cnt_le(msg->header) * 4;
> + txsize_len = hdr_len + txbuf_len - 1;
> +
> + /* Write message header sizeof(u16) to USB_PDPHY_TX_BUFFER_HDR_REG */
> + ret = regmap_bulk_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_HDR_REG,
> + &msg->header, hdr_len);
> + if (ret)
> + goto done;
> +
> + /* Write payload to USB_PDPHY_TX_BUFFER_DATA_REG for txbuf_len */
> + if (txbuf_len) {
> + ret = regmap_bulk_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_TX_BUFFER_DATA_REG,
> + &msg->payload, txbuf_len);
> + if (ret)
> + goto done;
> + }
> +
> + /* Write total length ((header + data) - 1) to USB_PDPHY_TX_SIZE_REG */
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_TX_SIZE_REG,
> + txsize_len);
> + if (ret)
> + goto done;
> +
> + /* Clear TX control register */
> + ret = qcom_pmic_typec_pdphy_clear_tx_control_reg(pmic_typec_pdphy);
> + if (ret)
> + goto done;
> +
> + /* Initiate transmit with retry count as indicated by PD revision */
> + val = TX_CONTROL_FRAME_TYPE(type) | TX_CONTROL_SEND_MSG;
> + if (pd_header_rev(msg->header) == PD_REV30)
> + val |= TX_CONTROL_RETRY_COUNT(2);
> + else
> + val |= TX_CONTROL_RETRY_COUNT(3);
> +
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_TX_CONTROL_REG, val);
> +
> +done:
> + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
> +
> + if (ret) {
> + dev_err(dev, "pd_transmit_payload: %d hdr %*ph data %*ph ret %d\n",
> + ret, hdr_len, &msg->header, txbuf_len, &msg->payload, ret);
> + }
> +
> + return ret;
> +}
> +
> +int qcom_pmic_typec_pdphy_pd_transmit(struct pmic_typec_pdphy *pmic_typec_pdphy,
> + enum tcpm_transmit_type type,
> + const struct pd_message *msg,
> + unsigned int negotiated_rev)
> +{
> + struct device *dev = pmic_typec_pdphy->dev;
> + int ret;
> +
> + if (msg) {
> + ret = qcom_pmic_typec_pdphy_pd_transmit_payload(pmic_typec_pdphy,
> + type, msg,
> + negotiated_rev);
> + } else {
> + ret = qcom_pmic_typec_pdphy_pd_transmit_signal(pmic_typec_pdphy,
> + type,
> + negotiated_rev);
> + }
> +
> + if (ret)
> + dev_dbg(dev, "pd_transmit: type %x result %d\n", type, ret);
> +
> + return ret;
> +}
> +
> +static void qcom_pmic_typec_pdphy_pd_receive(struct pmic_typec_pdphy *pmic_typec_pdphy)
> +{
> + struct device *dev = pmic_typec_pdphy->dev;
> + struct pd_message msg;
> + unsigned int size, rx_status;
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
> +
> + ret = regmap_read(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_RX_SIZE_REG, &size);
> + if (ret)
> + goto done;
> +
> + /* If we received a subsequent RX sig this value can be zero */
> + if ((size < 1 || size > sizeof(msg.payload))) {
> + dev_dbg(dev, "pd_receive: invalid size %d\n", size);
> + goto done;
> + }
> +
> + size += 1;
> + ret = regmap_read(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_RX_STATUS_REG,
> + &rx_status);
> +
> + if (ret)
> + goto done;
> +
> + ret = regmap_bulk_read(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_RX_BUFFER_REG,
> + (u8 *)&msg, size);
> + if (ret)
> + goto done;
> +
> + /* Return ownership of RX buffer to hardware */
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, 0);
> +
> +done:
> + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
> +
> + if (!ret) {
> + dev_vdbg(dev, "pd_receive: handing %d bytes to tcpm\n", size);
> + tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg);
> + }
> +}
> +
> +static irqreturn_t qcom_pmic_typec_pdphy_isr(int irq, void *dev_id)
> +{
> + struct pmic_typec_pdphy_irq_data *irq_data = dev_id;
> + struct pmic_typec_pdphy *pmic_typec_pdphy = irq_data->pmic_typec_pdphy;
> + struct device *dev = pmic_typec_pdphy->dev;
> +
> + switch (irq_data->virq) {
> + case PMIC_PDPHY_SIG_TX_IRQ:
> + dev_err(dev, "isr: tx_sig\n");
> + break;
> + case PMIC_PDPHY_SIG_RX_IRQ:
> + schedule_work(&pmic_typec_pdphy->reset_work);
> + break;
> + case PMIC_PDPHY_MSG_TX_IRQ:
> + tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
> + TCPC_TX_SUCCESS);
> + break;
> + case PMIC_PDPHY_MSG_RX_IRQ:
> + qcom_pmic_typec_pdphy_pd_receive(pmic_typec_pdphy);
> + break;
> + case PMIC_PDPHY_MSG_TX_FAIL_IRQ:
> + tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
> + TCPC_TX_FAILED);
> + break;
> + case PMIC_PDPHY_MSG_TX_DISCARD_IRQ:
> + tcpm_pd_transmit_complete(pmic_typec_pdphy->tcpm_port,
> + TCPC_TX_DISCARDED);
> + break;
> + }
> +
> + return IRQ_HANDLED;
> +}
> +
> +int qcom_pmic_typec_pdphy_set_pd_rx(struct pmic_typec_pdphy *pmic_typec_pdphy, bool on)
> +{
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
> +
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_RX_ACKNOWLEDGE_REG, !on);
> +
> + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
> +
> + dev_dbg(pmic_typec_pdphy->dev, "set_pd_rx: %s\n", on ? "on" : "off");
> +
> + return ret;
> +}
> +
> +int qcom_pmic_typec_pdphy_set_roles(struct pmic_typec_pdphy *pmic_typec_pdphy,
> + bool data_role_host, bool power_role_src)
> +{
> + struct device *dev = pmic_typec_pdphy->dev;
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&pmic_typec_pdphy->lock, flags);
> +
> + ret = regmap_update_bits(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG,
> + MSG_CONFIG_PORT_DATA_ROLE |
> + MSG_CONFIG_PORT_POWER_ROLE,
> + data_role_host << 3 | power_role_src << 2);
> +
> + spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags);
> +
> + dev_dbg(dev, "pdphy_set_roles: data_role_host=%d power_role_src=%d\n",
> + data_role_host, power_role_src);
> +
> + return ret;
> +}
> +
> +static int qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy *pmic_typec_pdphy)
> +{
> + struct device *dev = pmic_typec_pdphy->dev;
> + int ret;
> +
> + ret = regulator_enable(pmic_typec_pdphy->vdd_pdphy);
> + if (ret)
> + return ret;
> +
> + /* PD 2.0, DR=TYPEC_DEVICE, PR=TYPEC_SINK */
> + ret = regmap_update_bits(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG,
> + MSG_CONFIG_SPEC_REV_MASK, PD_REV20);
> + if (ret)
> + goto done;
> +
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0);
> + if (ret)
> + goto done;
> +
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG,
> + CONTROL_ENABLE);
> + if (ret)
> + goto done;
> +
> + qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
> +done:
> + if (ret) {
> + regulator_disable(pmic_typec_pdphy->vdd_pdphy);
> + dev_err(dev, "pdphy_enable fail %d\n", ret);
> + }
> +
> + return ret;
> +}
> +
> +static int qcom_pmic_typec_pdphy_disable(struct pmic_typec_pdphy *pmic_typec_pdphy)
> +{
> + int ret;
> +
> + qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
> +
> + ret = regmap_write(pmic_typec_pdphy->regmap,
> + pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0);
> +
> + regulator_disable(pmic_typec_pdphy->vdd_pdphy);
> +
> + return ret;
> +}
> +
> +static int pmic_typec_pdphy_reset(struct pmic_typec_pdphy *pmic_typec_pdphy)
> +{
> + int ret;
> +
> + ret = qcom_pmic_typec_pdphy_disable(pmic_typec_pdphy);
> + if (ret)
> + goto done;
> +
> + usleep_range(400, 500);
> + ret = qcom_pmic_typec_pdphy_enable(pmic_typec_pdphy);
> +done:
> + return ret;
> +}
> +
> +int qcom_pmic_typec_pdphy_start(struct pmic_typec_pdphy *pmic_typec_pdphy,
> + struct tcpm_port *tcpm_port)
> +{
> + int i;
> + int ret;
> +
> + pmic_typec_pdphy->tcpm_port = tcpm_port;
> +
> + ret = pmic_typec_pdphy_reset(pmic_typec_pdphy);
> + if (ret)
> + return ret;
> +
> + for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
> + enable_irq(pmic_typec_pdphy->irq_data[i].irq);
> +
> + return 0;
> +}
> +
> +void qcom_pmic_typec_pdphy_stop(struct pmic_typec_pdphy *pmic_typec_pdphy)
> +{
> + int i;
> +
> + for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
> + disable_irq(pmic_typec_pdphy->irq_data[i].irq);
> +
> + qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
> +}
> +
> +struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev)
> +{
> + return devm_kzalloc(dev, sizeof(struct pmic_typec_pdphy), GFP_KERNEL);
> +}
> +
> +int qcom_pmic_typec_pdphy_probe(struct platform_device *pdev,
> + struct pmic_typec_pdphy *pmic_typec_pdphy,
> + struct pmic_typec_pdphy_resources *res,
> + struct regmap *regmap,
> + u32 base)
> +{
> + struct device *dev = &pdev->dev;
> + struct pmic_typec_pdphy_irq_data *irq_data;
> + int i, ret, irq;
> +
> + if (!res->nr_irqs || res->nr_irqs > PMIC_PDPHY_MAX_IRQS)
> + return -EINVAL;
> +
> + irq_data = devm_kzalloc(dev, sizeof(*irq_data) * res->nr_irqs,
> + GFP_KERNEL);
> + if (!irq_data)
> + return -ENOMEM;
> +
> + pmic_typec_pdphy->vdd_pdphy = devm_regulator_get(dev, "vdd-pdphy");
> + if (IS_ERR(pmic_typec_pdphy->vdd_pdphy))
> + return PTR_ERR(pmic_typec_pdphy->vdd_pdphy);
> +
> + pmic_typec_pdphy->dev = dev;
> + pmic_typec_pdphy->base = base;
> + pmic_typec_pdphy->regmap = regmap;
> + pmic_typec_pdphy->nr_irqs = res->nr_irqs;
> + pmic_typec_pdphy->irq_data = irq_data;
> + spin_lock_init(&pmic_typec_pdphy->lock);
> + INIT_WORK(&pmic_typec_pdphy->reset_work, qcom_pmic_typec_pdphy_sig_reset_work);
> +
> + for (i = 0; i < res->nr_irqs; i++, irq_data++) {
> + irq = platform_get_irq_byname(pdev, res->irq_params[i].irq_name);
> + if (irq < 0)
> + return irq;
> +
> + irq_data->pmic_typec_pdphy = pmic_typec_pdphy;
> + irq_data->irq = irq;
> + irq_data->virq = res->irq_params[i].virq;
> +
> + ret = devm_request_threaded_irq(dev, irq, NULL,
> + qcom_pmic_typec_pdphy_isr,
> + IRQF_ONESHOT | IRQF_NO_AUTOEN,
> + res->irq_params[i].irq_name,
> + irq_data);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
> new file mode 100644
> index 0000000000000..ebd33c9ae0606
> --- /dev/null
> +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.h
> @@ -0,0 +1,115 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
> + * Copyright (c) 2023, Linaro Ltd. All rights reserved.
> + */
> +#ifndef __QCOM_PMIC_PDPHY_H__
> +#define __QCOM_PMIC_PDPHY_H__
> +
> +#define USB_PDPHY_MAX_DATA_OBJ_LEN 28
> +#define USB_PDPHY_MSG_HDR_LEN 2
> +
> +/* PD PHY register offsets and bit fields */
> +#define USB_PDPHY_MSG_CONFIG_REG 0x40
> +#define MSG_CONFIG_PORT_DATA_ROLE BIT(3)
> +#define MSG_CONFIG_PORT_POWER_ROLE BIT(2)
> +#define MSG_CONFIG_SPEC_REV_MASK (BIT(1) | BIT(0))
> +
> +#define USB_PDPHY_EN_CONTROL_REG 0x46
> +#define CONTROL_ENABLE BIT(0)
> +
> +#define USB_PDPHY_RX_STATUS_REG 0x4A
> +#define RX_FRAME_TYPE (BIT(0) | BIT(1) | BIT(2))
> +
> +#define USB_PDPHY_FRAME_FILTER_REG 0x4C
> +#define FRAME_FILTER_EN_HARD_RESET BIT(5)
> +#define FRAME_FILTER_EN_SOP BIT(0)
> +
> +#define USB_PDPHY_TX_SIZE_REG 0x42
> +#define TX_SIZE_MASK 0xF
> +
> +#define USB_PDPHY_TX_CONTROL_REG 0x44
> +#define TX_CONTROL_RETRY_COUNT(n) (((n) & 0x3) << 5)
> +#define TX_CONTROL_FRAME_TYPE(n) (((n) & 0x7) << 2)
> +#define TX_CONTROL_FRAME_TYPE_CABLE_RESET (0x1 << 2)
> +#define TX_CONTROL_SEND_SIGNAL BIT(1)
> +#define TX_CONTROL_SEND_MSG BIT(0)
> +
> +#define USB_PDPHY_RX_SIZE_REG 0x48
> +
> +#define USB_PDPHY_RX_ACKNOWLEDGE_REG 0x4B
> +#define RX_BUFFER_TOKEN BIT(0)
> +
> +#define USB_PDPHY_BIST_MODE_REG 0x4E
> +#define BIST_MODE_MASK 0xF
> +#define BIST_ENABLE BIT(7)
> +#define PD_MSG_BIST 0x3
> +#define PD_BIST_TEST_DATA_MODE 0x8
> +
> +#define USB_PDPHY_TX_BUFFER_HDR_REG 0x60
> +#define USB_PDPHY_TX_BUFFER_DATA_REG 0x62
> +
> +#define USB_PDPHY_RX_BUFFER_REG 0x80
> +
> +/* VDD regulator */
> +#define VDD_PDPHY_VOL_MIN 2800000 /* uV */
> +#define VDD_PDPHY_VOL_MAX 3300000 /* uV */
> +#define VDD_PDPHY_HPM_LOAD 3000 /* uA */
> +
> +/* Message Spec Rev field */
> +#define PD_MSG_HDR_REV(hdr) (((hdr) >> 6) & 3)
> +
> +/* timers */
> +#define RECEIVER_RESPONSE_TIME 15 /* tReceiverResponse */
> +#define HARD_RESET_COMPLETE_TIME 5 /* tHardResetComplete */
> +
> +/* Interrupt numbers */
> +#define PMIC_PDPHY_SIG_TX_IRQ 0x0
> +#define PMIC_PDPHY_SIG_RX_IRQ 0x1
> +#define PMIC_PDPHY_MSG_TX_IRQ 0x2
> +#define PMIC_PDPHY_MSG_RX_IRQ 0x3
> +#define PMIC_PDPHY_MSG_TX_FAIL_IRQ 0x4
> +#define PMIC_PDPHY_MSG_TX_DISCARD_IRQ 0x5
> +#define PMIC_PDPHY_MSG_RX_DISCARD_IRQ 0x6
> +#define PMIC_PDPHY_FR_SWAP_IRQ 0x7
> +
> +/* Resources */
> +#define PMIC_PDPHY_MAX_IRQS 0x08
> +
> +struct pmic_typec_pdphy_irq_params {
> + int virq;
> + char *irq_name;
> +};
> +
> +struct pmic_typec_pdphy_resources {
> + unsigned int nr_irqs;
> + struct pmic_typec_pdphy_irq_params irq_params[PMIC_PDPHY_MAX_IRQS];
> +};
> +
> +/* API */
> +struct pmic_typec_pdphy;
> +
> +struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev);
> +
> +int qcom_pmic_typec_pdphy_probe(struct platform_device *pdev,
> + struct pmic_typec_pdphy *pmic_typec_pdphy,
> + struct pmic_typec_pdphy_resources *res,
> + struct regmap *regmap,
> + u32 base);
> +
> +int qcom_pmic_typec_pdphy_start(struct pmic_typec_pdphy *pmic_typec_pdphy,
> + struct tcpm_port *tcpm_port);
> +
> +void qcom_pmic_typec_pdphy_stop(struct pmic_typec_pdphy *pmic_typec_pdphy);
> +
> +int qcom_pmic_typec_pdphy_set_roles(struct pmic_typec_pdphy *pmic_typec_pdphy,
> + bool power_role_src, bool data_role_host);
> +
> +int qcom_pmic_typec_pdphy_set_pd_rx(struct pmic_typec_pdphy *pmic_typec_pdphy, bool on);
> +
> +int qcom_pmic_typec_pdphy_pd_transmit(struct pmic_typec_pdphy *pmic_typec_pdphy,
> + enum tcpm_transmit_type type,
> + const struct pd_message *msg,
> + unsigned int negotiated_rev);
> +
> +#endif /* __QCOM_PMIC_TYPEC_PDPHY_H__ */
> diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
> new file mode 100644
> index 0000000000000..42c956b6a1a1d
> --- /dev/null
> +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
> @@ -0,0 +1,560 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2023, Linaro Ltd. All rights reserved.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +#include <linux/usb/tcpm.h>
> +#include <linux/usb/typec_mux.h>
> +#include <linux/workqueue.h>
> +#include "qcom_pmic_typec_port.h"
> +
> +struct pmic_typec_port_irq_data {
> + int virq;
> + int irq;
> + struct pmic_typec_port *pmic_typec_port;
> +};
> +
> +struct pmic_typec_port {
> + struct device *dev;
> + struct tcpm_port *tcpm_port;
> + struct regmap *regmap;
> + u32 base;
> + unsigned int nr_irqs;
> + struct pmic_typec_port_irq_data *irq_data;
> +
> + struct regulator *vdd_vbus;
> +
> + int cc;
> + bool debouncing_cc;
> + struct delayed_work cc_debounce_dwork;
> +
> + spinlock_t lock; /* Register atomicity */
> +};
> +
> +static const char * const typec_cc_status_name[] = {
> + [TYPEC_CC_OPEN] = "Open",
> + [TYPEC_CC_RA] = "Ra",
> + [TYPEC_CC_RD] = "Rd",
> + [TYPEC_CC_RP_DEF] = "Rp-def",
> + [TYPEC_CC_RP_1_5] = "Rp-1.5",
> + [TYPEC_CC_RP_3_0] = "Rp-3.0",
> +};
> +
> +static const char *rp_unknown = "unknown";
> +
> +static const char *cc_to_name(enum typec_cc_status cc)
> +{
> + if (cc > TYPEC_CC_RP_3_0)
> + return rp_unknown;
> +
> + return typec_cc_status_name[cc];
> +}
> +
> +static const char * const rp_sel_name[] = {
> + [TYPEC_SRC_RP_SEL_80UA] = "Rp-def-80uA",
> + [TYPEC_SRC_RP_SEL_180UA] = "Rp-1.5-180uA",
> + [TYPEC_SRC_RP_SEL_330UA] = "Rp-3.0-330uA",
> +};
> +
> +static const char *rp_sel_to_name(int rp_sel)
> +{
> + if (rp_sel > TYPEC_SRC_RP_SEL_330UA)
> + return rp_unknown;
> +
> + return rp_sel_name[rp_sel];
> +}
> +
> +#define misc_to_cc(msic) !!(misc & CC_ORIENTATION) ? "cc1" : "cc2"
> +#define misc_to_vconn(msic) !!(misc & CC_ORIENTATION) ? "cc2" : "cc1"
> +
> +static void qcom_pmic_typec_port_cc_debounce(struct work_struct *work)
> +{
> + struct pmic_typec_port *pmic_typec_port =
> + container_of(work, struct pmic_typec_port, cc_debounce_dwork.work);
> + unsigned long flags;
> +
> + spin_lock_irqsave(&pmic_typec_port->lock, flags);
> + pmic_typec_port->debouncing_cc = false;
> + spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
> +
> + dev_dbg(pmic_typec_port->dev, "Debounce cc complete\n");
> +}
> +
> +static irqreturn_t pmic_typec_port_isr(int irq, void *dev_id)
> +{
> + struct pmic_typec_port_irq_data *irq_data = dev_id;
> + struct pmic_typec_port *pmic_typec_port = irq_data->pmic_typec_port;
> + u32 misc_stat;
> + bool vbus_change = false;
> + bool cc_change = false;
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&pmic_typec_port->lock, flags);
> +
> + ret = regmap_read(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
> + &misc_stat);
> + if (ret)
> + goto done;
> +
> + switch (irq_data->virq) {
> + case PMIC_TYPEC_VBUS_IRQ:
> + /* Incoming vbus assert/de-assert detect */
> + vbus_change = true;
> + break;
> + case PMIC_TYPEC_CC_STATE_IRQ:
> + if (!pmic_typec_port->debouncing_cc)
> + cc_change = true;
> + break;
> + case PMIC_TYPEC_ATTACH_DETACH_IRQ:
> + if (!pmic_typec_port->debouncing_cc)
> + cc_change = true;
> + break;
> + }
> +
> +done:
> + spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
> +
> + if (vbus_change)
> + tcpm_vbus_change(pmic_typec_port->tcpm_port);
> +
> + if (cc_change)
> + tcpm_cc_change(pmic_typec_port->tcpm_port);
> +
> + return IRQ_HANDLED;
> +}
> +
> +int qcom_pmic_typec_port_get_vbus(struct pmic_typec_port *pmic_typec_port)
> +{
> + struct device *dev = pmic_typec_port->dev;
> + unsigned int misc;
> + int ret;
> +
> + ret = regmap_read(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
> + &misc);
> + if (ret)
> + misc = 0;
> +
> + dev_dbg(dev, "get_vbus: 0x%08x detect %d\n", misc, !!(misc & TYPEC_VBUS_DETECT));
> +
> + return !!(misc & TYPEC_VBUS_DETECT);
> +}
> +
> +int qcom_pmic_typec_port_set_vbus(struct pmic_typec_port *pmic_typec_port, bool on)
> +{
> + u32 sm_stat;
> + u32 val;
> + int ret;
> +
> + if (on) {
> + ret = regulator_enable(pmic_typec_port->vdd_vbus);
> + if (ret)
> + return ret;
> +
> + val = TYPEC_SM_VBUS_VSAFE5V;
> + } else {
> + ret = regulator_disable(pmic_typec_port->vdd_vbus);
> + if (ret)
> + return ret;
> +
> + val = TYPEC_SM_VBUS_VSAFE0V;
> + }
> +
> + /* Poll waiting for transition to required vSafe5V or vSafe0V */
> + ret = regmap_read_poll_timeout(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_SM_STATUS_REG,
> + sm_stat, sm_stat & val,
> + 100, 250000);
> + if (ret)
> + dev_warn(pmic_typec_port->dev, "vbus vsafe%dv fail\n", on ? 5 : 0);
> +
> + return 0;
> +}
> +
> +int qcom_pmic_typec_port_get_cc(struct pmic_typec_port *pmic_typec_port,
> + enum typec_cc_status *cc1,
> + enum typec_cc_status *cc2)
> +{
> + struct device *dev = pmic_typec_port->dev;
> + unsigned int misc, val;
> + bool attached;
> + int ret = 0;
> +
> + ret = regmap_read(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc);
> + if (ret)
> + goto done;
> +
> + attached = !!(misc & CC_ATTACHED);
> +
> + if (pmic_typec_port->debouncing_cc) {
> + ret = -EBUSY;
> + goto done;
> + }
> +
> + *cc1 = TYPEC_CC_OPEN;
> + *cc2 = TYPEC_CC_OPEN;
> +
> + if (!(attached))
> + goto done;
> +
> + if (misc & SNK_SRC_MODE) {
> + ret = regmap_read(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_SRC_STATUS_REG,
> + &val);
> + if (ret)
> + goto done;
> + switch (val & DETECTED_SRC_TYPE_MASK) {
> + case SRC_RD_OPEN:
> + val = TYPEC_CC_RD;
> + break;
> + case SRC_RD_RA_VCONN:
> + val = TYPEC_CC_RD;
> + *cc1 = TYPEC_CC_RA;
> + *cc2 = TYPEC_CC_RA;
> + break;
> + default:
> + dev_warn(dev, "unexpected src status %.2x\n", val);
> + val = TYPEC_CC_RD;
> + break;
> + }
> + } else {
> + ret = regmap_read(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_SNK_STATUS_REG,
> + &val);
> + if (ret)
> + goto done;
> + switch (val & DETECTED_SNK_TYPE_MASK) {
> + case SNK_RP_STD:
> + val = TYPEC_CC_RP_DEF;
> + break;
> + case SNK_RP_1P5:
> + val = TYPEC_CC_RP_1_5;
> + break;
> + case SNK_RP_3P0:
> + val = TYPEC_CC_RP_3_0;
> + break;
> + default:
> + dev_warn(dev, "unexpected snk status %.2x\n", val);
> + val = TYPEC_CC_RP_DEF;
> + break;
> + }
> + val = TYPEC_CC_RP_DEF;
> + }
> +
> + if (misc & CC_ORIENTATION)
> + *cc2 = val;
> + else
> + *cc1 = val;
> +
> +done:
> + dev_dbg(dev, "get_cc: misc 0x%08x cc1 0x%08x %s cc2 0x%08x %s attached %d cc=%s\n",
> + misc, *cc1, cc_to_name(*cc1), *cc2, cc_to_name(*cc2), attached,
> + misc_to_cc(misc));
> +
> + return ret;
> +}
> +
> +static void qcom_pmic_set_cc_debounce(struct pmic_typec_port *pmic_typec_port)
> +{
> + pmic_typec_port->debouncing_cc = true;
> + schedule_delayed_work(&pmic_typec_port->cc_debounce_dwork,
> + msecs_to_jiffies(2));
> +}
> +
> +int qcom_pmic_typec_port_set_cc(struct pmic_typec_port *pmic_typec_port,
> + enum typec_cc_status cc)
> +{
> + struct device *dev = pmic_typec_port->dev;
> + unsigned int mode, currsrc;
> + unsigned int misc;
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&pmic_typec_port->lock, flags);
> +
> + ret = regmap_read(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
> + &misc);
> + if (ret)
> + goto done;
> +
> + mode = EN_SRC_ONLY;
> +
> + switch (cc) {
> + case TYPEC_CC_OPEN:
> + currsrc = TYPEC_SRC_RP_SEL_80UA;
> + break;
> + case TYPEC_CC_RP_DEF:
> + currsrc = TYPEC_SRC_RP_SEL_80UA;
> + break;
> + case TYPEC_CC_RP_1_5:
> + currsrc = TYPEC_SRC_RP_SEL_180UA;
> + break;
> + case TYPEC_CC_RP_3_0:
> + currsrc = TYPEC_SRC_RP_SEL_330UA;
> + break;
> + case TYPEC_CC_RD:
> + currsrc = TYPEC_SRC_RP_SEL_80UA;
> + mode = EN_SNK_ONLY;
> + break;
> + default:
> + dev_warn(dev, "unexpected set_cc %d\n", cc);
> + ret = -EINVAL;
> + goto done;
> + }
> +
> + if (mode == EN_SRC_ONLY) {
> + ret = regmap_write(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_CURRSRC_CFG_REG,
> + currsrc);
> + if (ret)
> + goto done;
> + }
> +
> + pmic_typec_port->cc = cc;
> + qcom_pmic_set_cc_debounce(pmic_typec_port);
> + ret = 0;
> +
> +done:
> + spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
> +
> + dev_dbg(dev, "set_cc: currsrc=%x %s mode %s debounce %d attached %d cc=%s\n",
> + currsrc, rp_sel_to_name(currsrc),
> + mode == EN_SRC_ONLY ? "EN_SRC_ONLY" : "EN_SNK_ONLY",
> + pmic_typec_port->debouncing_cc, !!(misc & CC_ATTACHED),
> + misc_to_cc(misc));
> +
> + return ret;
> +}
> +
> +int qcom_pmic_typec_port_set_vconn(struct pmic_typec_port *pmic_typec_port, bool on)
> +{
> + struct device *dev = pmic_typec_port->dev;
> + unsigned int orientation, misc, mask, value;
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&pmic_typec_port->lock, flags);
> +
> + ret = regmap_read(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc);
> + if (ret)
> + goto done;
> +
> + /* Set VCONN on the inversion of the active CC channel */
> + orientation = (misc & CC_ORIENTATION) ? 0 : VCONN_EN_ORIENTATION;
> + if (on) {
> + mask = VCONN_EN_ORIENTATION | VCONN_EN_VALUE;
> + value = orientation | VCONN_EN_VALUE | VCONN_EN_SRC;
> + } else {
> + mask = VCONN_EN_VALUE;
> + value = 0;
> + }
> +
> + ret = regmap_update_bits(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_VCONN_CONTROL_REG,
> + mask, value);
> +done:
> + spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
> +
> + dev_dbg(dev, "set_vconn: orientation %d control 0x%08x state %s cc %s vconn %s\n",
> + orientation, value, on ? "on" : "off", misc_to_vconn(misc), misc_to_cc(misc));
> +
> + return ret;
> +}
> +
> +int qcom_pmic_typec_port_start_toggling(struct pmic_typec_port *pmic_typec_port,
> + enum typec_port_type port_type,
> + enum typec_cc_status cc)
> +{
> + struct device *dev = pmic_typec_port->dev;
> + unsigned int misc;
> + u8 mode = 0;
> + unsigned long flags;
> + int ret;
> +
> + switch (port_type) {
> + case TYPEC_PORT_SRC:
> + mode = EN_SRC_ONLY;
> + break;
> + case TYPEC_PORT_SNK:
> + mode = EN_SNK_ONLY;
> + break;
> + case TYPEC_PORT_DRP:
> + mode = EN_TRY_SNK;
> + break;
> + }
> +
> + spin_lock_irqsave(&pmic_typec_port->lock, flags);
> +
> + ret = regmap_read(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_MISC_STATUS_REG, &misc);
> + if (ret)
> + goto done;
> +
> + dev_dbg(dev, "start_toggling: misc 0x%08x attached %d port_type %d current cc %d new %d\n",
> + misc, !!(misc & CC_ATTACHED), port_type, pmic_typec_port->cc, cc);
> +
> + qcom_pmic_set_cc_debounce(pmic_typec_port);
> +
> + /* force it to toggle at least once */
> + ret = regmap_write(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_MODE_CFG_REG,
> + TYPEC_DISABLE_CMD);
> + if (ret)
> + goto done;
> +
> + ret = regmap_write(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_MODE_CFG_REG,
> + mode);
> +done:
> + spin_unlock_irqrestore(&pmic_typec_port->lock, flags);
> +
> + return ret;
> +}
> +
> +#define TYPEC_INTR_EN_CFG_1_MASK \
> + (TYPEC_LEGACY_CABLE_INT_EN | \
> + TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN | \
> + TYPEC_TRYSOURCE_DETECT_INT_EN | \
> + TYPEC_TRYSINK_DETECT_INT_EN | \
> + TYPEC_CCOUT_DETACH_INT_EN | \
> + TYPEC_CCOUT_ATTACH_INT_EN | \
> + TYPEC_VBUS_DEASSERT_INT_EN | \
> + TYPEC_VBUS_ASSERT_INT_EN)
> +
> +#define TYPEC_INTR_EN_CFG_2_MASK \
> + (TYPEC_STATE_MACHINE_CHANGE_INT_EN | TYPEC_VBUS_ERROR_INT_EN | \
> + TYPEC_DEBOUNCE_DONE_INT_EN)
> +
> +int qcom_pmic_typec_port_start(struct pmic_typec_port *pmic_typec_port,
> + struct tcpm_port *tcpm_port)
> +{
> + int i;
> + int mask;
> + int ret;
> +
> + /* Configure interrupt sources */
> + ret = regmap_write(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_INTERRUPT_EN_CFG_1_REG,
> + TYPEC_INTR_EN_CFG_1_MASK);
> + if (ret)
> + goto done;
> +
> + ret = regmap_write(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_INTERRUPT_EN_CFG_2_REG,
> + TYPEC_INTR_EN_CFG_2_MASK);
> + if (ret)
> + goto done;
> +
> + /* start in TRY_SNK mode */
> + ret = regmap_write(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_MODE_CFG_REG, EN_TRY_SNK);
> + if (ret)
> + goto done;
> +
> + /* Configure VCONN for software control */
> + ret = regmap_update_bits(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_VCONN_CONTROL_REG,
> + VCONN_EN_SRC | VCONN_EN_VALUE, VCONN_EN_SRC);
> + if (ret)
> + goto done;
> +
> + /* Set CC threshold to 1.6 Volts | tPDdebounce = 10-20ms */
> + mask = SEL_SRC_UPPER_REF | USE_TPD_FOR_EXITING_ATTACHSRC;
> + ret = regmap_update_bits(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_EXIT_STATE_CFG_REG,
> + mask, mask);
> + if (ret)
> + goto done;
> +
> + pmic_typec_port->tcpm_port = tcpm_port;
> +
> + for (i = 0; i < pmic_typec_port->nr_irqs; i++)
> + enable_irq(pmic_typec_port->irq_data[i].irq);
> +
> +done:
> + return ret;
> +}
> +
> +void qcom_pmic_typec_port_stop(struct pmic_typec_port *pmic_typec_port)
> +{
> + int i;
> +
> + for (i = 0; i < pmic_typec_port->nr_irqs; i++)
> + disable_irq(pmic_typec_port->irq_data[i].irq);
> +}
> +
> +struct pmic_typec_port *qcom_pmic_typec_port_alloc(struct device *dev)
> +{
> + return devm_kzalloc(dev, sizeof(struct pmic_typec_port), GFP_KERNEL);
> +}
> +
> +int qcom_pmic_typec_port_probe(struct platform_device *pdev,
> + struct pmic_typec_port *pmic_typec_port,
> + struct pmic_typec_port_resources *res,
> + struct regmap *regmap,
> + u32 base)
> +{
> + struct device *dev = &pdev->dev;
> + struct pmic_typec_port_irq_data *irq_data;
> + int i, ret, irq;
> +
> + if (!res->nr_irqs || res->nr_irqs > PMIC_TYPEC_MAX_IRQS)
> + return -EINVAL;
> +
> + irq_data = devm_kzalloc(dev, sizeof(*irq_data) * res->nr_irqs,
> + GFP_KERNEL);
> + if (!irq_data)
> + return -ENOMEM;
> +
> + pmic_typec_port->vdd_vbus = devm_regulator_get(dev, "vdd-vbus");
> + if (IS_ERR(pmic_typec_port->vdd_vbus))
> + return PTR_ERR(pmic_typec_port->vdd_vbus);
> +
> + pmic_typec_port->dev = dev;
> + pmic_typec_port->base = base;
> + pmic_typec_port->regmap = regmap;
> + pmic_typec_port->nr_irqs = res->nr_irqs;
> + pmic_typec_port->irq_data = irq_data;
> + spin_lock_init(&pmic_typec_port->lock);
> + INIT_DELAYED_WORK(&pmic_typec_port->cc_debounce_dwork,
> + qcom_pmic_typec_port_cc_debounce);
> +
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return irq;
> +
> + for (i = 0; i < res->nr_irqs; i++, irq_data++) {
> + irq = platform_get_irq_byname(pdev,
> + res->irq_params[i].irq_name);
> + if (irq < 0)
> + return irq;
> +
> + irq_data->pmic_typec_port = pmic_typec_port;
> + irq_data->irq = irq;
> + irq_data->virq = res->irq_params[i].virq;
> + ret = devm_request_threaded_irq(dev, irq, NULL, pmic_typec_port_isr,
> + IRQF_ONESHOT | IRQF_NO_AUTOEN,
> + res->irq_params[i].irq_name,
> + irq_data);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
> new file mode 100644
> index 0000000000000..5a9c47373c614
> --- /dev/null
> +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.h
> @@ -0,0 +1,194 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
> + * Copyright (c) 2023, Linaro Ltd. All rights reserved.
> + */
> +#ifndef __QCOM_PMIC_TYPEC_H__
> +#define __QCOM_PMIC_TYPEC_H__
> +
> +#include <linux/usb/tcpm.h>
> +
> +#define TYPEC_SNK_STATUS_REG 0x06
> +#define DETECTED_SNK_TYPE_MASK GENMASK(6, 0)
> +#define SNK_DAM_MASK GENMASK(6, 4)
> +#define SNK_DAM_500MA BIT(6)
> +#define SNK_DAM_1500MA BIT(5)
> +#define SNK_DAM_3000MA BIT(4)
> +#define SNK_RP_STD BIT(3)
> +#define SNK_RP_1P5 BIT(2)
> +#define SNK_RP_3P0 BIT(1)
> +#define SNK_RP_SHORT BIT(0)
> +
> +#define TYPEC_SRC_STATUS_REG 0x08
> +#define DETECTED_SRC_TYPE_MASK GENMASK(4, 0)
> +#define SRC_HIGH_BATT BIT(5)
> +#define SRC_DEBUG_ACCESS BIT(4)
> +#define SRC_RD_OPEN BIT(3)
> +#define SRC_RD_RA_VCONN BIT(2)
> +#define SRC_RA_OPEN BIT(1)
> +#define AUDIO_ACCESS_RA_RA BIT(0)
> +
> +#define TYPEC_STATE_MACHINE_STATUS_REG 0x09
> +#define TYPEC_ATTACH_DETACH_STATE BIT(5)
> +
> +#define TYPEC_SM_STATUS_REG 0x0A
> +#define TYPEC_SM_VBUS_VSAFE5V BIT(5)
> +#define TYPEC_SM_VBUS_VSAFE0V BIT(6)
> +#define TYPEC_SM_USBIN_LT_LV BIT(7)
> +
> +#define TYPEC_MISC_STATUS_REG 0x0B
> +#define TYPEC_WATER_DETECTION_STATUS BIT(7)
> +#define SNK_SRC_MODE BIT(6)
> +#define TYPEC_VBUS_DETECT BIT(5)
> +#define TYPEC_VBUS_ERROR_STATUS BIT(4)
> +#define TYPEC_DEBOUNCE_DONE BIT(3)
> +#define CC_ORIENTATION BIT(1)
> +#define CC_ATTACHED BIT(0)
> +
> +#define LEGACY_CABLE_STATUS_REG 0x0D
> +#define TYPEC_LEGACY_CABLE_STATUS BIT(1)
> +#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS BIT(0)
> +
> +#define TYPEC_U_USB_STATUS_REG 0x0F
> +#define U_USB_GROUND_NOVBUS BIT(6)
> +#define U_USB_GROUND BIT(4)
> +#define U_USB_FMB1 BIT(3)
> +#define U_USB_FLOAT1 BIT(2)
> +#define U_USB_FMB2 BIT(1)
> +#define U_USB_FLOAT2 BIT(0)
> +
> +#define TYPEC_MODE_CFG_REG 0x44
> +#define TYPEC_TRY_MODE_MASK GENMASK(4, 3)
> +#define EN_TRY_SNK BIT(4)
> +#define EN_TRY_SRC BIT(3)
> +#define TYPEC_POWER_ROLE_CMD_MASK GENMASK(2, 0)
> +#define EN_SRC_ONLY BIT(2)
> +#define EN_SNK_ONLY BIT(1)
> +#define TYPEC_DISABLE_CMD BIT(0)
> +
> +#define TYPEC_VCONN_CONTROL_REG 0x46
> +#define VCONN_EN_ORIENTATION BIT(2)
> +#define VCONN_EN_VALUE BIT(1)
> +#define VCONN_EN_SRC BIT(0)
> +
> +#define TYPEC_CCOUT_CONTROL_REG 0x48
> +#define TYPEC_CCOUT_BUFFER_EN BIT(2)
> +#define TYPEC_CCOUT_VALUE BIT(1)
> +#define TYPEC_CCOUT_SRC BIT(0)
> +
> +#define DEBUG_ACCESS_SRC_CFG_REG 0x4C
> +#define EN_UNORIENTED_DEBUG_ACCESS_SRC BIT(0)
> +
> +#define TYPE_C_CRUDE_SENSOR_CFG_REG 0x4e
> +#define EN_SRC_CRUDE_SENSOR BIT(1)
> +#define EN_SNK_CRUDE_SENSOR BIT(0)
> +
> +#define TYPEC_EXIT_STATE_CFG_REG 0x50
> +#define BYPASS_VSAFE0V_DURING_ROLE_SWAP BIT(3)
> +#define SEL_SRC_UPPER_REF BIT(2)
> +#define USE_TPD_FOR_EXITING_ATTACHSRC BIT(1)
> +#define EXIT_SNK_BASED_ON_CC BIT(0)
> +
> +#define TYPEC_CURRSRC_CFG_REG 0x52
> +#define TYPEC_SRC_RP_SEL_330UA BIT(1)
> +#define TYPEC_SRC_RP_SEL_180UA BIT(0)
> +#define TYPEC_SRC_RP_SEL_80UA 0
> +#define TYPEC_SRC_RP_SEL_MASK GENMASK(1, 0)
> +
> +#define TYPEC_INTERRUPT_EN_CFG_1_REG 0x5E
> +#define TYPEC_LEGACY_CABLE_INT_EN BIT(7)
> +#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN BIT(6)
> +#define TYPEC_TRYSOURCE_DETECT_INT_EN BIT(5)
> +#define TYPEC_TRYSINK_DETECT_INT_EN BIT(4)
> +#define TYPEC_CCOUT_DETACH_INT_EN BIT(3)
> +#define TYPEC_CCOUT_ATTACH_INT_EN BIT(2)
> +#define TYPEC_VBUS_DEASSERT_INT_EN BIT(1)
> +#define TYPEC_VBUS_ASSERT_INT_EN BIT(0)
> +
> +#define TYPEC_INTERRUPT_EN_CFG_2_REG 0x60
> +#define TYPEC_SRC_BATT_HPWR_INT_EN BIT(6)
> +#define MICRO_USB_STATE_CHANGE_INT_EN BIT(5)
> +#define TYPEC_STATE_MACHINE_CHANGE_INT_EN BIT(4)
> +#define TYPEC_DEBUG_ACCESS_DETECT_INT_EN BIT(3)
> +#define TYPEC_WATER_DETECTION_INT_EN BIT(2)
> +#define TYPEC_VBUS_ERROR_INT_EN BIT(1)
> +#define TYPEC_DEBOUNCE_DONE_INT_EN BIT(0)
> +
> +#define TYPEC_DEBOUNCE_OPTION_REG 0x62
> +#define REDUCE_TCCDEBOUNCE_TO_2MS BIT(2)
> +
> +#define TYPE_C_SBU_CFG_REG 0x6A
> +#define SEL_SBU1_ISRC_VAL 0x04
> +#define SEL_SBU2_ISRC_VAL 0x01
> +
> +#define TYPEC_U_USB_CFG_REG 0x70
> +#define EN_MICRO_USB_FACTORY_MODE BIT(1)
> +#define EN_MICRO_USB_MODE BIT(0)
> +
> +#define TYPEC_PMI632_U_USB_WATER_PROTECTION_CFG_REG 0x72
> +
> +#define TYPEC_U_USB_WATER_PROTECTION_CFG_REG 0x73
> +#define EN_MICRO_USB_WATER_PROTECTION BIT(4)
> +#define MICRO_USB_DETECTION_ON_TIME_CFG_MASK GENMASK(3, 2)
> +#define MICRO_USB_DETECTION_PERIOD_CFG_MASK GENMASK(1, 0)
> +
> +#define TYPEC_PMI632_MICRO_USB_MODE_REG 0x73
> +#define MICRO_USB_MODE_ONLY BIT(0)
> +
> +/* Interrupt numbers */
> +#define PMIC_TYPEC_OR_RID_IRQ 0x0
> +#define PMIC_TYPEC_VPD_IRQ 0x1
> +#define PMIC_TYPEC_CC_STATE_IRQ 0x2
> +#define PMIC_TYPEC_VCONN_OC_IRQ 0x3
> +#define PMIC_TYPEC_VBUS_IRQ 0x4
> +#define PMIC_TYPEC_ATTACH_DETACH_IRQ 0x5
> +#define PMIC_TYPEC_LEGACY_CABLE_IRQ 0x6
> +#define PMIC_TYPEC_TRY_SNK_SRC_IRQ 0x7
> +
> +/* Resources */
> +#define PMIC_TYPEC_MAX_IRQS 0x08
> +
> +struct pmic_typec_port_irq_params {
> + int virq;
> + char *irq_name;
> +};
> +
> +struct pmic_typec_port_resources {
> + unsigned int nr_irqs;
> + struct pmic_typec_port_irq_params irq_params[PMIC_TYPEC_MAX_IRQS];
> +};
> +
> +/* API */
> +struct pmic_typec;
> +
> +struct pmic_typec_port *qcom_pmic_typec_port_alloc(struct device *dev);
> +
> +int qcom_pmic_typec_port_probe(struct platform_device *pdev,
> + struct pmic_typec_port *pmic_typec_port,
> + struct pmic_typec_port_resources *res,
> + struct regmap *regmap,
> + u32 base);
> +
> +int qcom_pmic_typec_port_start(struct pmic_typec_port *pmic_typec_port,
> + struct tcpm_port *tcpm_port);
> +
> +void qcom_pmic_typec_port_stop(struct pmic_typec_port *pmic_typec_port);
> +
> +int qcom_pmic_typec_port_get_cc(struct pmic_typec_port *pmic_typec_port,
> + enum typec_cc_status *cc1,
> + enum typec_cc_status *cc2);
> +
> +int qcom_pmic_typec_port_set_cc(struct pmic_typec_port *pmic_typec_port,
> + enum typec_cc_status cc);
> +
> +int qcom_pmic_typec_port_get_vbus(struct pmic_typec_port *pmic_typec_port);
> +
> +int qcom_pmic_typec_port_set_vconn(struct pmic_typec_port *pmic_typec_port, bool on);
> +
> +int qcom_pmic_typec_port_start_toggling(struct pmic_typec_port *pmic_typec_port,
> + enum typec_port_type port_type,
> + enum typec_cc_status cc);
> +
> +int qcom_pmic_typec_port_set_vbus(struct pmic_typec_port *pmic_typec_port, bool on);
> +
> +#endif /* __QCOM_PMIC_TYPE_C_PORT_H__ */
> --
> 2.39.2
--
heikki
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 13/14] usb: typec: qcom: Add Qualcomm PMIC TCPM support
2023-04-24 13:11 ` Heikki Krogerus
@ 2023-04-24 13:48 ` Bryan O'Donoghue
0 siblings, 0 replies; 43+ messages in thread
From: Bryan O'Donoghue @ 2023-04-24 13:48 UTC (permalink / raw)
To: Heikki Krogerus, Bryan O'Donoghue
Cc: linux, gregkh, andersson, robh+dt, krzysztof.kozlowski+dt,
linux-usb, linux-arm-msm, devicetree, caleb.connolly,
konrad.dybcio, subbaram, jackp, robertom
On 24/04/2023 14:11, Heikki Krogerus wrote:
> I think you need to rewrite the commit message - you still have that
> third driver in there - but otherwise I don't have any more comments.
> I hope Guenter has time to check this. In any case, FWIW:
>
> Acked-by: Heikki Krogerus<heikki.krogerus@linux.intel.com>
appreciated
---
bod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-22 22:16 ` Bryan O'Donoghue
@ 2023-04-25 7:29 ` Luca Weiss
0 siblings, 0 replies; 43+ messages in thread
From: Luca Weiss @ 2023-04-25 7:29 UTC (permalink / raw)
To: Bryan O'Donoghue, Bryan O'Donoghue, linux,
heikki.krogerus, gregkh, andersson, robh+dt,
krzysztof.kozlowski+dt, linux-usb, linux-arm-msm, devicetree
Cc: caleb.connolly, konrad.dybcio, subbaram, jackp, robertom
On Sun Apr 23, 2023 at 12:16 AM CEST, Bryan O'Donoghue wrote:
> On 21/04/2023 11:26, Luca Weiss wrote:
> > With the "user-space triggered role-switching" patch I can see that
> > whatever scenario the USB-C port is in, the role is stuck on "device".
>
> Hmm.
>
> Could you share a branch ?
Sure, at https://github.com/z3ntu/linux I pushed the following branches.
All are a bit messy, sorry for that, but the end result should be okay.
* fp4-6.2.y-wip-tcpm2: TCPM patches v4, worked for the most part apart
from the host mode not working in one direction as mentioned in the
emails there
* fp4-6.2.y-wip-tcpm3: TCPM patches v5
* fp4-6.2.y-wip-tcpm4: TCPM patches from the branch you posted, probably
not much difference to the previous branch
Regards
Luca
>
> ---
> bod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v5 00/14] Add Qualcomm PMIC TPCM support
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
` (14 preceding siblings ...)
2023-04-13 14:19 ` [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Luca Weiss
@ 2023-09-20 2:13 ` Bjorn Andersson
15 siblings, 0 replies; 43+ messages in thread
From: Bjorn Andersson @ 2023-09-20 2:13 UTC (permalink / raw)
To: linux-usb, linux-arm-msm, linux, robh+dt, heikki.krogerus,
devicetree, gregkh, krzysztof.kozlowski+dt, Bryan O'Donoghue
Cc: konrad.dybcio, subbaram, caleb.connolly, robertom, jackp
On Thu, 13 Apr 2023 12:34:24 +0100, Bryan O'Donoghue wrote:
> V5:
> - Amagamates into once device, Heikki, Rob
>
> - Takes feedback on usage form Luka and Jianhua on VSafeV state transition detection
> dev_err() -> dev_warn()
>
> - Orientation graph example and general expected bindings
> I discussed offline with Bjorn the conclusions of the glink/sbu model.
> The expected orientation-switch path is
> connector/port@0 <-> phy/port@X <-> dp/port@0
> This can then be expanded to
> connector/port@0 <-> redriver/port@0 <-> phy/port@X <-> dp/port@0
>
> [...]
Applied, thanks!
[01/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required
(no commit info)
[02/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark regulator-*-microamp required
(no commit info)
[03/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add orientation-switch as optional
(no commit info)
[04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional
(no commit info)
[05/14] dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema
(no commit info)
[06/14] dt-bindings: mfd: qcom,spmi-pmic: Add typec to SPMI device types
(no commit info)
[07/14] arm64: dts: qcom: sm8250: Define ports for qmpphy orientation-switching
commit: ea96b90a58cf5d2e91ac177f081118ff26b85c1d
[08/14] arm64: dts: qcom: pm8150b: Add a TCPM description
commit: 5a0539515cbfad30b3e08a00004ed0c86136add5
[09/14] arm64: dts: qcom: qrb5165-rb5: Switch on Type-C VBUS boost
commit: c627d7337aae4d83b4db621fdb9e8f638056dcee
[10/14] arm64: dts: qcom: qrb5165-rb5: Switch on basic TCPM
commit: 5b1b6da9d39d515395d85dc678ddac7ff1689438
[11/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for usb_1
commit: 25defdca4d902b338c05bc01a1de1064a6d3b7f3
[12/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM orientation-switch for usb_1_qmpphy
commit: 45219a6b9497cb7713dd2bc221248ee1a7e9bb3d
[13/14] usb: typec: qcom: Add Qualcomm PMIC TCPM support
(no commit info)
[14/14] phy: qcom-qmp: Register as a typec switch for orientation detection
(no commit info)
Best regards,
--
Bjorn Andersson <andersson@kernel.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2023-09-20 2:09 UTC | newest]
Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-13 11:34 [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 01/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark reg as required Bryan O'Donoghue
2023-04-16 17:43 ` Krzysztof Kozlowski
2023-04-13 11:34 ` [PATCH v5 02/14] dt-bindings: regulator: qcom,usb-vbus-regulator: Mark regulator-*-microamp required Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 03/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add orientation-switch as optional Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 04/14] dt-bindings: phy: qcom,sc7180-qmp-usb3-dp-phy: Add ports as an optional Bryan O'Donoghue
2023-04-14 7:23 ` Marijn Suijten
2023-04-16 17:47 ` Krzysztof Kozlowski
2023-04-17 0:09 ` Bryan O'Donoghue
2023-04-17 6:16 ` Krzysztof Kozlowski
2023-04-13 11:34 ` [PATCH v5 05/14] dt-bindings: usb: Add Qualcomm PMIC Type-C YAML schema Bryan O'Donoghue
2023-04-14 7:27 ` Marijn Suijten
2023-04-16 17:49 ` Krzysztof Kozlowski
2023-04-13 11:34 ` [PATCH v5 06/14] dt-bindings: mfd: qcom,spmi-pmic: Add typec to SPMI device types Bryan O'Donoghue
2023-04-16 17:50 ` Krzysztof Kozlowski
2023-04-13 11:34 ` [PATCH v5 07/14] arm64: dts: qcom: sm8250: Define ports for qmpphy orientation-switching Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 08/14] arm64: dts: qcom: pm8150b: Add a TCPM description Bryan O'Donoghue
2023-04-13 20:28 ` kernel test robot
2023-04-15 13:51 ` kernel test robot
2023-04-13 11:34 ` [PATCH v5 09/14] arm64: dts: qcom: qrb5165-rb5: Switch on Type-C VBUS boost Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 10/14] arm64: dts: qcom: qrb5165-rb5: Switch on basic TCPM Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 11/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM usb-role-switching for usb_1 Bryan O'Donoghue
2023-04-22 14:52 ` Konrad Dybcio
2023-04-22 14:53 ` Konrad Dybcio
2023-04-13 11:34 ` [PATCH v5 12/14] arm64: dts: qcom: qrb5165-rb5: Switch on TCPM orientation-switch for usb_1_qmpphy Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 13/14] usb: typec: qcom: Add Qualcomm PMIC TCPM support Bryan O'Donoghue
2023-04-24 13:11 ` Heikki Krogerus
2023-04-24 13:48 ` Bryan O'Donoghue
2023-04-13 11:34 ` [PATCH v5 14/14] phy: qcom-qmp: Register as a typec switch for orientation detection Bryan O'Donoghue
2023-04-13 13:34 ` kernel test robot
2023-04-18 12:57 ` Bjorn Andersson
2023-04-18 16:54 ` Bryan O'Donoghue
2023-04-13 14:19 ` [PATCH v5 00/14] Add Qualcomm PMIC TPCM support Luca Weiss
2023-04-13 15:08 ` Bryan O'Donoghue
2023-04-14 6:51 ` Luca Weiss
2023-04-17 0:30 ` Bryan O'Donoghue
2023-04-17 7:35 ` Luca Weiss
2023-04-17 10:04 ` Bryan O'Donoghue
2023-04-17 10:11 ` Bryan O'Donoghue
2023-04-21 10:26 ` Luca Weiss
2023-04-22 22:16 ` Bryan O'Donoghue
2023-04-25 7:29 ` Luca Weiss
2023-09-20 2:13 ` Bjorn Andersson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.