| .. | .. |
|---|
| 108 | 108 | USB_IDLE = 0, |
|---|
| 109 | 109 | USB_PERIPHERAL, |
|---|
| 110 | 110 | USB_HOST, |
|---|
| 111 | | - USB_DEDICATED_CHG |
|---|
| 111 | + USB_DEDICATED_CHG, |
|---|
| 112 | + USB_UART |
|---|
| 112 | 113 | }; |
|---|
| 113 | 114 | |
|---|
| 114 | 115 | /* Register USB_LINK_STATUS interrupt */ |
|---|
| .. | .. |
|---|
| 330 | 331 | switch (lsts) { |
|---|
| 331 | 332 | case USB_LINK_ACA_RID_B_8505: |
|---|
| 332 | 333 | event = UX500_MUSB_RIDB; |
|---|
| 334 | + fallthrough; |
|---|
| 333 | 335 | case USB_LINK_NOT_CONFIGURED_8505: |
|---|
| 334 | 336 | case USB_LINK_RESERVED0_8505: |
|---|
| 335 | 337 | case USB_LINK_RESERVED1_8505: |
|---|
| .. | .. |
|---|
| 350 | 352 | |
|---|
| 351 | 353 | case USB_LINK_ACA_RID_C_NM_8505: |
|---|
| 352 | 354 | event = UX500_MUSB_RIDC; |
|---|
| 355 | + fallthrough; |
|---|
| 353 | 356 | case USB_LINK_STD_HOST_NC_8505: |
|---|
| 354 | 357 | case USB_LINK_STD_HOST_C_NS_8505: |
|---|
| 355 | 358 | case USB_LINK_STD_HOST_C_S_8505: |
|---|
| .. | .. |
|---|
| 368 | 371 | case USB_LINK_ACA_RID_A_8505: |
|---|
| 369 | 372 | case USB_LINK_ACA_DOCK_CHGR_8505: |
|---|
| 370 | 373 | event = UX500_MUSB_RIDA; |
|---|
| 374 | + fallthrough; |
|---|
| 371 | 375 | case USB_LINK_HM_IDGND_8505: |
|---|
| 372 | 376 | if (ab->mode == USB_IDLE) { |
|---|
| 373 | 377 | ab->mode = USB_HOST; |
|---|
| .. | .. |
|---|
| 388 | 392 | atomic_notifier_call_chain(&ab->phy.notifier, |
|---|
| 389 | 393 | event, &ab->vbus_draw); |
|---|
| 390 | 394 | usb_phy_set_event(&ab->phy, USB_EVENT_CHARGER); |
|---|
| 395 | + break; |
|---|
| 396 | + |
|---|
| 397 | + /* |
|---|
| 398 | + * FIXME: For now we rely on the boot firmware to set up the necessary |
|---|
| 399 | + * PHY/pin configuration for UART mode. |
|---|
| 400 | + * |
|---|
| 401 | + * AB8505 does not seem to report any status change for UART cables, |
|---|
| 402 | + * possibly because it cannot detect them autonomously. |
|---|
| 403 | + * We may need to measure the ID resistance manually to reliably |
|---|
| 404 | + * detect UART cables after bootup. |
|---|
| 405 | + */ |
|---|
| 406 | + case USB_LINK_SAMSUNG_UART_CBL_PHY_EN_8505: |
|---|
| 407 | + case USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_8505: |
|---|
| 408 | + if (ab->mode == USB_IDLE) { |
|---|
| 409 | + ab->mode = USB_UART; |
|---|
| 410 | + ab8500_usb_peri_phy_en(ab); |
|---|
| 411 | + } |
|---|
| 412 | + |
|---|
| 391 | 413 | break; |
|---|
| 392 | 414 | |
|---|
| 393 | 415 | default: |
|---|
| .. | .. |
|---|
| 422 | 444 | switch (lsts) { |
|---|
| 423 | 445 | case USB_LINK_ACA_RID_B_8500: |
|---|
| 424 | 446 | event = UX500_MUSB_RIDB; |
|---|
| 447 | + fallthrough; |
|---|
| 425 | 448 | case USB_LINK_NOT_CONFIGURED_8500: |
|---|
| 426 | 449 | case USB_LINK_NOT_VALID_LINK_8500: |
|---|
| 427 | 450 | ab->mode = USB_IDLE; |
|---|
| .. | .. |
|---|
| 438 | 461 | case USB_LINK_ACA_RID_C_HS_8500: |
|---|
| 439 | 462 | case USB_LINK_ACA_RID_C_HS_CHIRP_8500: |
|---|
| 440 | 463 | event = UX500_MUSB_RIDC; |
|---|
| 464 | + fallthrough; |
|---|
| 441 | 465 | case USB_LINK_STD_HOST_NC_8500: |
|---|
| 442 | 466 | case USB_LINK_STD_HOST_C_NS_8500: |
|---|
| 443 | 467 | case USB_LINK_STD_HOST_C_S_8500: |
|---|
| .. | .. |
|---|
| 457 | 481 | |
|---|
| 458 | 482 | case USB_LINK_ACA_RID_A_8500: |
|---|
| 459 | 483 | event = UX500_MUSB_RIDA; |
|---|
| 484 | + fallthrough; |
|---|
| 460 | 485 | case USB_LINK_HM_IDGND_8500: |
|---|
| 461 | 486 | if (ab->mode == USB_IDLE) { |
|---|
| 462 | 487 | ab->mode = USB_HOST; |
|---|
| .. | .. |
|---|
| 493 | 518 | * 3. Enable AB regulators |
|---|
| 494 | 519 | * 4. Enable USB phy |
|---|
| 495 | 520 | * 5. Reset the musb controller |
|---|
| 496 | | - * 6. Switch the ULPI GPIO pins to fucntion mode |
|---|
| 521 | + * 6. Switch the ULPI GPIO pins to function mode |
|---|
| 497 | 522 | * 7. Enable the musb Peripheral5 clock |
|---|
| 498 | 523 | * 8. Restore MUSB context |
|---|
| 499 | 524 | */ |
|---|
| .. | .. |
|---|
| 505 | 530 | if (is_ab8500(ab->ab8500)) { |
|---|
| 506 | 531 | enum ab8500_usb_link_status lsts; |
|---|
| 507 | 532 | |
|---|
| 508 | | - abx500_get_register_interruptible(ab->dev, |
|---|
| 533 | + ret = abx500_get_register_interruptible(ab->dev, |
|---|
| 509 | 534 | AB8500_USB, AB8500_USB_LINE_STAT_REG, ®); |
|---|
| 535 | + if (ret < 0) |
|---|
| 536 | + return ret; |
|---|
| 510 | 537 | lsts = (reg >> 3) & 0x0F; |
|---|
| 511 | 538 | ret = ab8500_usb_link_status_update(ab, lsts); |
|---|
| 512 | 539 | } else if (is_ab8505(ab->ab8500)) { |
|---|
| 513 | 540 | enum ab8505_usb_link_status lsts; |
|---|
| 514 | 541 | |
|---|
| 515 | | - abx500_get_register_interruptible(ab->dev, |
|---|
| 542 | + ret = abx500_get_register_interruptible(ab->dev, |
|---|
| 516 | 543 | AB8500_USB, AB8505_USB_LINE_STAT_REG, ®); |
|---|
| 544 | + if (ret < 0) |
|---|
| 545 | + return ret; |
|---|
| 517 | 546 | lsts = (reg >> 3) & 0x1F; |
|---|
| 518 | 547 | ret = ab8505_usb_link_status_update(ab, lsts); |
|---|
| 519 | 548 | } |
|---|
| .. | .. |
|---|
| 554 | 583 | ab->mode = USB_IDLE; |
|---|
| 555 | 584 | ab->phy.otg->default_a = false; |
|---|
| 556 | 585 | ab->vbus_draw = 0; |
|---|
| 586 | + } |
|---|
| 587 | + |
|---|
| 588 | + if (ab->mode == USB_UART) { |
|---|
| 589 | + ab8500_usb_peri_phy_dis(ab); |
|---|
| 590 | + ab->mode = USB_IDLE; |
|---|
| 557 | 591 | } |
|---|
| 558 | 592 | |
|---|
| 559 | 593 | if (is_ab8500_2p0(ab->ab8500)) { |
|---|
| .. | .. |
|---|
| 708 | 742 | |
|---|
| 709 | 743 | if (ab->flags & AB8500_USB_FLAG_USE_LINK_STATUS_IRQ) { |
|---|
| 710 | 744 | irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS"); |
|---|
| 711 | | - if (irq < 0) { |
|---|
| 712 | | - dev_err(&pdev->dev, "Link status irq not found\n"); |
|---|
| 745 | + if (irq < 0) |
|---|
| 713 | 746 | return irq; |
|---|
| 714 | | - } |
|---|
| 715 | 747 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
|---|
| 716 | 748 | ab8500_usb_link_status_irq, |
|---|
| 717 | 749 | IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, |
|---|
| .. | .. |
|---|
| 724 | 756 | |
|---|
| 725 | 757 | if (ab->flags & AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ) { |
|---|
| 726 | 758 | irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); |
|---|
| 727 | | - if (irq < 0) { |
|---|
| 728 | | - dev_err(&pdev->dev, "ID fall irq not found\n"); |
|---|
| 759 | + if (irq < 0) |
|---|
| 729 | 760 | return irq; |
|---|
| 730 | | - } |
|---|
| 731 | 761 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
|---|
| 732 | 762 | ab8500_usb_disconnect_irq, |
|---|
| 733 | 763 | IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, |
|---|
| .. | .. |
|---|
| 740 | 770 | |
|---|
| 741 | 771 | if (ab->flags & AB8500_USB_FLAG_USE_VBUS_DET_IRQ) { |
|---|
| 742 | 772 | irq = platform_get_irq_byname(pdev, "VBUS_DET_F"); |
|---|
| 743 | | - if (irq < 0) { |
|---|
| 744 | | - dev_err(&pdev->dev, "VBUS fall irq not found\n"); |
|---|
| 773 | + if (irq < 0) |
|---|
| 745 | 774 | return irq; |
|---|
| 746 | | - } |
|---|
| 747 | 775 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
|---|
| 748 | 776 | ab8500_usb_disconnect_irq, |
|---|
| 749 | 777 | IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, |
|---|