USB: serial: visor: fix crash on detecting device without write_urbs
[pandora-kernel.git] / drivers / usb / host / ohci-cns3xxx.c
1 /*
2  * Copyright 2008 Cavium Networks
3  *
4  * This file is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License, Version 2, as
6  * published by the Free Software Foundation.
7  */
8
9 #include <linux/platform_device.h>
10 #include <linux/atomic.h>
11 #include <mach/cns3xxx.h>
12 #include <mach/pm.h>
13
14 static int __devinit
15 cns3xxx_ohci_start(struct usb_hcd *hcd)
16 {
17         struct ohci_hcd *ohci = hcd_to_ohci(hcd);
18         int ret;
19
20         /*
21          * EHCI and OHCI share the same clock and power,
22          * resetting twice would cause the 1st controller been reset.
23          * Therefore only do power up  at the first up device, and
24          * power down at the last down device.
25          *
26          * Set USB AHB INCR length to 16
27          */
28         if (atomic_inc_return(&usb_pwr_ref) == 1) {
29                 cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
30                 cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
31                 cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
32                 __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
33                         MISC_CHIP_CONFIG_REG);
34         }
35
36         ret = ohci_init(ohci);
37         if (ret < 0)
38                 return ret;
39
40         ohci->num_ports = 1;
41
42         ret = ohci_run(ohci);
43         if (ret < 0) {
44                 err("can't start %s", hcd->self.bus_name);
45                 ohci_stop(hcd);
46                 return ret;
47         }
48         return 0;
49 }
50
51 static const struct hc_driver cns3xxx_ohci_hc_driver = {
52         .description            = hcd_name,
53         .product_desc           = "CNS3XXX OHCI Host controller",
54         .hcd_priv_size          = sizeof(struct ohci_hcd),
55         .irq                    = ohci_irq,
56         .flags                  = HCD_USB11 | HCD_MEMORY,
57         .start                  = cns3xxx_ohci_start,
58         .stop                   = ohci_stop,
59         .shutdown               = ohci_shutdown,
60         .urb_enqueue            = ohci_urb_enqueue,
61         .urb_dequeue            = ohci_urb_dequeue,
62         .endpoint_disable       = ohci_endpoint_disable,
63         .get_frame_number       = ohci_get_frame,
64         .hub_status_data        = ohci_hub_status_data,
65         .hub_control            = ohci_hub_control,
66 #ifdef CONFIG_PM
67         .bus_suspend            = ohci_bus_suspend,
68         .bus_resume             = ohci_bus_resume,
69 #endif
70         .start_port_reset       = ohci_start_port_reset,
71 };
72
73 static int cns3xxx_ohci_probe(struct platform_device *pdev)
74 {
75         struct device *dev = &pdev->dev;
76         struct usb_hcd *hcd;
77         const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
78         struct resource *res;
79         int irq;
80         int retval;
81
82         if (usb_disabled())
83                 return -ENODEV;
84
85         res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
86         if (!res) {
87                 dev_err(dev, "Found HC with no IRQ.\n");
88                 return -ENODEV;
89         }
90         irq = res->start;
91
92         hcd = usb_create_hcd(driver, dev, dev_name(dev));
93         if (!hcd)
94                 return -ENOMEM;
95
96         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
97         if (!res) {
98                 dev_err(dev, "Found HC with no register addr.\n");
99                 retval = -ENODEV;
100                 goto err1;
101         }
102         hcd->rsrc_start = res->start;
103         hcd->rsrc_len = resource_size(res);
104
105         if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
106                         driver->description)) {
107                 dev_dbg(dev, "controller already in use\n");
108                 retval = -EBUSY;
109                 goto err1;
110         }
111
112         hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
113         if (!hcd->regs) {
114                 dev_dbg(dev, "error mapping memory\n");
115                 retval = -EFAULT;
116                 goto err2;
117         }
118
119         ohci_hcd_init(hcd_to_ohci(hcd));
120
121         retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
122         if (retval == 0)
123                 return retval;
124
125         iounmap(hcd->regs);
126 err2:
127         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
128 err1:
129         usb_put_hcd(hcd);
130         return retval;
131 }
132
133 static int cns3xxx_ohci_remove(struct platform_device *pdev)
134 {
135         struct usb_hcd *hcd = platform_get_drvdata(pdev);
136
137         usb_remove_hcd(hcd);
138         iounmap(hcd->regs);
139         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
140
141         /*
142          * EHCI and OHCI share the same clock and power,
143          * resetting twice would cause the 1st controller been reset.
144          * Therefore only do power up  at the first up device, and
145          * power down at the last down device.
146          */
147         if (atomic_dec_return(&usb_pwr_ref) == 0)
148                 cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
149
150         usb_put_hcd(hcd);
151
152         platform_set_drvdata(pdev, NULL);
153
154         return 0;
155 }
156
157 MODULE_ALIAS("platform:cns3xxx-ohci");
158
159 static struct platform_driver ohci_hcd_cns3xxx_driver = {
160         .probe = cns3xxx_ohci_probe,
161         .remove = cns3xxx_ohci_remove,
162         .driver = {
163                 .name = "cns3xxx-ohci",
164         },
165 };