Merge tag 'backport/v3.14.24-ltsi-rc1/phy-rcar-gen2-usb-to-v3.15' into backport/v3...
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / usb / host / ehci-tegra.c
index a8f4471..7cc7357 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk/tegra.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
@@ -29,6 +28,7 @@
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/usb/ehci_def.h>
 #include <linux/usb/tegra_usb_phy.h>
@@ -62,6 +62,7 @@ static int (*orig_hub_control)(struct usb_hcd *hcd,
 struct tegra_ehci_hcd {
        struct tegra_usb_phy *phy;
        struct clk *clk;
+       struct reset_control *rst;
        int port_resuming;
        bool needs_double_reset;
        enum tegra_usb_phy_port_speed port_speed;
@@ -157,7 +158,7 @@ static int tegra_ehci_hub_control(
                if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
                        /* Resume completed, re-enable disconnect detection */
                        tegra->port_resuming = 0;
-                       tegra_usb_phy_postresume(hcd->phy);
+                       tegra_usb_phy_postresume(hcd->usb_phy);
                }
        }
 
@@ -210,7 +211,7 @@ static int tegra_ehci_hub_control(
                        goto done;
 
                /* Disable disconnect detection during port resume */
-               tegra_usb_phy_preresume(hcd->phy);
+               tegra_usb_phy_preresume(hcd->usb_phy);
 
                ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
 
@@ -385,20 +386,27 @@ static int tegra_ehci_probe(struct platform_device *pdev)
                goto cleanup_hcd_create;
        }
 
+       tegra->rst = devm_reset_control_get(&pdev->dev, "usb");
+       if (IS_ERR(tegra->rst)) {
+               dev_err(&pdev->dev, "Can't get ehci reset\n");
+               err = PTR_ERR(tegra->rst);
+               goto cleanup_hcd_create;
+       }
+
        err = clk_prepare_enable(tegra->clk);
        if (err)
                goto cleanup_hcd_create;
 
-       tegra_periph_reset_assert(tegra->clk);
+       reset_control_assert(tegra->rst);
        udelay(1);
-       tegra_periph_reset_deassert(tegra->clk);
+       reset_control_deassert(tegra->rst);
 
        u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
        if (IS_ERR(u_phy)) {
                err = PTR_ERR(u_phy);
                goto cleanup_clk_en;
        }
-       hcd->phy = u_phy;
+       hcd->usb_phy = u_phy;
 
        tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
                "nvidia,needs-double-reset");
@@ -420,7 +428,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
        ehci->caps = hcd->regs + 0x100;
        ehci->has_hostpc = soc_config->has_hostpc;
 
-       err = usb_phy_init(hcd->phy);
+       err = usb_phy_init(hcd->usb_phy);
        if (err) {
                dev_err(&pdev->dev, "Failed to initialize phy\n");
                goto cleanup_clk_en;
@@ -435,7 +443,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
        }
        u_phy->otg->host = hcd_to_bus(hcd);
 
-       err = usb_phy_set_suspend(hcd->phy, 0);
+       err = usb_phy_set_suspend(hcd->usb_phy, 0);
        if (err) {
                dev_err(&pdev->dev, "Failed to power on the phy\n");
                goto cleanup_phy;
@@ -462,7 +470,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 cleanup_otg_set_host:
        otg_set_host(u_phy->otg, NULL);
 cleanup_phy:
-       usb_phy_shutdown(hcd->phy);
+       usb_phy_shutdown(hcd->usb_phy);
 cleanup_clk_en:
        clk_disable_unprepare(tegra->clk);
 cleanup_hcd_create:
@@ -476,9 +484,9 @@ static int tegra_ehci_remove(struct platform_device *pdev)
        struct tegra_ehci_hcd *tegra =
                (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
 
-       otg_set_host(hcd->phy->otg, NULL);
+       otg_set_host(hcd->usb_phy->otg, NULL);
 
-       usb_phy_shutdown(hcd->phy);
+       usb_phy_shutdown(hcd->usb_phy);
        usb_remove_hcd(hcd);
        usb_put_hcd(hcd);
 
@@ -505,8 +513,31 @@ static struct platform_driver tegra_ehci_driver = {
        }
 };
 
+static int tegra_ehci_reset(struct usb_hcd *hcd)
+{
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+       int retval;
+       int txfifothresh;
+
+       retval = ehci_setup(hcd);
+       if (retval)
+               return retval;
+
+       /*
+        * We should really pull this value out of tegra_ehci_soc_config, but
+        * to avoid needing access to it, make use of the fact that Tegra20 is
+        * the only one so far that needs a value of 10, and Tegra20 is the
+        * only one which doesn't set has_hostpc.
+        */
+       txfifothresh = ehci->has_hostpc ? 0x10 : 10;
+       ehci_writel(ehci, txfifothresh << 16, &ehci->regs->txfill_tuning);
+
+       return 0;
+}
+
 static const struct ehci_driver_overrides tegra_overrides __initconst = {
        .extra_priv_size        = sizeof(struct tegra_ehci_hcd),
+       .reset                  = tegra_ehci_reset,
 };
 
 static int __init ehci_tegra_init(void)