Signed-off-by: Matthieu CASTET <matthieu.castet@xxxxxxxxxx> --- drivers/usb/host/ehci-hcd.c | 4 +- drivers/usb/host/ehci-hub.c | 104 ++++++++++++++++++++----------------------- drivers/usb/host/ehci.h | 6 ++- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 2149583..00425af 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -722,8 +722,10 @@ static int ehci_init(struct usb_hcd *hcd) hird = 0; } temp |= hird << 24; - if (ehci_is_TDI(ehci)) + if (ehci_is_TDI(ehci)) { ehci->has_hostpc = 1; + ehci->has_tdi_phy_lpm = 1; + } } ehci->command = temp; diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 38fe076..b70fca6 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -31,6 +31,37 @@ #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) +static void tdi_phy_lpm_clear(struct ehci_hcd *ehci, int port) +{ + if (ehci->has_hostpc) { + u32 __iomem *hostpc_reg; + u32 temp; + + hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs + + HOSTPC0 + 4 * port); + temp = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); + } +} + +static void tdi_phy_lpm_set(struct ehci_hcd *ehci, int port) +{ + if (ehci->has_hostpc) { + u32 __iomem *hostpc_reg; + u32 t3; + + hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs + + HOSTPC0 + 4 * port); + t3 = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); + t3 = ehci_readl(ehci, hostpc_reg); + ehci_dbg(ehci, "Port %d phy low-power mode %s\n", + port, (t3 & HOSTPC_PHCD) ? + "succeeded" : "failed"); + } +} + + #ifdef CONFIG_PM static int ehci_hub_control( @@ -146,15 +177,10 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, spin_lock_irqsave(&ehci->lock, flags); /* clear phy low-power mode before changing wakeup flags */ - if (ehci->has_hostpc) { + if (ehci->has_tdi_phy_lpm) { port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *hostpc_reg; - - hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs - + HOSTPC0 + 4 * port); - temp = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); + while (port--) + tdi_phy_lpm_clear(ehci, port); } spin_unlock_irqrestore(&ehci->lock, flags); msleep(5); @@ -182,16 +208,10 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, } /* enter phy low-power mode again */ - if (ehci->has_hostpc) { + if (ehci->has_tdi_phy_lpm) { port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *hostpc_reg; - - hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs - + HOSTPC0 + 4 * port); - temp = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); - } + while (port--) + tdi_phy_lpm_set(ehci, port); } /* Does the root hub have a port wakeup pending? */ @@ -279,25 +299,14 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) } } - if (changed && ehci->has_hostpc) { + if (changed && ehci->has_tdi_phy_lpm) { spin_unlock_irq(&ehci->lock); msleep(5); /* 5 ms for HCD to enter low-power mode */ spin_lock_irq(&ehci->lock); port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *hostpc_reg; - u32 t3; - - hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs - + HOSTPC0 + 4 * port); - t3 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); - t3 = ehci_readl(ehci, hostpc_reg); - ehci_dbg(ehci, "Port %d phy low-power mode %s\n", - port, (t3 & HOSTPC_PHCD) ? - "succeeded" : "failed"); - } + while (port--) + tdi_phy_lpm_set(ehci, port); } /* Apparently some devices need a >= 1-uframe delay here */ @@ -384,17 +393,11 @@ static int ehci_bus_resume (struct usb_hcd *hcd) spin_lock_irq(&ehci->lock); /* clear phy low-power mode before resume */ - if (ehci->bus_suspended && ehci->has_hostpc) { + if (ehci->bus_suspended && ehci->has_tdi_phy_lpm) { i = HCS_N_PORTS(ehci->hcs_params); while (i--) { if (test_bit(i, &ehci->bus_suspended)) { - u32 __iomem *hostpc_reg; - - hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs - + HOSTPC0 + 4 * i); - temp = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp & ~HOSTPC_PHCD, - hostpc_reg); + tdi_phy_lpm_clear(ehci, i); } } spin_unlock_irq(&ehci->lock); @@ -666,7 +669,7 @@ static int ehci_hub_control ( int ports = HCS_N_PORTS (ehci->hcs_params); u32 __iomem *status_reg = &ehci->regs->port_status[ (wIndex & 0xff) - 1]; - u32 __iomem *hostpc_reg = NULL; + u32 __iomem *hostpc_reg; u32 temp, temp1, status; unsigned long flags; int retval = 0; @@ -679,9 +682,6 @@ static int ehci_hub_control ( * power, "this is the one", etc. EHCI spec supports this. */ - if (ehci->has_hostpc) - hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs - + HOSTPC0 + 4 * ((wIndex & 0xff) - 1)); spin_lock_irqsave (&ehci->lock, flags); switch (typeReq) { case ClearHubFeature: @@ -733,10 +733,8 @@ static int ehci_hub_control ( goto error; /* clear phy low-power mode before resume */ - if (hostpc_reg) { - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, - hostpc_reg); + if (ehci->has_tdi_phy_lpm) { + tdi_phy_lpm_clear(ehci, wIndex); spin_unlock_irqrestore(&ehci->lock, flags); msleep(5);/* wait to leave low-power mode */ spin_lock_irqsave(&ehci->lock, flags); @@ -907,6 +905,8 @@ static int ehci_hub_control ( status |= USB_PORT_STAT_CONNECTION; // status may be from integrated TT if (ehci->has_hostpc) { + hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs + + HOSTPC0 + 4 * wIndex); temp1 = ehci_readl(ehci, hostpc_reg); status |= ehci_port_speed(ehci, temp1); } else @@ -986,17 +986,11 @@ static int ehci_hub_control ( temp &= ~PORT_WKCONN_E; temp |= PORT_WKDISC_E | PORT_WKOC_E; ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); - if (hostpc_reg) { + if (ehci->has_tdi_phy_lpm) { spin_unlock_irqrestore(&ehci->lock, flags); msleep(5);/* 5ms for HCD enter low pwr mode */ spin_lock_irqsave(&ehci->lock, flags); - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp1 | HOSTPC_PHCD, - hostpc_reg); - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", - wIndex, (temp1 & HOSTPC_PHCD) ? - "succeeded" : "failed"); + tdi_phy_lpm_set(ehci, wIndex); } set_bit(wIndex, &ehci->suspended_ports); break; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 2694ed6..a9e288a 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -158,9 +158,13 @@ struct ehci_hcd { /* one per controller */ #define OHCI_HCCTRL_OFFSET 0x4 #define OHCI_HCCTRL_LEN 0x4 __hc32 *ohci_hcctrl_reg; - unsigned has_hostpc:1; + /* ehci extension */ unsigned has_lpm:1; /* support link power management */ unsigned has_ppcd:1; /* support per-port change bits */ + /* extension for TDI/chipidea core */ + unsigned has_tdi_phy_lpm:1; /* support PHY low power suspend */ + unsigned has_hostpc:1; /* have hostpc register */ + u8 sbrn; /* packed release number */ /* irq statistics */ -- 1.7.10 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html