diff options
-rw-r--r-- | drivers/usb/dwc3/core.c | 65 | ||||
-rw-r--r-- | drivers/usb/dwc3/core.h | 5 |
2 files changed, 58 insertions, 12 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index d6d3fa0fa528..dcacc7056271 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -49,6 +49,57 @@ #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */ +/** + * dwc3_get_dr_mode - Validates and sets dr_mode + * @dwc: pointer to our context structure + */ +static int dwc3_get_dr_mode(struct dwc3 *dwc) +{ + enum usb_dr_mode mode; + struct device *dev = dwc->dev; + unsigned int hw_mode; + + if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) + dwc->dr_mode = USB_DR_MODE_OTG; + + mode = dwc->dr_mode; + hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); + + switch (hw_mode) { + case DWC3_GHWPARAMS0_MODE_GADGET: + if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) { + dev_err(dev, + "Controller does not support host mode.\n"); + return -EINVAL; + } + mode = USB_DR_MODE_PERIPHERAL; + break; + case DWC3_GHWPARAMS0_MODE_HOST: + if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { + dev_err(dev, + "Controller does not support device mode.\n"); + return -EINVAL; + } + mode = USB_DR_MODE_HOST; + break; + default: + if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) + mode = USB_DR_MODE_HOST; + else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) + mode = USB_DR_MODE_PERIPHERAL; + } + + if (mode != dwc->dr_mode) { + dev_warn(dev, + "Configuration mismatch. dr_mode forced to %s\n", + mode == USB_DR_MODE_HOST ? "host" : "gadget"); + + dwc->dr_mode = mode; + } + + return 0; +} + void dwc3_set_mode(struct dwc3 *dwc, u32 mode) { u32 reg; @@ -1023,17 +1074,9 @@ static int dwc3_probe(struct platform_device *pdev) goto err2; } - if (IS_ENABLED(CONFIG_USB_DWC3_HOST) && - (dwc->dr_mode == USB_DR_MODE_OTG || - dwc->dr_mode == USB_DR_MODE_UNKNOWN)) - dwc->dr_mode = USB_DR_MODE_HOST; - else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET) && - (dwc->dr_mode == USB_DR_MODE_OTG || - dwc->dr_mode == USB_DR_MODE_UNKNOWN)) - dwc->dr_mode = USB_DR_MODE_PERIPHERAL; - - if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) - dwc->dr_mode = USB_DR_MODE_OTG; + ret = dwc3_get_dr_mode(dwc); + if (ret) + goto err3; ret = dwc3_alloc_scratch_buffers(dwc); if (ret) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index b2317e702f57..6b60e42626a2 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -245,7 +245,10 @@ #define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff) /* Global HWPARAMS0 Register */ -#define DWC3_GHWPARAMS0_USB3_MODE(n) ((n) & 0x3) +#define DWC3_GHWPARAMS0_MODE(n) ((n) & 0x3) +#define DWC3_GHWPARAMS0_MODE_GADGET 0 +#define DWC3_GHWPARAMS0_MODE_HOST 1 +#define DWC3_GHWPARAMS0_MODE_DRD 2 #define DWC3_GHWPARAMS0_MBUS_TYPE(n) (((n) >> 3) & 0x7) #define DWC3_GHWPARAMS0_SBUS_TYPE(n) (((n) >> 6) & 0x3) #define DWC3_GHWPARAMS0_MDWIDTH(n) (((n) >> 8) & 0xff) |