1 /* ehci-msm.c - HSUSB Host Controller Driver Implementation
3 * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
5 * Partly derived from ehci-fsl.c and ehci-hcd.c
6 * Copyright (c) 2000-2004 by David Brownell
7 * Copyright (c) 2005 MontaVista Software
9 * All source code in this file is licensed under the following license except
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published
14 * by the Free Software Foundation.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 * See the GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you can find it at http://www.fsf.org
25 # include <linux/platform_device.h>
26 # include <linux/clk.h>
27 # include <linux/err.h>
28 # include <linux/device.h>
29 # include <linux/of.h>
30 # include <linux/of_platform.h>
32 #ifdef CONFIG_DWC_OTG_274
33 # include "../dwc_otg/usbdev_rk.h"
35 #ifdef CONFIG_DWC_OTG_310
36 # include "../dwc_otg_310/usbdev_rk.h"
39 static int rkhsic_status = 1;
40 static struct ehci_hcd *g_hsic_ehci;
41 #define HSIC_EHCI_PRINT(x...) printk( KERN_INFO "HSIC_EHCI: " x )
43 static struct rkehci_pdata_id rkhsic_pdata[] = {
45 .name = "rk3188-hsic",
46 .pdata = &rkhsic_pdata_rk3188,
49 .name = "rk3288-hsic",
50 .pdata = &rkhsic_pdata_rk3288,
55 static void ehci_rkhsic_port_power (struct ehci_hcd *ehci, int is_on)
59 if (!HCS_PPC (ehci->hcs_params))
62 ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down");
63 for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
64 (void) ehci_hub_control(ehci_to_hcd(ehci),
65 is_on ? SetPortFeature : ClearPortFeature,
68 /* Flush those writes */
69 ehci_readl(ehci, &ehci->regs->command);
73 static struct hc_driver rk_hsic_driver = {
74 .description = hcd_name,
75 .product_desc = "Rockchip On-Chip HSIC EHCI Host Controller",
76 .hcd_priv_size = sizeof(struct ehci_hcd),
79 * generic hardware linkage
82 .flags = HCD_USB2 | HCD_MEMORY,
88 .shutdown = ehci_shutdown,
91 * managing i/o requests and associated device resources
93 .urb_enqueue = ehci_urb_enqueue,
94 .urb_dequeue = ehci_urb_dequeue,
95 .endpoint_disable = ehci_endpoint_disable,
96 .endpoint_reset = ehci_endpoint_reset,
97 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
102 .get_frame_number = ehci_get_frame,
107 .hub_status_data = ehci_hub_status_data,
108 .hub_control = ehci_hub_control,
109 .relinquish_port = ehci_relinquish_port,
110 .port_handed_over = ehci_port_handed_over,
116 .bus_suspend = ehci_bus_suspend,
117 .bus_resume = ehci_bus_resume,
121 static ssize_t ehci_rkhsic_power_show( struct device *_dev,
122 struct device_attribute *attr, char *buf)
124 return sprintf(buf, "%d\n", rkhsic_status);
126 static ssize_t ehci_rkhsic_power_store( struct device *_dev,
127 struct device_attribute *attr,
128 const char *buf, size_t count )
130 uint32_t val = simple_strtoul(buf, NULL, 16);
131 struct usb_hcd *hcd = dev_get_drvdata(_dev);
132 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
133 struct rkehci_platform_data *pldata = _dev->platform_data;
135 printk("%s: %d setting to: %d\n", __func__, rkhsic_status, val);
136 if(val == rkhsic_status)
142 ehci_rkhsic_port_power(ehci, 0);
143 writel_relaxed(0 ,hcd->regs +0xb0);
149 pldata->soft_reset();
150 usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED);
152 ehci_rkhsic_port_power(ehci, 1);
153 writel_relaxed(1 ,hcd->regs +0xb0);
154 writel_relaxed(0x1d4d ,hcd->regs +0x90);
155 writel_relaxed(0x4 ,hcd->regs +0xa0);
164 static DEVICE_ATTR(ehci_rkhsic_power, S_IRUGO|S_IWUSR, ehci_rkhsic_power_show, ehci_rkhsic_power_store);
166 static ssize_t hsic_debug_show( struct device *_dev,
167 struct device_attribute *attr, char *buf)
169 volatile uint32_t *addr;
171 HSIC_EHCI_PRINT("******** EHCI Capability Registers **********\n");
172 addr = &g_hsic_ehci->caps->hc_capbase;
173 HSIC_EHCI_PRINT("HCIVERSION / CAPLENGTH @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
174 addr = &g_hsic_ehci->caps->hcs_params;
175 HSIC_EHCI_PRINT("HCSPARAMS @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
176 addr = &g_hsic_ehci->caps->hcc_params;
177 HSIC_EHCI_PRINT("HCCPARAMS @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
178 HSIC_EHCI_PRINT("********* EHCI Operational Registers *********\n");
179 addr = &g_hsic_ehci->regs->command;
180 HSIC_EHCI_PRINT("USBCMD @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
181 addr = &g_hsic_ehci->regs->status;
182 HSIC_EHCI_PRINT("USBSTS @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
183 addr = &g_hsic_ehci->regs->intr_enable;
184 HSIC_EHCI_PRINT("USBINTR @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
185 addr = &g_hsic_ehci->regs->frame_index;
186 HSIC_EHCI_PRINT("FRINDEX @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
187 addr = &g_hsic_ehci->regs->segment;
188 HSIC_EHCI_PRINT("CTRLDSSEGMENT @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
189 addr = &g_hsic_ehci->regs->frame_list;
190 HSIC_EHCI_PRINT("PERIODICLISTBASE @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
191 addr = &g_hsic_ehci->regs->async_next;
192 HSIC_EHCI_PRINT("ASYNCLISTADDR @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
193 addr = &g_hsic_ehci->regs->configured_flag;
194 HSIC_EHCI_PRINT("CONFIGFLAG @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
195 addr = g_hsic_ehci->regs->port_status;
196 HSIC_EHCI_PRINT("PORTSC @0x%08x: 0x%08x\n", (uint32_t)addr, readl_relaxed(addr));
197 return sprintf(buf, "HSIC_EHCI Registers Dump\n");
199 static DEVICE_ATTR(hsic_debug_ehci, S_IRUGO, hsic_debug_show, NULL);
201 static struct of_device_id rk_hsic_of_match[] = {
203 .compatible = "rockchip,rk3188_rk_hsic_host",
204 .data = &rkhsic_pdata[RK3188_USB_CTLR],
207 .compatible = "rockchip,rk3288_rk_hsic_host",
208 .data = &rkhsic_pdata[RK3288_USB_CTLR],
213 MODULE_DEVICE_TABLE(of, rk_hsic_of_match);
215 static int ehci_rkhsic_probe(struct platform_device *pdev)
218 struct ehci_hcd *ehci;
219 struct resource *res;
220 struct device *dev = &pdev->dev;
221 struct rkehci_platform_data *pldata;
224 static u64 usb_dmamask = 0xffffffffUL;
225 struct device_node *node = pdev->dev.of_node;
226 struct rkehci_pdata_id *p;
227 const struct of_device_id *match =
228 of_match_device(of_match_ptr( rk_hsic_of_match ), &pdev->dev);
230 dev_dbg(&pdev->dev, "ehci_rkhsic proble\n");
233 p = (struct rkehci_pdata_id *)match->data;
235 dev_err(dev, "ehci_rkhsic match failed\n");
239 dev->platform_data = p->pdata;
240 pldata = dev->platform_data;
244 dev_err(dev, "device node not found\n");
248 dev->dma_mask = &usb_dmamask;
250 retval = device_create_file(dev, &dev_attr_ehci_rkhsic_power);
251 retval = device_create_file(dev, &dev_attr_hsic_debug_ehci);
252 hcd = usb_create_hcd(&rk_hsic_driver, &pdev->dev, dev_name(&pdev->dev));
254 dev_err(&pdev->dev, "Unable to create HCD\n");
261 if(pldata->clock_init){
262 pldata->clock_init(pldata);
263 pldata->clock_enable(pldata, 1);
266 if(pldata->soft_reset)
267 pldata->soft_reset();
269 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
271 dev_err(&pdev->dev, "Unable to get memory resource\n");
276 hcd->rsrc_start = res->start;
277 hcd->rsrc_len = resource_size(res);
278 hcd->regs = devm_ioremap_resource(dev, res);
281 dev_err(&pdev->dev, "ioremap failed\n");
286 hcd->irq = platform_get_irq(pdev, 0);
288 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
293 ehci = hcd_to_ehci(hcd);
294 ehci->caps = hcd->regs;
295 ehci->regs = hcd->regs + 0x10;
296 printk("%s %p %p\n", __func__, ehci->caps, ehci->regs);
298 dbg_hcs_params(ehci, "reset");
299 dbg_hcc_params(ehci, "reset");
301 ehci->hcs_params = readl(&ehci->caps->hcs_params);
303 ret = usb_add_hcd(hcd, hcd->irq, IRQF_DISABLED | IRQF_SHARED);
305 dev_err(&pdev->dev, "Failed to add USB HCD\n");
310 ehci_rkhsic_port_power(ehci, 1);
311 writel_relaxed(1 ,hcd->regs +0xb0);
312 writel_relaxed(0x1d4d ,hcd->regs +0x90);
313 writel_relaxed(0x4 ,hcd->regs +0xa0);
317 printk("%s ok\n", __func__);
322 if(pldata->clock_enable)
323 pldata->clock_enable(pldata, 0);
329 static int ehci_rkhsic_remove(struct platform_device *pdev)
331 struct usb_hcd *hcd = platform_get_drvdata(pdev);
339 static int ehci_rkhsic_pm_suspend(struct device *dev)
341 struct usb_hcd *hcd = dev_get_drvdata(dev);
342 bool do_wakeup = device_may_wakeup(dev);
345 dev_dbg(dev, "ehci-rkhsic PM suspend\n");
346 ret = ehci_suspend(hcd, do_wakeup);
351 static int ehci_rkhsic_pm_resume(struct device *dev)
353 struct usb_hcd *hcd = dev_get_drvdata(dev);
355 dev_dbg(dev, "ehci-rkhsic PM resume\n");
356 ehci_resume(hcd, false);
361 #define ehci_rkhsic_pm_suspend NULL
362 #define ehci_rkhsic_pm_resume NULL
365 static const struct dev_pm_ops ehci_rkhsic_dev_pm_ops = {
366 .suspend = ehci_rkhsic_pm_suspend,
367 .resume = ehci_rkhsic_pm_resume,
370 static struct platform_driver ehci_rkhsic_driver = {
371 .probe = ehci_rkhsic_probe,
372 .remove = ehci_rkhsic_remove,
374 .name = "rockchip_hsic_host",
375 .of_match_table = of_match_ptr(rk_hsic_of_match),
377 .pm = &ehci_rkhsic_dev_pm_ops,