106 lines
3.2 KiB
Diff
106 lines
3.2 KiB
Diff
From e00d73a6c2b3ec5f99f13e6d405dfb597d63e8a6 Mon Sep 17 00:00:00 2001
|
|
From: Saranya Gopal <saranya.gopal@intel.com>
|
|
Date: Fri, 5 Oct 2018 15:20:15 +0530
|
|
Subject: [PATCH 071/743] roles: Enable static DRD mode for role switch in
|
|
Intel platforms
|
|
|
|
Enable static DRD mode in Intel platforms which guarantees
|
|
successful role switch all the time. This fixes issues like
|
|
software role switch failure after cold boot and issue with
|
|
role switch when 3.0 OTG cable is used. But, do not enable
|
|
static DRD mode for Cherrytrail devices which rely on firmware
|
|
for role switch.
|
|
|
|
Signed-off-by: Saranya Gopal <saranya.gopal@intel.com>
|
|
Signed-off-by: M, Balaji <m.balaji@intel.com>
|
|
[ heikki: Minor cleanup ]
|
|
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
|
|
---
|
|
.../usb/roles/intel-xhci-usb-role-switch.c | 26 ++++++++++++++++++-
|
|
1 file changed, 25 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/usb/roles/intel-xhci-usb-role-switch.c b/drivers/usb/roles/intel-xhci-usb-role-switch.c
|
|
index 277de96181f9..f9ed262c15b3 100644
|
|
--- a/drivers/usb/roles/intel-xhci-usb-role-switch.c
|
|
+++ b/drivers/usb/roles/intel-xhci-usb-role-switch.c
|
|
@@ -19,6 +19,7 @@
|
|
#include <linux/module.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/pm_runtime.h>
|
|
+#include <linux/property.h>
|
|
#include <linux/usb/role.h>
|
|
|
|
/* register definition */
|
|
@@ -26,6 +27,9 @@
|
|
#define SW_VBUS_VALID BIT(24)
|
|
#define SW_IDPIN_EN BIT(21)
|
|
#define SW_IDPIN BIT(20)
|
|
+#define SW_SWITCH_EN_CFG0 BIT(16)
|
|
+#define SW_DRD_STATIC_HOST_CFG0 1
|
|
+#define SW_DRD_STATIC_DEV_CFG0 2
|
|
|
|
#define DUAL_ROLE_CFG1 0x6c
|
|
#define HOST_MODE BIT(29)
|
|
@@ -37,6 +41,7 @@
|
|
struct intel_xhci_usb_data {
|
|
struct usb_role_switch *role_sw;
|
|
void __iomem *base;
|
|
+ bool disable_sw_switch;
|
|
};
|
|
|
|
static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role)
|
|
@@ -59,23 +64,39 @@ static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role)
|
|
|
|
pm_runtime_get_sync(dev);
|
|
|
|
- /* Set idpin value as requested */
|
|
+ /*
|
|
+ * Set idpin value as requested.
|
|
+ * Since some devices rely on firmware setting DRD_CONFIG and
|
|
+ * SW_SWITCH_EN_CFG0 bits to be zero for role switch,
|
|
+ * do not set these bits for those devices.
|
|
+ */
|
|
val = readl(data->base + DUAL_ROLE_CFG0);
|
|
switch (role) {
|
|
case USB_ROLE_NONE:
|
|
val |= SW_IDPIN;
|
|
val &= ~SW_VBUS_VALID;
|
|
+ val &= ~(SW_DRD_STATIC_DEV_CFG0 | SW_DRD_STATIC_HOST_CFG0);
|
|
break;
|
|
case USB_ROLE_HOST:
|
|
val &= ~SW_IDPIN;
|
|
val &= ~SW_VBUS_VALID;
|
|
+ if (!data->disable_sw_switch) {
|
|
+ val &= ~SW_DRD_STATIC_DEV_CFG0;
|
|
+ val |= SW_DRD_STATIC_HOST_CFG0;
|
|
+ }
|
|
break;
|
|
case USB_ROLE_DEVICE:
|
|
val |= SW_IDPIN;
|
|
val |= SW_VBUS_VALID;
|
|
+ if (!data->disable_sw_switch) {
|
|
+ val &= ~SW_DRD_STATIC_HOST_CFG0;
|
|
+ val |= SW_DRD_STATIC_DEV_CFG0;
|
|
+ }
|
|
break;
|
|
}
|
|
val |= SW_IDPIN_EN;
|
|
+ if (!data->disable_sw_switch)
|
|
+ val |= SW_SWITCH_EN_CFG0;
|
|
|
|
writel(val, data->base + DUAL_ROLE_CFG0);
|
|
|
|
@@ -147,6 +168,9 @@ static int intel_xhci_usb_probe(struct platform_device *pdev)
|
|
|
|
platform_set_drvdata(pdev, data);
|
|
|
|
+ data->disable_sw_switch = device_property_read_bool(dev,
|
|
+ "drd,sw_switch_disable");
|
|
+
|
|
data->role_sw = usb_role_switch_register(dev, &sw_desc);
|
|
if (IS_ERR(data->role_sw))
|
|
return PTR_ERR(data->role_sw);
|
|
--
|
|
2.19.2
|
|
|