userns: Convert audit to work with user namespaces enabled
[firefly-linux-kernel-4.4.55.git] / drivers / usb / host / ehci-ppc-of.c
1 /*
2  * EHCI HCD (Host Controller Driver) for USB.
3  *
4  * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
5  * Tested on AMCC PPC 440EPx
6  *
7  * Valentine Barshak <vbarshak@ru.mvista.com>
8  *
9  * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
10  * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
11  *
12  * This file is licenced under the GPL.
13  */
14
15 #include <linux/signal.h>
16
17 #include <linux/of.h>
18 #include <linux/of_platform.h>
19
20
21 static const struct hc_driver ehci_ppc_of_hc_driver = {
22         .description            = hcd_name,
23         .product_desc           = "OF EHCI",
24         .hcd_priv_size          = sizeof(struct ehci_hcd),
25
26         /*
27          * generic hardware linkage
28          */
29         .irq                    = ehci_irq,
30         .flags                  = HCD_MEMORY | HCD_USB2,
31
32         /*
33          * basic lifecycle operations
34          */
35         .reset                  = ehci_setup,
36         .start                  = ehci_run,
37         .stop                   = ehci_stop,
38         .shutdown               = ehci_shutdown,
39
40         /*
41          * managing i/o requests and associated device resources
42          */
43         .urb_enqueue            = ehci_urb_enqueue,
44         .urb_dequeue            = ehci_urb_dequeue,
45         .endpoint_disable       = ehci_endpoint_disable,
46         .endpoint_reset         = ehci_endpoint_reset,
47
48         /*
49          * scheduling support
50          */
51         .get_frame_number       = ehci_get_frame,
52
53         /*
54          * root hub support
55          */
56         .hub_status_data        = ehci_hub_status_data,
57         .hub_control            = ehci_hub_control,
58 #ifdef  CONFIG_PM
59         .bus_suspend            = ehci_bus_suspend,
60         .bus_resume             = ehci_bus_resume,
61 #endif
62         .relinquish_port        = ehci_relinquish_port,
63         .port_handed_over       = ehci_port_handed_over,
64
65         .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
66 };
67
68
69 /*
70  * 440EPx Errata USBH_3
71  * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
72  */
73 #define PPC440EPX_EHCI0_INSREG_BMT      (0x1 << 0)
74 static int __devinit
75 ppc44x_enable_bmt(struct device_node *dn)
76 {
77         __iomem u32 *insreg_virt;
78
79         insreg_virt = of_iomap(dn, 1);
80         if (!insreg_virt)
81                 return  -EINVAL;
82
83         out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT);
84
85         iounmap(insreg_virt);
86         return 0;
87 }
88
89
90 static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
91 {
92         struct device_node *dn = op->dev.of_node;
93         struct usb_hcd *hcd;
94         struct ehci_hcd *ehci = NULL;
95         struct resource res;
96         int irq;
97         int rv;
98
99         struct device_node *np;
100
101         if (usb_disabled())
102                 return -ENODEV;
103
104         dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
105
106         rv = of_address_to_resource(dn, 0, &res);
107         if (rv)
108                 return rv;
109
110         hcd = usb_create_hcd(&ehci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
111         if (!hcd)
112                 return -ENOMEM;
113
114         hcd->rsrc_start = res.start;
115         hcd->rsrc_len = resource_size(&res);
116
117         if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
118                 printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
119                 rv = -EBUSY;
120                 goto err_rmr;
121         }
122
123         irq = irq_of_parse_and_map(dn, 0);
124         if (irq == NO_IRQ) {
125                 printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
126                 rv = -EBUSY;
127                 goto err_irq;
128         }
129
130         hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
131         if (!hcd->regs) {
132                 printk(KERN_ERR "%s: ioremap failed\n", __FILE__);
133                 rv = -ENOMEM;
134                 goto err_ioremap;
135         }
136
137         ehci = hcd_to_ehci(hcd);
138         np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
139         if (np != NULL) {
140                 /* claim we really affected by usb23 erratum */
141                 if (!of_address_to_resource(np, 0, &res))
142                         ehci->ohci_hcctrl_reg = ioremap(res.start +
143                                         OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN);
144                 else
145                         pr_debug("%s: no ohci offset in fdt\n", __FILE__);
146                 if (!ehci->ohci_hcctrl_reg) {
147                         pr_debug("%s: ioremap for ohci hcctrl failed\n", __FILE__);
148                 } else {
149                         ehci->has_amcc_usb23 = 1;
150                 }
151         }
152
153         if (of_get_property(dn, "big-endian", NULL)) {
154                 ehci->big_endian_mmio = 1;
155                 ehci->big_endian_desc = 1;
156         }
157         if (of_get_property(dn, "big-endian-regs", NULL))
158                 ehci->big_endian_mmio = 1;
159         if (of_get_property(dn, "big-endian-desc", NULL))
160                 ehci->big_endian_desc = 1;
161
162         ehci->caps = hcd->regs;
163
164         if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
165                 rv = ppc44x_enable_bmt(dn);
166                 ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n",
167                                 rv ? "NOT ": "");
168         }
169
170         rv = usb_add_hcd(hcd, irq, 0);
171         if (rv)
172                 goto err_ehci;
173
174         return 0;
175
176 err_ehci:
177         if (ehci->has_amcc_usb23)
178                 iounmap(ehci->ohci_hcctrl_reg);
179         iounmap(hcd->regs);
180 err_ioremap:
181         irq_dispose_mapping(irq);
182 err_irq:
183         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
184 err_rmr:
185         usb_put_hcd(hcd);
186
187         return rv;
188 }
189
190
191 static int ehci_hcd_ppc_of_remove(struct platform_device *op)
192 {
193         struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
194         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
195
196         struct device_node *np;
197         struct resource res;
198
199         dev_set_drvdata(&op->dev, NULL);
200
201         dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
202
203         usb_remove_hcd(hcd);
204
205         iounmap(hcd->regs);
206         irq_dispose_mapping(hcd->irq);
207         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
208
209         /* use request_mem_region to test if the ohci driver is loaded.  if so
210          * ensure the ohci core is operational.
211          */
212         if (ehci->has_amcc_usb23) {
213                 np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
214                 if (np != NULL) {
215                         if (!of_address_to_resource(np, 0, &res))
216                                 if (!request_mem_region(res.start,
217                                                             0x4, hcd_name))
218                                         set_ohci_hcfs(ehci, 1);
219                                 else
220                                         release_mem_region(res.start, 0x4);
221                         else
222                                 pr_debug("%s: no ohci offset in fdt\n", __FILE__);
223                         of_node_put(np);
224                 }
225
226                 iounmap(ehci->ohci_hcctrl_reg);
227         }
228         usb_put_hcd(hcd);
229
230         return 0;
231 }
232
233
234 static void ehci_hcd_ppc_of_shutdown(struct platform_device *op)
235 {
236         struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
237
238         if (hcd->driver->shutdown)
239                 hcd->driver->shutdown(hcd);
240 }
241
242
243 static const struct of_device_id ehci_hcd_ppc_of_match[] = {
244         {
245                 .compatible = "usb-ehci",
246         },
247         {},
248 };
249 MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
250
251
252 static struct platform_driver ehci_hcd_ppc_of_driver = {
253         .probe          = ehci_hcd_ppc_of_probe,
254         .remove         = ehci_hcd_ppc_of_remove,
255         .shutdown       = ehci_hcd_ppc_of_shutdown,
256         .driver = {
257                 .name = "ppc-of-ehci",
258                 .owner = THIS_MODULE,
259                 .of_match_table = ehci_hcd_ppc_of_match,
260         },
261 };