usb: renesas_usbhs: shrink spin lock area
[pandora-kernel.git] / drivers / usb / host / ehci-vt8500.c
1 /*
2  * drivers/usb/host/ehci-vt8500.c
3  *
4  * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5  *
6  * Based on ehci-au1xxx.c
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  */
18
19 #include <linux/platform_device.h>
20
21 static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
22 {
23         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
24         int rc = 0;
25
26         if (!udev->parent) /* udev is root hub itself, impossible */
27                 rc = -1;
28         /* we only support lpm device connected to root hub yet */
29         if (ehci->has_lpm && !udev->parent->parent) {
30                 rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
31                 if (!rc)
32                         rc = ehci_lpm_check(ehci, udev->portnum);
33         }
34         return rc;
35 }
36
37 static const struct hc_driver vt8500_ehci_hc_driver = {
38         .description            = hcd_name,
39         .product_desc           = "VT8500 EHCI",
40         .hcd_priv_size          = sizeof(struct ehci_hcd),
41
42         /*
43          * generic hardware linkage
44          */
45         .irq                    = ehci_irq,
46         .flags                  = HCD_MEMORY | HCD_USB2,
47
48         /*
49          * basic lifecycle operations
50          */
51         .reset                  = ehci_init,
52         .start                  = ehci_run,
53         .stop                   = ehci_stop,
54         .shutdown               = ehci_shutdown,
55
56         /*
57          * managing i/o requests and associated device resources
58          */
59         .urb_enqueue            = ehci_urb_enqueue,
60         .urb_dequeue            = ehci_urb_dequeue,
61         .endpoint_disable       = ehci_endpoint_disable,
62         .endpoint_reset         = ehci_endpoint_reset,
63
64         /*
65          * scheduling support
66          */
67         .get_frame_number       = ehci_get_frame,
68
69         /*
70          * root hub support
71          */
72         .hub_status_data        = ehci_hub_status_data,
73         .hub_control            = ehci_hub_control,
74         .bus_suspend            = ehci_bus_suspend,
75         .bus_resume             = ehci_bus_resume,
76         .relinquish_port        = ehci_relinquish_port,
77         .port_handed_over       = ehci_port_handed_over,
78
79         /*
80          * call back when device connected and addressed
81          */
82         .update_device =        ehci_update_device,
83
84         .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
85 };
86
87 static int vt8500_ehci_drv_probe(struct platform_device *pdev)
88 {
89         struct usb_hcd *hcd;
90         struct ehci_hcd *ehci;
91         struct resource *res;
92         int ret;
93
94         if (usb_disabled())
95                 return -ENODEV;
96
97         if (pdev->resource[1].flags != IORESOURCE_IRQ) {
98                 pr_debug("resource[1] is not IORESOURCE_IRQ");
99                 return -ENOMEM;
100         }
101         hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500");
102         if (!hcd)
103                 return -ENOMEM;
104
105         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
106         hcd->rsrc_start = res->start;
107         hcd->rsrc_len = resource_size(res);
108
109         if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
110                 pr_debug("request_mem_region failed");
111                 ret = -EBUSY;
112                 goto err1;
113         }
114
115         hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
116         if (!hcd->regs) {
117                 pr_debug("ioremap failed");
118                 ret = -ENOMEM;
119                 goto err2;
120         }
121
122         ehci = hcd_to_ehci(hcd);
123         ehci->caps = hcd->regs;
124         ehci->regs = hcd->regs +
125                 HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
126
127         dbg_hcs_params(ehci, "reset");
128         dbg_hcc_params(ehci, "reset");
129
130         /* cache this readonly data; minimize chip reads */
131         ehci->hcs_params = readl(&ehci->caps->hcs_params);
132
133         ehci_port_power(ehci, 1);
134
135         ret = usb_add_hcd(hcd, pdev->resource[1].start,
136                           IRQF_DISABLED | IRQF_SHARED);
137         if (ret == 0) {
138                 platform_set_drvdata(pdev, hcd);
139                 return ret;
140         }
141
142         iounmap(hcd->regs);
143 err2:
144         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
145 err1:
146         usb_put_hcd(hcd);
147         return ret;
148 }
149
150 static int vt8500_ehci_drv_remove(struct platform_device *pdev)
151 {
152         struct usb_hcd *hcd = platform_get_drvdata(pdev);
153
154         usb_remove_hcd(hcd);
155         iounmap(hcd->regs);
156         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
157         usb_put_hcd(hcd);
158         platform_set_drvdata(pdev, NULL);
159
160         return 0;
161 }
162
163 static struct platform_driver vt8500_ehci_driver = {
164         .probe          = vt8500_ehci_drv_probe,
165         .remove         = vt8500_ehci_drv_remove,
166         .shutdown       = usb_hcd_platform_shutdown,
167         .driver = {
168                 .name   = "vt8500-ehci",
169                 .owner  = THIS_MODULE,
170         }
171 };
172
173 MODULE_ALIAS("platform:vt8500-ehci");