Skip to content

Commit

Permalink
usb: roles: intel_xhci: Enable runtime PM
Browse files Browse the repository at this point in the history
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 <sathyanarayanan.kuppuswamy@intel.com>
Fixes: f6fb9ec ("usb: roles: Add Intel xHCI USB role switch driver")
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Heikki Krogerus authored and gregkh committed May 24, 2018
1 parent c9359f4 commit cb29684
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion drivers/usb/roles/intel-xhci-usb-role-switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/usb/role.h>

/* register definition */
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit cb29684

Please sign in to comment.