blob: c30da6ab9f921c89af391dc0663512525dcf5398 [file] [log] [blame]
Andrew Victor39a269c2006-01-22 10:32:13 -08001/*
2 * OHCI HCD (Host Controller Driver) for USB.
3 *
4 * Copyright (C) 2004 SAN People (Pty) Ltd.
5 * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
6 *
David Brownell0365ee02006-06-19 14:27:20 -07007 * AT91 Bus Glue
Andrew Victor39a269c2006-01-22 10:32:13 -08008 *
9 * Based on fragments of 2.4 driver by Rick Bronson.
10 * Based on ohci-omap.c
11 *
12 * This file is licenced under the GPL.
13 */
14
15#include <linux/clk.h>
16#include <linux/platform_device.h>
Jean-Christophe PLAGNIOL-VILLARD24197302011-11-21 06:55:18 +080017#include <linux/of_platform.h>
18#include <linux/of_gpio.h>
Andrew Victor39a269c2006-01-22 10:32:13 -080019
Russell Kinga09e64f2008-08-05 16:14:15 +010020#include <mach/hardware.h>
David Brownell4bde4a42007-12-27 11:19:49 -080021#include <asm/gpio.h>
22
Russell Kinga09e64f2008-08-05 16:14:15 +010023#include <mach/board.h>
24#include <mach/cpu.h>
Andrew Victor39a269c2006-01-22 10:32:13 -080025
David Brownell0365ee02006-06-19 14:27:20 -070026#ifndef CONFIG_ARCH_AT91
27#error "CONFIG_ARCH_AT91 must be defined."
Andrew Victor39a269c2006-01-22 10:32:13 -080028#endif
29
Andrew Victored077bb2007-02-16 10:18:58 -080030/* interface and function clocks; sometimes also an AHB clock */
31static struct clk *iclk, *fclk, *hclk;
David Brownell0365ee02006-06-19 14:27:20 -070032static int clocked;
Andrew Victor39a269c2006-01-22 10:32:13 -080033
34extern int usb_disabled(void);
35
36/*-------------------------------------------------------------------------*/
37
Andrew Victored077bb2007-02-16 10:18:58 -080038static void at91_start_clock(void)
39{
Jean-Christophe PLAGNIOL-VILLARD0af43162011-08-30 03:29:28 +020040 clk_enable(hclk);
Andrew Victored077bb2007-02-16 10:18:58 -080041 clk_enable(iclk);
42 clk_enable(fclk);
43 clocked = 1;
44}
45
46static void at91_stop_clock(void)
47{
48 clk_disable(fclk);
49 clk_disable(iclk);
Jean-Christophe PLAGNIOL-VILLARD0af43162011-08-30 03:29:28 +020050 clk_disable(hclk);
Andrew Victored077bb2007-02-16 10:18:58 -080051 clocked = 0;
52}
53
Andrew Victor39a269c2006-01-22 10:32:13 -080054static void at91_start_hc(struct platform_device *pdev)
55{
56 struct usb_hcd *hcd = platform_get_drvdata(pdev);
57 struct ohci_regs __iomem *regs = hcd->regs;
58
David Brownell0365ee02006-06-19 14:27:20 -070059 dev_dbg(&pdev->dev, "start\n");
Andrew Victor39a269c2006-01-22 10:32:13 -080060
61 /*
62 * Start the USB clocks.
63 */
Andrew Victored077bb2007-02-16 10:18:58 -080064 at91_start_clock();
Andrew Victor39a269c2006-01-22 10:32:13 -080065
66 /*
67 * The USB host controller must remain in reset.
68 */
69 writel(0, &regs->control);
70}
71
72static void at91_stop_hc(struct platform_device *pdev)
73{
74 struct usb_hcd *hcd = platform_get_drvdata(pdev);
75 struct ohci_regs __iomem *regs = hcd->regs;
76
David Brownell0365ee02006-06-19 14:27:20 -070077 dev_dbg(&pdev->dev, "stop\n");
Andrew Victor39a269c2006-01-22 10:32:13 -080078
79 /*
80 * Put the USB host controller into reset.
81 */
82 writel(0, &regs->control);
83
84 /*
85 * Stop the USB clocks.
86 */
Andrew Victored077bb2007-02-16 10:18:58 -080087 at91_stop_clock();
Andrew Victor39a269c2006-01-22 10:32:13 -080088}
89
90
91/*-------------------------------------------------------------------------*/
92
Pete Zaitcev421b4bf2008-06-01 14:38:43 -070093static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
Andrew Victor39a269c2006-01-22 10:32:13 -080094
95/* configure so an HC device and id are always provided */
96/* always called with process context; sleeping is OK */
97
98
99/**
David Brownell0365ee02006-06-19 14:27:20 -0700100 * usb_hcd_at91_probe - initialize AT91-based HCDs
Andrew Victor39a269c2006-01-22 10:32:13 -0800101 * Context: !in_interrupt()
102 *
103 * Allocates basic resources for this USB host controller, and
104 * then invokes the start() method for the HCD associated with it
105 * through the hotplug entry's driver_data.
Andrew Victor39a269c2006-01-22 10:32:13 -0800106 */
David Brownell0365ee02006-06-19 14:27:20 -0700107static int usb_hcd_at91_probe(const struct hc_driver *driver,
108 struct platform_device *pdev)
Andrew Victor39a269c2006-01-22 10:32:13 -0800109{
110 int retval;
111 struct usb_hcd *hcd = NULL;
112
113 if (pdev->num_resources != 2) {
114 pr_debug("hcd probe: invalid num_resources");
115 return -ENODEV;
116 }
117
David Brownell0365ee02006-06-19 14:27:20 -0700118 if ((pdev->resource[0].flags != IORESOURCE_MEM)
119 || (pdev->resource[1].flags != IORESOURCE_IRQ)) {
Andrew Victor39a269c2006-01-22 10:32:13 -0800120 pr_debug("hcd probe: invalid resource type\n");
121 return -ENODEV;
122 }
123
David Brownell0365ee02006-06-19 14:27:20 -0700124 hcd = usb_create_hcd(driver, &pdev->dev, "at91");
Andrew Victor39a269c2006-01-22 10:32:13 -0800125 if (!hcd)
126 return -ENOMEM;
127 hcd->rsrc_start = pdev->resource[0].start;
128 hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
129
130 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
131 pr_debug("request_mem_region failed\n");
132 retval = -EBUSY;
133 goto err1;
134 }
135
136 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
137 if (!hcd->regs) {
138 pr_debug("ioremap failed\n");
139 retval = -EIO;
140 goto err2;
141 }
142
143 iclk = clk_get(&pdev->dev, "ohci_clk");
Jean-Christophe PLAGNIOL-VILLARD68134632011-12-08 16:32:00 +0100144 if (IS_ERR(iclk)) {
145 dev_err(&pdev->dev, "failed to get ohci_clk\n");
146 retval = PTR_ERR(iclk);
147 goto err3;
148 }
Andrew Victor39a269c2006-01-22 10:32:13 -0800149 fclk = clk_get(&pdev->dev, "uhpck");
Jean-Christophe PLAGNIOL-VILLARD68134632011-12-08 16:32:00 +0100150 if (IS_ERR(fclk)) {
151 dev_err(&pdev->dev, "failed to get uhpck\n");
152 retval = PTR_ERR(fclk);
153 goto err4;
154 }
Jean-Christophe PLAGNIOL-VILLARD0af43162011-08-30 03:29:28 +0200155 hclk = clk_get(&pdev->dev, "hclk");
Jean-Christophe PLAGNIOL-VILLARD68134632011-12-08 16:32:00 +0100156 if (IS_ERR(hclk)) {
157 dev_err(&pdev->dev, "failed to get hclk\n");
158 retval = PTR_ERR(hclk);
159 goto err5;
160 }
Andrew Victor39a269c2006-01-22 10:32:13 -0800161
162 at91_start_hc(pdev);
163 ohci_hcd_init(hcd_to_ohci(hcd));
164
Nicolas Ferre2f2cac32009-07-27 14:59:24 -0700165 retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
Andrew Victor39a269c2006-01-22 10:32:13 -0800166 if (retval == 0)
167 return retval;
168
169 /* Error handling */
170 at91_stop_hc(pdev);
171
Jean-Christophe PLAGNIOL-VILLARD0af43162011-08-30 03:29:28 +0200172 clk_put(hclk);
Jean-Christophe PLAGNIOL-VILLARD68134632011-12-08 16:32:00 +0100173 err5:
Andrew Victor39a269c2006-01-22 10:32:13 -0800174 clk_put(fclk);
Jean-Christophe PLAGNIOL-VILLARD68134632011-12-08 16:32:00 +0100175 err4:
Andrew Victor39a269c2006-01-22 10:32:13 -0800176 clk_put(iclk);
177
Jean-Christophe PLAGNIOL-VILLARD68134632011-12-08 16:32:00 +0100178 err3:
Andrew Victor39a269c2006-01-22 10:32:13 -0800179 iounmap(hcd->regs);
180
181 err2:
182 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
183
184 err1:
185 usb_put_hcd(hcd);
186 return retval;
187}
188
189
Andrew Victor39a269c2006-01-22 10:32:13 -0800190/* may be called with controller, bus, and devices active */
191
192/**
David Brownell0365ee02006-06-19 14:27:20 -0700193 * usb_hcd_at91_remove - shutdown processing for AT91-based HCDs
Andrew Victor39a269c2006-01-22 10:32:13 -0800194 * @dev: USB Host Controller being removed
195 * Context: !in_interrupt()
196 *
197 * Reverses the effect of usb_hcd_at91_probe(), first invoking
198 * the HCD's stop() method. It is always called from a thread
David Brownell0365ee02006-06-19 14:27:20 -0700199 * context, "rmmod" or something similar.
Andrew Victor39a269c2006-01-22 10:32:13 -0800200 *
201 */
Pete Zaitcev421b4bf2008-06-01 14:38:43 -0700202static void usb_hcd_at91_remove(struct usb_hcd *hcd,
David Brownell0365ee02006-06-19 14:27:20 -0700203 struct platform_device *pdev)
Andrew Victor39a269c2006-01-22 10:32:13 -0800204{
205 usb_remove_hcd(hcd);
206 at91_stop_hc(pdev);
207 iounmap(hcd->regs);
David Brownell68ba61b2006-04-02 20:26:21 -0800208 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
Pete Zaitcev421b4bf2008-06-01 14:38:43 -0700209 usb_put_hcd(hcd);
Andrew Victor39a269c2006-01-22 10:32:13 -0800210
Jean-Christophe PLAGNIOL-VILLARD0af43162011-08-30 03:29:28 +0200211 clk_put(hclk);
David Brownell68ba61b2006-04-02 20:26:21 -0800212 clk_put(fclk);
213 clk_put(iclk);
Andrew Victored077bb2007-02-16 10:18:58 -0800214 fclk = iclk = hclk = NULL;
Andrew Victor39a269c2006-01-22 10:32:13 -0800215
216 dev_set_drvdata(&pdev->dev, NULL);
Andrew Victor39a269c2006-01-22 10:32:13 -0800217}
218
219/*-------------------------------------------------------------------------*/
220
221static int __devinit
222ohci_at91_start (struct usb_hcd *hcd)
223{
David Brownell0365ee02006-06-19 14:27:20 -0700224 struct at91_usbh_data *board = hcd->self.controller->platform_data;
Andrew Victor39a269c2006-01-22 10:32:13 -0800225 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
226 int ret;
227
228 if ((ret = ohci_init(ohci)) < 0)
229 return ret;
230
David Brownellcd22afd2006-09-03 12:21:50 -0700231 ohci->num_ports = board->ports;
David Brownell0365ee02006-06-19 14:27:20 -0700232
Andrew Victor39a269c2006-01-22 10:32:13 -0800233 if ((ret = ohci_run(ohci)) < 0) {
234 err("can't start %s", hcd->self.bus_name);
235 ohci_stop(hcd);
236 return ret;
237 }
Andrew Victor39a269c2006-01-22 10:32:13 -0800238 return 0;
239}
240
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200241static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable)
242{
243 if (port < 0 || port >= 2)
244 return;
245
Jean-Christophe PLAGNIOL-VILLARD8a7a49d2011-09-19 15:32:23 +0800246 if (!gpio_is_valid(pdata->vbus_pin[port]))
Jean-Christophe PLAGNIOL-VILLARD770f0ba2011-11-12 16:46:13 +0100247 return;
248
Jean-Christophe PLAGNIOL-VILLARD8134ff52011-12-08 16:32:01 +0100249 gpio_set_value(pdata->vbus_pin[port],
Nicolas Ferre1e7caf82012-03-21 14:38:55 +0100250 pdata->vbus_pin_active_low[port] ^ enable);
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200251}
252
253static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
254{
255 if (port < 0 || port >= 2)
256 return -EINVAL;
257
Jean-Christophe PLAGNIOL-VILLARD8a7a49d2011-09-19 15:32:23 +0800258 if (!gpio_is_valid(pdata->vbus_pin[port]))
Jean-Christophe PLAGNIOL-VILLARD770f0ba2011-11-12 16:46:13 +0100259 return -EINVAL;
260
Jean-Christophe PLAGNIOL-VILLARD8134ff52011-12-08 16:32:01 +0100261 return gpio_get_value(pdata->vbus_pin[port]) ^
Nicolas Ferre1e7caf82012-03-21 14:38:55 +0100262 pdata->vbus_pin_active_low[port];
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200263}
264
265/*
266 * Update the status data from the hub with the over-current indicator change.
267 */
268static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
269{
270 struct at91_usbh_data *pdata = hcd->self.controller->platform_data;
271 int length = ohci_hub_status_data(hcd, buf);
272 int port;
273
274 for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) {
275 if (pdata->overcurrent_changed[port]) {
276 if (! length)
277 length = 1;
278 buf[0] |= 1 << (port + 1);
279 }
280 }
281
282 return length;
283}
284
285/*
286 * Look at the control requests to the root hub and see if we need to override.
287 */
288static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
289 u16 wIndex, char *buf, u16 wLength)
290{
291 struct at91_usbh_data *pdata = hcd->self.controller->platform_data;
292 struct usb_hub_descriptor *desc;
293 int ret = -EINVAL;
294 u32 *data = (u32 *)buf;
295
296 dev_dbg(hcd->self.controller,
297 "ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n",
298 hcd, typeReq, wValue, wIndex, buf, wLength);
299
300 switch (typeReq) {
301 case SetPortFeature:
302 if (wValue == USB_PORT_FEAT_POWER) {
303 dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n");
304 ohci_at91_usb_set_power(pdata, wIndex - 1, 1);
305 goto out;
306 }
307 break;
308
309 case ClearPortFeature:
310 switch (wValue) {
311 case USB_PORT_FEAT_C_OVER_CURRENT:
312 dev_dbg(hcd->self.controller,
313 "ClearPortFeature: C_OVER_CURRENT\n");
314
315 if (wIndex == 1 || wIndex == 2) {
316 pdata->overcurrent_changed[wIndex-1] = 0;
317 pdata->overcurrent_status[wIndex-1] = 0;
318 }
319
320 goto out;
321
322 case USB_PORT_FEAT_OVER_CURRENT:
323 dev_dbg(hcd->self.controller,
324 "ClearPortFeature: OVER_CURRENT\n");
325
326 if (wIndex == 1 || wIndex == 2) {
327 pdata->overcurrent_status[wIndex-1] = 0;
328 }
329
330 goto out;
331
332 case USB_PORT_FEAT_POWER:
333 dev_dbg(hcd->self.controller,
334 "ClearPortFeature: POWER\n");
335
336 if (wIndex == 1 || wIndex == 2) {
337 ohci_at91_usb_set_power(pdata, wIndex - 1, 0);
338 return 0;
339 }
340 }
341 break;
342 }
343
344 ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
345 if (ret)
346 goto out;
347
348 switch (typeReq) {
349 case GetHubDescriptor:
350
351 /* update the hub's descriptor */
352
353 desc = (struct usb_hub_descriptor *)buf;
354
355 dev_dbg(hcd->self.controller, "wHubCharacteristics 0x%04x\n",
356 desc->wHubCharacteristics);
357
358 /* remove the old configurations for power-switching, and
359 * over-current protection, and insert our new configuration
360 */
361
362 desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_LPSM);
363 desc->wHubCharacteristics |= cpu_to_le16(0x0001);
364
365 if (pdata->overcurrent_supported) {
366 desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM);
367 desc->wHubCharacteristics |= cpu_to_le16(0x0008|0x0001);
368 }
369
370 dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n",
371 desc->wHubCharacteristics);
372
373 return ret;
374
375 case GetPortStatus:
376 /* check port status */
377
378 dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex);
379
380 if (wIndex == 1 || wIndex == 2) {
381 if (! ohci_at91_usb_get_power(pdata, wIndex-1)) {
382 *data &= ~cpu_to_le32(RH_PS_PPS);
383 }
384
385 if (pdata->overcurrent_changed[wIndex-1]) {
386 *data |= cpu_to_le32(RH_PS_OCIC);
387 }
388
389 if (pdata->overcurrent_status[wIndex-1]) {
390 *data |= cpu_to_le32(RH_PS_POCI);
391 }
392 }
393 }
394
395 out:
396 return ret;
397}
398
Andrew Victor39a269c2006-01-22 10:32:13 -0800399/*-------------------------------------------------------------------------*/
400
401static const struct hc_driver ohci_at91_hc_driver = {
402 .description = hcd_name,
David Brownell0365ee02006-06-19 14:27:20 -0700403 .product_desc = "AT91 OHCI",
Andrew Victor39a269c2006-01-22 10:32:13 -0800404 .hcd_priv_size = sizeof(struct ohci_hcd),
405
406 /*
407 * generic hardware linkage
408 */
409 .irq = ohci_irq,
410 .flags = HCD_USB11 | HCD_MEMORY,
411
412 /*
413 * basic lifecycle operations
414 */
415 .start = ohci_at91_start,
416 .stop = ohci_stop,
David Brownelldd9048a2006-12-05 03:18:31 -0800417 .shutdown = ohci_shutdown,
Andrew Victor39a269c2006-01-22 10:32:13 -0800418
419 /*
420 * managing i/o requests and associated device resources
421 */
422 .urb_enqueue = ohci_urb_enqueue,
423 .urb_dequeue = ohci_urb_dequeue,
424 .endpoint_disable = ohci_endpoint_disable,
425
426 /*
427 * scheduling support
428 */
429 .get_frame_number = ohci_get_frame,
430
431 /*
432 * root hub support
433 */
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200434 .hub_status_data = ohci_at91_hub_status_data,
435 .hub_control = ohci_at91_hub_control,
Andrew Victor39a269c2006-01-22 10:32:13 -0800436#ifdef CONFIG_PM
David Brownell68ba61b2006-04-02 20:26:21 -0800437 .bus_suspend = ohci_bus_suspend,
438 .bus_resume = ohci_bus_resume,
Andrew Victor39a269c2006-01-22 10:32:13 -0800439#endif
440 .start_port_reset = ohci_start_port_reset,
441};
442
443/*-------------------------------------------------------------------------*/
444
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200445static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
446{
447 struct platform_device *pdev = data;
448 struct at91_usbh_data *pdata = pdev->dev.platform_data;
449 int val, gpio, port;
450
451 /* From the GPIO notifying the over-current situation, find
452 * out the corresponding port */
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200453 for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) {
Nicolas Ferree4499072012-02-11 14:23:06 +0100454 if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
455 gpio = pdata->overcurrent_pin[port];
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200456 break;
Nicolas Ferree4499072012-02-11 14:23:06 +0100457 }
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200458 }
459
460 if (port == ARRAY_SIZE(pdata->overcurrent_pin)) {
461 dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n");
462 return IRQ_HANDLED;
463 }
464
465 val = gpio_get_value(gpio);
466
467 /* When notified of an over-current situation, disable power
468 on the corresponding port, and mark this port in
469 over-current. */
470 if (! val) {
471 ohci_at91_usb_set_power(pdata, port, 0);
472 pdata->overcurrent_status[port] = 1;
473 pdata->overcurrent_changed[port] = 1;
474 }
475
476 dev_dbg(& pdev->dev, "overcurrent situation %s\n",
477 val ? "exited" : "notified");
478
479 return IRQ_HANDLED;
480}
481
Jean-Christophe PLAGNIOL-VILLARD24197302011-11-21 06:55:18 +0800482#ifdef CONFIG_OF
483static const struct of_device_id at91_ohci_dt_ids[] = {
484 { .compatible = "atmel,at91rm9200-ohci" },
485 { /* sentinel */ }
486};
487
488MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
489
490static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
491
492static int __devinit ohci_at91_of_init(struct platform_device *pdev)
493{
494 struct device_node *np = pdev->dev.of_node;
Nicolas Ferreaaf9f5f2012-03-21 16:58:11 +0100495 int i, gpio;
Jean-Christophe PLAGNIOL-VILLARD24197302011-11-21 06:55:18 +0800496 enum of_gpio_flags flags;
497 struct at91_usbh_data *pdata;
498 u32 ports;
499
500 if (!np)
501 return 0;
502
503 /* Right now device-tree probed devices don't get dma_mask set.
504 * Since shared usb code relies on it, set it here for now.
505 * Once we have dma capability bindings this can go away.
506 */
507 if (!pdev->dev.dma_mask)
508 pdev->dev.dma_mask = &at91_ohci_dma_mask;
509
510 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
511 if (!pdata)
512 return -ENOMEM;
513
514 if (!of_property_read_u32(np, "num-ports", &ports))
515 pdata->ports = ports;
516
517 for (i = 0; i < 2; i++) {
518 gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags);
519 pdata->vbus_pin[i] = gpio;
520 if (!gpio_is_valid(gpio))
521 continue;
522 pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
Jean-Christophe PLAGNIOL-VILLARD24197302011-11-21 06:55:18 +0800523 }
524
Nicolas Ferreaaf9f5f2012-03-21 16:58:11 +0100525 for (i = 0; i < 2; i++)
526 pdata->overcurrent_pin[i] =
527 of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
Jean-Christophe PLAGNIOL-VILLARD24197302011-11-21 06:55:18 +0800528
529 pdev->dev.platform_data = pdata;
530
531 return 0;
532}
533#else
534static int __devinit ohci_at91_of_init(struct platform_device *pdev)
535{
536 return 0;
537}
538#endif
539
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200540/*-------------------------------------------------------------------------*/
541
David Brownell0365ee02006-06-19 14:27:20 -0700542static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
Andrew Victor39a269c2006-01-22 10:32:13 -0800543{
Jean-Christophe PLAGNIOL-VILLARD24197302011-11-21 06:55:18 +0800544 struct at91_usbh_data *pdata;
David Brownell4bde4a42007-12-27 11:19:49 -0800545 int i;
Nicolas Ferreaaf9f5f2012-03-21 16:58:11 +0100546 int gpio;
547 int ret;
David Brownell4bde4a42007-12-27 11:19:49 -0800548
Jean-Christophe PLAGNIOL-VILLARD24197302011-11-21 06:55:18 +0800549 i = ohci_at91_of_init(pdev);
550
551 if (i)
552 return i;
553
554 pdata = pdev->dev.platform_data;
555
David Brownell4bde4a42007-12-27 11:19:49 -0800556 if (pdata) {
Justin Waters3d6fdf72009-04-03 21:06:53 +0100557 for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
Jean-Christophe PLAGNIOL-VILLARD8a7a49d2011-09-19 15:32:23 +0800558 if (!gpio_is_valid(pdata->vbus_pin[i]))
David Brownell4bde4a42007-12-27 11:19:49 -0800559 continue;
Nicolas Ferreaaf9f5f2012-03-21 16:58:11 +0100560 gpio = pdata->vbus_pin[i];
561
562 ret = gpio_request(gpio, "ohci_vbus");
563 if (ret) {
564 dev_err(&pdev->dev,
565 "can't request vbus gpio %d\n", gpio);
566 continue;
567 }
568 ret = gpio_direction_output(gpio,
569 !pdata->vbus_pin_active_low[i]);
570 if (ret) {
571 dev_err(&pdev->dev,
572 "can't put vbus gpio %d as output %d\n",
573 gpio, !pdata->vbus_pin_active_low[i]);
574 gpio_free(gpio);
575 continue;
576 }
577
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200578 ohci_at91_usb_set_power(pdata, i, 1);
579 }
580
581 for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) {
Jean-Christophe PLAGNIOL-VILLARD8a7a49d2011-09-19 15:32:23 +0800582 if (!gpio_is_valid(pdata->overcurrent_pin[i]))
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200583 continue;
Nicolas Ferreaaf9f5f2012-03-21 16:58:11 +0100584 gpio = pdata->overcurrent_pin[i];
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200585
Nicolas Ferreaaf9f5f2012-03-21 16:58:11 +0100586 ret = gpio_request(gpio, "ohci_overcurrent");
587 if (ret) {
588 dev_err(&pdev->dev,
589 "can't request overcurrent gpio %d\n",
590 gpio);
591 continue;
592 }
593
594 ret = gpio_direction_input(gpio);
595 if (ret) {
596 dev_err(&pdev->dev,
597 "can't configure overcurrent gpio %d as input\n",
598 gpio);
599 gpio_free(gpio);
600 continue;
601 }
602
603 ret = request_irq(gpio_to_irq(gpio),
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200604 ohci_hcd_at91_overcurrent_irq,
605 IRQF_SHARED, "ohci_overcurrent", pdev);
606 if (ret) {
Nicolas Ferreaaf9f5f2012-03-21 16:58:11 +0100607 gpio_free(gpio);
608 dev_err(&pdev->dev,
609 "can't get gpio IRQ for overcurrent\n");
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200610 }
David Brownell4bde4a42007-12-27 11:19:49 -0800611 }
612 }
613
David Brownell0365ee02006-06-19 14:27:20 -0700614 device_init_wakeup(&pdev->dev, 1);
615 return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
Andrew Victor39a269c2006-01-22 10:32:13 -0800616}
617
David Brownell0365ee02006-06-19 14:27:20 -0700618static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
Andrew Victor39a269c2006-01-22 10:32:13 -0800619{
David Brownell4bde4a42007-12-27 11:19:49 -0800620 struct at91_usbh_data *pdata = pdev->dev.platform_data;
621 int i;
622
623 if (pdata) {
Justin Waters3d6fdf72009-04-03 21:06:53 +0100624 for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
Jean-Christophe PLAGNIOL-VILLARD8a7a49d2011-09-19 15:32:23 +0800625 if (!gpio_is_valid(pdata->vbus_pin[i]))
David Brownell4bde4a42007-12-27 11:19:49 -0800626 continue;
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200627 ohci_at91_usb_set_power(pdata, i, 0);
David Brownell4bde4a42007-12-27 11:19:49 -0800628 gpio_free(pdata->vbus_pin[i]);
629 }
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200630
631 for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) {
Jean-Christophe PLAGNIOL-VILLARD8a7a49d2011-09-19 15:32:23 +0800632 if (!gpio_is_valid(pdata->overcurrent_pin[i]))
Thomas Petazzoniaa6e52a2011-07-13 11:29:17 +0200633 continue;
634 free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev);
635 gpio_free(pdata->overcurrent_pin[i]);
636 }
David Brownell4bde4a42007-12-27 11:19:49 -0800637 }
638
David Brownell0365ee02006-06-19 14:27:20 -0700639 device_init_wakeup(&pdev->dev, 0);
Pete Zaitcev421b4bf2008-06-01 14:38:43 -0700640 usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
641 return 0;
Andrew Victor39a269c2006-01-22 10:32:13 -0800642}
643
644#ifdef CONFIG_PM
Andrew Victor39a269c2006-01-22 10:32:13 -0800645
David Brownell68ba61b2006-04-02 20:26:21 -0800646static int
David Brownell0365ee02006-06-19 14:27:20 -0700647ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg)
David Brownell68ba61b2006-04-02 20:26:21 -0800648{
David Brownell0365ee02006-06-19 14:27:20 -0700649 struct usb_hcd *hcd = platform_get_drvdata(pdev);
650 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
651
652 if (device_may_wakeup(&pdev->dev))
653 enable_irq_wake(hcd->irq);
David Brownell0365ee02006-06-19 14:27:20 -0700654
655 /*
656 * The integrated transceivers seem unable to notice disconnect,
657 * reconnect, or wakeup without the 48 MHz clock active. so for
658 * correctness, always discard connection state (using reset).
659 *
660 * REVISIT: some boards will be able to turn VBUS off...
661 */
662 if (at91_suspend_entering_slow_clock()) {
663 ohci_usb_reset (ohci);
Patrice Vilchez869aa982010-04-28 13:45:40 +0200664 /* flush the writes */
665 (void) ohci_readl (ohci, &ohci->regs->control);
Andrew Victored077bb2007-02-16 10:18:58 -0800666 at91_stop_clock();
David Brownell0365ee02006-06-19 14:27:20 -0700667 }
Andrew Victor39a269c2006-01-22 10:32:13 -0800668
669 return 0;
670}
671
David Brownell0365ee02006-06-19 14:27:20 -0700672static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
Andrew Victor39a269c2006-01-22 10:32:13 -0800673{
Marc Pignat6dde8962007-01-09 14:00:11 -0800674 struct usb_hcd *hcd = platform_get_drvdata(pdev);
675
676 if (device_may_wakeup(&pdev->dev))
677 disable_irq_wake(hcd->irq);
678
Andrew Victored077bb2007-02-16 10:18:58 -0800679 if (!clocked)
680 at91_start_clock();
Andrew Victor39a269c2006-01-22 10:32:13 -0800681
Alan Stern43bbb7e2008-04-03 18:03:17 -0400682 ohci_finish_controller_resume(hcd);
Andrew Victor39a269c2006-01-22 10:32:13 -0800683 return 0;
684}
685#else
686#define ohci_hcd_at91_drv_suspend NULL
687#define ohci_hcd_at91_drv_resume NULL
688#endif
689
Kay Sieversf4fce612008-04-10 21:29:22 -0700690MODULE_ALIAS("platform:at91_ohci");
David Brownell68ba61b2006-04-02 20:26:21 -0800691
Andrew Victor39a269c2006-01-22 10:32:13 -0800692static struct platform_driver ohci_hcd_at91_driver = {
693 .probe = ohci_hcd_at91_drv_probe,
694 .remove = ohci_hcd_at91_drv_remove,
Aleksey Gorelov64a21d02006-08-08 17:24:08 -0700695 .shutdown = usb_hcd_platform_shutdown,
Andrew Victor39a269c2006-01-22 10:32:13 -0800696 .suspend = ohci_hcd_at91_drv_suspend,
697 .resume = ohci_hcd_at91_drv_resume,
698 .driver = {
David Brownell0365ee02006-06-19 14:27:20 -0700699 .name = "at91_ohci",
Andrew Victor39a269c2006-01-22 10:32:13 -0800700 .owner = THIS_MODULE,
Jean-Christophe PLAGNIOL-VILLARD24197302011-11-21 06:55:18 +0800701 .of_match_table = of_match_ptr(at91_ohci_dt_ids),
Andrew Victor39a269c2006-01-22 10:32:13 -0800702 },
703};