From 329ffacea542163fe7ac798b77db7cb3599a65ac Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 11 Mar 2020 19:15:00 +0000 Subject: [PATCH 1/2] usb: dwc3: Add support for a role-switch notifier Role-switching is a 1:1 mapping between a producer and a consumer. For DWC3 we have some vendor specific wrappers, notably the qcom wrapper that want to toggle some PHY related bits on a USB role switch. This patch adds a role-switch notifier to the dwc3 drd code. When the USB role-switch set() routine runs, the notifier will fire passing the notified mode to the consumer, thus allowing vendor specific fix-ups to toggle from the role-switching events. Signed-off-by: Bryan O'Donoghue --- drivers/usb/dwc3/core.h | 8 ++++++++ drivers/usb/dwc3/drd.c | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index dccdf13b5f9e..7f81ee3a9657 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -995,6 +995,7 @@ struct dwc3_scratchpad_array { * @role_sw: usb_role_switch handle * @role_switch_default_mode: default operation mode of controller while * usb role is USB_ROLE_NONE. + * @role_sw_nl: role switch notifier list * @usb_psy: pointer to power supply interface. * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY @@ -1136,6 +1137,7 @@ struct dwc3 { struct notifier_block edev_nb; enum usb_phy_interface hsphy_mode; struct usb_role_switch *role_sw; + struct raw_notifier_head role_sw_nl; enum usb_dr_mode role_switch_default_mode; struct power_supply *usb_psy; @@ -1586,4 +1588,10 @@ static inline void dwc3_ulpi_exit(struct dwc3 *dwc) { } #endif +#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) +void __weak +dwc3_set_parent_role_switch_notifier(struct device *parent, + struct raw_notifier_head *role_sw_nl) {} +#endif + #endif /* __DRIVERS_USB_DWC3_CORE_H */ diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index 8fcbac10510c..7ae09730a319 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c @@ -507,6 +507,8 @@ static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, } dwc3_set_mode(dwc, mode); + raw_notifier_call_chain(&dwc->role_sw_nl, mode, NULL); + return 0; } @@ -563,6 +565,9 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc) if (IS_ERR(dwc->role_sw)) return PTR_ERR(dwc->role_sw); + RAW_INIT_NOTIFIER_HEAD(&dwc->role_sw_nl); + dwc3_set_parent_role_switch_notifier(dwc->dev->parent, + &dwc->role_sw_nl); dwc3_set_mode(dwc, mode); return 0; } -- 2.30.1