Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6ff6cbf authored by Guoqing Zhang's avatar Guoqing Zhang Committed by Greg Kroah-Hartman
Browse files

usb: xhci: Add helper function xhci_set_power_on().



Refactoring port power on/off related code into
a helper function xhci_set_power_on() which can
be reused when enabling test mode.

[set port state to neutral before writing port power -Mathias]
Signed-off-by: default avatarGuoqing Zhang <guoqing.zhang@intel.com>
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d1001ab4
Loading
Loading
Loading
Loading
+45 −21
Original line number Diff line number Diff line
@@ -540,6 +540,49 @@ static int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array)
	return max_ports;
}

static __le32 __iomem *xhci_get_port_io_addr(struct usb_hcd *hcd, int index)
{
	__le32 __iomem **port_array;

	xhci_get_ports(hcd, &port_array);
	return port_array[index];
}

/*
 * xhci_set_port_power() must be called with xhci->lock held.
 * It will release and re-aquire the lock while calling ACPI
 * method.
 */
static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
				u16 index, bool on)
{
	__le32 __iomem *addr;
	u32 temp;
	unsigned long flags = 0;

	addr = xhci_get_port_io_addr(hcd, index);
	temp = readl(addr);
	temp = xhci_port_state_to_neutral(temp);
	if (on) {
		/* Power on */
		writel(temp | PORT_POWER, addr);
		temp = readl(addr);
		xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n",
						index, temp);
	} else {
		/* Power off */
		writel(temp & ~PORT_POWER, addr);
	}

	spin_unlock_irqrestore(&xhci->lock, flags);
	temp = usb_acpi_power_manageable(hcd->self.root_hub,
					index);
	if (temp)
		usb_acpi_set_power_state(hcd->self.root_hub,
			index, on);
	spin_lock_irqsave(&xhci->lock, flags);
}

void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
				int port_id, u32 link_state)
{
@@ -1092,18 +1135,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			 * However, hub_wq will ignore the roothub events until
			 * the roothub is registered.
			 */
			writel(temp | PORT_POWER, port_array[wIndex]);

			temp = readl(port_array[wIndex]);
			xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", wIndex, temp);

			spin_unlock_irqrestore(&xhci->lock, flags);
			temp = usb_acpi_power_manageable(hcd->self.root_hub,
					wIndex);
			if (temp)
				usb_acpi_set_power_state(hcd->self.root_hub,
						wIndex, true);
			spin_lock_irqsave(&xhci->lock, flags);
			xhci_set_port_power(xhci, hcd, wIndex, true);
			break;
		case USB_PORT_FEAT_RESET:
			temp = (temp | PORT_RESET);
@@ -1207,15 +1239,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
					port_array[wIndex], temp);
			break;
		case USB_PORT_FEAT_POWER:
			writel(temp & ~PORT_POWER, port_array[wIndex]);

			spin_unlock_irqrestore(&xhci->lock, flags);
			temp = usb_acpi_power_manageable(hcd->self.root_hub,
					wIndex);
			if (temp)
				usb_acpi_set_power_state(hcd->self.root_hub,
						wIndex, false);
			spin_lock_irqsave(&xhci->lock, flags);
			xhci_set_port_power(xhci, hcd, wIndex, false);
			break;
		default:
			goto error;