Skip to content

Commit 9d6173e

Browse files
tnsnpsFelipe Balbi
authored andcommitted
usb: dwc3: Fix dr_mode validation
This patch follows the similar fix in dwc2. See commit 5268ed9 ("usb: dwc2: Fix dr_mode validation") Currently, the dr_mode is only checked against the module configuration. It also needs to be checked against the hardware capablities. The driver now checks if both the module configuration and hardware are capable of the dr_mode value. If not, then it will issue a warning and fall back to a supported value. If it is unable to fall back to a suitable value, then the probe will fail. Behavior summary: module : actual HW config dr_mode : dr_mode --------------------------------- host host any : host host dev any : INVALID host otg any : host dev host any : INVALID dev dev any : dev dev otg any : dev otg host any : host otg dev any : dev otg otg any : dr_mode Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
1 parent 073c47a commit 9d6173e

File tree

2 files changed

+58
-12
lines changed

2 files changed

+58
-12
lines changed

drivers/usb/dwc3/core.c

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,57 @@
4949

5050
#define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */
5151

52+
/**
53+
* dwc3_get_dr_mode - Validates and sets dr_mode
54+
* @dwc: pointer to our context structure
55+
*/
56+
static int dwc3_get_dr_mode(struct dwc3 *dwc)
57+
{
58+
enum usb_dr_mode mode;
59+
struct device *dev = dwc->dev;
60+
unsigned int hw_mode;
61+
62+
if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
63+
dwc->dr_mode = USB_DR_MODE_OTG;
64+
65+
mode = dwc->dr_mode;
66+
hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
67+
68+
switch (hw_mode) {
69+
case DWC3_GHWPARAMS0_MODE_GADGET:
70+
if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) {
71+
dev_err(dev,
72+
"Controller does not support host mode.\n");
73+
return -EINVAL;
74+
}
75+
mode = USB_DR_MODE_PERIPHERAL;
76+
break;
77+
case DWC3_GHWPARAMS0_MODE_HOST:
78+
if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
79+
dev_err(dev,
80+
"Controller does not support device mode.\n");
81+
return -EINVAL;
82+
}
83+
mode = USB_DR_MODE_HOST;
84+
break;
85+
default:
86+
if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
87+
mode = USB_DR_MODE_HOST;
88+
else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
89+
mode = USB_DR_MODE_PERIPHERAL;
90+
}
91+
92+
if (mode != dwc->dr_mode) {
93+
dev_warn(dev,
94+
"Configuration mismatch. dr_mode forced to %s\n",
95+
mode == USB_DR_MODE_HOST ? "host" : "gadget");
96+
97+
dwc->dr_mode = mode;
98+
}
99+
100+
return 0;
101+
}
102+
52103
void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
53104
{
54105
u32 reg;
@@ -1023,17 +1074,9 @@ static int dwc3_probe(struct platform_device *pdev)
10231074
goto err2;
10241075
}
10251076

1026-
if (IS_ENABLED(CONFIG_USB_DWC3_HOST) &&
1027-
(dwc->dr_mode == USB_DR_MODE_OTG ||
1028-
dwc->dr_mode == USB_DR_MODE_UNKNOWN))
1029-
dwc->dr_mode = USB_DR_MODE_HOST;
1030-
else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET) &&
1031-
(dwc->dr_mode == USB_DR_MODE_OTG ||
1032-
dwc->dr_mode == USB_DR_MODE_UNKNOWN))
1033-
dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
1034-
1035-
if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
1036-
dwc->dr_mode = USB_DR_MODE_OTG;
1077+
ret = dwc3_get_dr_mode(dwc);
1078+
if (ret)
1079+
goto err3;
10371080

10381081
ret = dwc3_alloc_scratch_buffers(dwc);
10391082
if (ret)

drivers/usb/dwc3/core.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,10 @@
245245
#define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff)
246246

247247
/* Global HWPARAMS0 Register */
248-
#define DWC3_GHWPARAMS0_USB3_MODE(n) ((n) & 0x3)
248+
#define DWC3_GHWPARAMS0_MODE(n) ((n) & 0x3)
249+
#define DWC3_GHWPARAMS0_MODE_GADGET 0
250+
#define DWC3_GHWPARAMS0_MODE_HOST 1
251+
#define DWC3_GHWPARAMS0_MODE_DRD 2
249252
#define DWC3_GHWPARAMS0_MBUS_TYPE(n) (((n) >> 3) & 0x7)
250253
#define DWC3_GHWPARAMS0_SBUS_TYPE(n) (((n) >> 6) & 0x3)
251254
#define DWC3_GHWPARAMS0_MDWIDTH(n) (((n) >> 8) & 0xff)

0 commit comments

Comments
 (0)