* [PATCH v4 0/4] usb: typec: Add new driver for Parade PS8830 Type-C Retimer
@ 2024-11-01 16:29 Abel Vesa
2024-11-01 16:29 ` [PATCH v4 1/4] dt-bindings: usb: Add Parade PS8830 Type-C retimer bindings Abel Vesa
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Abel Vesa @ 2024-11-01 16:29 UTC (permalink / raw)
To: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, Bjorn Andersson, Konrad Dybcio, Rajendra Nayak,
Sibi Sankar, Johan Hovold, Dmitry Baryshkov, Trilok Soni,
linux-kernel, linux-usb, devicetree, Abel Vesa
The Parade PS8830 is a Type-C multi-protocol retimer that is controlled
via I2C. It provides altmode and orientation handling and usually sits
between the Type-C port and the PHY.
It is currently used alongside Qualcomm Snapdragon X Elite SoCs on quite
a few laptops already.
This new driver adds support for the following 3 modes:
- DP 4lanes (pin assignments C and E)
- DP 2lanes + USB3 (pin assignment D)
- USB3
This retimer is a LTTPR (Link-Training Tunable PHY Repeater) which means
it can support link training from source to itself. This means that the
DP driver needs to be aware of the repeater presence and to handle
the link training accordingly. This is currently missing from msm dp
driver, but there is already a patchset [1] on the list that adds it.
Once done, full external DP will be working on all X1E laptops that make
use of this retimer.
NOTE: Currently, due to both LTTPR missing support in msm DP and a
reported crash that can happen on DP unplug, the DP DT patch is not
supposed to be merged yet. That patch is only shared for testing purposes.
Once those 2 issues have been resolved, the MDSS DP 0-2 enablement patch
will be respun.
The LTTPR patchset is already on the list:
[1] https://lore.kernel.org/all/20241031-drm-dp-msm-add-lttpr-transparent-mode-set-v1-0-cafbb9855f40@linaro.org/
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
Changes in v4:
- Renamed the driver and bindings schema to ps883x to allow future
support for the PS8833.
- Dropped the dedicated DT property for keeping the retimers from
resetting on probe, and replaced that with a read to figure out
if it has been already configured or not. This involves leaving the
reset gpio as-is on probe if the retimer has been already configured.
- Replaced the fwnode_typec_switch_get() call with typec_switch_get()
- Replaced the fwnode_typec_mux_get() call with typec_mux_get()
- Dropped the clock name, as there is only one clock. As per Bjorn's
suggestion.
- Dropped regcache as it seems it is not needed.
- Re-worded all commit messages to explain better the problem and the
proposed changes.
- Link to v3: https://lore.kernel.org/r/20241022-x1e80100-ps8830-v3-0-68a95f351e99@linaro.org
Changes in v3:
- Reworked the schema binding by using the usb/usb-switch.yaml defined
port graph and properties. Addressed all comments from Johan and
Dmitry.
- Dropped the manual caching of the config values on regmap write in the
driver.
- Reordered the DP pin assignment states within the switch clause, as
Dmitry suggested.
- Added SVID check to not allow any altmode other than DP.
- Added DT patches (retimer for USB orientation handling and DP
enablement). Did this in order to offer a full picture of how it all
fits together.
- Split the DP enablement in DT in a separate patchset so the USB
handling can be merged separately.
- Added ps8830,boot-on to let the driver know it is supposed to skip
resetting the retimer on driver probe, as the bootloader might already
let it in a pre-configured state.
- Marked all retimer voltage regulators as boot-on since we want to
maintain the state for coldplug orientation.
- Added pinconf for all retimer0 gpios.
- Didn't pick up Konrad's T-b tags and Krzysztof's R-b tag as the rework
is quite extensive. Especially because of the ps8830,boot-on and what
it does.
- Link to v2: https://lore.kernel.org/r/20241004-x1e80100-ps8830-v2-0-5cd8008c8c40@linaro.org
Changes in v2:
- Addressed all comments from Johan and Konrad.
- Reworked the handling of the vregs so it would be more cleaner.
Dropped the usage of bulk regulators API and handled them separately.
Also discribed all regulators according to data sheet.
- Added all delays according to data sheet.
- Fixed coldplug (on boot) orientation detection.
- Didn't pick Krzysztof's R-b tag because the bindings changed w.r.t
supplies.
- Link to v1: https://lore.kernel.org/r/20240829-x1e80100-ps8830-v1-0-bcc4790b1d45@linaro.org
---
Abel Vesa (4):
dt-bindings: usb: Add Parade PS8830 Type-C retimer bindings
usb: typec: Add support for Parade PS8830 Type-C Retimer
arm64: dts: qcom: x1e80100-crd: Describe the Parade PS8830 retimers
arm64: dts: qcom: x1e80100-crd: Enable external DisplayPort support
.../devicetree/bindings/usb/parade,ps883x.yaml | 123 ++++++
arch/arm64/boot/dts/qcom/x1e80100-crd.dts | 463 ++++++++++++++++++++-
drivers/usb/typec/mux/Kconfig | 10 +
drivers/usb/typec/mux/Makefile | 1 +
drivers/usb/typec/mux/ps883x.c | 422 +++++++++++++++++++
5 files changed, 1013 insertions(+), 6 deletions(-)
---
base-commit: 6fb2fa9805c501d9ade047fc511961f3273cdcb5
change-id: 20240521-x1e80100-ps8830-d5ccca95b557
Best regards,
--
Abel Vesa <abel.vesa@linaro.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 1/4] dt-bindings: usb: Add Parade PS8830 Type-C retimer bindings
2024-11-01 16:29 [PATCH v4 0/4] usb: typec: Add new driver for Parade PS8830 Type-C Retimer Abel Vesa
@ 2024-11-01 16:29 ` Abel Vesa
2024-11-02 8:58 ` Krzysztof Kozlowski
2024-11-01 16:29 ` [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer Abel Vesa
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Abel Vesa @ 2024-11-01 16:29 UTC (permalink / raw)
To: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, Bjorn Andersson, Konrad Dybcio, Rajendra Nayak,
Sibi Sankar, Johan Hovold, Dmitry Baryshkov, Trilok Soni,
linux-kernel, linux-usb, devicetree, Abel Vesa
The Parade PS8830 is a USB4, DisplayPort and Thunderbolt 4 retimer,
controlled over I2C. It usually sits between a USB/DisplayPort PHY and the
Type-C connector, and provides orientation and altmode handling.
Currently, it is found on all boards featuring the Qualcomm Snapdragon
X Elite SoCs.
Document bindings for its new driver. Future-proof the schema for the
PS8833 variant, which seems to be similar to PS8830.
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
.../devicetree/bindings/usb/parade,ps883x.yaml | 123 +++++++++++++++++++++
1 file changed, 123 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/parade,ps883x.yaml b/Documentation/devicetree/bindings/usb/parade,ps883x.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4045714e487a43681336c961143b27264c081856
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/parade,ps883x.yaml
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/parade,ps883x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Parade PS883x USB and DisplayPort Retimer
+
+maintainers:
+ - Abel Vesa <abel.vesa@linaro.org>
+
+properties:
+ compatible:
+ enum:
+ - parade,ps8830
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: XO Clock
+
+ ps8830,boot-on:
+ description: Left enabled at boot, so skip resetting
+ type: boolean
+
+ reset-gpios:
+ maxItems: 1
+
+ vdd-supply:
+ description: power supply (1.07V)
+
+ vdd33-supply:
+ description: power supply (3.3V)
+
+ vdd33-cap-supply:
+ description: power supply (3.3V)
+
+ vddar-supply:
+ description: power supply (1.07V)
+
+ vddat-supply:
+ description: power supply (1.07V)
+
+ vddio-supply:
+ description: power supply (1.2V or 1.8V)
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - reset-gpios
+ - vdd-supply
+ - vdd33-supply
+ - vdd33-cap-supply
+ - vddat-supply
+ - vddio-supply
+ - orientation-switch
+ - retimer-switch
+
+allOf:
+ - $ref: usb-switch.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ typec-mux@8 {
+ compatible = "parade,ps8830";
+ reg = <0x8>;
+
+ clocks = <&clk_rtmr_xo>;
+
+ vdd-supply = <&vreg_rtmr_1p15>;
+ vdd33-supply = <&vreg_rtmr_3p3>;
+ vdd33-cap-supply = <&vreg_rtmr_3p3>;
+ vddar-supply = <&vreg_rtmr_1p15>;
+ vddat-supply = <&vreg_rtmr_1p15>;
+ vddio-supply = <&vreg_rtmr_1p8>;
+
+ reset-gpios = <&tlmm 10 GPIO_ACTIVE_LOW>;
+
+ retimer-switch;
+ orientation-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&typec_con_ss>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ endpoint {
+ remote-endpoint = <&usb_phy_ss>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ endpoint {
+ remote-endpoint = <&typec_dp_aux>;
+ };
+ };
+ };
+ };
+ };
+...
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer
2024-11-01 16:29 [PATCH v4 0/4] usb: typec: Add new driver for Parade PS8830 Type-C Retimer Abel Vesa
2024-11-01 16:29 ` [PATCH v4 1/4] dt-bindings: usb: Add Parade PS8830 Type-C retimer bindings Abel Vesa
@ 2024-11-01 16:29 ` Abel Vesa
2024-11-01 16:56 ` Christophe JAILLET
2024-11-02 9:17 ` Konrad Dybcio
2024-11-01 16:29 ` [PATCH v4 3/4] arm64: dts: qcom: x1e80100-crd: Describe the Parade PS8830 retimers Abel Vesa
2024-11-01 16:29 ` [PATCH v4 4/4] arm64: dts: qcom: x1e80100-crd: Enable external DisplayPort support Abel Vesa
3 siblings, 2 replies; 13+ messages in thread
From: Abel Vesa @ 2024-11-01 16:29 UTC (permalink / raw)
To: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, Bjorn Andersson, Konrad Dybcio, Rajendra Nayak,
Sibi Sankar, Johan Hovold, Dmitry Baryshkov, Trilok Soni,
linux-kernel, linux-usb, devicetree, Abel Vesa
The Parade PS8830 is a USB4, DisplayPort and Thunderbolt 4 retimer,
controlled over I2C. It usually sits between a USB/DisplayPort PHY
and the Type-C connector, and provides orientation and altmode handling.
The boards that use this retimer are the ones featuring the Qualcomm
Snapdragon X Elite SoCs.
Add a driver with support for the following modes:
- DisplayPort 4-lanes
- DisplayPort 2-lanes + USB3
- USB3
There is another variant of this retimer which is called PS8833. It seems
to be really similar to the PS8830, so future-proof this driver by
naming it ps883x.
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
drivers/usb/typec/mux/Kconfig | 10 +
drivers/usb/typec/mux/Makefile | 1 +
drivers/usb/typec/mux/ps883x.c | 422 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 433 insertions(+)
diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig
index ce7db6ad30572a0a74890f5f11944fb3ff07f635..10c3464324dd7226e0c7304a99d6a558d3743553 100644
--- a/drivers/usb/typec/mux/Kconfig
+++ b/drivers/usb/typec/mux/Kconfig
@@ -56,6 +56,16 @@ config TYPEC_MUX_NB7VPQ904M
Say Y or M if your system has a On Semiconductor NB7VPQ904M Type-C
redriver chip found on some devices with a Type-C port.
+config TYPEC_MUX_PS883X
+ tristate "Parade PS883x Type-C retimer driver"
+ depends on I2C
+ depends on DRM || DRM=n
+ select DRM_AUX_BRIDGE if DRM_BRIDGE && OF
+ select REGMAP_I2C
+ help
+ Say Y or M if your system has a Parade PS883x Type-C retimer chip
+ found on some devices with a Type-C port.
+
config TYPEC_MUX_PTN36502
tristate "NXP PTN36502 Type-C redriver driver"
depends on I2C
diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile
index bb96f30267af05b33b9277dcf1cc0e1527d2dcdd..732aded5f0590b21d45deb07bb9751d807c115f7 100644
--- a/drivers/usb/typec/mux/Makefile
+++ b/drivers/usb/typec/mux/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_TYPEC_MUX_PI3USB30532) += pi3usb30532.o
obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o
obj-$(CONFIG_TYPEC_MUX_IT5205) += it5205.o
obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o
+obj-$(CONFIG_TYPEC_MUX_PS883X) += ps883x.o
obj-$(CONFIG_TYPEC_MUX_PTN36502) += ptn36502.o
obj-$(CONFIG_TYPEC_MUX_WCD939X_USBSS) += wcd939x-usbss.o
diff --git a/drivers/usb/typec/mux/ps883x.c b/drivers/usb/typec/mux/ps883x.c
new file mode 100644
index 0000000000000000000000000000000000000000..101e3dc3a867601f13385f55935af5a9701e7ec3
--- /dev/null
+++ b/drivers/usb/typec/mux/ps883x.c
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Parade ps883x usb retimer driver
+ *
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <drm/bridge/aux-bridge.h>
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/typec_altmode.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/usb/typec_retimer.h>
+
+struct ps883x_retimer {
+ struct i2c_client *client;
+ struct gpio_desc *reset_gpio;
+ struct regmap *regmap;
+ struct typec_switch_dev *sw;
+ struct typec_retimer *retimer;
+ struct clk *xo_clk;
+ struct regulator *vdd_supply;
+ struct regulator *vdd33_supply;
+ struct regulator *vdd33_cap_supply;
+ struct regulator *vddat_supply;
+ struct regulator *vddar_supply;
+ struct regulator *vddio_supply;
+
+ struct typec_switch *typec_switch;
+ struct typec_mux *typec_mux;
+
+ struct mutex lock; /* protect non-concurrent retimer & switch */
+
+ enum typec_orientation orientation;
+ unsigned long mode;
+ unsigned int svid;
+};
+
+static void ps883x_configure(struct ps883x_retimer *retimer, int cfg0, int cfg1, int cfg2)
+{
+ regmap_write(retimer->regmap, 0x0, cfg0);
+ regmap_write(retimer->regmap, 0x1, cfg1);
+ regmap_write(retimer->regmap, 0x2, cfg2);
+}
+
+static int ps883x_set(struct ps883x_retimer *retimer)
+{
+ int cfg0 = 0x00;
+ int cfg1 = 0x00;
+ int cfg2 = 0x00;
+
+ if (retimer->orientation == TYPEC_ORIENTATION_NONE ||
+ retimer->mode == TYPEC_STATE_SAFE) {
+ ps883x_configure(retimer, 0x1, 0x0, 0x0);
+ return 0;
+ }
+
+ if (retimer->mode != TYPEC_STATE_USB && retimer->svid != USB_TYPEC_DP_SID)
+ return -EINVAL;
+
+ if (retimer->orientation == TYPEC_ORIENTATION_NORMAL)
+ cfg0 = 0x01;
+ else
+ cfg0 = 0x03;
+
+ switch (retimer->mode) {
+ case TYPEC_STATE_USB:
+ cfg0 |= 0x20;
+ break;
+
+ case TYPEC_DP_STATE_C:
+ cfg1 = 0x85;
+ break;
+
+ case TYPEC_DP_STATE_D:
+ cfg0 |= 0x20;
+ cfg1 = 0x85;
+ break;
+
+ case TYPEC_DP_STATE_E:
+ cfg1 = 0x81;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ ps883x_configure(retimer, cfg0, cfg1, cfg2);
+
+ return 0;
+}
+
+static int ps883x_sw_set(struct typec_switch_dev *sw,
+ enum typec_orientation orientation)
+{
+ struct ps883x_retimer *retimer = typec_switch_get_drvdata(sw);
+ int ret = 0;
+
+ ret = typec_switch_set(retimer->typec_switch, orientation);
+ if (ret)
+ return ret;
+
+ mutex_lock(&retimer->lock);
+
+ if (retimer->orientation != orientation) {
+ retimer->orientation = orientation;
+
+ ret = ps883x_set(retimer);
+ }
+
+ mutex_unlock(&retimer->lock);
+
+ return ret;
+}
+
+static int ps883x_retimer_set(struct typec_retimer *rtmr,
+ struct typec_retimer_state *state)
+{
+ struct ps883x_retimer *retimer = typec_retimer_get_drvdata(rtmr);
+ struct typec_mux_state mux_state;
+ int ret = 0;
+
+ mutex_lock(&retimer->lock);
+
+ if (state->mode != retimer->mode) {
+ retimer->mode = state->mode;
+
+ if (state->alt)
+ retimer->svid = state->alt->svid;
+ else
+ retimer->svid = 0; // No SVID
+
+ ret = ps883x_set(retimer);
+ }
+
+ mutex_unlock(&retimer->lock);
+
+ if (ret)
+ return ret;
+
+ mux_state.alt = state->alt;
+ mux_state.data = state->data;
+ mux_state.mode = state->mode;
+
+ return typec_mux_set(retimer->typec_mux, &mux_state);
+}
+
+static int ps883x_enable_vregs(struct ps883x_retimer *retimer)
+{
+ struct device *dev = &retimer->client->dev;
+ int ret;
+
+ ret = regulator_enable(retimer->vdd33_supply);
+ if (ret) {
+ dev_err(dev, "cannot enable VDD 3.3V regulator: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_enable(retimer->vdd33_cap_supply);
+ if (ret) {
+ dev_err(dev, "cannot enable VDD 3.3V CAP regulator: %d\n", ret);
+ goto err_vdd33_disable;
+ }
+
+ usleep_range(4000, 10000);
+
+ ret = regulator_enable(retimer->vdd_supply);
+ if (ret) {
+ dev_err(dev, "cannot enable VDD regulator: %d\n", ret);
+ goto err_vdd33_cap_disable;
+ }
+
+ ret = regulator_enable(retimer->vddar_supply);
+ if (ret) {
+ dev_err(dev, "cannot enable VDD AR regulator: %d\n", ret);
+ goto err_vdd_disable;
+ }
+
+ ret = regulator_enable(retimer->vddat_supply);
+ if (ret) {
+ dev_err(dev, "cannot enable VDD AT regulator: %d\n", ret);
+ goto err_vddar_disable;
+ }
+
+ ret = regulator_enable(retimer->vddio_supply);
+ if (ret) {
+ dev_err(dev, "cannot enable VDD IO regulator: %d\n", ret);
+ goto err_vddat_disable;
+ }
+
+ return 0;
+
+err_vddat_disable:
+ regulator_disable(retimer->vddat_supply);
+err_vddar_disable:
+ regulator_disable(retimer->vddar_supply);
+err_vdd_disable:
+ regulator_disable(retimer->vdd_supply);
+err_vdd33_cap_disable:
+ regulator_disable(retimer->vdd33_cap_supply);
+err_vdd33_disable:
+ regulator_disable(retimer->vdd33_supply);
+
+ return ret;
+}
+
+static void ps883x_disable_vregs(struct ps883x_retimer *retimer)
+{
+ regulator_disable(retimer->vddio_supply);
+ regulator_disable(retimer->vddat_supply);
+ regulator_disable(retimer->vddar_supply);
+ regulator_disable(retimer->vdd_supply);
+ regulator_disable(retimer->vdd33_cap_supply);
+ regulator_disable(retimer->vdd33_supply);
+}
+
+static int ps883x_get_vregs(struct ps883x_retimer *retimer)
+{
+ struct device *dev = &retimer->client->dev;
+
+ retimer->vdd_supply = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(retimer->vdd_supply))
+ return dev_err_probe(dev, PTR_ERR(retimer->vdd_supply),
+ "failed to get VDD\n");
+
+ retimer->vdd33_supply = devm_regulator_get(dev, "vdd33");
+ if (IS_ERR(retimer->vdd33_supply))
+ return dev_err_probe(dev, PTR_ERR(retimer->vdd33_supply),
+ "failed to get VDD 3.3V\n");
+
+ retimer->vdd33_cap_supply = devm_regulator_get(dev, "vdd33-cap");
+ if (IS_ERR(retimer->vdd33_cap_supply))
+ return dev_err_probe(dev, PTR_ERR(retimer->vdd33_cap_supply),
+ "failed to get VDD CAP 3.3V\n");
+
+ retimer->vddat_supply = devm_regulator_get(dev, "vddat");
+ if (IS_ERR(retimer->vddat_supply))
+ return dev_err_probe(dev, PTR_ERR(retimer->vddat_supply),
+ "failed to get VDD AT\n");
+
+ retimer->vddar_supply = devm_regulator_get(dev, "vddar");
+ if (IS_ERR(retimer->vddar_supply))
+ return dev_err_probe(dev, PTR_ERR(retimer->vddar_supply),
+ "failed to get VDD AR\n");
+
+ retimer->vddio_supply = devm_regulator_get(dev, "vddio");
+ if (IS_ERR(retimer->vddio_supply))
+ return dev_err_probe(dev, PTR_ERR(retimer->vddio_supply),
+ "failed to get VDD IO\n");
+
+ return 0;
+}
+
+static const struct regmap_config ps883x_retimer_regmap = {
+ .max_register = 0x1f,
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int ps883x_retimer_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct typec_switch_desc sw_desc = { };
+ struct typec_retimer_desc rtmr_desc = { };
+ struct ps883x_retimer *retimer;
+ int ret;
+
+ retimer = devm_kzalloc(dev, sizeof(*retimer), GFP_KERNEL);
+ if (!retimer)
+ return -ENOMEM;
+
+ retimer->client = client;
+
+ mutex_init(&retimer->lock);
+
+ retimer->regmap = devm_regmap_init_i2c(client, &ps883x_retimer_regmap);
+ if (IS_ERR(retimer->regmap)) {
+ ret = PTR_ERR(retimer->regmap);
+ dev_err(dev, "failed to allocate register map: %d\n", ret);
+ return ret;
+ }
+
+ ret = ps883x_get_vregs(retimer);
+ if (ret)
+ return ret;
+
+ retimer->xo_clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(retimer->xo_clk))
+ return dev_err_probe(dev, PTR_ERR(retimer->xo_clk),
+ "failed to get xo clock\n");
+
+ retimer->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
+ if (IS_ERR(retimer->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(retimer->reset_gpio),
+ "failed to get reset gpio\n");
+
+ retimer->typec_switch = typec_switch_get(dev);
+ if (IS_ERR(retimer->typec_switch))
+ return dev_err_probe(dev, PTR_ERR(retimer->typec_switch),
+ "failed to acquire orientation-switch\n");
+
+ retimer->typec_mux = typec_mux_get(dev);
+ if (IS_ERR(retimer->typec_mux)) {
+ ret = dev_err_probe(dev, PTR_ERR(retimer->typec_mux),
+ "failed to acquire mode-mux\n");
+ goto err_switch_put;
+ }
+
+ ret = drm_aux_bridge_register(dev);
+ if (ret)
+ goto err_mux_put;
+
+ ret = clk_prepare_enable(retimer->xo_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable XO: %d\n", ret);
+ goto err_mux_put;
+ }
+
+ ret = ps883x_enable_vregs(retimer);
+ if (ret)
+ goto err_clk_disable;
+
+ sw_desc.drvdata = retimer;
+ sw_desc.fwnode = dev_fwnode(dev);
+ sw_desc.set = ps883x_sw_set;
+
+ retimer->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(retimer->sw)) {
+ ret = PTR_ERR(retimer->sw);
+ dev_err(dev, "failed to register typec switch: %d\n", ret);
+ goto err_vregs_disable;
+ }
+
+ rtmr_desc.drvdata = retimer;
+ rtmr_desc.fwnode = dev_fwnode(dev);
+ rtmr_desc.set = ps883x_retimer_set;
+
+ retimer->retimer = typec_retimer_register(dev, &rtmr_desc);
+ if (IS_ERR(retimer->retimer)) {
+ ret = PTR_ERR(retimer->retimer);
+ dev_err(dev, "failed to register typec retimer: %d\n", ret);
+ goto err_switch_unregister;
+ }
+
+ /* skip resetting if already configured */
+ if (regmap_test_bits(retimer->regmap, 0x00, BIT(0)))
+ return 0;
+
+ gpiod_direction_output(retimer->reset_gpio, 1);
+
+ /* VDD IO supply enable to reset release delay */
+ usleep_range(4000, 14000);
+
+ gpiod_set_value(retimer->reset_gpio, 0);
+
+ /* firmware initialization delay */
+ msleep(60);
+
+ return 0;
+
+err_switch_unregister:
+ typec_switch_unregister(retimer->sw);
+err_vregs_disable:
+ ps883x_disable_vregs(retimer);
+err_clk_disable:
+ clk_disable_unprepare(retimer->xo_clk);
+err_mux_put:
+ typec_mux_put(retimer->typec_mux);
+err_switch_put:
+ typec_switch_put(retimer->typec_switch);
+
+ return ret;
+}
+
+static void ps883x_retimer_remove(struct i2c_client *client)
+{
+ struct ps883x_retimer *retimer = i2c_get_clientdata(client);
+
+ typec_retimer_unregister(retimer->retimer);
+ typec_switch_unregister(retimer->sw);
+
+ gpiod_set_value(retimer->reset_gpio, 1);
+
+ regulator_disable(retimer->vddio_supply);
+ regulator_disable(retimer->vddat_supply);
+ regulator_disable(retimer->vddar_supply);
+ regulator_disable(retimer->vdd_supply);
+ regulator_disable(retimer->vdd33_cap_supply);
+ regulator_disable(retimer->vdd33_supply);
+
+ clk_disable_unprepare(retimer->xo_clk);
+
+ typec_mux_put(retimer->typec_mux);
+ typec_switch_put(retimer->typec_switch);
+}
+
+static const struct of_device_id ps883x_retimer_of_table[] = {
+ { .compatible = "parade,ps8830" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ps883x_retimer_of_table);
+
+static struct i2c_driver ps883x_retimer_driver = {
+ .driver = {
+ .name = "ps883x_retimer",
+ .of_match_table = ps883x_retimer_of_table,
+ },
+ .probe = ps883x_retimer_probe,
+ .remove = ps883x_retimer_remove,
+};
+
+module_i2c_driver(ps883x_retimer_driver);
+
+MODULE_DESCRIPTION("Parade ps883x Type-C Retimer driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v4 3/4] arm64: dts: qcom: x1e80100-crd: Describe the Parade PS8830 retimers
2024-11-01 16:29 [PATCH v4 0/4] usb: typec: Add new driver for Parade PS8830 Type-C Retimer Abel Vesa
2024-11-01 16:29 ` [PATCH v4 1/4] dt-bindings: usb: Add Parade PS8830 Type-C retimer bindings Abel Vesa
2024-11-01 16:29 ` [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer Abel Vesa
@ 2024-11-01 16:29 ` Abel Vesa
2024-11-01 16:29 ` [PATCH v4 4/4] arm64: dts: qcom: x1e80100-crd: Enable external DisplayPort support Abel Vesa
3 siblings, 0 replies; 13+ messages in thread
From: Abel Vesa @ 2024-11-01 16:29 UTC (permalink / raw)
To: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, Bjorn Andersson, Konrad Dybcio, Rajendra Nayak,
Sibi Sankar, Johan Hovold, Dmitry Baryshkov, Trilok Soni,
linux-kernel, linux-usb, devicetree, Abel Vesa
The X Elite CRD board comes with 3 Parade PS8830 retimers, one for each
Type-C port. These handle the orientation and altmode switching and are
controlled over I2C. In the connection chain, they sit between the
USB/DisplayPort combo PHY and the Type-C connector.
Describe the retimers and all gpio controlled voltage regulators used by
each retimer. Also, modify the pmic glink graph to include the retimers in
between the SuperSpeed/Sideband in endpoints and the QMP PHY out endpoints.
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
arch/arm64/boot/dts/qcom/x1e80100-crd.dts | 439 +++++++++++++++++++++++++++++-
1 file changed, 433 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
index 279697f2c72890a6d379aa0c153171960e44bd63..6e1b9e1d227ce0a3607af708e2438be33424eec5 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
+++ b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
@@ -99,7 +99,15 @@ port@1 {
reg = <1>;
pmic_glink_ss0_ss_in: endpoint {
- remote-endpoint = <&usb_1_ss0_qmpphy_out>;
+ remote-endpoint = <&retimer_ss0_ss_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pmic_glink_ss0_con_sbu_in: endpoint {
+ remote-endpoint = <&retimer_ss0_con_sbu_out>;
};
};
};
@@ -128,7 +136,15 @@ port@1 {
reg = <1>;
pmic_glink_ss1_ss_in: endpoint {
- remote-endpoint = <&usb_1_ss1_qmpphy_out>;
+ remote-endpoint = <&retimer_ss1_ss_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pmic_glink_ss1_con_sbu_in: endpoint {
+ remote-endpoint = <&retimer_ss1_con_sbu_out>;
};
};
};
@@ -157,7 +173,15 @@ port@1 {
reg = <1>;
pmic_glink_ss2_ss_in: endpoint {
- remote-endpoint = <&usb_1_ss2_qmpphy_out>;
+ remote-endpoint = <&retimer_ss2_ss_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ pmic_glink_ss2_con_sbu_in: endpoint {
+ remote-endpoint = <&retimer_ss2_con_sbu_out>;
};
};
};
@@ -293,6 +317,150 @@ vreg_nvme: regulator-nvme {
regulator-boot-on;
};
+ vreg_rtmr0_1p15: regulator-rtmr0-1p15 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_RTMR0_1P15";
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+
+ gpio = <&pmc8380_5_gpios 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&usb0_pwr_1p15_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_rtmr0_1p8: regulator-rtmr0-1p8 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_RTMR0_1P8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&pm8550ve_9_gpios 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&usb0_1p8_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_rtmr0_3p3: regulator-rtmr0-3p3 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_RTMR0_3P3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&pm8550_gpios 11 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&usb0_3p3_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_rtmr1_1p15: regulator-rtmr1-1p15 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_RTMR1_1P15";
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+
+ gpio = <&tlmm 188 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&usb1_pwr_1p15_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_rtmr1_1p8: regulator-rtmr1-1p8 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_RTMR1_1P8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&tlmm 175 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&usb1_pwr_1p8_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_rtmr1_3p3: regulator-rtmr1-3p3 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_RTMR1_3P3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 186 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&usb1_pwr_3p3_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_rtmr2_1p15: regulator-rtmr2-1p15 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_RTMR2_1P15";
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+
+ gpio = <&tlmm 189 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&usb2_pwr_1p15_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_rtmr2_1p8: regulator-rtmr2-1p8 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_RTMR2_1P8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&tlmm 126 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&usb2_pwr_1p8_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
+ vreg_rtmr2_3p3: regulator-rtmr2-3p3 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VREG_RTMR2_3P3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 187 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&usb2_pwr_3p3_reg_en>;
+ pinctrl-names = "default";
+
+ regulator-boot-on;
+ };
+
vph_pwr: regulator-vph-pwr {
compatible = "regulator-fixed";
@@ -711,6 +879,178 @@ keyboard@3a {
};
};
+&i2c1 {
+ clock-frequency = <400000>;
+
+ status = "okay";
+
+ typec-mux@8 {
+ compatible = "parade,ps8830";
+ reg = <0x08>;
+
+ clocks = <&rpmhcc RPMH_RF_CLK5>;
+
+ vdd-supply = <&vreg_rtmr2_1p15>;
+ vdd33-supply = <&vreg_rtmr2_3p3>;
+ vdd33-cap-supply = <&vreg_rtmr2_3p3>;
+ vddar-supply = <&vreg_rtmr2_1p15>;
+ vddat-supply = <&vreg_rtmr2_1p15>;
+ vddio-supply = <&vreg_rtmr2_1p8>;
+
+ reset-gpios = <&tlmm 185 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&rtmr2_default>;
+ pinctrl-names = "default";
+
+ orientation-switch;
+ retimer-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ retimer_ss2_ss_out: endpoint {
+ remote-endpoint = <&pmic_glink_ss2_ss_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ retimer_ss2_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss2_qmpphy_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ retimer_ss2_con_sbu_out: endpoint {
+ remote-endpoint = <&pmic_glink_ss2_con_sbu_in>;
+ };
+ };
+ };
+ };
+};
+
+&i2c3 {
+ clock-frequency = <400000>;
+
+ status = "okay";
+
+ typec-mux@8 {
+ compatible = "parade,ps8830";
+ reg = <0x08>;
+
+ clocks = <&rpmhcc RPMH_RF_CLK3>;
+
+ vdd-supply = <&vreg_rtmr0_1p15>;
+ vdd33-supply = <&vreg_rtmr0_3p3>;
+ vdd33-cap-supply = <&vreg_rtmr0_3p3>;
+ vddar-supply = <&vreg_rtmr0_1p15>;
+ vddat-supply = <&vreg_rtmr0_1p15>;
+ vddio-supply = <&vreg_rtmr0_1p8>;
+
+ reset-gpios = <&pm8550_gpios 10 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&rtmr0_default>;
+ pinctrl-names = "default";
+
+ retimer-switch;
+ orientation-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ retimer_ss0_ss_out: endpoint {
+ remote-endpoint = <&pmic_glink_ss0_ss_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ retimer_ss0_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss0_qmpphy_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ retimer_ss0_con_sbu_out: endpoint {
+ remote-endpoint = <&pmic_glink_ss0_con_sbu_in>;
+ };
+ };
+ };
+ };
+};
+
+&i2c7 {
+ clock-frequency = <400000>;
+
+ status = "okay";
+
+ typec-mux@8 {
+ compatible = "parade,ps8830";
+ reg = <0x8>;
+
+ clocks = <&rpmhcc RPMH_RF_CLK4>;
+
+ vdd-supply = <&vreg_rtmr1_1p15>;
+ vdd33-supply = <&vreg_rtmr1_3p3>;
+ vdd33-cap-supply = <&vreg_rtmr1_3p3>;
+ vddar-supply = <&vreg_rtmr1_1p15>;
+ vddat-supply = <&vreg_rtmr1_1p15>;
+ vddio-supply = <&vreg_rtmr1_1p8>;
+
+ reset-gpios = <&tlmm 176 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&rtmr1_default>;
+ pinctrl-names = "default";
+
+ retimer-switch;
+ orientation-switch;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ retimer_ss1_ss_out: endpoint {
+ remote-endpoint = <&pmic_glink_ss1_ss_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ retimer_ss1_ss_in: endpoint {
+ remote-endpoint = <&usb_1_ss1_qmpphy_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ retimer_ss1_con_sbu_out: endpoint {
+ remote-endpoint = <&pmic_glink_ss1_con_sbu_in>;
+ };
+ };
+
+ };
+ };
+};
+
&i2c8 {
clock-frequency = <400000>;
@@ -856,6 +1196,28 @@ &pcie6a_phy {
status = "okay";
};
+&pm8550_gpios {
+ rtmr0_default: rtmr0-reset-n-active-state {
+ pins = "gpio10";
+ function = "normal";
+ power-source = <1>; /* 1.8V */
+ };
+
+ usb0_3p3_reg_en: usb0-3p3-reg-en-state {
+ pins = "gpio11";
+ function = "normal";
+ power-source = <1>; /* 1.8V */
+ };
+};
+
+&pm8550ve_9_gpios {
+ usb0_1p8_reg_en: usb0-1p8-reg-en-state {
+ pins = "gpio8";
+ function = "normal";
+ power-source = <1>; /* 1.8V */
+ };
+};
+
&pmc8380_3_gpios {
edp_bl_en: edp-bl-en-state {
pins = "gpio4";
@@ -866,6 +1228,15 @@ edp_bl_en: edp-bl-en-state {
};
};
+&pmc8380_5_gpios {
+ usb0_pwr_1p15_reg_en: usb0-pwr-1p15-reg-en-state {
+ pins = "gpio8";
+ function = "normal";
+ power-source = <1>; /* 1.8V */
+ bias-disable;
+ };
+};
+
&qupv3_0 {
status = "okay";
};
@@ -1095,6 +1466,62 @@ wake-n-pins {
};
};
+ usb1_pwr_1p15_reg_en: usb1-pwr-1p15-reg-en-state {
+ pins = "gpio188";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ usb1_pwr_1p8_reg_en: usb1-pwr-1p8-reg-en-state {
+ pins = "gpio175";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ usb1_pwr_3p3_reg_en: usb1-pwr-3p3-reg-en-state {
+ pins = "gpio186";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rtmr1_default: rtmr1-reset-n-active-state {
+ pins = "gpio176";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ usb2_pwr_1p15_reg_en: usb2-pwr-1p15-reg-en-state {
+ pins = "gpio189";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ usb2_pwr_1p8_reg_en: usb2-pwr-1p8-reg-en-state {
+ pins = "gpio126";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ usb2_pwr_3p3_reg_en: usb2-pwr-3p3-reg-en-state {
+ pins = "gpio187";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rtmr2_default: rtmr2-reset-n-active-state {
+ pins = "gpio185";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
tpad_default: tpad-default-state {
pins = "gpio3";
function = "gpio";
@@ -1162,7 +1589,7 @@ &usb_1_ss0_dwc3_hs {
};
&usb_1_ss0_qmpphy_out {
- remote-endpoint = <&pmic_glink_ss0_ss_in>;
+ remote-endpoint = <&retimer_ss0_ss_in>;
};
&usb_1_ss1_hsphy {
@@ -1190,7 +1617,7 @@ &usb_1_ss1_dwc3_hs {
};
&usb_1_ss1_qmpphy_out {
- remote-endpoint = <&pmic_glink_ss1_ss_in>;
+ remote-endpoint = <&retimer_ss1_ss_in>;
};
&usb_1_ss2_hsphy {
@@ -1218,5 +1645,5 @@ &usb_1_ss2_dwc3_hs {
};
&usb_1_ss2_qmpphy_out {
- remote-endpoint = <&pmic_glink_ss2_ss_in>;
+ remote-endpoint = <&retimer_ss2_ss_in>;
};
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v4 4/4] arm64: dts: qcom: x1e80100-crd: Enable external DisplayPort support
2024-11-01 16:29 [PATCH v4 0/4] usb: typec: Add new driver for Parade PS8830 Type-C Retimer Abel Vesa
` (2 preceding siblings ...)
2024-11-01 16:29 ` [PATCH v4 3/4] arm64: dts: qcom: x1e80100-crd: Describe the Parade PS8830 retimers Abel Vesa
@ 2024-11-01 16:29 ` Abel Vesa
3 siblings, 0 replies; 13+ messages in thread
From: Abel Vesa @ 2024-11-01 16:29 UTC (permalink / raw)
To: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, Bjorn Andersson, Konrad Dybcio, Rajendra Nayak,
Sibi Sankar, Johan Hovold, Dmitry Baryshkov, Trilok Soni,
linux-kernel, linux-usb, devicetree, Abel Vesa
The X Elite CRD provides external DisplayPort on all 3 USB Type-C ports.
Each one of this ports is connected to a dedicated DisplayPort
controller.
Due to support missing in the USB/DisplayPort combo PHY driver,
the external DisplayPort is limited to 2 lanes.
So enable all 3 remaining DisplayPort controllers and limit their data
lanes number to 2.
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
arch/arm64/boot/dts/qcom/x1e80100-crd.dts | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
index 6e1b9e1d227ce0a3607af708e2438be33424eec5..4863efd793641136e8788882c371efafa7f23c3c 100644
--- a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
+++ b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts
@@ -1098,6 +1098,30 @@ &mdss {
status = "okay";
};
+&mdss_dp0 {
+ status = "okay";
+};
+
+&mdss_dp0_out {
+ data-lanes = <0 1>;
+};
+
+&mdss_dp1 {
+ status = "okay";
+};
+
+&mdss_dp1_out {
+ data-lanes = <0 1>;
+};
+
+&mdss_dp2 {
+ status = "okay";
+};
+
+&mdss_dp2_out {
+ data-lanes = <0 1>;
+};
+
&mdss_dp3 {
compatible = "qcom,x1e80100-dp";
/delete-property/ #sound-dai-cells;
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer
2024-11-01 16:29 ` [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer Abel Vesa
@ 2024-11-01 16:56 ` Christophe JAILLET
2024-11-04 10:36 ` Abel Vesa
2024-11-02 9:17 ` Konrad Dybcio
1 sibling, 1 reply; 13+ messages in thread
From: Christophe JAILLET @ 2024-11-01 16:56 UTC (permalink / raw)
To: Abel Vesa
Cc: linux-arm-msm, Bjorn Andersson, Konrad Dybcio, Rajendra Nayak,
Sibi Sankar, Johan Hovold, Dmitry Baryshkov, Trilok Soni,
linux-kernel, linux-usb, devicetree, Abel Vesa, Heikki Krogerus,
Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Le 01/11/2024 à 17:29, Abel Vesa a écrit :
> The Parade PS8830 is a USB4, DisplayPort and Thunderbolt 4 retimer,
> controlled over I2C. It usually sits between a USB/DisplayPort PHY
> and the Type-C connector, and provides orientation and altmode handling.
>
> The boards that use this retimer are the ones featuring the Qualcomm
> Snapdragon X Elite SoCs.
>
> Add a driver with support for the following modes:
> - DisplayPort 4-lanes
> - DisplayPort 2-lanes + USB3
> - USB3
>
> There is another variant of this retimer which is called PS8833. It seems
> to be really similar to the PS8830, so future-proof this driver by
> naming it ps883x.
>
> Signed-off-by: Abel Vesa <abel.vesa-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
Hi,
...
> +static void ps883x_disable_vregs(struct ps883x_retimer *retimer)
> +{
> + regulator_disable(retimer->vddio_supply);
> + regulator_disable(retimer->vddat_supply);
> + regulator_disable(retimer->vddar_supply);
> + regulator_disable(retimer->vdd_supply);
> + regulator_disable(retimer->vdd33_cap_supply);
> + regulator_disable(retimer->vdd33_supply);
> +}
> +
> +static int ps883x_get_vregs(struct ps883x_retimer *retimer)
This could maybe be replaced by a
devm_regulator_bulk_get() call?
(and use the bulk API in other places)
> +{
> + struct device *dev = &retimer->client->dev;
> +
> + retimer->vdd_supply = devm_regulator_get(dev, "vdd");
> + if (IS_ERR(retimer->vdd_supply))
> + return dev_err_probe(dev, PTR_ERR(retimer->vdd_supply),
> + "failed to get VDD\n");
> +
> + retimer->vdd33_supply = devm_regulator_get(dev, "vdd33");
> + if (IS_ERR(retimer->vdd33_supply))
> + return dev_err_probe(dev, PTR_ERR(retimer->vdd33_supply),
> + "failed to get VDD 3.3V\n");
> +
> + retimer->vdd33_cap_supply = devm_regulator_get(dev, "vdd33-cap");
> + if (IS_ERR(retimer->vdd33_cap_supply))
> + return dev_err_probe(dev, PTR_ERR(retimer->vdd33_cap_supply),
> + "failed to get VDD CAP 3.3V\n");
> +
> + retimer->vddat_supply = devm_regulator_get(dev, "vddat");
> + if (IS_ERR(retimer->vddat_supply))
> + return dev_err_probe(dev, PTR_ERR(retimer->vddat_supply),
> + "failed to get VDD AT\n");
> +
> + retimer->vddar_supply = devm_regulator_get(dev, "vddar");
> + if (IS_ERR(retimer->vddar_supply))
> + return dev_err_probe(dev, PTR_ERR(retimer->vddar_supply),
> + "failed to get VDD AR\n");
> +
> + retimer->vddio_supply = devm_regulator_get(dev, "vddio");
> + if (IS_ERR(retimer->vddio_supply))
> + return dev_err_probe(dev, PTR_ERR(retimer->vddio_supply),
> + "failed to get VDD IO\n");
> +
> + return 0;
> +}
...
> +static int ps883x_retimer_probe(struct i2c_client *client)
> +{
> + struct device *dev = &client->dev;
> + struct typec_switch_desc sw_desc = { };
> + struct typec_retimer_desc rtmr_desc = { };
> + struct ps883x_retimer *retimer;
> + int ret;
> +
> + retimer = devm_kzalloc(dev, sizeof(*retimer), GFP_KERNEL);
> + if (!retimer)
> + return -ENOMEM;
> +
> + retimer->client = client;
> +
> + mutex_init(&retimer->lock);
> +
> + retimer->regmap = devm_regmap_init_i2c(client, &ps883x_retimer_regmap);
> + if (IS_ERR(retimer->regmap)) {
> + ret = PTR_ERR(retimer->regmap);
> + dev_err(dev, "failed to allocate register map: %d\n", ret);
Maybe dev_err_probe() as below?
> + return ret;
> + }
> +
> + ret = ps883x_get_vregs(retimer);
> + if (ret)
> + return ret;
> +
> + retimer->xo_clk = devm_clk_get(dev, NULL);
> + if (IS_ERR(retimer->xo_clk))
> + return dev_err_probe(dev, PTR_ERR(retimer->xo_clk),
> + "failed to get xo clock\n");
> +
> + retimer->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
> + if (IS_ERR(retimer->reset_gpio))
> + return dev_err_probe(dev, PTR_ERR(retimer->reset_gpio),
> + "failed to get reset gpio\n");
> +
> + retimer->typec_switch = typec_switch_get(dev);
> + if (IS_ERR(retimer->typec_switch))
> + return dev_err_probe(dev, PTR_ERR(retimer->typec_switch),
> + "failed to acquire orientation-switch\n");
> +
> + retimer->typec_mux = typec_mux_get(dev);
> + if (IS_ERR(retimer->typec_mux)) {
> + ret = dev_err_probe(dev, PTR_ERR(retimer->typec_mux),
> + "failed to acquire mode-mux\n");
> + goto err_switch_put;
> + }
> +
> + ret = drm_aux_bridge_register(dev);
> + if (ret)
> + goto err_mux_put;
> +
> + ret = clk_prepare_enable(retimer->xo_clk);
> + if (ret) {
> + dev_err(dev, "failed to enable XO: %d\n", ret);
> + goto err_mux_put;
> + }
> +
> + ret = ps883x_enable_vregs(retimer);
> + if (ret)
> + goto err_clk_disable;
> +
> + sw_desc.drvdata = retimer;
> + sw_desc.fwnode = dev_fwnode(dev);
> + sw_desc.set = ps883x_sw_set;
> +
> + retimer->sw = typec_switch_register(dev, &sw_desc);
> + if (IS_ERR(retimer->sw)) {
> + ret = PTR_ERR(retimer->sw);
> + dev_err(dev, "failed to register typec switch: %d\n", ret);
Maybe dev_err_probe() as above?
> + goto err_vregs_disable;
> + }
> +
> + rtmr_desc.drvdata = retimer;
> + rtmr_desc.fwnode = dev_fwnode(dev);
> + rtmr_desc.set = ps883x_retimer_set;
> +
> + retimer->retimer = typec_retimer_register(dev, &rtmr_desc);
> + if (IS_ERR(retimer->retimer)) {
> + ret = PTR_ERR(retimer->retimer);
> + dev_err(dev, "failed to register typec retimer: %d\n", ret);
Maybe dev_err_probe() as above?
> + goto err_switch_unregister;
> + }
> +
> + /* skip resetting if already configured */
> + if (regmap_test_bits(retimer->regmap, 0x00, BIT(0)))
> + return 0;
> +
> + gpiod_direction_output(retimer->reset_gpio, 1);
> +
> + /* VDD IO supply enable to reset release delay */
> + usleep_range(4000, 14000);
> +
> + gpiod_set_value(retimer->reset_gpio, 0);
> +
> + /* firmware initialization delay */
> + msleep(60);
> +
> + return 0;
> +
> +err_switch_unregister:
> + typec_switch_unregister(retimer->sw);
> +err_vregs_disable:
> + ps883x_disable_vregs(retimer);
> +err_clk_disable:
> + clk_disable_unprepare(retimer->xo_clk);
> +err_mux_put:
> + typec_mux_put(retimer->typec_mux);
> +err_switch_put:
> + typec_switch_put(retimer->typec_switch);
> +
> + return ret;
> +}
> +
> +static void ps883x_retimer_remove(struct i2c_client *client)
> +{
> + struct ps883x_retimer *retimer = i2c_get_clientdata(client);
> +
> + typec_retimer_unregister(retimer->retimer);
> + typec_switch_unregister(retimer->sw);
> +
> + gpiod_set_value(retimer->reset_gpio, 1);
> +
> + regulator_disable(retimer->vddio_supply);
> + regulator_disable(retimer->vddat_supply);
> + regulator_disable(retimer->vddar_supply);
> + regulator_disable(retimer->vdd_supply);
> + regulator_disable(retimer->vdd33_cap_supply);
> + regulator_disable(retimer->vdd33_supply);
ps883x_disable_vregs()?
> +
> + clk_disable_unprepare(retimer->xo_clk);
> +
> + typec_mux_put(retimer->typec_mux);
> + typec_switch_put(retimer->typec_switch);
> +}
...
CJ
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/4] dt-bindings: usb: Add Parade PS8830 Type-C retimer bindings
2024-11-01 16:29 ` [PATCH v4 1/4] dt-bindings: usb: Add Parade PS8830 Type-C retimer bindings Abel Vesa
@ 2024-11-02 8:58 ` Krzysztof Kozlowski
2024-11-04 10:38 ` Abel Vesa
0 siblings, 1 reply; 13+ messages in thread
From: Krzysztof Kozlowski @ 2024-11-02 8:58 UTC (permalink / raw)
To: Abel Vesa
Cc: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, Bjorn Andersson,
Konrad Dybcio, Rajendra Nayak, Sibi Sankar, Johan Hovold,
Dmitry Baryshkov, Trilok Soni, linux-kernel, linux-usb,
devicetree
On Fri, Nov 01, 2024 at 06:29:39PM +0200, Abel Vesa wrote:
> +$id: http://devicetree.org/schemas/usb/parade,ps883x.yaml#
Filename based on compatible, so: parade,ps8830.yaml
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Parade PS883x USB and DisplayPort Retimer
> +
> +maintainers:
> + - Abel Vesa <abel.vesa@linaro.org>
> +
> +properties:
> + compatible:
> + enum:
> + - parade,ps8830
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: XO Clock
> +
> + ps8830,boot-on:
I don't see previous comments addressed/responded to.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer
2024-11-01 16:29 ` [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer Abel Vesa
2024-11-01 16:56 ` Christophe JAILLET
@ 2024-11-02 9:17 ` Konrad Dybcio
2024-11-04 10:16 ` Abel Vesa
1 sibling, 1 reply; 13+ messages in thread
From: Konrad Dybcio @ 2024-11-02 9:17 UTC (permalink / raw)
To: Abel Vesa, Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, Bjorn Andersson, Konrad Dybcio, Rajendra Nayak,
Sibi Sankar, Johan Hovold, Dmitry Baryshkov, Trilok Soni,
linux-kernel, linux-usb, devicetree
On 1.11.2024 5:29 PM, Abel Vesa wrote:
> The Parade PS8830 is a USB4, DisplayPort and Thunderbolt 4 retimer,
> controlled over I2C. It usually sits between a USB/DisplayPort PHY
> and the Type-C connector, and provides orientation and altmode handling.
>
> The boards that use this retimer are the ones featuring the Qualcomm
> Snapdragon X Elite SoCs.
>
> Add a driver with support for the following modes:
> - DisplayPort 4-lanes
> - DisplayPort 2-lanes + USB3
> - USB3
>
> There is another variant of this retimer which is called PS8833. It seems
> to be really similar to the PS8830, so future-proof this driver by
> naming it ps883x.
>
> Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
> ---
[...]
> +static void ps883x_configure(struct ps883x_retimer *retimer, int cfg0, int cfg1, int cfg2)
> +{
> + regmap_write(retimer->regmap, 0x0, cfg0);
> + regmap_write(retimer->regmap, 0x1, cfg1);
> + regmap_write(retimer->regmap, 0x2, cfg2);
> +}
Somewhere between introducing regcache and dropping it, you removed
muxing to a safe mode during _configure()
[...]
> + /* skip resetting if already configured */
> + if (regmap_test_bits(retimer->regmap, 0x00, BIT(0)))
> + return 0;
What is that register and what does BIT(0) mean?
Konrad
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer
2024-11-02 9:17 ` Konrad Dybcio
@ 2024-11-04 10:16 ` Abel Vesa
2024-11-04 10:25 ` Konrad Dybcio
0 siblings, 1 reply; 13+ messages in thread
From: Abel Vesa @ 2024-11-04 10:16 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, Bjorn Andersson,
Konrad Dybcio, Rajendra Nayak, Sibi Sankar, Johan Hovold,
Dmitry Baryshkov, Trilok Soni, linux-kernel, linux-usb,
devicetree
On 24-11-02 10:17:56, Konrad Dybcio wrote:
> On 1.11.2024 5:29 PM, Abel Vesa wrote:
> > The Parade PS8830 is a USB4, DisplayPort and Thunderbolt 4 retimer,
> > controlled over I2C. It usually sits between a USB/DisplayPort PHY
> > and the Type-C connector, and provides orientation and altmode handling.
> >
> > The boards that use this retimer are the ones featuring the Qualcomm
> > Snapdragon X Elite SoCs.
> >
> > Add a driver with support for the following modes:
> > - DisplayPort 4-lanes
> > - DisplayPort 2-lanes + USB3
> > - USB3
> >
> > There is another variant of this retimer which is called PS8833. It seems
> > to be really similar to the PS8830, so future-proof this driver by
> > naming it ps883x.
> >
> > Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
> > ---
>
> [...]
>
> > +static void ps883x_configure(struct ps883x_retimer *retimer, int cfg0, int cfg1, int cfg2)
> > +{
> > + regmap_write(retimer->regmap, 0x0, cfg0);
> > + regmap_write(retimer->regmap, 0x1, cfg1);
> > + regmap_write(retimer->regmap, 0x2, cfg2);
> > +}
>
> Somewhere between introducing regcache and dropping it, you removed
> muxing to a safe mode during _configure()
Oh, yeah, I forgot to mention that in the change log, it seems.
Configuring to safe mode is not needed since we always do that on
unplug anyway.
>
> [...]
>
> > + /* skip resetting if already configured */
> > + if (regmap_test_bits(retimer->regmap, 0x00, BIT(0)))
> > + return 0;
>
> What is that register and what does BIT(0) mean?
Looking at the documentation, the first register is
REG_USB_PORT_CONN_STATUS and spans over the first 4 bytes.
But it doesn't really help here.
BIT(0) doesn't really have a name, it just says "Connection present".
>
> Konrad
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer
2024-11-04 10:16 ` Abel Vesa
@ 2024-11-04 10:25 ` Konrad Dybcio
2024-11-04 10:40 ` Abel Vesa
0 siblings, 1 reply; 13+ messages in thread
From: Konrad Dybcio @ 2024-11-04 10:25 UTC (permalink / raw)
To: Abel Vesa, Konrad Dybcio
Cc: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, Bjorn Andersson,
Konrad Dybcio, Rajendra Nayak, Sibi Sankar, Johan Hovold,
Dmitry Baryshkov, Trilok Soni, linux-kernel, linux-usb,
devicetree
On 4.11.2024 11:16 AM, Abel Vesa wrote:
> On 24-11-02 10:17:56, Konrad Dybcio wrote:
>> On 1.11.2024 5:29 PM, Abel Vesa wrote:
>>> The Parade PS8830 is a USB4, DisplayPort and Thunderbolt 4 retimer,
>>> controlled over I2C. It usually sits between a USB/DisplayPort PHY
>>> and the Type-C connector, and provides orientation and altmode handling.
>>>
>>> The boards that use this retimer are the ones featuring the Qualcomm
>>> Snapdragon X Elite SoCs.
>>>
>>> Add a driver with support for the following modes:
>>> - DisplayPort 4-lanes
>>> - DisplayPort 2-lanes + USB3
>>> - USB3
>>>
>>> There is another variant of this retimer which is called PS8833. It seems
>>> to be really similar to the PS8830, so future-proof this driver by
>>> naming it ps883x.
>>>
>>> Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
>>> ---
>>
>> [...]
>>
>>> +static void ps883x_configure(struct ps883x_retimer *retimer, int cfg0, int cfg1, int cfg2)
>>> +{
>>> + regmap_write(retimer->regmap, 0x0, cfg0);
>>> + regmap_write(retimer->regmap, 0x1, cfg1);
>>> + regmap_write(retimer->regmap, 0x2, cfg2);
>>> +}
>>
>> Somewhere between introducing regcache and dropping it, you removed
>> muxing to a safe mode during _configure()
>
> Oh, yeah, I forgot to mention that in the change log, it seems.
>
> Configuring to safe mode is not needed since we always do that on
> unplug anyway.
>
>>
>> [...]
>>
>>> + /* skip resetting if already configured */
>>> + if (regmap_test_bits(retimer->regmap, 0x00, BIT(0)))
>>> + return 0;
>>
>> What is that register and what does BIT(0) mean?
>
> Looking at the documentation, the first register is
> REG_USB_PORT_CONN_STATUS and spans over the first 4 bytes.
>
> But it doesn't really help here.
>
> BIT(0) doesn't really have a name, it just says "Connection present".
Please define both then. STATUS_CONNECTION_PRESENT sounds good for the bit.
Konrad
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer
2024-11-01 16:56 ` Christophe JAILLET
@ 2024-11-04 10:36 ` Abel Vesa
0 siblings, 0 replies; 13+ messages in thread
From: Abel Vesa @ 2024-11-04 10:36 UTC (permalink / raw)
To: Christophe JAILLET
Cc: linux-arm-msm, Bjorn Andersson, Konrad Dybcio, Rajendra Nayak,
Sibi Sankar, Johan Hovold, Dmitry Baryshkov, Trilok Soni,
linux-kernel, linux-usb, devicetree, Heikki Krogerus,
Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
On 24-11-01 17:56:04, Christophe JAILLET wrote:
> Le 01/11/2024 à 17:29, Abel Vesa a écrit :
> > The Parade PS8830 is a USB4, DisplayPort and Thunderbolt 4 retimer,
> > controlled over I2C. It usually sits between a USB/DisplayPort PHY
> > and the Type-C connector, and provides orientation and altmode handling.
> >
> > The boards that use this retimer are the ones featuring the Qualcomm
> > Snapdragon X Elite SoCs.
> >
> > Add a driver with support for the following modes:
> > - DisplayPort 4-lanes
> > - DisplayPort 2-lanes + USB3
> > - USB3
> >
> > There is another variant of this retimer which is called PS8833. It seems
> > to be really similar to the PS8830, so future-proof this driver by
> > naming it ps883x.
> >
> > Signed-off-by: Abel Vesa <abel.vesa-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > ---
>
> Hi,
>
> ...
>
> > +static void ps883x_disable_vregs(struct ps883x_retimer *retimer)
> > +{
> > + regulator_disable(retimer->vddio_supply);
> > + regulator_disable(retimer->vddat_supply);
> > + regulator_disable(retimer->vddar_supply);
> > + regulator_disable(retimer->vdd_supply);
> > + regulator_disable(retimer->vdd33_cap_supply);
> > + regulator_disable(retimer->vdd33_supply);
> > +}
> > +
> > +static int ps883x_get_vregs(struct ps883x_retimer *retimer)
>
> This could maybe be replaced by a
> devm_regulator_bulk_get() call?
> (and use the bulk API in other places)
Nope, look in the ps883x_enable_vregs. There are some delays needed between
enabling them, according to spec.
>
> > +{
> > + struct device *dev = &retimer->client->dev;
> > +
> > + retimer->vdd_supply = devm_regulator_get(dev, "vdd");
> > + if (IS_ERR(retimer->vdd_supply))
> > + return dev_err_probe(dev, PTR_ERR(retimer->vdd_supply),
> > + "failed to get VDD\n");
> > +
> > + retimer->vdd33_supply = devm_regulator_get(dev, "vdd33");
> > + if (IS_ERR(retimer->vdd33_supply))
> > + return dev_err_probe(dev, PTR_ERR(retimer->vdd33_supply),
> > + "failed to get VDD 3.3V\n");
> > +
> > + retimer->vdd33_cap_supply = devm_regulator_get(dev, "vdd33-cap");
> > + if (IS_ERR(retimer->vdd33_cap_supply))
> > + return dev_err_probe(dev, PTR_ERR(retimer->vdd33_cap_supply),
> > + "failed to get VDD CAP 3.3V\n");
> > +
> > + retimer->vddat_supply = devm_regulator_get(dev, "vddat");
> > + if (IS_ERR(retimer->vddat_supply))
> > + return dev_err_probe(dev, PTR_ERR(retimer->vddat_supply),
> > + "failed to get VDD AT\n");
> > +
> > + retimer->vddar_supply = devm_regulator_get(dev, "vddar");
> > + if (IS_ERR(retimer->vddar_supply))
> > + return dev_err_probe(dev, PTR_ERR(retimer->vddar_supply),
> > + "failed to get VDD AR\n");
> > +
> > + retimer->vddio_supply = devm_regulator_get(dev, "vddio");
> > + if (IS_ERR(retimer->vddio_supply))
> > + return dev_err_probe(dev, PTR_ERR(retimer->vddio_supply),
> > + "failed to get VDD IO\n");
> > +
> > + return 0;
> > +}
>
> ...
>
> > +static int ps883x_retimer_probe(struct i2c_client *client)
> > +{
> > + struct device *dev = &client->dev;
> > + struct typec_switch_desc sw_desc = { };
> > + struct typec_retimer_desc rtmr_desc = { };
> > + struct ps883x_retimer *retimer;
> > + int ret;
> > +
> > + retimer = devm_kzalloc(dev, sizeof(*retimer), GFP_KERNEL);
> > + if (!retimer)
> > + return -ENOMEM;
> > +
> > + retimer->client = client;
> > +
> > + mutex_init(&retimer->lock);
> > +
> > + retimer->regmap = devm_regmap_init_i2c(client, &ps883x_retimer_regmap);
> > + if (IS_ERR(retimer->regmap)) {
> > + ret = PTR_ERR(retimer->regmap);
> > + dev_err(dev, "failed to allocate register map: %d\n", ret);
>
> Maybe dev_err_probe() as below?
Sure, even though this one here doesn't return EPROBE_DEFER.
But will help with stringifying the error code nonetheless.
So will do that in the next version.
>
> > + return ret;
> > + }
> > +
> > + ret = ps883x_get_vregs(retimer);
> > + if (ret)
> > + return ret;
> > +
> > + retimer->xo_clk = devm_clk_get(dev, NULL);
> > + if (IS_ERR(retimer->xo_clk))
> > + return dev_err_probe(dev, PTR_ERR(retimer->xo_clk),
> > + "failed to get xo clock\n");
> > +
> > + retimer->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
> > + if (IS_ERR(retimer->reset_gpio))
> > + return dev_err_probe(dev, PTR_ERR(retimer->reset_gpio),
> > + "failed to get reset gpio\n");
> > +
> > + retimer->typec_switch = typec_switch_get(dev);
> > + if (IS_ERR(retimer->typec_switch))
> > + return dev_err_probe(dev, PTR_ERR(retimer->typec_switch),
> > + "failed to acquire orientation-switch\n");
> > +
> > + retimer->typec_mux = typec_mux_get(dev);
> > + if (IS_ERR(retimer->typec_mux)) {
> > + ret = dev_err_probe(dev, PTR_ERR(retimer->typec_mux),
> > + "failed to acquire mode-mux\n");
> > + goto err_switch_put;
> > + }
> > +
> > + ret = drm_aux_bridge_register(dev);
> > + if (ret)
> > + goto err_mux_put;
> > +
> > + ret = clk_prepare_enable(retimer->xo_clk);
> > + if (ret) {
> > + dev_err(dev, "failed to enable XO: %d\n", ret);
> > + goto err_mux_put;
> > + }
> > +
> > + ret = ps883x_enable_vregs(retimer);
> > + if (ret)
> > + goto err_clk_disable;
> > +
> > + sw_desc.drvdata = retimer;
> > + sw_desc.fwnode = dev_fwnode(dev);
> > + sw_desc.set = ps883x_sw_set;
> > +
> > + retimer->sw = typec_switch_register(dev, &sw_desc);
> > + if (IS_ERR(retimer->sw)) {
> > + ret = PTR_ERR(retimer->sw);
> > + dev_err(dev, "failed to register typec switch: %d\n", ret);
>
> Maybe dev_err_probe() as above?
Yep.
>
> > + goto err_vregs_disable;
> > + }
> > +
> > + rtmr_desc.drvdata = retimer;
> > + rtmr_desc.fwnode = dev_fwnode(dev);
> > + rtmr_desc.set = ps883x_retimer_set;
> > +
> > + retimer->retimer = typec_retimer_register(dev, &rtmr_desc);
> > + if (IS_ERR(retimer->retimer)) {
> > + ret = PTR_ERR(retimer->retimer);
> > + dev_err(dev, "failed to register typec retimer: %d\n", ret);
>
> Maybe dev_err_probe() as above?
Yep.
>
> > + goto err_switch_unregister;
> > + }
> > +
> > + /* skip resetting if already configured */
> > + if (regmap_test_bits(retimer->regmap, 0x00, BIT(0)))
> > + return 0;
> > +
> > + gpiod_direction_output(retimer->reset_gpio, 1);
> > +
> > + /* VDD IO supply enable to reset release delay */
> > + usleep_range(4000, 14000);
> > +
> > + gpiod_set_value(retimer->reset_gpio, 0);
> > +
> > + /* firmware initialization delay */
> > + msleep(60);
> > +
> > + return 0;
> > +
> > +err_switch_unregister:
> > + typec_switch_unregister(retimer->sw);
> > +err_vregs_disable:
> > + ps883x_disable_vregs(retimer);
> > +err_clk_disable:
> > + clk_disable_unprepare(retimer->xo_clk);
> > +err_mux_put:
> > + typec_mux_put(retimer->typec_mux);
> > +err_switch_put:
> > + typec_switch_put(retimer->typec_switch);
> > +
> > + return ret;
> > +}
> > +
> > +static void ps883x_retimer_remove(struct i2c_client *client)
> > +{
> > + struct ps883x_retimer *retimer = i2c_get_clientdata(client);
> > +
> > + typec_retimer_unregister(retimer->retimer);
> > + typec_switch_unregister(retimer->sw);
> > +
> > + gpiod_set_value(retimer->reset_gpio, 1);
> > +
> > + regulator_disable(retimer->vddio_supply);
> > + regulator_disable(retimer->vddat_supply);
> > + regulator_disable(retimer->vddar_supply);
> > + regulator_disable(retimer->vdd_supply);
> > + regulator_disable(retimer->vdd33_cap_supply);
> > + regulator_disable(retimer->vdd33_supply);
>
> ps883x_disable_vregs()?
Makes sense. Will do
>
> > +
> > + clk_disable_unprepare(retimer->xo_clk);
> > +
> > + typec_mux_put(retimer->typec_mux);
> > + typec_switch_put(retimer->typec_switch);
> > +}
>
> ...
>
> CJ
Thanks for reviewing.
Abel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/4] dt-bindings: usb: Add Parade PS8830 Type-C retimer bindings
2024-11-02 8:58 ` Krzysztof Kozlowski
@ 2024-11-04 10:38 ` Abel Vesa
0 siblings, 0 replies; 13+ messages in thread
From: Abel Vesa @ 2024-11-04 10:38 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, Bjorn Andersson,
Konrad Dybcio, Rajendra Nayak, Sibi Sankar, Johan Hovold,
Dmitry Baryshkov, Trilok Soni, linux-kernel, linux-usb,
devicetree
On 24-11-02 09:58:12, Krzysztof Kozlowski wrote:
> On Fri, Nov 01, 2024 at 06:29:39PM +0200, Abel Vesa wrote:
> > +$id: http://devicetree.org/schemas/usb/parade,ps883x.yaml#
>
> Filename based on compatible, so: parade,ps8830.yaml
>
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Parade PS883x USB and DisplayPort Retimer
> > +
> > +maintainers:
> > + - Abel Vesa <abel.vesa@linaro.org>
> > +
> > +properties:
> > + compatible:
> > + enum:
> > + - parade,ps8830
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + clocks:
> > + items:
> > + - description: XO Clock
> > +
> > + ps8830,boot-on:
>
> I don't see previous comments addressed/responded to.
Urgh, sorry, this should've been dropped.
Will drop it in the next version.
>
> Best regards,
> Krzysztof
>
Thanks for reviewing.
Abel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer
2024-11-04 10:25 ` Konrad Dybcio
@ 2024-11-04 10:40 ` Abel Vesa
0 siblings, 0 replies; 13+ messages in thread
From: Abel Vesa @ 2024-11-04 10:40 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Heikki Krogerus, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, Bjorn Andersson,
Konrad Dybcio, Rajendra Nayak, Sibi Sankar, Johan Hovold,
Dmitry Baryshkov, Trilok Soni, linux-kernel, linux-usb,
devicetree
On 24-11-04 11:25:40, Konrad Dybcio wrote:
> On 4.11.2024 11:16 AM, Abel Vesa wrote:
> > On 24-11-02 10:17:56, Konrad Dybcio wrote:
> >> On 1.11.2024 5:29 PM, Abel Vesa wrote:
> >>> The Parade PS8830 is a USB4, DisplayPort and Thunderbolt 4 retimer,
> >>> controlled over I2C. It usually sits between a USB/DisplayPort PHY
> >>> and the Type-C connector, and provides orientation and altmode handling.
> >>>
> >>> The boards that use this retimer are the ones featuring the Qualcomm
> >>> Snapdragon X Elite SoCs.
> >>>
> >>> Add a driver with support for the following modes:
> >>> - DisplayPort 4-lanes
> >>> - DisplayPort 2-lanes + USB3
> >>> - USB3
> >>>
> >>> There is another variant of this retimer which is called PS8833. It seems
> >>> to be really similar to the PS8830, so future-proof this driver by
> >>> naming it ps883x.
> >>>
> >>> Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
> >>> ---
> >>
> >> [...]
> >>
> >>> +static void ps883x_configure(struct ps883x_retimer *retimer, int cfg0, int cfg1, int cfg2)
> >>> +{
> >>> + regmap_write(retimer->regmap, 0x0, cfg0);
> >>> + regmap_write(retimer->regmap, 0x1, cfg1);
> >>> + regmap_write(retimer->regmap, 0x2, cfg2);
> >>> +}
> >>
> >> Somewhere between introducing regcache and dropping it, you removed
> >> muxing to a safe mode during _configure()
> >
> > Oh, yeah, I forgot to mention that in the change log, it seems.
> >
> > Configuring to safe mode is not needed since we always do that on
> > unplug anyway.
> >
> >>
> >> [...]
> >>
> >>> + /* skip resetting if already configured */
> >>> + if (regmap_test_bits(retimer->regmap, 0x00, BIT(0)))
> >>> + return 0;
> >>
> >> What is that register and what does BIT(0) mean?
> >
> > Looking at the documentation, the first register is
> > REG_USB_PORT_CONN_STATUS and spans over the first 4 bytes.
> >
> > But it doesn't really help here.
> >
> > BIT(0) doesn't really have a name, it just says "Connection present".
>
> Please define both then. STATUS_CONNECTION_PRESENT sounds good for the bit.
Sure, will do.
For the register name I'll just define as:
REG_USB_PORT_CONN_STATUS_1
REG_USB_PORT_CONN_STATUS_2
REG_USB_PORT_CONN_STATUS_3
And that's it.
>
> Konrad
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2024-11-04 10:40 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-01 16:29 [PATCH v4 0/4] usb: typec: Add new driver for Parade PS8830 Type-C Retimer Abel Vesa
2024-11-01 16:29 ` [PATCH v4 1/4] dt-bindings: usb: Add Parade PS8830 Type-C retimer bindings Abel Vesa
2024-11-02 8:58 ` Krzysztof Kozlowski
2024-11-04 10:38 ` Abel Vesa
2024-11-01 16:29 ` [PATCH v4 2/4] usb: typec: Add support for Parade PS8830 Type-C Retimer Abel Vesa
2024-11-01 16:56 ` Christophe JAILLET
2024-11-04 10:36 ` Abel Vesa
2024-11-02 9:17 ` Konrad Dybcio
2024-11-04 10:16 ` Abel Vesa
2024-11-04 10:25 ` Konrad Dybcio
2024-11-04 10:40 ` Abel Vesa
2024-11-01 16:29 ` [PATCH v4 3/4] arm64: dts: qcom: x1e80100-crd: Describe the Parade PS8830 retimers Abel Vesa
2024-11-01 16:29 ` [PATCH v4 4/4] arm64: dts: qcom: x1e80100-crd: Enable external DisplayPort support Abel Vesa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox