Skip to content

Commit 9b2b156

Browse files
svenpeter42jannau
authored andcommitted
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>
1 parent 895933b commit 9b2b156

4 files changed

Lines changed: 131 additions & 5 deletions

File tree

drivers/usb/dwc3/core.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
133133
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg);
134134
}
135135
}
136+
EXPORT_SYMBOL_GPL(dwc3_enable_susphy);
136137

137138
void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
138139
{
@@ -159,6 +160,7 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy)
159160
dwc->current_dr_role = mode;
160161
trace_dwc3_set_prtcap(mode);
161162
}
163+
EXPORT_SYMBOL_GPL(dwc3_set_prtcap);
162164

163165
static void __dwc3_set_mode(struct work_struct *work)
164166
{
@@ -976,14 +978,15 @@ static void dwc3_clk_disable(struct dwc3 *dwc)
976978
clk_disable_unprepare(dwc->bus_clk);
977979
}
978980

979-
static void dwc3_core_exit(struct dwc3 *dwc)
981+
void dwc3_core_exit(struct dwc3 *dwc)
980982
{
981983
dwc3_event_buffers_cleanup(dwc);
982984
dwc3_phy_power_off(dwc);
983985
dwc3_phy_exit(dwc);
984986
dwc3_clk_disable(dwc);
985987
reset_control_assert(dwc->reset);
986988
}
989+
EXPORT_SYMBOL_GPL(dwc3_core_exit);
987990

988991
static bool dwc3_core_is_valid(struct dwc3 *dwc)
989992
{
@@ -1329,7 +1332,7 @@ static void dwc3_config_threshold(struct dwc3 *dwc)
13291332
*
13301333
* Returns 0 on success otherwise negative errno.
13311334
*/
1332-
static int dwc3_core_init(struct dwc3 *dwc)
1335+
int dwc3_core_init(struct dwc3 *dwc)
13331336
{
13341337
unsigned int hw_mode;
13351338
u32 reg;
@@ -1529,6 +1532,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
15291532

15301533
return ret;
15311534
}
1535+
EXPORT_SYMBOL_GPL(dwc3_core_init);
15321536

15331537
static int dwc3_core_get_phy(struct dwc3 *dwc)
15341538
{
@@ -2307,9 +2311,11 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
23072311
dwc3_check_params(dwc);
23082312
dwc3_debugfs_init(dwc);
23092313

2310-
ret = dwc3_core_init_mode(dwc);
2311-
if (ret)
2312-
goto err_exit_debugfs;
2314+
if (!data->skip_core_init_mode) {
2315+
ret = dwc3_core_init_mode(dwc);
2316+
if (ret)
2317+
goto err_exit_debugfs;
2318+
}
23132319

23142320
pm_runtime_put(dev);
23152321

drivers/usb/dwc3/gadget.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4817,6 +4817,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
48174817
err0:
48184818
return ret;
48194819
}
4820+
EXPORT_SYMBOL_GPL(dwc3_gadget_init);
48204821

48214822
/* -------------------------------------------------------------------------- */
48224823

@@ -4835,6 +4836,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
48354836
dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2,
48364837
dwc->ep0_trb, dwc->ep0_trb_addr);
48374838
}
4839+
EXPORT_SYMBOL_GPL(dwc3_gadget_exit);
48384840

48394841
int dwc3_gadget_suspend(struct dwc3 *dwc)
48404842
{

drivers/usb/dwc3/glue.h

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@ struct dwc3_properties {
2727
* @res: resource for the DWC3 core mmio region
2828
* @ignore_clocks_and_resets: clocks and resets defined for the device should
2929
* 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
3032
* @properties: dwc3 software manage properties
3133
*/
3234
struct dwc3_probe_data {
3335
struct dwc3 *dwc;
3436
struct resource *res;
3537
bool ignore_clocks_and_resets;
38+
bool skip_core_init_mode;
3639
struct dwc3_properties properties;
3740
};
3841

@@ -74,4 +77,117 @@ int dwc3_pm_resume(struct dwc3 *dwc);
7477
void dwc3_pm_complete(struct dwc3 *dwc);
7578
int dwc3_pm_prepare(struct dwc3 *dwc);
7679

80+
81+
/* All of the following functions must only be used with skip_core_init_mode */
82+
83+
/**
84+
* dwc3_core_init - Initialize DWC3 core hardware
85+
* @dwc: Pointer to DWC3 controller context
86+
*
87+
* Configures and initializes the core hardware, usually done by dwc3_core_probe.
88+
* This function is provided for platforms that use skip_core_init_mode and need
89+
* to finalize the core initialization after some platform-specific setup.
90+
* It must only be called when using skip_core_init_mode and before
91+
* dwc3_host_init or dwc3_gadget_init.
92+
*
93+
* Return: 0 on success, negative error code on failure
94+
*/
95+
int dwc3_core_init(struct dwc3 *dwc);
96+
97+
/**
98+
* dwc3_core_exit - Shut down DWC3 core hardware
99+
* @dwc: Pointer to DWC3 controller context
100+
*
101+
* Disables and cleans up the core hardware state. This is usually handled
102+
* internally by dwc3 and must only be called when using skip_core_init_mode
103+
* and only after dwc3_core_init. Afterwards, dwc3_core_init may be called
104+
* again.
105+
*/
106+
void dwc3_core_exit(struct dwc3 *dwc);
107+
108+
/**
109+
* dwc3_host_init - Initialize host mode operation
110+
* @dwc: Pointer to DWC3 controller context
111+
*
112+
* Initializes the controller for USB host mode operation, usually done by
113+
* dwc3_core_probe or from within the dwc3 USB role switch callback.
114+
* This function is provided for platforms that use skip_core_init_mode and need
115+
* to finalize the host initialization after some platform-specific setup.
116+
* It must not be called before dwc3_core_init or when skip_core_init_mode is
117+
* not used. It must also not be called when gadget or host mode has already
118+
* been initialized.
119+
*
120+
* Return: 0 on success, negative error code on failure
121+
*/
122+
int dwc3_host_init(struct dwc3 *dwc);
123+
124+
/**
125+
* dwc3_host_exit - Shut down host mode operation
126+
* @dwc: Pointer to DWC3 controller context
127+
*
128+
* Disables and cleans up host mode resources, usually done by
129+
* the dwc3 USB role switch callback before switching controller mode.
130+
* It must only be called when skip_core_init_mode is used and only after
131+
* dwc3_host_init.
132+
*/
133+
void dwc3_host_exit(struct dwc3 *dwc);
134+
135+
/**
136+
* dwc3_gadget_init - Initialize gadget mode operation
137+
* @dwc: Pointer to DWC3 controller context
138+
*
139+
* Initializes the controller for USB gadget mode operation, usually done by
140+
* dwc3_core_probe or from within the dwc3 USB role switch callback. This
141+
* function is provided for platforms that use skip_core_init_mode and need to
142+
* finalize the gadget initialization after some platform-specific setup.
143+
* It must not be called before dwc3_core_init or when skip_core_init_mode is
144+
* not used. It must also not be called when gadget or host mode has already
145+
* been initialized.
146+
*
147+
* Return: 0 on success, negative error code on failure
148+
*/
149+
int dwc3_gadget_init(struct dwc3 *dwc);
150+
151+
/**
152+
* dwc3_gadget_exit - Shut down gadget mode operation
153+
* @dwc: Pointer to DWC3 controller context
154+
*
155+
* Disables and cleans up gadget mode resources, usually done by
156+
* the dwc3 USB role switch callback before switching controller mode.
157+
* It must only be called when skip_core_init_mode is used and only after
158+
* dwc3_gadget_init.
159+
*/
160+
void dwc3_gadget_exit(struct dwc3 *dwc);
161+
162+
/**
163+
* dwc3_enable_susphy - Control SUSPHY status for all USB ports
164+
* @dwc: Pointer to DWC3 controller context
165+
* @enable: True to enable SUSPHY, false to disable
166+
*
167+
* Enables or disables the USB3 PHY SUSPEND and USB2 PHY SUSPHY feature for
168+
* all available ports.
169+
* This is usually handled by the dwc3 core code and should only be used
170+
* when skip_core_init_mode is used and the glue layer needs to manage SUSPHY
171+
* settings itself, e.g., due to platform-specific requirements during mode
172+
* switches.
173+
*/
174+
void dwc3_enable_susphy(struct dwc3 *dwc, bool enable);
175+
176+
/**
177+
* dwc3_set_prtcap - Set the USB controller PRTCAP mode
178+
* @dwc: Pointer to DWC3 controller context
179+
* @mode: Target mode, must be one of DWC3_GCTL_PRTCAP_{HOST,DEVICE,OTG}
180+
* @ignore_susphy: If true, skip disabling the SUSPHY and keep the current state
181+
*
182+
* Updates PRTCAP of the controller and current_dr_role inside the dwc3
183+
* structure. For DRD controllers, this also disables SUSPHY unless explicitly
184+
* told to skip via the ignore_susphy parameter.
185+
*
186+
* This is usually handled by the dwc3 core code and should only be used
187+
* when skip_core_init_mode is used and the glue layer needs to manage mode
188+
* transitions itself due to platform-specific requirements. It must be called
189+
* with the correct mode before calling dwc3_host_init or dwc3_gadget_init.
190+
*/
191+
void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy);
192+
77193
#endif

drivers/usb/dwc3/host.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ int dwc3_host_init(struct dwc3 *dwc)
220220
platform_device_put(xhci);
221221
return ret;
222222
}
223+
EXPORT_SYMBOL_GPL(dwc3_host_init);
223224

224225
void dwc3_host_exit(struct dwc3 *dwc)
225226
{
@@ -230,3 +231,4 @@ void dwc3_host_exit(struct dwc3 *dwc)
230231
platform_device_unregister(dwc->xhci);
231232
dwc->xhci = NULL;
232233
}
234+
EXPORT_SYMBOL_GPL(dwc3_host_exit);

0 commit comments

Comments
 (0)