2 * ROCKCHIP USB HOST OHCI Controller
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
14 #include <linux/clk.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/of_platform.h>
17 #ifdef CONFIG_DWC_OTG_274
18 # include "../dwc_otg/usbdev_rk.h"
20 #ifdef CONFIG_DWC_OTG_310
21 # include "../dwc_otg_310/usbdev_rk.h"
24 static struct rkehci_pdata_id rkohci_pdata[] = {
26 .name = "rk3188-reserved",
30 .name = "rk3288-ohci",
31 .pdata = &rkohci_pdata_rk3288,
36 static int ohci_rk_init(struct usb_hcd *hcd)
38 dev_dbg(hcd->self.controller, "starting OHCI controller\n");
40 return ohci_init(hcd_to_ohci(hcd));
43 static int ohci_rk_start(struct usb_hcd *hcd)
45 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
49 * RemoteWakeupConnected has to be set explicitly before
50 * calling ohci_run. The reset value of RWC is 0.
52 ohci->hc_control = OHCI_CTRL_RWC;
53 writel(OHCI_CTRL_RWC, &ohci->regs->control);
58 dev_err(hcd->self.controller, "can't start\n");
65 static const struct hc_driver ohci_rk_hc_driver = {
66 .description = hcd_name,
67 .product_desc = "RK OHCI Host Controller",
68 .hcd_priv_size = sizeof(struct ohci_hcd),
71 * generic hardware linkage
74 .flags = HCD_USB11 | HCD_MEMORY,
77 * basic lifecycle operations
79 .reset = ohci_rk_init,
80 .start = ohci_rk_start,
82 .shutdown = ohci_shutdown,
85 * managing i/o requests and associated device resources
87 .urb_enqueue = ohci_urb_enqueue,
88 .urb_dequeue = ohci_urb_dequeue,
89 .endpoint_disable = ohci_endpoint_disable,
94 .get_frame_number = ohci_get_frame,
99 .hub_status_data = ohci_hub_status_data,
100 .hub_control = ohci_hub_control,
102 .bus_suspend = ohci_bus_suspend,
103 .bus_resume = ohci_bus_resume,
105 .start_port_reset = ohci_start_port_reset,
108 static struct of_device_id rk_ohci_of_match[] = {
110 .compatible = "rockchip,rk3288_rk_ohci_host",
111 .data = &rkohci_pdata[RK3288_USB_CTLR],
115 MODULE_DEVICE_TABLE(of, rk_ohci_of_match);
117 /* ohci_hcd_rk_probe - initialize RK-based HCDs
118 * Allocates basic resources for this USB host controller, and
119 * then invokes the start() method for the HCD associated with it
120 * through the hotplug entry's driver_data.
122 static int ohci_hcd_rk_probe(struct platform_device *pdev)
124 struct device *dev = &pdev->dev;
125 struct usb_hcd *hcd = NULL;
126 void __iomem *regs = NULL;
127 struct resource *res;
130 struct rkehci_platform_data *pldata;
131 struct device_node *node = pdev->dev.of_node;
132 struct rkehci_pdata_id *p;
133 const struct of_device_id *match =
134 of_match_device(of_match_ptr( rk_ohci_of_match ), &pdev->dev);
136 dev_dbg(&pdev->dev, "ohci_hcd_rk_probe\n");
142 p = (struct rkehci_pdata_id *)match->data;
144 dev_err(dev, "ohci_rk match failed\n");
148 dev->platform_data = p->pdata;
149 pldata = dev->platform_data;
153 dev_err(dev, "device node not found\n");
160 if(pldata->clock_init){
161 pldata->clock_init(pldata);
162 pldata->clock_enable(pldata, 1);
165 if(pldata->soft_reset)
166 pldata->soft_reset();
168 irq = platform_get_irq(pdev, 0);
170 dev_err(dev, "OHCI irq failed\n");
175 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
177 dev_err(dev, "UHH OHCI get resource failed\n");
182 regs = devm_ioremap_resource(dev, res);
184 dev_err(dev, "UHH OHCI ioremap failed\n");
190 * Right now device-tree probed devices don't get dma_mask set.
191 * Since shared usb code relies on it, set it here for now.
192 * Once we have dma capability bindings this can go away.
195 dev->dma_mask = &dev->coherent_dma_mask;
196 if (!dev->coherent_dma_mask)
197 dev->coherent_dma_mask = DMA_BIT_MASK(32);
199 hcd = usb_create_hcd(&ohci_rk_hc_driver, dev,
202 dev_err(dev, "usb_create_hcd failed\n");
207 hcd->rsrc_start = res->start;
208 hcd->rsrc_len = resource_size(res);
211 ohci_hcd_init(hcd_to_ohci(hcd));
213 ret = usb_add_hcd(hcd, irq, 0);
215 dev_dbg(dev, "failed to add hcd with err %d\n", ret);
225 if(pldata->clock_enable)
226 pldata->clock_enable(pldata, 0);
231 static int ohci_hcd_rk_remove(struct platform_device *pdev)
233 struct device *dev = &pdev->dev;
234 struct usb_hcd *hcd = dev_get_drvdata(dev);
241 static void ohci_hcd_rk_shutdown(struct platform_device *pdev)
243 struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
245 if (hcd->driver->shutdown)
246 hcd->driver->shutdown(hcd);
249 static struct platform_driver ohci_hcd_rk_driver = {
250 .probe = ohci_hcd_rk_probe,
251 .remove = ohci_hcd_rk_remove,
252 .shutdown = ohci_hcd_rk_shutdown,
255 .of_match_table = of_match_ptr(rk_ohci_of_match),
258 MODULE_ALIAS("platform:rockchip-ohci");