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.

usb: dwc3: glue: Allow more fine grained control over mode switches

We need fine grained control over mode switched on the DWC3 controller
present on Apple Silicon. Export core, host and gadget init and exit,
ptrcap and susphy control functions. Also introduce an additional
parameter to probe_data that allows to skip the final initialization
step that would bring up host or gadget mode.

Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Signed-off-by: Sven Peter <sven@kernel.org>
Link: https://patch.msgid.link/20251015-b4-aplpe-dwc3-v2-4-cbd65a2d511a@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sven Peter and committed by
Greg Kroah-Hartman
f854920e e10bc796

+131 -5
+11 -5
drivers/usb/dwc3/core.c
··· 132 132 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg); 133 133 } 134 134 } 135 + EXPORT_SYMBOL_GPL(dwc3_enable_susphy); 135 136 136 137 void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy) 137 138 { ··· 159 158 dwc->current_dr_role = mode; 160 159 trace_dwc3_set_prtcap(mode); 161 160 } 161 + EXPORT_SYMBOL_GPL(dwc3_set_prtcap); 162 162 163 163 static void __dwc3_set_mode(struct work_struct *work) 164 164 { ··· 977 975 clk_disable_unprepare(dwc->bus_clk); 978 976 } 979 977 980 - static void dwc3_core_exit(struct dwc3 *dwc) 978 + void dwc3_core_exit(struct dwc3 *dwc) 981 979 { 982 980 dwc3_event_buffers_cleanup(dwc); 983 981 dwc3_phy_power_off(dwc); ··· 985 983 dwc3_clk_disable(dwc); 986 984 reset_control_assert(dwc->reset); 987 985 } 986 + EXPORT_SYMBOL_GPL(dwc3_core_exit); 988 987 989 988 static bool dwc3_core_is_valid(struct dwc3 *dwc) 990 989 { ··· 1331 1328 * 1332 1329 * Returns 0 on success otherwise negative errno. 1333 1330 */ 1334 - static int dwc3_core_init(struct dwc3 *dwc) 1331 + int dwc3_core_init(struct dwc3 *dwc) 1335 1332 { 1336 1333 unsigned int hw_mode; 1337 1334 u32 reg; ··· 1531 1528 1532 1529 return ret; 1533 1530 } 1531 + EXPORT_SYMBOL_GPL(dwc3_core_init); 1534 1532 1535 1533 static int dwc3_core_get_phy(struct dwc3 *dwc) 1536 1534 { ··· 2310 2306 dwc3_check_params(dwc); 2311 2307 dwc3_debugfs_init(dwc); 2312 2308 2313 - ret = dwc3_core_init_mode(dwc); 2314 - if (ret) 2315 - goto err_exit_debugfs; 2309 + if (!data->skip_core_init_mode) { 2310 + ret = dwc3_core_init_mode(dwc); 2311 + if (ret) 2312 + goto err_exit_debugfs; 2313 + } 2316 2314 2317 2315 pm_runtime_put(dev); 2318 2316
+2
drivers/usb/dwc3/gadget.c
··· 4810 4810 err0: 4811 4811 return ret; 4812 4812 } 4813 + EXPORT_SYMBOL_GPL(dwc3_gadget_init); 4813 4814 4814 4815 /* -------------------------------------------------------------------------- */ 4815 4816 ··· 4829 4828 dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, 4830 4829 dwc->ep0_trb, dwc->ep0_trb_addr); 4831 4830 } 4831 + EXPORT_SYMBOL_GPL(dwc3_gadget_exit); 4832 4832 4833 4833 int dwc3_gadget_suspend(struct dwc3 *dwc) 4834 4834 {
+116
drivers/usb/dwc3/glue.h
··· 27 27 * @res: resource for the DWC3 core mmio region 28 28 * @ignore_clocks_and_resets: clocks and resets defined for the device should 29 29 * be ignored by the DWC3 core, as they are managed by the glue 30 + * @skip_core_init_mode: Skip the finial initialization of the target mode, as 31 + * it must be managed by the glue 30 32 * @properties: dwc3 software manage properties 31 33 */ 32 34 struct dwc3_probe_data { 33 35 struct dwc3 *dwc; 34 36 struct resource *res; 35 37 bool ignore_clocks_and_resets; 38 + bool skip_core_init_mode; 36 39 struct dwc3_properties properties; 37 40 }; 38 41 ··· 76 73 int dwc3_pm_resume(struct dwc3 *dwc); 77 74 void dwc3_pm_complete(struct dwc3 *dwc); 78 75 int dwc3_pm_prepare(struct dwc3 *dwc); 76 + 77 + 78 + /* All of the following functions must only be used with skip_core_init_mode */ 79 + 80 + /** 81 + * dwc3_core_init - Initialize DWC3 core hardware 82 + * @dwc: Pointer to DWC3 controller context 83 + * 84 + * Configures and initializes the core hardware, usually done by dwc3_core_probe. 85 + * This function is provided for platforms that use skip_core_init_mode and need 86 + * to finalize the core initialization after some platform-specific setup. 87 + * It must only be called when using skip_core_init_mode and before 88 + * dwc3_host_init or dwc3_gadget_init. 89 + * 90 + * Return: 0 on success, negative error code on failure 91 + */ 92 + int dwc3_core_init(struct dwc3 *dwc); 93 + 94 + /** 95 + * dwc3_core_exit - Shut down DWC3 core hardware 96 + * @dwc: Pointer to DWC3 controller context 97 + * 98 + * Disables and cleans up the core hardware state. This is usually handled 99 + * internally by dwc3 and must only be called when using skip_core_init_mode 100 + * and only after dwc3_core_init. Afterwards, dwc3_core_init may be called 101 + * again. 102 + */ 103 + void dwc3_core_exit(struct dwc3 *dwc); 104 + 105 + /** 106 + * dwc3_host_init - Initialize host mode operation 107 + * @dwc: Pointer to DWC3 controller context 108 + * 109 + * Initializes the controller for USB host mode operation, usually done by 110 + * dwc3_core_probe or from within the dwc3 USB role switch callback. 111 + * This function is provided for platforms that use skip_core_init_mode and need 112 + * to finalize the host initialization after some platform-specific setup. 113 + * It must not be called before dwc3_core_init or when skip_core_init_mode is 114 + * not used. It must also not be called when gadget or host mode has already 115 + * been initialized. 116 + * 117 + * Return: 0 on success, negative error code on failure 118 + */ 119 + int dwc3_host_init(struct dwc3 *dwc); 120 + 121 + /** 122 + * dwc3_host_exit - Shut down host mode operation 123 + * @dwc: Pointer to DWC3 controller context 124 + * 125 + * Disables and cleans up host mode resources, usually done by 126 + * the dwc3 USB role switch callback before switching controller mode. 127 + * It must only be called when skip_core_init_mode is used and only after 128 + * dwc3_host_init. 129 + */ 130 + void dwc3_host_exit(struct dwc3 *dwc); 131 + 132 + /** 133 + * dwc3_gadget_init - Initialize gadget mode operation 134 + * @dwc: Pointer to DWC3 controller context 135 + * 136 + * Initializes the controller for USB gadget mode operation, usually done by 137 + * dwc3_core_probe or from within the dwc3 USB role switch callback. This 138 + * function is provided for platforms that use skip_core_init_mode and need to 139 + * finalize the gadget initialization after some platform-specific setup. 140 + * It must not be called before dwc3_core_init or when skip_core_init_mode is 141 + * not used. It must also not be called when gadget or host mode has already 142 + * been initialized. 143 + * 144 + * Return: 0 on success, negative error code on failure 145 + */ 146 + int dwc3_gadget_init(struct dwc3 *dwc); 147 + 148 + /** 149 + * dwc3_gadget_exit - Shut down gadget mode operation 150 + * @dwc: Pointer to DWC3 controller context 151 + * 152 + * Disables and cleans up gadget mode resources, usually done by 153 + * the dwc3 USB role switch callback before switching controller mode. 154 + * It must only be called when skip_core_init_mode is used and only after 155 + * dwc3_gadget_init. 156 + */ 157 + void dwc3_gadget_exit(struct dwc3 *dwc); 158 + 159 + /** 160 + * dwc3_enable_susphy - Control SUSPHY status for all USB ports 161 + * @dwc: Pointer to DWC3 controller context 162 + * @enable: True to enable SUSPHY, false to disable 163 + * 164 + * Enables or disables the USB3 PHY SUSPEND and USB2 PHY SUSPHY feature for 165 + * all available ports. 166 + * This is usually handled by the dwc3 core code and should only be used 167 + * when skip_core_init_mode is used and the glue layer needs to manage SUSPHY 168 + * settings itself, e.g., due to platform-specific requirements during mode 169 + * switches. 170 + */ 171 + void dwc3_enable_susphy(struct dwc3 *dwc, bool enable); 172 + 173 + /** 174 + * dwc3_set_prtcap - Set the USB controller PRTCAP mode 175 + * @dwc: Pointer to DWC3 controller context 176 + * @mode: Target mode, must be one of DWC3_GCTL_PRTCAP_{HOST,DEVICE,OTG} 177 + * @ignore_susphy: If true, skip disabling the SUSPHY and keep the current state 178 + * 179 + * Updates PRTCAP of the controller and current_dr_role inside the dwc3 180 + * structure. For DRD controllers, this also disables SUSPHY unless explicitly 181 + * told to skip via the ignore_susphy parameter. 182 + * 183 + * This is usually handled by the dwc3 core code and should only be used 184 + * when skip_core_init_mode is used and the glue layer needs to manage mode 185 + * transitions itself due to platform-specific requirements. It must be called 186 + * with the correct mode before calling dwc3_host_init or dwc3_gadget_init. 187 + */ 188 + void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy); 79 189 80 190 #endif
+2
drivers/usb/dwc3/host.c
··· 220 220 platform_device_put(xhci); 221 221 return ret; 222 222 } 223 + EXPORT_SYMBOL_GPL(dwc3_host_init); 223 224 224 225 void dwc3_host_exit(struct dwc3 *dwc) 225 226 { ··· 231 230 platform_device_unregister(dwc->xhci); 232 231 dwc->xhci = NULL; 233 232 } 233 + EXPORT_SYMBOL_GPL(dwc3_host_exit);