From 2eb3227bff035220172687564633b09abf1f3a6e Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Wed, 29 Mar 2017 18:26:34 +0800 Subject: [PATCH] usb: ehci: add rockchip relinquishing port quirk support Add a quirk to support rockchip relinquishing port from abnormal ohci to ehci when FS/LS devices plug in. To support this function, the rockchip-relinquish-port property must be specified in ehci node of dt. Change-Id: I91b58905132282ef2a836d54a1c7ace1e334d119 Signed-off-by: William Wu Signed-off-by: Frank Wang --- drivers/usb/core/hub.c | 3 ++- drivers/usb/host/ehci-platform.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 17202b2ee063..2df38b487858 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5272,7 +5272,8 @@ loop: done: hub_port_disable(hub, port1, 1); if (hcd->driver->relinquish_port && !hub->hdev->parent) { - if (status != -ENOTCONN && status != -ENODEV) + if ((status != -ENOTCONN && status != -ENODEV) || + (status == -ENOTCONN && of_machine_is_compatible("rockchip,rk3288"))) hcd->driver->relinquish_port(hcd, port1); } } diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index a48dd3fac153..f363d5509883 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -56,6 +56,18 @@ struct ehci_platform_priv { static const char hcd_name[] = "ehci-platform"; +static void ehci_rockchip_relinquish_port(struct usb_hcd *hcd, int portnum) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + u32 __iomem *status_reg = &ehci->regs->port_status[--portnum]; + u32 portsc; + + portsc = ehci_readl(ehci, status_reg); + portsc &= ~(PORT_OWNER | PORT_RWC_BITS); + + ehci_writel(ehci, portsc, status_reg); +} + static int ehci_platform_reset(struct usb_hcd *hcd) { struct platform_device *pdev = to_platform_device(hcd->self.controller); @@ -297,6 +309,12 @@ static int ehci_platform_probe(struct platform_device *dev) if (soc_device_match(quirk_poll_match)) priv->quirk_poll = true; + if (of_machine_is_compatible("rockchip,rk3288") && + of_property_read_bool(dev->dev.of_node, + "rockchip-relinquish-port")) + ehci_platform_hc_driver.relinquish_port = + ehci_rockchip_relinquish_port; + for (clk = 0; clk < EHCI_MAX_CLKS; clk++) { priv->clks[clk] = of_clk_get(dev->dev.of_node, clk); if (IS_ERR(priv->clks[clk])) {