#define USBGRF_UOC0_CON0 (GRF_REG_BASE+0x10c)\r
#define USBGRF_UOC0_CON2 (GRF_REG_BASE+0x114)\r
#define USBGRF_UOC0_CON3 (GRF_REG_BASE+0x118)\r
+#define USBGRF_UOC1_CON0 (GRF_REG_BASE+0x11C)\r
#define USBGRF_UOC1_CON2 (GRF_REG_BASE+0x124)\r
#define USBGRF_UOC1_CON3 (GRF_REG_BASE+0x128)\r
\r
+#define USBGRF_UOC2_CON0 (GRF_REG_BASE+0x12C)\r
#if defined(CONFIG_SOC_RK3066B) || defined(CONFIG_SOC_RK3108) \r
#define RK3066B_HOST_DRV_VBUS RK30_PIN0_PD7\r
#define RK3066B_OTG_DRV_VBUS RK30_PIN0_PD6\r
},\r
};\r
#endif\r
+#ifdef CONFIG_USB_EHCI_RK\r
+void rkehci_hw_init(void)\r
+{\r
+ unsigned int * phy_con0 = (unsigned int*)(USBGRF_UOC2_CON0);\r
+ unsigned int * phy_con1 = (unsigned int*)(USBGRF_UOC1_CON0);\r
+ unsigned int * phy_con2 = (unsigned int*)(USBGRF_UOC0_CON0);\r
+ // usb phy config init\r
+ // hsic phy config init, set hsicphy_txsrtune\r
+ *phy_con0 = ((0xf<<6)<<16)|(0xf<<6);\r
+\r
+ // other haredware init\r
+ // set common_on, in suspend mode, otg/host PLL blocks remain powered\r
+#ifdef CONFIG_ARCH_RK3188\r
+ *phy_con1 = (1<<16)|0;\r
+#else\r
+ *phy_con2 = (1<<16)|0;\r
+#endif\r
+}\r
+\r
+void rkehci_clock_init(void* pdata)\r
+{\r
+ struct rkehci_platform_data *usbpdata=pdata;\r
+\r
+#ifdef CONFIG_ARCH_RK3188 \r
+ struct clk *clk_otg, *clk_hs;\r
+\r
+ /* By default, hsicphy_480m's parent is otg phy 480MHz clk\r
+ * rk3188 must use host phy 480MHz clk\r
+ */\r
+ clk_hs = clk_get(NULL, "hsicphy_480m");\r
+ clk_otg = clk_get(NULL, "otgphy1_480m");\r
+ clk_set_parent(clk_hs, clk_otg);\r
+#endif\r
+\r
+ usbpdata->hclk_hsic = clk_get(NULL, "hclk_hsic");\r
+ usbpdata->hsic_phy_480m = clk_get(NULL, "hsicphy_480m");\r
+ usbpdata->hsic_phy_12m = clk_get(NULL, "hsicphy_12m");\r
+}\r
+\r
+void rkehci_clock_enable(void* pdata, int enable)\r
+{\r
+ struct rkehci_platform_data *usbpdata=pdata;\r
+\r
+ if(enable == usbpdata->clk_status)\r
+ return;\r
+\r
+ if(enable){\r
+ clk_enable(usbpdata->hclk_hsic);\r
+ clk_enable(usbpdata->hsic_phy_480m);\r
+ clk_enable(usbpdata->hsic_phy_12m);\r
+ usbpdata->clk_status = 1;\r
+ }else{\r
+ clk_disable(usbpdata->hsic_phy_12m);\r
+ clk_disable(usbpdata->hsic_phy_480m);\r
+ clk_disable(usbpdata->hclk_hsic);\r
+ usbpdata->clk_status = 0;\r
+ }\r
+}\r
+\r
+void rkehci_soft_reset(void)\r
+{\r
+ unsigned int * phy_con0 = (unsigned int*)(USBGRF_UOC2_CON0);\r
+\r
+ cru_set_soft_reset(SOFT_RST_HSICPHY, true);\r
+ udelay(12);\r
+ cru_set_soft_reset(SOFT_RST_HSICPHY, false);\r
+ mdelay(2);\r
+\r
+ *phy_con0 = ((1<<10)<<16)|(1<<10);\r
+ udelay(2);\r
+ *phy_con0 = ((1<<10)<<16)|(0<<10);\r
+ udelay(2);\r
+\r
+ cru_set_soft_reset(SOFT_RST_HSIC_AHB, true);\r
+ udelay(2);\r
+ cru_set_soft_reset(SOFT_RST_HSIC_AHB, false);\r
+ udelay(2);\r
+}\r
+\r
+struct rkehci_platform_data rkehci_pdata = {\r
+ .hclk_hsic = NULL,\r
+ .hsic_phy_12m = NULL,\r
+ .hsic_phy_480m = NULL,\r
+ .clk_status = -1,\r
+ .hw_init = rkehci_hw_init,\r
+ .clock_init = rkehci_clock_init,\r
+ .clock_enable = rkehci_clock_enable,\r
+ .soft_reset = rkehci_soft_reset,\r
+};\r
+\r
static struct resource resources_hsusb_host[] = {\r
{\r
.start = IRQ_HSIC,\r
.resource = resources_hsusb_host,\r
.dev = {\r
.coherent_dma_mask = 0xffffffff,\r
+ .platform_data = &rkehci_pdata,\r
},\r
};\r
+#endif\r
\r
static int __init usbdev_init_devices(void)\r
{\r
#include <linux/err.h>\r
#include <linux/device.h>\r
\r
+#include <mach/gpio.h>\r
#include "ehci.h"\r
+#include "../dwc_otg/usbdev_rk.h"\r
\r
+static int rkehci_status = 1;\r
+static struct ehci_hcd *g_ehci;\r
+#define EHCI_DEVICE_FILE "/sys/devices/platform/rk_hsusb_host/ehci_power"\r
+#define EHCI_PRINT(x...) printk( KERN_INFO "EHCI: " x )\r
\r
static struct hc_driver rk_hc_driver = {\r
.description = hcd_name,\r
.bus_resume = ehci_bus_resume,\r
};\r
\r
+static ssize_t ehci_power_show( struct device *_dev, \r
+ struct device_attribute *attr, char *buf) \r
+{\r
+ return sprintf(buf, "%d\n", rkehci_status);\r
+}\r
+static ssize_t ehci_power_store( struct device *_dev,\r
+ struct device_attribute *attr, \r
+ const char *buf, size_t count ) \r
+{\r
+ uint32_t val = simple_strtoul(buf, NULL, 16);\r
+ struct usb_hcd *hcd = dev_get_drvdata(_dev);\r
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);\r
+ struct rkehci_platform_data *pldata = _dev->platform_data;\r
+\r
+ printk("%s: %d setting to: %d\n", __func__, rkehci_status, val);\r
+ if(val == rkehci_status)\r
+ goto out;\r
+ \r
+ rkehci_status = val;\r
+ switch(val){\r
+ case 0: //power down\r
+ ehci_port_power(ehci, 0);\r
+ writel_relaxed(0 ,hcd->regs +0xb0);\r
+ dsb();\r
+ msleep(5);\r
+ usb_remove_hcd(hcd);\r
+ break;\r
+ case 1: // power on\r
+ pldata->soft_reset();\r
+ usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED);\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
+ break;\r
+ default:\r
+ break;\r
+ }\r
+out:\r
+ return count;\r
+}\r
+static DEVICE_ATTR(ehci_power, S_IRUGO|S_IWUSR, ehci_power_show, ehci_power_store);\r
+\r
+static ssize_t debug_show( struct device *_dev,\r
+ struct device_attribute *attr, char *buf)\r
+{\r
+ volatile uint32_t *addr;\r
+\r
+ EHCI_PRINT("******** EHCI Capability Registers **********\n");\r
+ addr = &g_ehci->caps->hc_capbase;\r
+ EHCI_PRINT("HCIVERSION / CAPLENGTH @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ addr = &g_ehci->caps->hcs_params;\r
+ EHCI_PRINT("HCSPARAMS @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ addr = &g_ehci->caps->hcc_params;\r
+ EHCI_PRINT("HCCPARAMS @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ EHCI_PRINT("********* EHCI Operational Registers *********\n");\r
+ addr = &g_ehci->regs->command;\r
+ EHCI_PRINT("USBCMD @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ addr = &g_ehci->regs->status;\r
+ EHCI_PRINT("USBSTS @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ addr = &g_ehci->regs->intr_enable;\r
+ EHCI_PRINT("USBINTR @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ addr = &g_ehci->regs->frame_index;\r
+ EHCI_PRINT("FRINDEX @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ addr = &g_ehci->regs->segment;\r
+ EHCI_PRINT("CTRLDSSEGMENT @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ addr = &g_ehci->regs->frame_list;\r
+ EHCI_PRINT("PERIODICLISTBASE @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr)); \r
+ addr = &g_ehci->regs->async_next;\r
+ EHCI_PRINT("ASYNCLISTADDR @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ addr = &g_ehci->regs->configured_flag;\r
+ EHCI_PRINT("CONFIGFLAG @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ addr = g_ehci->regs->port_status;\r
+ EHCI_PRINT("PORTSC @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));\r
+ return sprintf(buf, "EHCI Registers Dump\n");\r
+}\r
+static DEVICE_ATTR(debug_ehci, S_IRUGO, debug_show, NULL);\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
+ struct rkehci_platform_data *pldata = dev->platform_data;\r
int ret;\r
+ int retval = 0;\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
+ retval = device_create_file(dev, &dev_attr_ehci_power);\r
+ retval = device_create_file(dev, &dev_attr_debug_ehci);\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
+ pldata->hw_init();\r
+ pldata->clock_init(pldata);\r
+ pldata->clock_enable(pldata, 1);\r
\r
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
if (!res) {\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
+ 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
+ dbg_hcs_params(ehci, "reset");\r
+ dbg_hcc_params(ehci, "reset");\r
\r
- ehci->hcs_params = readl(&ehci->caps->hcs_params);\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
+ if (ret) {\r
+ dev_err(&pdev->dev, "Failed to add USB HCD\n");\r
+ goto unmap;\r
+ }\r
+ \r
+ g_ehci = ehci;\r
ehci_port_power(ehci, 1);\r
writel_relaxed(1 ,hcd->regs +0xb0);\r
writel_relaxed(0x1d4d ,hcd->regs +0x90);\r