diff options
Diffstat (limited to 'drivers/usb/host/ohci-at91.c')
-rw-r--r-- | drivers/usb/host/ohci-at91.c | 184 |
1 files changed, 146 insertions, 38 deletions
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 8e855eb0bf89..09f597ad6e00 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/of_platform.h> | ||
18 | #include <linux/of_gpio.h> | ||
17 | 19 | ||
18 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
19 | #include <asm/gpio.h> | 21 | #include <asm/gpio.h> |
@@ -25,6 +27,10 @@ | |||
25 | #error "CONFIG_ARCH_AT91 must be defined." | 27 | #error "CONFIG_ARCH_AT91 must be defined." |
26 | #endif | 28 | #endif |
27 | 29 | ||
30 | #define valid_port(index) ((index) >= 0 && (index) < AT91_MAX_USBH_PORTS) | ||
31 | #define at91_for_each_port(index) \ | ||
32 | for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++) | ||
33 | |||
28 | /* interface and function clocks; sometimes also an AHB clock */ | 34 | /* interface and function clocks; sometimes also an AHB clock */ |
29 | static struct clk *iclk, *fclk, *hclk; | 35 | static struct clk *iclk, *fclk, *hclk; |
30 | static int clocked; | 36 | static int clocked; |
@@ -238,26 +244,26 @@ ohci_at91_start (struct usb_hcd *hcd) | |||
238 | 244 | ||
239 | static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable) | 245 | static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable) |
240 | { | 246 | { |
241 | if (port < 0 || port >= 2) | 247 | if (!valid_port(port)) |
242 | return; | 248 | return; |
243 | 249 | ||
244 | if (!gpio_is_valid(pdata->vbus_pin[port])) | 250 | if (!gpio_is_valid(pdata->vbus_pin[port])) |
245 | return; | 251 | return; |
246 | 252 | ||
247 | gpio_set_value(pdata->vbus_pin[port], | 253 | gpio_set_value(pdata->vbus_pin[port], |
248 | !pdata->vbus_pin_active_low[port] ^ enable); | 254 | pdata->vbus_pin_active_low[port] ^ enable); |
249 | } | 255 | } |
250 | 256 | ||
251 | static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) | 257 | static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) |
252 | { | 258 | { |
253 | if (port < 0 || port >= 2) | 259 | if (!valid_port(port)) |
254 | return -EINVAL; | 260 | return -EINVAL; |
255 | 261 | ||
256 | if (!gpio_is_valid(pdata->vbus_pin[port])) | 262 | if (!gpio_is_valid(pdata->vbus_pin[port])) |
257 | return -EINVAL; | 263 | return -EINVAL; |
258 | 264 | ||
259 | return gpio_get_value(pdata->vbus_pin[port]) ^ | 265 | return gpio_get_value(pdata->vbus_pin[port]) ^ |
260 | !pdata->vbus_pin_active_low[port]; | 266 | pdata->vbus_pin_active_low[port]; |
261 | } | 267 | } |
262 | 268 | ||
263 | /* | 269 | /* |
@@ -269,9 +275,9 @@ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
269 | int length = ohci_hub_status_data(hcd, buf); | 275 | int length = ohci_hub_status_data(hcd, buf); |
270 | int port; | 276 | int port; |
271 | 277 | ||
272 | for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) { | 278 | at91_for_each_port(port) { |
273 | if (pdata->overcurrent_changed[port]) { | 279 | if (pdata->overcurrent_changed[port]) { |
274 | if (! length) | 280 | if (!length) |
275 | length = 1; | 281 | length = 1; |
276 | buf[0] |= 1 << (port + 1); | 282 | buf[0] |= 1 << (port + 1); |
277 | } | 283 | } |
@@ -295,11 +301,17 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
295 | "ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", | 301 | "ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", |
296 | hcd, typeReq, wValue, wIndex, buf, wLength); | 302 | hcd, typeReq, wValue, wIndex, buf, wLength); |
297 | 303 | ||
304 | wIndex--; | ||
305 | |||
298 | switch (typeReq) { | 306 | switch (typeReq) { |
299 | case SetPortFeature: | 307 | case SetPortFeature: |
300 | if (wValue == USB_PORT_FEAT_POWER) { | 308 | if (wValue == USB_PORT_FEAT_POWER) { |
301 | dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); | 309 | dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); |
302 | ohci_at91_usb_set_power(pdata, wIndex - 1, 1); | 310 | if (valid_port(wIndex)) { |
311 | ohci_at91_usb_set_power(pdata, wIndex, 1); | ||
312 | ret = 0; | ||
313 | } | ||
314 | |||
303 | goto out; | 315 | goto out; |
304 | } | 316 | } |
305 | break; | 317 | break; |
@@ -310,9 +322,9 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
310 | dev_dbg(hcd->self.controller, | 322 | dev_dbg(hcd->self.controller, |
311 | "ClearPortFeature: C_OVER_CURRENT\n"); | 323 | "ClearPortFeature: C_OVER_CURRENT\n"); |
312 | 324 | ||
313 | if (wIndex == 1 || wIndex == 2) { | 325 | if (valid_port(wIndex)) { |
314 | pdata->overcurrent_changed[wIndex-1] = 0; | 326 | pdata->overcurrent_changed[wIndex] = 0; |
315 | pdata->overcurrent_status[wIndex-1] = 0; | 327 | pdata->overcurrent_status[wIndex] = 0; |
316 | } | 328 | } |
317 | 329 | ||
318 | goto out; | 330 | goto out; |
@@ -321,9 +333,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
321 | dev_dbg(hcd->self.controller, | 333 | dev_dbg(hcd->self.controller, |
322 | "ClearPortFeature: OVER_CURRENT\n"); | 334 | "ClearPortFeature: OVER_CURRENT\n"); |
323 | 335 | ||
324 | if (wIndex == 1 || wIndex == 2) { | 336 | if (valid_port(wIndex)) |
325 | pdata->overcurrent_status[wIndex-1] = 0; | 337 | pdata->overcurrent_status[wIndex] = 0; |
326 | } | ||
327 | 338 | ||
328 | goto out; | 339 | goto out; |
329 | 340 | ||
@@ -331,15 +342,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
331 | dev_dbg(hcd->self.controller, | 342 | dev_dbg(hcd->self.controller, |
332 | "ClearPortFeature: POWER\n"); | 343 | "ClearPortFeature: POWER\n"); |
333 | 344 | ||
334 | if (wIndex == 1 || wIndex == 2) { | 345 | if (valid_port(wIndex)) { |
335 | ohci_at91_usb_set_power(pdata, wIndex - 1, 0); | 346 | ohci_at91_usb_set_power(pdata, wIndex, 0); |
336 | return 0; | 347 | return 0; |
337 | } | 348 | } |
338 | } | 349 | } |
339 | break; | 350 | break; |
340 | } | 351 | } |
341 | 352 | ||
342 | ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); | 353 | ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength); |
343 | if (ret) | 354 | if (ret) |
344 | goto out; | 355 | goto out; |
345 | 356 | ||
@@ -375,18 +386,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
375 | 386 | ||
376 | dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); | 387 | dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); |
377 | 388 | ||
378 | if (wIndex == 1 || wIndex == 2) { | 389 | if (valid_port(wIndex)) { |
379 | if (! ohci_at91_usb_get_power(pdata, wIndex-1)) { | 390 | if (!ohci_at91_usb_get_power(pdata, wIndex)) |
380 | *data &= ~cpu_to_le32(RH_PS_PPS); | 391 | *data &= ~cpu_to_le32(RH_PS_PPS); |
381 | } | ||
382 | 392 | ||
383 | if (pdata->overcurrent_changed[wIndex-1]) { | 393 | if (pdata->overcurrent_changed[wIndex]) |
384 | *data |= cpu_to_le32(RH_PS_OCIC); | 394 | *data |= cpu_to_le32(RH_PS_OCIC); |
385 | } | ||
386 | 395 | ||
387 | if (pdata->overcurrent_status[wIndex-1]) { | 396 | if (pdata->overcurrent_status[wIndex]) |
388 | *data |= cpu_to_le32(RH_PS_POCI); | 397 | *data |= cpu_to_le32(RH_PS_POCI); |
389 | } | ||
390 | } | 398 | } |
391 | } | 399 | } |
392 | 400 | ||
@@ -448,14 +456,14 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) | |||
448 | 456 | ||
449 | /* From the GPIO notifying the over-current situation, find | 457 | /* From the GPIO notifying the over-current situation, find |
450 | * out the corresponding port */ | 458 | * out the corresponding port */ |
451 | for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) { | 459 | at91_for_each_port(port) { |
452 | if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { | 460 | if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { |
453 | gpio = pdata->overcurrent_pin[port]; | 461 | gpio = pdata->overcurrent_pin[port]; |
454 | break; | 462 | break; |
455 | } | 463 | } |
456 | } | 464 | } |
457 | 465 | ||
458 | if (port == ARRAY_SIZE(pdata->overcurrent_pin)) { | 466 | if (port == AT91_MAX_USBH_PORTS) { |
459 | dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n"); | 467 | dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n"); |
460 | return IRQ_HANDLED; | 468 | return IRQ_HANDLED; |
461 | } | 469 | } |
@@ -465,7 +473,7 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) | |||
465 | /* When notified of an over-current situation, disable power | 473 | /* When notified of an over-current situation, disable power |
466 | on the corresponding port, and mark this port in | 474 | on the corresponding port, and mark this port in |
467 | over-current. */ | 475 | over-current. */ |
468 | if (! val) { | 476 | if (!val) { |
469 | ohci_at91_usb_set_power(pdata, port, 0); | 477 | ohci_at91_usb_set_power(pdata, port, 0); |
470 | pdata->overcurrent_status[port] = 1; | 478 | pdata->overcurrent_status[port] = 1; |
471 | pdata->overcurrent_changed[port] = 1; | 479 | pdata->overcurrent_changed[port] = 1; |
@@ -477,34 +485,133 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) | |||
477 | return IRQ_HANDLED; | 485 | return IRQ_HANDLED; |
478 | } | 486 | } |
479 | 487 | ||
488 | #ifdef CONFIG_OF | ||
489 | static const struct of_device_id at91_ohci_dt_ids[] = { | ||
490 | { .compatible = "atmel,at91rm9200-ohci" }, | ||
491 | { /* sentinel */ } | ||
492 | }; | ||
493 | |||
494 | MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids); | ||
495 | |||
496 | static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32); | ||
497 | |||
498 | static int __devinit ohci_at91_of_init(struct platform_device *pdev) | ||
499 | { | ||
500 | struct device_node *np = pdev->dev.of_node; | ||
501 | int i, gpio; | ||
502 | enum of_gpio_flags flags; | ||
503 | struct at91_usbh_data *pdata; | ||
504 | u32 ports; | ||
505 | |||
506 | if (!np) | ||
507 | return 0; | ||
508 | |||
509 | /* Right now device-tree probed devices don't get dma_mask set. | ||
510 | * Since shared usb code relies on it, set it here for now. | ||
511 | * Once we have dma capability bindings this can go away. | ||
512 | */ | ||
513 | if (!pdev->dev.dma_mask) | ||
514 | pdev->dev.dma_mask = &at91_ohci_dma_mask; | ||
515 | |||
516 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
517 | if (!pdata) | ||
518 | return -ENOMEM; | ||
519 | |||
520 | if (!of_property_read_u32(np, "num-ports", &ports)) | ||
521 | pdata->ports = ports; | ||
522 | |||
523 | at91_for_each_port(i) { | ||
524 | gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags); | ||
525 | pdata->vbus_pin[i] = gpio; | ||
526 | if (!gpio_is_valid(gpio)) | ||
527 | continue; | ||
528 | pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW; | ||
529 | } | ||
530 | |||
531 | at91_for_each_port(i) | ||
532 | pdata->overcurrent_pin[i] = | ||
533 | of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); | ||
534 | |||
535 | pdev->dev.platform_data = pdata; | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | #else | ||
540 | static int __devinit ohci_at91_of_init(struct platform_device *pdev) | ||
541 | { | ||
542 | return 0; | ||
543 | } | ||
544 | #endif | ||
545 | |||
480 | /*-------------------------------------------------------------------------*/ | 546 | /*-------------------------------------------------------------------------*/ |
481 | 547 | ||
482 | static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) | 548 | static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) |
483 | { | 549 | { |
484 | struct at91_usbh_data *pdata = pdev->dev.platform_data; | 550 | struct at91_usbh_data *pdata; |
485 | int i; | 551 | int i; |
552 | int gpio; | ||
553 | int ret; | ||
554 | |||
555 | ret = ohci_at91_of_init(pdev); | ||
556 | if (ret) | ||
557 | return ret; | ||
558 | |||
559 | pdata = pdev->dev.platform_data; | ||
486 | 560 | ||
487 | if (pdata) { | 561 | if (pdata) { |
488 | for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { | 562 | at91_for_each_port(i) { |
489 | if (!gpio_is_valid(pdata->vbus_pin[i])) | 563 | if (!gpio_is_valid(pdata->vbus_pin[i])) |
490 | continue; | 564 | continue; |
491 | gpio_request(pdata->vbus_pin[i], "ohci_vbus"); | 565 | gpio = pdata->vbus_pin[i]; |
566 | |||
567 | ret = gpio_request(gpio, "ohci_vbus"); | ||
568 | if (ret) { | ||
569 | dev_err(&pdev->dev, | ||
570 | "can't request vbus gpio %d\n", gpio); | ||
571 | continue; | ||
572 | } | ||
573 | ret = gpio_direction_output(gpio, | ||
574 | !pdata->vbus_pin_active_low[i]); | ||
575 | if (ret) { | ||
576 | dev_err(&pdev->dev, | ||
577 | "can't put vbus gpio %d as output %d\n", | ||
578 | gpio, !pdata->vbus_pin_active_low[i]); | ||
579 | gpio_free(gpio); | ||
580 | continue; | ||
581 | } | ||
582 | |||
492 | ohci_at91_usb_set_power(pdata, i, 1); | 583 | ohci_at91_usb_set_power(pdata, i, 1); |
493 | } | 584 | } |
494 | 585 | ||
495 | for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) { | 586 | at91_for_each_port(i) { |
496 | int ret; | ||
497 | |||
498 | if (!gpio_is_valid(pdata->overcurrent_pin[i])) | 587 | if (!gpio_is_valid(pdata->overcurrent_pin[i])) |
499 | continue; | 588 | continue; |
500 | gpio_request(pdata->overcurrent_pin[i], "ohci_overcurrent"); | 589 | gpio = pdata->overcurrent_pin[i]; |
590 | |||
591 | ret = gpio_request(gpio, "ohci_overcurrent"); | ||
592 | if (ret) { | ||
593 | dev_err(&pdev->dev, | ||
594 | "can't request overcurrent gpio %d\n", | ||
595 | gpio); | ||
596 | continue; | ||
597 | } | ||
598 | |||
599 | ret = gpio_direction_input(gpio); | ||
600 | if (ret) { | ||
601 | dev_err(&pdev->dev, | ||
602 | "can't configure overcurrent gpio %d as input\n", | ||
603 | gpio); | ||
604 | gpio_free(gpio); | ||
605 | continue; | ||
606 | } | ||
501 | 607 | ||
502 | ret = request_irq(gpio_to_irq(pdata->overcurrent_pin[i]), | 608 | ret = request_irq(gpio_to_irq(gpio), |
503 | ohci_hcd_at91_overcurrent_irq, | 609 | ohci_hcd_at91_overcurrent_irq, |
504 | IRQF_SHARED, "ohci_overcurrent", pdev); | 610 | IRQF_SHARED, "ohci_overcurrent", pdev); |
505 | if (ret) { | 611 | if (ret) { |
506 | gpio_free(pdata->overcurrent_pin[i]); | 612 | gpio_free(gpio); |
507 | dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n"); | 613 | dev_err(&pdev->dev, |
614 | "can't get gpio IRQ for overcurrent\n"); | ||
508 | } | 615 | } |
509 | } | 616 | } |
510 | } | 617 | } |
@@ -519,14 +626,14 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) | |||
519 | int i; | 626 | int i; |
520 | 627 | ||
521 | if (pdata) { | 628 | if (pdata) { |
522 | for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { | 629 | at91_for_each_port(i) { |
523 | if (!gpio_is_valid(pdata->vbus_pin[i])) | 630 | if (!gpio_is_valid(pdata->vbus_pin[i])) |
524 | continue; | 631 | continue; |
525 | ohci_at91_usb_set_power(pdata, i, 0); | 632 | ohci_at91_usb_set_power(pdata, i, 0); |
526 | gpio_free(pdata->vbus_pin[i]); | 633 | gpio_free(pdata->vbus_pin[i]); |
527 | } | 634 | } |
528 | 635 | ||
529 | for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) { | 636 | at91_for_each_port(i) { |
530 | if (!gpio_is_valid(pdata->overcurrent_pin[i])) | 637 | if (!gpio_is_valid(pdata->overcurrent_pin[i])) |
531 | continue; | 638 | continue; |
532 | free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev); | 639 | free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev); |
@@ -596,5 +703,6 @@ static struct platform_driver ohci_hcd_at91_driver = { | |||
596 | .driver = { | 703 | .driver = { |
597 | .name = "at91_ohci", | 704 | .name = "at91_ohci", |
598 | .owner = THIS_MODULE, | 705 | .owner = THIS_MODULE, |
706 | .of_match_table = of_match_ptr(at91_ohci_dt_ids), | ||
599 | }, | 707 | }, |
600 | }; | 708 | }; |