EHCI&HSIC support
authoryangkai <yk@rock-chips.com>
Thu, 21 Feb 2013 07:01:21 +0000 (15:01 +0800)
committeryangkai <yk@rock-chips.com>
Thu, 21 Feb 2013 07:01:21 +0000 (15:01 +0800)
arch/arm/mach-rk30/Kconfig
drivers/usb/dwc_otg/usbdev_rk30.c
drivers/usb/host/Kconfig [changed mode: 0644->0755]
drivers/usb/host/ehci-hcd.c [changed mode: 0644->0755]
drivers/usb/host/ehci-rk.c [new file with mode: 0755]

index dc7b6ec59ebfbc252b694b0d867d27c0fbbc8df4..377883062c1624402e78cb3b091003d30ec544d9 100755 (executable)
@@ -25,14 +25,17 @@ config SOC_RK3068
 config SOC_RK3066B
        bool "RK3066B"
        select ARCH_RK3066B
+       select USB_ARCH_HAS_EHCI
 
 config SOC_RK3108
        bool "RK3108"
        select ARCH_RK3066B
+       select USB_ARCH_HAS_EHCI
 
 config SOC_RK3168
        bool "RK3168"
        select ARCH_RK3066B
+       select USB_ARCH_HAS_EHCI
 
 endchoice
 
index 85d6f54de1f299b973f68e27aff562bc0de95d74..67dc21e46aa2b31103e91ab3b33af36a49867713 100755 (executable)
@@ -357,12 +357,12 @@ void usb20host_soft_reset(void)
     cru_set_soft_reset(SOFT_RST_USBOTG1, true);\r
     cru_set_soft_reset(SOFT_RST_USBPHY1, true);\r
     cru_set_soft_reset(SOFT_RST_OTGC1, true);\r
-    udelay(1);\r
+    udelay(5);\r
 \r
     cru_set_soft_reset(SOFT_RST_USBOTG1, false);\r
     cru_set_soft_reset(SOFT_RST_USBPHY1, false);\r
     cru_set_soft_reset(SOFT_RST_OTGC1, false);\r
-    mdelay(1);\r
+    mdelay(2);\r
 }\r
 void usb20host_clock_init(void* pdata)\r
 {\r
@@ -473,8 +473,34 @@ struct platform_device device_usb20_host = {
        },\r
 };\r
 #endif\r
