Message ID | 20241206-gs101-phy-lanes-orientation-phy-v4-6-f5961268b149@linaro.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | USB31DRD phy updates for Google Tensor gs101 (orientation & DWC3 rpm) | expand |
Hi André, Firstly, thanks for all your work getting USB on Pixel 6 / gs101 working upstream :) On Fri, 6 Dec 2024 at 16:31, André Draszik <andre.draszik@linaro.org> wrote: > > gs101's SS phy needs to be configured differently based on the > connector orientation, as the SS link can only be established if the > mux is configured correctly. > > The code to handle programming of the mux is in place already, this commit > now adds the missing pieces to subscribe to the Type-C orientation > switch event. > > Note that for this all to work we rely on the USB controller > re-initialising us. It should invoke our .exit() upon cable unplug, and > during cable plug we'll receive the orientation event after which we > expect our .init() to be called. > > Above reinitialisation happens if the DWC3 controller can enter runtime > suspend automatically. For the DWC3 driver, this is an opt-in: > echo auto > /sys/devices/.../11110000.usb/power/control > Once done, things work as long as the UDC is not bound as otherwise it > stays busy because it doesn't cancel / stop outstanding TRBs. For now > we have to manually unbind the UDC in that case: > echo "" > sys/kernel/config/usb_gadget/.../UDC > > Note that if the orientation-switch property is missing from the DT, > the code will behave as before this commit (meaning for gs101 it will > work in SS mode in one orientation only). Other platforms are not > affected either way. > > Signed-off-by: André Draszik <andre.draszik@linaro.org> Reviewed-by: Peter Griffin <peter.griffin@linaro.org> Tested-by: Peter Griffin <peter.griffin@linaro.org> Notes on testing: I tested this series with the corresponding DT using a Pixel 6 device with 2 different USB hubs and also plugging directly into my laptop. I've tried various combinations of plugging / unplugging from both ends of the USB cable and changing cable orientation. With the latest series the disconnect/reconnect always seems robustly detected and Pixel is enumerated as a USB device by the host, adb connection to the phone is possible even with the cable orientation changing between disconnect/reconnect. One thing I did notice during testing is that in one cable orientation Pixel is detected as a `SuperSpeed USB device` by the host and in the other cable orientation it is detected as a `high-speed USB device`. Which suggests there is still a latent bug in the phy re-configuration. Although I think it is fine to fix this incrementally, as prior to this series the other cable orientation didn't work at all. I just tested my personal Pixel 6 running the downstream production drivers, and that is detected as a `SuperSpeed USB device` in both cable orientations. Thanks, Peter
Hi André, On Sat, 7 Dec 2024 at 21:31, Peter Griffin <peter.griffin@linaro.org> wrote: > > Hi André, > > Firstly, thanks for all your work getting USB on Pixel 6 / gs101 > working upstream :) > > On Fri, 6 Dec 2024 at 16:31, André Draszik <andre.draszik@linaro.org> wrote: > > > > gs101's SS phy needs to be configured differently based on the > > connector orientation, as the SS link can only be established if the > > mux is configured correctly. > > > > The code to handle programming of the mux is in place already, this commit > > now adds the missing pieces to subscribe to the Type-C orientation > > switch event. > > > > Note that for this all to work we rely on the USB controller > > re-initialising us. It should invoke our .exit() upon cable unplug, and > > during cable plug we'll receive the orientation event after which we > > expect our .init() to be called. > > > > Above reinitialisation happens if the DWC3 controller can enter runtime > > suspend automatically. For the DWC3 driver, this is an opt-in: > > echo auto > /sys/devices/.../11110000.usb/power/control > > Once done, things work as long as the UDC is not bound as otherwise it > > stays busy because it doesn't cancel / stop outstanding TRBs. For now > > we have to manually unbind the UDC in that case: > > echo "" > sys/kernel/config/usb_gadget/.../UDC > > > > Note that if the orientation-switch property is missing from the DT, > > the code will behave as before this commit (meaning for gs101 it will > > work in SS mode in one orientation only). Other platforms are not > > affected either way. > > > > Signed-off-by: André Draszik <andre.draszik@linaro.org> > > Reviewed-by: Peter Griffin <peter.griffin@linaro.org> > Tested-by: Peter Griffin <peter.griffin@linaro.org> > > Notes on testing: > > I tested this series with the corresponding DT using a Pixel 6 device > with 2 different USB hubs and also plugging directly into my laptop. > I've tried various combinations of plugging / unplugging from both > ends of the USB cable and changing cable orientation. With the latest > series the disconnect/reconnect always seems robustly detected and > Pixel is enumerated as a USB device by the host, adb connection to the > phone is possible even with the cable orientation changing between > disconnect/reconnect. > > One thing I did notice during testing is that in one cable orientation > Pixel is detected as a `SuperSpeed USB device` by the host and in the > other cable orientation it is detected as a `high-speed USB device`. > Which suggests there is still a latent bug in the phy > re-configuration. You can disregard this last point, I had a typo in my test setup :( I just confirmed that it is detected as SuperSpeed in both orientations. Thanks, Peter
diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig index f10afa3d7ff5..fc7bd1088576 100644 --- a/drivers/phy/samsung/Kconfig +++ b/drivers/phy/samsung/Kconfig @@ -80,6 +80,7 @@ config PHY_EXYNOS5_USBDRD tristate "Exynos5 SoC series USB DRD PHY driver" depends on (ARCH_EXYNOS && OF) || COMPILE_TEST depends on HAS_IOMEM + depends on TYPEC || (TYPEC=n && COMPILE_TEST) depends on USB_DWC3_EXYNOS select GENERIC_PHY select MFD_SYSCON diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c index 61e0de4b3d4b..8fc15847cfd8 100644 --- a/drivers/phy/samsung/phy-exynos5-usbdrd.c +++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c @@ -24,6 +24,7 @@ #include <linux/regulator/consumer.h> #include <linux/soc/samsung/exynos-regs-pmu.h> #include <linux/usb/typec.h> +#include <linux/usb/typec_mux.h> /* Exynos USB PHY registers */ #define EXYNOS5_FSEL_9MHZ6 0x0 @@ -394,6 +395,7 @@ struct exynos5_usbdrd_phy_drvdata { * @extrefclk: frequency select settings when using 'separate * reference clocks' for SS and HS operations * @regulators: regulators for phy + * @sw: TypeC orientation switch handle * @orientation: TypeC connector orientation - normal or flipped */ struct exynos5_usbdrd_phy { @@ -415,6 +417,7 @@ struct exynos5_usbdrd_phy { u32 extrefclk; struct regulator_bulk_data *regulators; + struct typec_switch_dev *sw; enum typec_orientation orientation; }; @@ -1397,6 +1400,55 @@ static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd) return 0; } +static int exynos5_usbdrd_orien_sw_set(struct typec_switch_dev *sw, + enum typec_orientation orientation) +{ + struct exynos5_usbdrd_phy *phy_drd = typec_switch_get_drvdata(sw); + + scoped_guard(mutex, &phy_drd->phy_mutex) + phy_drd->orientation = orientation; + + return 0; +} + +static void exynos5_usbdrd_orien_switch_unregister(void *data) +{ + struct exynos5_usbdrd_phy *phy_drd = data; + + typec_switch_unregister(phy_drd->sw); +} + +static int exynos5_usbdrd_setup_notifiers(struct exynos5_usbdrd_phy *phy_drd) +{ + int ret; + + if (!IS_ENABLED(CONFIG_TYPEC)) + return 0; + + if (device_property_present(phy_drd->dev, "orientation-switch")) { + struct typec_switch_desc sw_desc = { }; + + sw_desc.drvdata = phy_drd; + sw_desc.fwnode = dev_fwnode(phy_drd->dev); + sw_desc.set = exynos5_usbdrd_orien_sw_set; + + phy_drd->sw = typec_switch_register(phy_drd->dev, &sw_desc); + if (IS_ERR(phy_drd->sw)) + return dev_err_probe(phy_drd->dev, + PTR_ERR(phy_drd->sw), + "Failed to register TypeC orientation switch\n"); + + ret = devm_add_action_or_reset(phy_drd->dev, + exynos5_usbdrd_orien_switch_unregister, + phy_drd); + if (ret) + return dev_err_probe(phy_drd->dev, ret, + "Failed to register TypeC orientation devm action\n"); + } + + return 0; +} + static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { { .id = EXYNOS5_DRDPHY_UTMI, @@ -1786,6 +1838,10 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "failed to get regulators\n"); + ret = exynos5_usbdrd_setup_notifiers(phy_drd); + if (ret) + return ret; + dev_vdbg(dev, "Creating usbdrd_phy phy\n"); for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
gs101's SS phy needs to be configured differently based on the connector orientation, as the SS link can only be established if the mux is configured correctly. The code to handle programming of the mux is in place already, this commit now adds the missing pieces to subscribe to the Type-C orientation switch event. Note that for this all to work we rely on the USB controller re-initialising us. It should invoke our .exit() upon cable unplug, and during cable plug we'll receive the orientation event after which we expect our .init() to be called. Above reinitialisation happens if the DWC3 controller can enter runtime suspend automatically. For the DWC3 driver, this is an opt-in: echo auto > /sys/devices/.../11110000.usb/power/control Once done, things work as long as the UDC is not bound as otherwise it stays busy because it doesn't cancel / stop outstanding TRBs. For now we have to manually unbind the UDC in that case: echo "" > sys/kernel/config/usb_gadget/.../UDC Note that if the orientation-switch property is missing from the DT, the code will behave as before this commit (meaning for gs101 it will work in SS mode in one orientation only). Other platforms are not affected either way. Signed-off-by: André Draszik <andre.draszik@linaro.org> --- v3: * drop init to -1 of phy_drd->orientation (Vinod) * avoid #ifdef and switch to normal conditional IS_ENABLED() for CONFIG_TYPEC v2: * move #include typec_mux.h from parent patch into this one (Peter) --- drivers/phy/samsung/Kconfig | 1 + drivers/phy/samsung/phy-exynos5-usbdrd.c | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+)