From cb296846860531defe93ebf75221e280970907f0 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Thu, 24 May 2018 11:18:27 +0300 Subject: usb: roles: intel_xhci: Enable runtime PM This fixes an issue where the mux does not get configured when the parent device is suspended. The registers for this mux are mapped to the parent device MMIO (usually xHCI PCI device), so in order for the driver to be able to program the registers, the parent device must be resumed. Reported-by: Sathyanarayanan Kuppuswamy Fixes: f6fb9ec02be1 ("usb: roles: Add Intel xHCI USB role switch driver") Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/usb/roles/intel-xhci-usb-role-switch.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/usb/roles') diff --git a/drivers/usb/roles/intel-xhci-usb-role-switch.c b/drivers/usb/roles/intel-xhci-usb-role-switch.c index 6e922b50b674..1fb3dd0f1dfa 100644 --- a/drivers/usb/roles/intel-xhci-usb-role-switch.c +++ b/drivers/usb/roles/intel-xhci-usb-role-switch.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* register definition */ @@ -56,6 +57,8 @@ static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) return -EIO; } + pm_runtime_get_sync(dev); + /* Set idpin value as requested */ val = readl(data->base + DUAL_ROLE_CFG0); switch (role) { @@ -84,13 +87,17 @@ static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) /* Polling on CFG1 register to confirm mode switch.*/ do { val = readl(data->base + DUAL_ROLE_CFG1); - if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) + if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) { + pm_runtime_put(dev); return 0; + } /* Interval for polling is set to about 5 - 10 ms */ usleep_range(5000, 10000); } while (time_before(jiffies, timeout)); + pm_runtime_put(dev); + dev_warn(dev, "Timeout waiting for role-switch\n"); return -ETIMEDOUT; } @@ -101,7 +108,9 @@ static enum usb_role intel_xhci_usb_get_role(struct device *dev) enum usb_role role; u32 val; + pm_runtime_get_sync(dev); val = readl(data->base + DUAL_ROLE_CFG0); + pm_runtime_put(dev); if (!(val & SW_IDPIN)) role = USB_ROLE_HOST; @@ -142,6 +151,9 @@ static int intel_xhci_usb_probe(struct platform_device *pdev) if (IS_ERR(data->role_sw)) return PTR_ERR(data->role_sw); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + return 0; } -- cgit v1.2.3