Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

phy: exynos5-usbdrd: subscribe to orientation notifier if required

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>
Tested-by: Will McVicker <willmcvicker@google.com>
Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Tested-by: Peter Griffin <peter.griffin@linaro.org>
Link: https://lore.kernel.org/r/20241206-gs101-phy-lanes-orientation-phy-v4-6-f5961268b149@linaro.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

André Draszik and committed by
Vinod Koul
09dc6742 0bccdcb3

+57
+1
drivers/phy/samsung/Kconfig
··· 81 81 tristate "Exynos5 SoC series USB DRD PHY driver" 82 82 depends on (ARCH_EXYNOS && OF) || COMPILE_TEST 83 83 depends on HAS_IOMEM 84 + depends on TYPEC || (TYPEC=n && COMPILE_TEST) 84 85 depends on USB_DWC3_EXYNOS 85 86 select GENERIC_PHY 86 87 select MFD_SYSCON
+56
drivers/phy/samsung/phy-exynos5-usbdrd.c
··· 24 24 #include <linux/regulator/consumer.h> 25 25 #include <linux/soc/samsung/exynos-regs-pmu.h> 26 26 #include <linux/usb/typec.h> 27 + #include <linux/usb/typec_mux.h> 27 28 28 29 /* Exynos USB PHY registers */ 29 30 #define EXYNOS5_FSEL_9MHZ6 0x0 ··· 395 394 * @extrefclk: frequency select settings when using 'separate 396 395 * reference clocks' for SS and HS operations 397 396 * @regulators: regulators for phy 397 + * @sw: TypeC orientation switch handle 398 398 * @orientation: TypeC connector orientation - normal or flipped 399 399 */ 400 400 struct exynos5_usbdrd_phy { ··· 417 415 u32 extrefclk; 418 416 struct regulator_bulk_data *regulators; 419 417 418 + struct typec_switch_dev *sw; 420 419 enum typec_orientation orientation; 421 420 }; 422 421 ··· 1400 1397 return 0; 1401 1398 } 1402 1399 1400 + static int exynos5_usbdrd_orien_sw_set(struct typec_switch_dev *sw, 1401 + enum typec_orientation orientation) 1402 + { 1403 + struct exynos5_usbdrd_phy *phy_drd = typec_switch_get_drvdata(sw); 1404 + 1405 + scoped_guard(mutex, &phy_drd->phy_mutex) 1406 + phy_drd->orientation = orientation; 1407 + 1408 + return 0; 1409 + } 1410 + 1411 + static void exynos5_usbdrd_orien_switch_unregister(void *data) 1412 + { 1413 + struct exynos5_usbdrd_phy *phy_drd = data; 1414 + 1415 + typec_switch_unregister(phy_drd->sw); 1416 + } 1417 + 1418 + static int exynos5_usbdrd_setup_notifiers(struct exynos5_usbdrd_phy *phy_drd) 1419 + { 1420 + int ret; 1421 + 1422 + if (!IS_ENABLED(CONFIG_TYPEC)) 1423 + return 0; 1424 + 1425 + if (device_property_present(phy_drd->dev, "orientation-switch")) { 1426 + struct typec_switch_desc sw_desc = { }; 1427 + 1428 + sw_desc.drvdata = phy_drd; 1429 + sw_desc.fwnode = dev_fwnode(phy_drd->dev); 1430 + sw_desc.set = exynos5_usbdrd_orien_sw_set; 1431 + 1432 + phy_drd->sw = typec_switch_register(phy_drd->dev, &sw_desc); 1433 + if (IS_ERR(phy_drd->sw)) 1434 + return dev_err_probe(phy_drd->dev, 1435 + PTR_ERR(phy_drd->sw), 1436 + "Failed to register TypeC orientation switch\n"); 1437 + 1438 + ret = devm_add_action_or_reset(phy_drd->dev, 1439 + exynos5_usbdrd_orien_switch_unregister, 1440 + phy_drd); 1441 + if (ret) 1442 + return dev_err_probe(phy_drd->dev, ret, 1443 + "Failed to register TypeC orientation devm action\n"); 1444 + } 1445 + 1446 + return 0; 1447 + } 1448 + 1403 1449 static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { 1404 1450 { 1405 1451 .id = EXYNOS5_DRDPHY_UTMI, ··· 1837 1785 phy_drd->regulators); 1838 1786 if (ret) 1839 1787 return dev_err_probe(dev, ret, "failed to get regulators\n"); 1788 + 1789 + ret = exynos5_usbdrd_setup_notifiers(phy_drd); 1790 + if (ret) 1791 + return ret; 1840 1792 1841 1793 dev_vdbg(dev, "Creating usbdrd_phy phy\n"); 1842 1794