]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/usb/host/uhci-platform.c
Merge branch 'for-3.13/logitech' into for-next
[karo-tx-linux.git] / drivers / usb / host / uhci-platform.c
1 /*
2  * Generic UHCI HCD (Host Controller Driver) for Platform Devices
3  *
4  * Copyright (c) 2011 Tony Prisk <linux@prisktech.co.nz>
5  *
6  * This file is based on uhci-grlib.c
7  * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
8  */
9
10 #include <linux/of.h>
11 #include <linux/platform_device.h>
12
13 static int uhci_platform_init(struct usb_hcd *hcd)
14 {
15         struct uhci_hcd *uhci = hcd_to_uhci(hcd);
16
17         uhci->rh_numports = uhci_count_ports(hcd);
18
19         /* Set up pointers to to generic functions */
20         uhci->reset_hc = uhci_generic_reset_hc;
21         uhci->check_and_reset_hc = uhci_generic_check_and_reset_hc;
22
23         /* No special actions need to be taken for the functions below */
24         uhci->configure_hc = NULL;
25         uhci->resume_detect_interrupts_are_broken = NULL;
26         uhci->global_suspend_mode_is_broken = NULL;
27
28         /* Reset if the controller isn't already safely quiescent. */
29         check_and_reset_hc(uhci);
30         return 0;
31 }
32
33 static const struct hc_driver uhci_platform_hc_driver = {
34         .description =          hcd_name,
35         .product_desc =         "Generic UHCI Host Controller",
36         .hcd_priv_size =        sizeof(struct uhci_hcd),
37
38         /* Generic hardware linkage */
39         .irq =                  uhci_irq,
40         .flags =                HCD_MEMORY | HCD_USB11,
41
42         /* Basic lifecycle operations */
43         .reset =                uhci_platform_init,
44         .start =                uhci_start,
45 #ifdef CONFIG_PM
46         .pci_suspend =          NULL,
47         .pci_resume =           NULL,
48         .bus_suspend =          uhci_rh_suspend,
49         .bus_resume =           uhci_rh_resume,
50 #endif
51         .stop =                 uhci_stop,
52
53         .urb_enqueue =          uhci_urb_enqueue,
54         .urb_dequeue =          uhci_urb_dequeue,
55
56         .endpoint_disable =     uhci_hcd_endpoint_disable,
57         .get_frame_number =     uhci_hcd_get_frame_number,
58
59         .hub_status_data =      uhci_hub_status_data,
60         .hub_control =          uhci_hub_control,
61 };
62
63 static int uhci_hcd_platform_probe(struct platform_device *pdev)
64 {
65         struct usb_hcd *hcd;
66         struct uhci_hcd *uhci;
67         struct resource *res;
68         int ret;
69
70         if (usb_disabled())
71                 return -ENODEV;
72
73         /*
74          * Right now device-tree probed devices don't get dma_mask set.
75          * Since shared usb code relies on it, set it here for now.
76          * Once we have dma capability bindings this can go away.
77          */
78         if (!pdev->dev.dma_mask)
79                 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
80         if (!pdev->dev.coherent_dma_mask)
81                 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
82
83         hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev,
84                         pdev->name);
85         if (!hcd)
86                 return -ENOMEM;
87
88         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
89         hcd->rsrc_start = res->start;
90         hcd->rsrc_len = resource_size(res);
91
92         if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
93                 pr_err("%s: request_mem_region failed\n", __func__);
94                 ret = -EBUSY;
95                 goto err_rmr;
96         }
97
98         hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
99         if (!hcd->regs) {
100                 pr_err("%s: ioremap failed\n", __func__);
101                 ret = -ENOMEM;
102                 goto err_irq;
103         }
104         uhci = hcd_to_uhci(hcd);
105
106         uhci->regs = hcd->regs;
107
108         ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED |
109                                                                 IRQF_SHARED);
110         if (ret)
111                 goto err_uhci;
112
113         return 0;
114
115 err_uhci:
116         iounmap(hcd->regs);
117 err_irq:
118         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
119 err_rmr:
120         usb_put_hcd(hcd);
121
122         return ret;
123 }
124
125 static int uhci_hcd_platform_remove(struct platform_device *pdev)
126 {
127         struct usb_hcd *hcd = platform_get_drvdata(pdev);
128
129         usb_remove_hcd(hcd);
130         iounmap(hcd->regs);
131         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
132         usb_put_hcd(hcd);
133
134         return 0;
135 }
136
137 /* Make sure the controller is quiescent and that we're not using it
138  * any more.  This is mainly for the benefit of programs which, like kexec,
139  * expect the hardware to be idle: not doing DMA or generating IRQs.
140  *
141  * This routine may be called in a damaged or failing kernel.  Hence we
142  * do not acquire the spinlock before shutting down the controller.
143  */
144 static void uhci_hcd_platform_shutdown(struct platform_device *op)
145 {
146         struct usb_hcd *hcd = platform_get_drvdata(op);
147
148         uhci_hc_died(hcd_to_uhci(hcd));
149 }
150
151 static const struct of_device_id platform_uhci_ids[] = {
152         { .compatible = "platform-uhci", },
153         {}
154 };
155
156 static struct platform_driver uhci_platform_driver = {
157         .probe          = uhci_hcd_platform_probe,
158         .remove         = uhci_hcd_platform_remove,
159         .shutdown       = uhci_hcd_platform_shutdown,
160         .driver = {
161                 .name = "platform-uhci",
162                 .owner = THIS_MODULE,
163                 .of_match_table = platform_uhci_ids,
164         },
165 };