+static struct resource resources_hsusb_host[] = {\r
+    {\r
+        .start = IRQ_HSIC,\r
+        .end   = IRQ_HSIC,\r
+        .flags = IORESOURCE_IRQ,\r
+    },\r
+    {\r
+        .start = RK30_HSIC_PHYS,\r
+        .end   = RK30_HSIC_PHYS + RK30_HSIC_SIZE - 1,\r
+        .flags = IORESOURCE_MEM,\r
+    },\r
+};\r
+\r
+struct platform_device device_hsusb_host = {\r
+    .name           = "rk_hsusb_host",\r
+    .id             = -1,\r
+    .num_resources  = ARRAY_SIZE(resources_hsusb_host),\r
+    .resource       = resources_hsusb_host,\r
+    .dev            = {\r
+        .coherent_dma_mask      = 0xffffffff,\r
+    },\r
+};\r
+\r
 static int __init usbdev_init_devices(void)\r
 {\r
+#ifdef CONFIG_USB_EHCI_RK\r
+       platform_device_register(&device_hsusb_host);\r
+#endif\r
 #ifdef CONFIG_USB20_OTG\r
        platform_device_register(&device_usb20_otg);\r
 #endif\r
old mode 100644 (file)
new mode 100755 (executable)
index ab085f1..0ba9e7b
@@ -91,6 +91,14 @@ config USB_EHCI_TT_NEWSCHED
 
          If unsure, say Y.
 
+config USB_EHCI_RK
+       bool "Rockchip EHCI HSIC support"
+       depends on USB_EHCI_HCD 
+       select USB_EHCI_ROOT_HUB_TT
+       default y
+       ---help---
+               Enables support for the onchip USB controller on the RK3108.
+
 config USB_EHCI_HCD_PMC_MSP
        tristate "EHCI support for on-chip PMC MSP71xx USB controller"
        depends on USB_EHCI_HCD && MSP_HAS_USB
old mode 100644 (file)
new mode 100755 (executable)
index f89f77f..1990062
@@ -1292,6 +1292,11 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_msm_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_RK
+#include "ehci-rk.c"
+#define PLATFORM_DRIVER                ehci_rk_driver
+#endif
+
 #ifdef CONFIG_USB_EHCI_HCD_PMC_MSP
 #include "ehci-pmcmsp.c"
 #define        PLATFORM_DRIVER         ehci_hcd_msp_driver
diff --git a/drivers/usb/host/ehci-rk.c b/drivers/usb/host/ehci-rk.c
new file mode 100755 (executable)
index 0000000..e5e8b7e
--- /dev/null
@@ -0,0 +1,224 @@
+/* ehci-msm.c - HSUSB Host Controller Driver Implementation\r
+ *\r
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.\r
+ *\r
+ * Partly derived from ehci-fsl.c and ehci-hcd.c\r
+ * Copyright (c) 2000-2004 by David Brownell\r
+ * Copyright (c) 2005 MontaVista Software\r
+ *\r
+ * All source code in this file is licensed under the following license except\r
+ * where indicated.\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 as published\r
+ * by the Free Software Foundation.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ * See the GNU General Public License for more details.\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, you can find it at http://www.fsf.org\r
+ */\r
+\r
+#include <linux/platform_device.h>\r
+#include <linux/clk.h>\r
+#include <linux/err.h>\r
+#include <linux/device.h>\r
+\r
+#include "ehci.h"\r
+\r
+\r
+static struct hc_driver rk_hc_driver = {\r
+       .description            = hcd_name,\r
+       .product_desc           = "Rockchip On-Chip EHCI Host Controller",\r
+       .hcd_priv_size          = sizeof(struct ehci_hcd),\r
+\r
+       /*\r
+        * generic hardware linkage\r
+        */\r
+       .irq                    = ehci_irq,\r
+       .flags                  = HCD_USB2 | HCD_MEMORY,\r
+\r
+       .reset                  = ehci_init,\r
+       .start                  = ehci_run,\r
+\r
+       .stop                   = ehci_stop,\r
+       .shutdown               = ehci_shutdown,\r
+\r
+       /*\r
+        * managing i/o requests and associated device resources\r
+        */\r
+       .urb_enqueue            = ehci_urb_enqueue,\r
+       .urb_dequeue            = ehci_urb_dequeue,\r
+       .endpoint_disable       = ehci_endpoint_disable,\r
+       .endpoint_reset         = ehci_endpoint_reset,\r
+       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,\r
+\r
+       /*\r
+        * scheduling support\r
+        */\r
+       .get_frame_number       = ehci_get_frame,\r
+\r
+       /*\r
+        * root hub support\r
+        */\r
+       .hub_status_data        = ehci_hub_status_data,\r
+       .hub_control            = ehci_hub_control,\r
+       .relinquish_port        = ehci_relinquish_port,\r
+       .port_handed_over       = ehci_port_handed_over,\r
+\r
+       /*\r
+        * PM support\r
+        */\r
+       .bus_suspend            = ehci_bus_suspend,\r
+       .bus_resume             = ehci_bus_resume,\r
+};\r
+\r
+static int ehci_rk_probe(struct platform_device *pdev)\r
+{\r
+       struct usb_hcd *hcd;\r
+       struct ehci_hcd *ehci;\r
+       struct resource *res;\r
+       struct clk *clk1;\r
+       struct clk *clk2;\r
+       struct clk *clk3;\r
+       struct device *dev = &pdev->dev;\r
+       int ret;\r
+       static u64 usb_dmamask = 0xffffffffUL;\r
+\r
+       dev_dbg(&pdev->dev, "ehci_rk proble\n");\r
+       \r
+       dev->dma_mask = &usb_dmamask;\r
+\r
+       hcd = usb_create_hcd(&rk_hc_driver, &pdev->dev, dev_name(&pdev->dev));\r
+       if (!hcd) {\r
+               dev_err(&pdev->dev, "Unable to create HCD\n");\r
+               return  -ENOMEM;\r
+       }\r
+    clk1 = clk_get(NULL, "hclk_hsic");\r
+    clk2 = clk_get(NULL, "hsicphy_480m");\r
+    clk3 = clk_get(NULL, "hsicphy_12m");\r
+    clk_enable(clk1);\r
+    clk_enable(clk2);\r
+    clk_enable(clk3);\r
+\r
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+       if (!res) {\r
+               dev_err(&pdev->dev, "Unable to get memory resource\n");\r
+               ret = -ENODEV;\r
+               goto put_hcd;\r
+       }\r
+       hcd->rsrc_start = res->start;\r
+       hcd->rsrc_len = resource_size(res);\r
+       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);\r
+       if (!hcd->regs) {\r
+               dev_err(&pdev->dev, "ioremap failed\n");\r
+               ret = -ENOMEM;\r
+               goto put_hcd;\r
+       }\r
+       \r
+       hcd->irq = platform_get_irq(pdev, 0);\r
+       if (hcd->irq < 0) {\r
+               dev_err(&pdev->dev, "Unable to get IRQ resource\n");\r
+               ret = hcd->irq;\r
+               goto put_hcd;\r
+       }\r
+       \r
+    ehci = hcd_to_ehci(hcd);\r
+    ehci->caps = hcd->regs;\r
+    ehci->regs = hcd->regs + 0x10;\r
+    printk("%s %p %p\n", __func__, ehci->caps, ehci->regs);\r
+    \r
+    dbg_hcs_params(ehci, "reset");\r
+    dbg_hcc_params(ehci, "reset");\r
+\r
+    ehci->hcs_params = readl(&ehci->caps->hcs_params);\r
+\r
+       ret = usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED);\r
+    if (ret) {\r
+        dev_err(&pdev->dev, "Failed to add USB HCD\n");\r
+          goto unmap;\r
+    }\r
+\r
+       ehci_port_power(ehci, 1);\r
+       writel_relaxed(1 ,hcd->regs +0xb0);\r
+       writel_relaxed(0x1d4d ,hcd->regs +0x90);\r
+       writel_relaxed(0x4 ,hcd->regs +0xa0);\r
+       dsb();\r
+\r
+\r
+       printk("%s ok\n", __func__);\r
+\r
+       return 0;\r
+\r
+unmap:\r
+       iounmap(hcd->regs);\r
+put_hcd:\r
+       usb_put_hcd(hcd);\r
+\r
+       return ret;\r
+}\r
+\r
+static int __devexit ehci_rk_remove(struct platform_device *pdev)\r
+{\r
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);\r
+\r
+       usb_put_hcd(hcd);\r
+\r
+       return 0;\r
+}\r
+\r
+#ifdef CONFIG_PM\r
+static int ehci_rk_pm_suspend(struct device *dev)\r
+{\r
+       struct usb_hcd *hcd = dev_get_drvdata(dev);\r
+       bool wakeup = device_may_wakeup(dev);\r
+\r
+       dev_dbg(dev, "ehci-rk PM suspend\n");\r
+\r
+       /*\r
+        * EHCI helper function has also the same check before manipulating\r
+        * port wakeup flags.  We do check here the same condition before\r
+        * calling the same helper function to avoid bringing hardware\r
+        * from Low power mode when there is no need for adjusting port\r
+        * wakeup flags.\r
+        */\r
+       if (hcd->self.root_hub->do_remote_wakeup && !wakeup) {\r
+               pm_runtime_resume(dev);\r
+               ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),\r
+                               wakeup);\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static int ehci_rk_pm_resume(struct device *dev)\r
+{\r
+       struct usb_hcd *hcd = dev_get_drvdata(dev);\r
+\r
+       dev_dbg(dev, "ehci-rk PM resume\n");\r
+       ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));\r
+\r
+       return 0;\r
+}\r
+#else\r
+#define ehci_rk_pm_suspend     NULL\r
+#define ehci_rk_pm_resume      NULL\r
+#endif\r
+\r
+static const struct dev_pm_ops ehci_rk_dev_pm_ops = {\r
+       .suspend         = ehci_rk_pm_suspend,\r
+       .resume          = ehci_rk_pm_resume,\r
+};\r
+\r
+static struct platform_driver ehci_rk_driver = {\r
+       .probe  = ehci_rk_probe,\r
+       .remove = __devexit_p(ehci_rk_remove),\r
+       .driver = {\r
+                  .name = "rk_hsusb_host",\r
+                  .pm = &ehci_rk_dev_pm_ops,\r
+       },\r
+};\r
+\r