USB: serial: visor: fix crash on detecting device without write_urbs
[pandora-kernel.git] / drivers / usb / host / ehci-sh.c
1 /*
2  * SuperH EHCI host controller driver
3  *
4  * Copyright (C) 2010  Paul Mundt
5  *
6  * Based on ohci-sh.c and ehci-atmel.c.
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file "COPYING" in the main directory of this archive
10  * for more details.
11  */
12 #include <linux/platform_device.h>
13 #include <linux/clk.h>
14
15 struct ehci_sh_priv {
16         struct clk *iclk, *fclk;
17         struct usb_hcd *hcd;
18 };
19
20 static int ehci_sh_reset(struct usb_hcd *hcd)
21 {
22         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
23         int ret;
24
25         ehci->caps = hcd->regs;
26         ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
27                 &ehci->caps->hc_capbase));
28
29         dbg_hcs_params(ehci, "reset");
30         dbg_hcc_params(ehci, "reset");
31
32         ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
33
34         ret = ehci_halt(ehci);
35         if (unlikely(ret))
36                 return ret;
37
38         ret = ehci_init(hcd);
39         if (unlikely(ret))
40                 return ret;
41
42         ehci->sbrn = 0x20;
43
44         ehci_reset(ehci);
45         ehci_port_power(ehci, 0);
46
47         return ret;
48 }
49
50 static const struct hc_driver ehci_sh_hc_driver = {
51         .description                    = hcd_name,
52         .product_desc                   = "SuperH EHCI",
53         .hcd_priv_size                  = sizeof(struct ehci_hcd),
54
55         /*
56          * generic hardware linkage
57          */
58         .irq                            = ehci_irq,
59         .flags                          = HCD_USB2 | HCD_MEMORY,
60
61         /*
62          * basic lifecycle operations
63          */
64         .reset                          = ehci_sh_reset,
65         .start                          = ehci_run,
66         .stop                           = ehci_stop,
67         .shutdown                       = ehci_shutdown,
68
69         /*
70          * managing i/o requests and associated device resources
71          */
72         .urb_enqueue                    = ehci_urb_enqueue,
73         .urb_dequeue                    = ehci_urb_dequeue,
74         .endpoint_disable               = ehci_endpoint_disable,
75         .endpoint_reset                 = ehci_endpoint_reset,
76
77         /*
78          * scheduling support
79          */
80         .get_frame_number               = ehci_get_frame,
81
82         /*
83          * root hub support
84          */
85         .hub_status_data                = ehci_hub_status_data,
86         .hub_control                    = ehci_hub_control,
87
88 #ifdef CONFIG_PM
89         .bus_suspend                    = ehci_bus_suspend,
90         .bus_resume                     = ehci_bus_resume,
91 #endif
92
93         .relinquish_port                = ehci_relinquish_port,
94         .port_handed_over               = ehci_port_handed_over,
95         .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
96 };
97
98 static int ehci_hcd_sh_probe(struct platform_device *pdev)
99 {
100         const struct hc_driver *driver = &ehci_sh_hc_driver;
101         struct resource *res;
102         struct ehci_sh_priv *priv;
103         struct usb_hcd *hcd;
104         int irq, ret;
105
106         if (usb_disabled())
107                 return -ENODEV;
108
109         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
110         if (!res) {
111                 dev_err(&pdev->dev,
112                         "Found HC with no register addr. Check %s setup!\n",
113                         dev_name(&pdev->dev));
114                 ret = -ENODEV;
115                 goto fail_create_hcd;
116         }
117
118         irq = platform_get_irq(pdev, 0);
119         if (irq <= 0) {
120                 dev_err(&pdev->dev,
121                         "Found HC with no IRQ. Check %s setup!\n",
122                         dev_name(&pdev->dev));
123                 ret = -ENODEV;
124                 goto fail_create_hcd;
125         }
126
127         /* initialize hcd */
128         hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev,
129                              dev_name(&pdev->dev));
130         if (!hcd) {
131                 ret = -ENOMEM;
132                 goto fail_create_hcd;
133         }
134
135         hcd->rsrc_start = res->start;
136         hcd->rsrc_len = resource_size(res);
137
138         if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
139                                 driver->description)) {
140                 dev_dbg(&pdev->dev, "controller already in use\n");
141                 ret = -EBUSY;
142                 goto fail_request_resource;
143         }
144
145         hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
146         if (hcd->regs == NULL) {
147                 dev_dbg(&pdev->dev, "error mapping memory\n");
148                 ret = -ENXIO;
149                 goto fail_ioremap;
150         }
151
152         priv = kmalloc(sizeof(struct ehci_sh_priv), GFP_KERNEL);
153         if (!priv) {
154                 dev_dbg(&pdev->dev, "error allocating priv data\n");
155                 ret = -ENOMEM;
156                 goto fail_alloc;
157         }
158
159         /* These are optional, we don't care if they fail */
160         priv->fclk = clk_get(&pdev->dev, "usb_fck");
161         if (IS_ERR(priv->fclk))
162                 priv->fclk = NULL;
163
164         priv->iclk = clk_get(&pdev->dev, "usb_ick");
165         if (IS_ERR(priv->iclk))
166                 priv->iclk = NULL;
167
168         clk_enable(priv->fclk);
169         clk_enable(priv->iclk);
170
171         ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
172         if (ret != 0) {
173                 dev_err(&pdev->dev, "Failed to add hcd");
174                 goto fail_add_hcd;
175         }
176
177         priv->hcd = hcd;
178         platform_set_drvdata(pdev, priv);
179
180         return ret;
181
182 fail_add_hcd:
183         clk_disable(priv->iclk);
184         clk_disable(priv->fclk);
185
186         clk_put(priv->iclk);
187         clk_put(priv->fclk);
188
189         kfree(priv);
190 fail_alloc:
191         iounmap(hcd->regs);
192 fail_ioremap:
193         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
194 fail_request_resource:
195         usb_put_hcd(hcd);
196 fail_create_hcd:
197         dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), ret);
198
199         return ret;
200 }
201
202 static int __exit ehci_hcd_sh_remove(struct platform_device *pdev)
203 {
204         struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
205         struct usb_hcd *hcd = priv->hcd;
206
207         usb_remove_hcd(hcd);
208         iounmap(hcd->regs);
209         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
210         usb_put_hcd(hcd);
211         platform_set_drvdata(pdev, NULL);
212
213         clk_disable(priv->fclk);
214         clk_disable(priv->iclk);
215
216         clk_put(priv->fclk);
217         clk_put(priv->iclk);
218
219         kfree(priv);
220
221         return 0;
222 }
223
224 static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
225 {
226         struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
227         struct usb_hcd *hcd = priv->hcd;
228
229         if (hcd->driver->shutdown)
230                 hcd->driver->shutdown(hcd);
231 }
232
233 static struct platform_driver ehci_hcd_sh_driver = {
234         .probe          = ehci_hcd_sh_probe,
235         .remove         = __exit_p(ehci_hcd_sh_remove),
236         .shutdown       = ehci_hcd_sh_shutdown,
237         .driver         = {
238                 .name   = "sh_ehci",
239                 .owner  = THIS_MODULE,
240         },
241 };
242
243 MODULE_ALIAS("platform:sh_ehci");