UPSTREAM: clk: rockchip: rk3399: fix copy-paste error
[firefly-linux-kernel-4.4.55.git] / drivers / usb / host / ohci-rockchip.c
1 /*
2  * ROCKCHIP USB HOST OHCI Controller
3  *
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.
8  *
9  */
10
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/of.h>
14 #include <linux/clk.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/of_platform.h>
17 #include "../dwc_otg_310/usbdev_rk.h"
18
19 static int ohci_rk_init(struct usb_hcd *hcd)
20 {
21         dev_dbg(hcd->self.controller, "starting OHCI controller\n");
22
23         return ohci_init(hcd_to_ohci(hcd));
24 }
25
26 static int ohci_rk_start(struct usb_hcd *hcd)
27 {
28         struct ohci_hcd *ohci = hcd_to_ohci(hcd);
29         int ret;
30
31         /*
32          * RemoteWakeupConnected has to be set explicitly before
33          * calling ohci_run. The reset value of RWC is 0.
34          */
35         ohci->hc_control = OHCI_CTRL_RWC;
36         writel(OHCI_CTRL_RWC, &ohci->regs->control);
37
38         ret = ohci_run(ohci);
39
40         if (ret < 0) {
41                 dev_err(hcd->self.controller, "can't start\n");
42                 ohci_stop(hcd);
43         }
44
45         return ret;
46 }
47
48 static const struct hc_driver ohci_rk_hc_driver = {
49         .description = hcd_name,
50         .product_desc = "RK OHCI Host Controller",
51         .hcd_priv_size = sizeof(struct ohci_hcd),
52
53         /*
54          * generic hardware linkage
55          */
56         .irq = ohci_irq,
57         .flags = HCD_USB11 | HCD_MEMORY,
58
59         /*
60          * basic lifecycle operations
61          */
62         .reset = ohci_rk_init,
63         .start = ohci_rk_start,
64         .stop = ohci_stop,
65         .shutdown = ohci_shutdown,
66
67         /*
68          * managing i/o requests and associated device resources
69          */
70         .urb_enqueue = ohci_urb_enqueue,
71         .urb_dequeue = ohci_urb_dequeue,
72         .endpoint_disable = ohci_endpoint_disable,
73
74         /*
75          * scheduling support
76          */
77         .get_frame_number = ohci_get_frame,
78
79         /*
80          * root hub support
81          */
82         .hub_status_data = ohci_hub_status_data,
83         .hub_control = ohci_hub_control,
84 #ifdef  CONFIG_PM
85         .bus_suspend = ohci_bus_suspend,
86         .bus_resume = ohci_bus_resume,
87 #endif
88         .start_port_reset = ohci_start_port_reset,
89 };
90
91 static struct of_device_id rk_ohci_of_match[] = {
92 #ifdef CONFIG_ARM
93         {
94          .compatible = "rockchip,rk3126_ohci",
95          .data = &usb20ohci_pdata_rk3126,
96          },
97 #endif
98 #ifdef CONFIG_ARM64
99         {
100          .compatible = "rockchip,rk3368_ohci",
101          .data = &usb20ohci_pdata_rk3368,
102          },
103 #endif
104         {},
105 };
106
107 MODULE_DEVICE_TABLE(of, rk_ohci_of_match);
108
109 /* ohci_hcd_rk_probe - initialize RK-based HCDs
110  * Allocates basic resources for this USB host controller, and
111  * then invokes the start() method for the HCD associated with it
112  * through the hotplug entry's driver_data.
113  */
114 static int ohci_hcd_rk_probe(struct platform_device *pdev)
115 {
116         struct device *dev = &pdev->dev;
117         struct usb_hcd *hcd = NULL;
118         void __iomem *regs = NULL;
119         struct resource *res;
120         int ret = -ENODEV;
121         int irq;
122         struct dwc_otg_platform_data *pldata;
123         const struct of_device_id *match;
124
125         dev_dbg(&pdev->dev, "ohci_hcd_rk_probe\n");
126
127         if (usb_disabled())
128                 return -ENODEV;
129
130         match = of_match_device(of_match_ptr(rk_ohci_of_match), &pdev->dev);
131         if (match && match->data) {
132                 pldata = (struct dwc_otg_platform_data *)match->data;
133         } else {
134                 dev_err(dev, "ohci_rk match failed\n");
135                 return -EINVAL;
136         }
137
138         pldata->dev = dev;
139         dev->platform_data = pldata;
140
141         if (pldata->hw_init)
142                 pldata->hw_init();
143
144         if (pldata->clock_init) {
145                 pldata->clock_init(pldata);
146                 pldata->clock_enable(pldata, 1);
147         }
148
149         irq = platform_get_irq(pdev, 0);
150         if (irq < 0) {
151                 dev_err(dev, "OHCI irq failed\n");
152                 ret = irq;
153                 goto clk_disable;
154         }
155
156         if (!pdev->dev.dma_mask)
157                 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
158         dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
159
160
161         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
162         if (!res) {
163                 dev_err(dev, "UHH OHCI get resource failed\n");
164                 ret = -ENOMEM;
165                 goto clk_disable;
166         }
167
168         regs = devm_ioremap_resource(dev, res);
169         if (!regs) {
170                 dev_err(dev, "UHH OHCI ioremap failed\n");
171                 ret = -ENOMEM;
172                 goto clk_disable;
173         }
174
175         /*
176          * Right now device-tree probed devices don't get dma_mask set.
177          * Since shared usb code relies on it, set it here for now.
178          * Once we have dma capability bindings this can go away.
179          */
180         if (!dev->dma_mask)
181                 dev->dma_mask = &dev->coherent_dma_mask;
182         if (!dev->coherent_dma_mask)
183                 dev->coherent_dma_mask = DMA_BIT_MASK(32);
184
185         hcd = usb_create_hcd(&ohci_rk_hc_driver, dev, dev_name(dev));
186         if (!hcd) {
187                 dev_err(dev, "usb_create_hcd failed\n");
188                 ret = -ENOMEM;
189                 goto clk_disable;
190         }
191
192         hcd->rsrc_start = res->start;
193         hcd->rsrc_len = resource_size(res);
194         hcd->regs = regs;
195
196         ohci_hcd_init(hcd_to_ohci(hcd));
197
198         ret = usb_add_hcd(hcd, irq, 0);
199         if (ret) {
200                 dev_dbg(dev, "failed to add hcd with err %d\n", ret);
201                 goto err_add_hcd;
202         }
203
204         return 0;
205
206 err_add_hcd:
207         usb_put_hcd(hcd);
208
209 clk_disable:
210         if (pldata->clock_enable)
211                 pldata->clock_enable(pldata, 0);
212
213         return ret;
214 }
215
216 static int ohci_hcd_rk_remove(struct platform_device *pdev)
217 {
218         struct device *dev = &pdev->dev;
219         struct usb_hcd *hcd = dev_get_drvdata(dev);
220
221         usb_remove_hcd(hcd);
222         usb_put_hcd(hcd);
223         return 0;
224 }
225
226 static void ohci_hcd_rk_shutdown(struct platform_device *pdev)
227 {
228         struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
229
230         if (hcd->driver->shutdown)
231                 hcd->driver->shutdown(hcd);
232 }
233
234 static struct platform_driver ohci_hcd_rk_driver = {
235         .probe = ohci_hcd_rk_probe,
236         .remove = ohci_hcd_rk_remove,
237         .shutdown = ohci_hcd_rk_shutdown,
238         .driver = {
239                    .name = "ohci-rockchip",
240                    .of_match_table = of_match_ptr(rk_ohci_of_match),
241                    },
242 };
243
244 MODULE_ALIAS("platform:rockchip-ohci");