usb: dwc3: Add support for role-switch-default-mode binding
authorJohn Stultz <john.stultz@linaro.org>
Tue, 25 Feb 2020 17:53:01 +0000 (17:53 +0000)
committerFelipe Balbi <balbi@kernel.org>
Sun, 15 Mar 2020 09:30:44 +0000 (11:30 +0200)
Support the new role-switch-default-mode binding for configuring
the default role the controller assumes as when the usb role is
USB_ROLE_NONE

This patch was split out from a larger patch originally by
Yu Chen <chenyu56@huawei.com>

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
CC: ShuFan Lee <shufan_lee@richtek.com>
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Chunfeng Yun <chunfeng.yun@mediatek.com>
Cc: Yu Chen <chenyu56@huawei.com>
Cc: Felipe Balbi <balbi@kernel.org>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: Jun Li <lijun.kernel@gmail.com>
Cc: Valentin Schneider <valentin.schneider@arm.com>
Cc: Guillaume Gardet <Guillaume.Gardet@arm.com>
Cc: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Cc: Jack Pham <jackp@codeaurora.org>
Cc: linux-usb@vger.kernel.org
Cc: devicetree@vger.kernel.org
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
drivers/usb/dwc3/core.h
drivers/usb/dwc3/drd.c

index 1e9513c..6846eb0 100644 (file)
@@ -956,6 +956,8 @@ struct dwc3_scratchpad_array {
  *             - USBPHY_INTERFACE_MODE_UTMI
  *             - USBPHY_INTERFACE_MODE_UTMIW
  * @role_sw: usb_role_switch handle
+ * @role_switch_default_mode: default operation mode of controller while
+ *                     usb role is USB_ROLE_NONE.
  * @usb2_phy: pointer to USB2 PHY
  * @usb3_phy: pointer to USB3 PHY
  * @usb2_generic_phy: pointer to USB2 PHY
@@ -1092,6 +1094,7 @@ struct dwc3 {
        struct notifier_block   edev_nb;
        enum usb_phy_interface  hsphy_mode;
        struct usb_role_switch  *role_sw;
+       enum usb_dr_mode        role_switch_default_mode;
 
        u32                     fladj;
        u32                     irq_gadget;
index 331c6e9..db68d48 100644 (file)
@@ -491,7 +491,10 @@ static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role)
                mode = DWC3_GCTL_PRTCAP_DEVICE;
                break;
        default:
-               mode = DWC3_GCTL_PRTCAP_DEVICE;
+               if (dwc->role_switch_default_mode == USB_DR_MODE_HOST)
+                       mode = DWC3_GCTL_PRTCAP_HOST;
+               else
+                       mode = DWC3_GCTL_PRTCAP_DEVICE;
                break;
        }
 
@@ -517,7 +520,10 @@ static enum usb_role dwc3_usb_role_switch_get(struct device *dev)
                role = dwc->current_otg_role;
                break;
        default:
-               role = USB_ROLE_DEVICE;
+               if (dwc->role_switch_default_mode == USB_DR_MODE_HOST)
+                       role = USB_ROLE_HOST;
+               else
+                       role = USB_ROLE_DEVICE;
                break;
        }
        spin_unlock_irqrestore(&dwc->lock, flags);
@@ -527,6 +533,19 @@ static enum usb_role dwc3_usb_role_switch_get(struct device *dev)
 static int dwc3_setup_role_switch(struct dwc3 *dwc)
 {
        struct usb_role_switch_desc dwc3_role_switch = {NULL};
+       const char *str;
+       u32 mode;
+       int ret;
+
+       ret = device_property_read_string(dwc->dev, "role-switch-default-mode",
+                                         &str);
+       if (ret >= 0  && !strncmp(str, "host", strlen("host"))) {
+               dwc->role_switch_default_mode = USB_DR_MODE_HOST;
+               mode = DWC3_GCTL_PRTCAP_HOST;
+       } else {
+               dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL;
+               mode = DWC3_GCTL_PRTCAP_DEVICE;
+       }
 
        dwc3_role_switch.fwnode = dev_fwnode(dwc->dev);
        dwc3_role_switch.set = dwc3_usb_role_switch_set;
@@ -535,7 +554,7 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)
        if (IS_ERR(dwc->role_sw))
                return PTR_ERR(dwc->role_sw);
 
-       dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+       dwc3_set_mode(dwc, mode);
        return 0;
 }
 #else