1 // SPDX-License-Identifier: GPL-2.0
3 * drd.c - DesignWare USB2 DRD Controller Dual-role support
5 * Copyright (C) 2020 STMicroelectronics
7 * Author(s): Amelie Delaunay <amelie.delaunay@st.com>
10 #include <linux/clk.h>
11 #include <linux/iopoll.h>
12 #include <linux/platform_device.h>
13 #include <linux/usb/role.h>
16 #define dwc2_ovr_gotgctl(gotgctl) \
17 ((gotgctl) |= GOTGCTL_BVALOEN | GOTGCTL_AVALOEN | GOTGCTL_VBVALOEN | \
18 GOTGCTL_DBNCE_FLTR_BYPASS)
20 static void dwc2_ovr_init(struct dwc2_hsotg
*hsotg
)
25 spin_lock_irqsave(&hsotg
->lock
, flags
);
27 gotgctl
= dwc2_readl(hsotg
, GOTGCTL
);
28 dwc2_ovr_gotgctl(gotgctl
);
29 gotgctl
&= ~(GOTGCTL_BVALOVAL
| GOTGCTL_AVALOVAL
| GOTGCTL_VBVALOVAL
);
30 if (hsotg
->role_sw_default_mode
== USB_DR_MODE_HOST
)
31 gotgctl
|= GOTGCTL_AVALOVAL
| GOTGCTL_VBVALOVAL
;
32 else if (hsotg
->role_sw_default_mode
== USB_DR_MODE_PERIPHERAL
)
33 gotgctl
|= GOTGCTL_BVALOVAL
| GOTGCTL_VBVALOVAL
;
34 dwc2_writel(hsotg
, gotgctl
, GOTGCTL
);
36 spin_unlock_irqrestore(&hsotg
->lock
, flags
);
38 dwc2_force_mode(hsotg
, (hsotg
->dr_mode
== USB_DR_MODE_HOST
) ||
39 (hsotg
->role_sw_default_mode
== USB_DR_MODE_HOST
));
42 static int dwc2_ovr_avalid(struct dwc2_hsotg
*hsotg
, bool valid
)
44 u32 gotgctl
= dwc2_readl(hsotg
, GOTGCTL
);
46 /* Check if A-Session is already in the right state */
47 if ((valid
&& (gotgctl
& GOTGCTL_ASESVLD
)) ||
48 (!valid
&& !(gotgctl
& GOTGCTL_ASESVLD
)))
51 /* Always enable overrides to handle the resume case */
52 dwc2_ovr_gotgctl(gotgctl
);
54 gotgctl
&= ~GOTGCTL_BVALOVAL
;
56 gotgctl
|= GOTGCTL_AVALOVAL
| GOTGCTL_VBVALOVAL
;
58 gotgctl
&= ~(GOTGCTL_AVALOVAL
| GOTGCTL_VBVALOVAL
);
59 dwc2_writel(hsotg
, gotgctl
, GOTGCTL
);
64 static int dwc2_ovr_bvalid(struct dwc2_hsotg
*hsotg
, bool valid
)
66 u32 gotgctl
= dwc2_readl(hsotg
, GOTGCTL
);
68 /* Check if B-Session is already in the right state */
69 if ((valid
&& (gotgctl
& GOTGCTL_BSESVLD
)) ||
70 (!valid
&& !(gotgctl
& GOTGCTL_BSESVLD
)))
73 /* Always enable overrides to handle the resume case */
74 dwc2_ovr_gotgctl(gotgctl
);
76 gotgctl
&= ~GOTGCTL_AVALOVAL
;
78 gotgctl
|= GOTGCTL_BVALOVAL
| GOTGCTL_VBVALOVAL
;
80 gotgctl
&= ~(GOTGCTL_BVALOVAL
| GOTGCTL_VBVALOVAL
);
81 dwc2_writel(hsotg
, gotgctl
, GOTGCTL
);
86 static int dwc2_drd_role_sw_set(struct usb_role_switch
*sw
, enum usb_role role
)
88 struct dwc2_hsotg
*hsotg
= usb_role_switch_get_drvdata(sw
);
92 /* Skip session not in line with dr_mode */
93 if ((role
== USB_ROLE_DEVICE
&& hsotg
->dr_mode
== USB_DR_MODE_HOST
) ||
94 (role
== USB_ROLE_HOST
&& hsotg
->dr_mode
== USB_DR_MODE_PERIPHERAL
))
97 #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
98 IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
99 /* Skip session if core is in test mode */
100 if (role
== USB_ROLE_NONE
&& hsotg
->test_mode
) {
101 dev_dbg(hsotg
->dev
, "Core is in test mode\n");
107 * In case of USB_DR_MODE_PERIPHERAL, clock is disabled at the end of
108 * the probe and enabled on udc_start.
109 * If role-switch set is called before the udc_start, we need to enable
110 * the clock to read/write GOTGCTL and GUSBCFG registers to override
111 * mode and sessions. It is the case if cable is plugged at boot.
113 if (!hsotg
->ll_hw_enabled
&& hsotg
->clk
) {
114 int ret
= clk_prepare_enable(hsotg
->clk
);
120 spin_lock_irqsave(&hsotg
->lock
, flags
);
122 if (role
== USB_ROLE_NONE
) {
123 /* default operation mode when usb role is USB_ROLE_NONE */
124 if (hsotg
->role_sw_default_mode
== USB_DR_MODE_HOST
)
125 role
= USB_ROLE_HOST
;
126 else if (hsotg
->role_sw_default_mode
== USB_DR_MODE_PERIPHERAL
)
127 role
= USB_ROLE_DEVICE
;
130 if ((IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL
) ||
131 IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE
)) &&
132 dwc2_is_device_mode(hsotg
) &&
133 hsotg
->lx_state
== DWC2_L2
&&
134 hsotg
->params
.power_down
== DWC2_POWER_DOWN_PARAM_NONE
&&
135 hsotg
->bus_suspended
&&
136 !hsotg
->params
.no_clock_gating
)
137 dwc2_gadget_exit_clock_gating(hsotg
, 0);
139 if (role
== USB_ROLE_HOST
) {
140 already
= dwc2_ovr_avalid(hsotg
, true);
141 } else if (role
== USB_ROLE_DEVICE
) {
142 already
= dwc2_ovr_bvalid(hsotg
, true);
143 if (dwc2_is_device_enabled(hsotg
)) {
144 /* This clear DCTL.SFTDISCON bit */
145 dwc2_hsotg_core_connect(hsotg
);
148 if (dwc2_is_device_mode(hsotg
)) {
149 if (!dwc2_ovr_bvalid(hsotg
, false))
150 /* This set DCTL.SFTDISCON bit */
151 dwc2_hsotg_core_disconnect(hsotg
);
153 dwc2_ovr_avalid(hsotg
, false);
157 spin_unlock_irqrestore(&hsotg
->lock
, flags
);
159 if (!already
&& hsotg
->dr_mode
== USB_DR_MODE_OTG
)
160 /* This will raise a Connector ID Status Change Interrupt */
161 dwc2_force_mode(hsotg
, role
== USB_ROLE_HOST
);
163 if (!hsotg
->ll_hw_enabled
&& hsotg
->clk
)
164 clk_disable_unprepare(hsotg
->clk
);
166 dev_dbg(hsotg
->dev
, "%s-session valid\n",
167 role
== USB_ROLE_NONE
? "No" :
168 role
== USB_ROLE_HOST
? "A" : "B");
173 int dwc2_drd_init(struct dwc2_hsotg
*hsotg
)
175 struct usb_role_switch_desc role_sw_desc
= {0};
176 struct usb_role_switch
*role_sw
;
179 if (!device_property_read_bool(hsotg
->dev
, "usb-role-switch"))
182 hsotg
->role_sw_default_mode
= usb_get_role_switch_default_mode(hsotg
->dev
);
183 role_sw_desc
.driver_data
= hsotg
;
184 role_sw_desc
.fwnode
= dev_fwnode(hsotg
->dev
);
185 role_sw_desc
.set
= dwc2_drd_role_sw_set
;
186 role_sw_desc
.allow_userspace_control
= true;
188 role_sw
= usb_role_switch_register(hsotg
->dev
, &role_sw_desc
);
189 if (IS_ERR(role_sw
)) {
190 ret
= PTR_ERR(role_sw
);
192 "failed to register role switch: %d\n", ret
);
196 hsotg
->role_sw
= role_sw
;
198 /* Enable override and initialize values */
199 dwc2_ovr_init(hsotg
);
204 void dwc2_drd_suspend(struct dwc2_hsotg
*hsotg
)
206 u32 gintsts
, gintmsk
;
208 if (hsotg
->role_sw
&& !hsotg
->params
.external_id_pin_ctl
) {
209 gintmsk
= dwc2_readl(hsotg
, GINTMSK
);
210 gintmsk
&= ~GINTSTS_CONIDSTSCHNG
;
211 dwc2_writel(hsotg
, gintmsk
, GINTMSK
);
212 gintsts
= dwc2_readl(hsotg
, GINTSTS
);
213 dwc2_writel(hsotg
, gintsts
| GINTSTS_CONIDSTSCHNG
, GINTSTS
);
217 void dwc2_drd_resume(struct dwc2_hsotg
*hsotg
)
219 u32 gintsts
, gintmsk
;
222 if (hsotg
->role_sw
) {
223 /* get last known role (as the get ops isn't implemented by this driver) */
224 role
= usb_role_switch_get_role(hsotg
->role_sw
);
226 if (role
== USB_ROLE_NONE
) {
227 if (hsotg
->role_sw_default_mode
== USB_DR_MODE_HOST
)
228 role
= USB_ROLE_HOST
;
229 else if (hsotg
->role_sw_default_mode
== USB_DR_MODE_PERIPHERAL
)
230 role
= USB_ROLE_DEVICE
;
233 /* restore last role that may have been lost */
234 if (role
== USB_ROLE_HOST
)
235 dwc2_ovr_avalid(hsotg
, true);
236 else if (role
== USB_ROLE_DEVICE
)
237 dwc2_ovr_bvalid(hsotg
, true);
239 dwc2_force_mode(hsotg
, role
== USB_ROLE_HOST
);
241 dev_dbg(hsotg
->dev
, "resuming %s-session valid\n",
242 role
== USB_ROLE_NONE
? "No" :
243 role
== USB_ROLE_HOST
? "A" : "B");
246 if (hsotg
->role_sw
&& !hsotg
->params
.external_id_pin_ctl
) {
247 gintsts
= dwc2_readl(hsotg
, GINTSTS
);
248 dwc2_writel(hsotg
, gintsts
| GINTSTS_CONIDSTSCHNG
, GINTSTS
);
249 gintmsk
= dwc2_readl(hsotg
, GINTMSK
);
250 gintmsk
|= GINTSTS_CONIDSTSCHNG
;
251 dwc2_writel(hsotg
, gintmsk
, GINTMSK
);
255 void dwc2_drd_exit(struct dwc2_hsotg
*hsotg
)
258 usb_role_switch_unregister(hsotg
->role_sw
);