diff options
Diffstat (limited to 'drivers/usb/chipidea/core.c')
-rw-r--r-- | drivers/usb/chipidea/core.c | 173 |
1 files changed, 69 insertions, 104 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 3dbb4a21ab44..79ad8e91632e 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
@@ -62,7 +62,6 @@ | |||
62 | #include <linux/usb/chipidea.h> | 62 | #include <linux/usb/chipidea.h> |
63 | #include <linux/usb/of.h> | 63 | #include <linux/usb/of.h> |
64 | #include <linux/of.h> | 64 | #include <linux/of.h> |
65 | #include <linux/phy.h> | ||
66 | #include <linux/regulator/consumer.h> | 65 | #include <linux/regulator/consumer.h> |
67 | #include <linux/usb/ehci_def.h> | 66 | #include <linux/usb/ehci_def.h> |
68 | 67 | ||
@@ -86,6 +85,7 @@ static const u8 ci_regs_nolpm[] = { | |||
86 | [OP_ENDPTLISTADDR] = 0x18U, | 85 | [OP_ENDPTLISTADDR] = 0x18U, |
87 | [OP_TTCTRL] = 0x1CU, | 86 | [OP_TTCTRL] = 0x1CU, |
88 | [OP_BURSTSIZE] = 0x20U, | 87 | [OP_BURSTSIZE] = 0x20U, |
88 | [OP_ULPI_VIEWPORT] = 0x30U, | ||
89 | [OP_PORTSC] = 0x44U, | 89 | [OP_PORTSC] = 0x44U, |
90 | [OP_DEVLC] = 0x84U, | 90 | [OP_DEVLC] = 0x84U, |
91 | [OP_OTGSC] = 0x64U, | 91 | [OP_OTGSC] = 0x64U, |
@@ -110,6 +110,7 @@ static const u8 ci_regs_lpm[] = { | |||
110 | [OP_ENDPTLISTADDR] = 0x18U, | 110 | [OP_ENDPTLISTADDR] = 0x18U, |
111 | [OP_TTCTRL] = 0x1CU, | 111 | [OP_TTCTRL] = 0x1CU, |
112 | [OP_BURSTSIZE] = 0x20U, | 112 | [OP_BURSTSIZE] = 0x20U, |
113 | [OP_ULPI_VIEWPORT] = 0x30U, | ||
113 | [OP_PORTSC] = 0x44U, | 114 | [OP_PORTSC] = 0x44U, |
114 | [OP_DEVLC] = 0x84U, | 115 | [OP_DEVLC] = 0x84U, |
115 | [OP_OTGSC] = 0xC4U, | 116 | [OP_OTGSC] = 0xC4U, |
@@ -285,7 +286,7 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base) | |||
285 | return 0; | 286 | return 0; |
286 | } | 287 | } |
287 | 288 | ||
288 | static void hw_phymode_configure(struct ci_hdrc *ci) | 289 | void hw_phymode_configure(struct ci_hdrc *ci) |
289 | { | 290 | { |
290 | u32 portsc, lpm, sts = 0; | 291 | u32 portsc, lpm, sts = 0; |
291 | 292 | ||
@@ -325,6 +326,7 @@ static void hw_phymode_configure(struct ci_hdrc *ci) | |||
325 | hw_write(ci, OP_PORTSC, PORTSC_STS, PORTSC_STS); | 326 | hw_write(ci, OP_PORTSC, PORTSC_STS, PORTSC_STS); |
326 | } | 327 | } |
327 | } | 328 | } |
329 | EXPORT_SYMBOL_GPL(hw_phymode_configure); | ||
328 | 330 | ||
329 | /** | 331 | /** |
330 | * _ci_usb_phy_init: initialize phy taking in account both phy and usb_phy | 332 | * _ci_usb_phy_init: initialize phy taking in account both phy and usb_phy |
@@ -361,6 +363,9 @@ static int _ci_usb_phy_init(struct ci_hdrc *ci) | |||
361 | */ | 363 | */ |
362 | static void ci_usb_phy_exit(struct ci_hdrc *ci) | 364 | static void ci_usb_phy_exit(struct ci_hdrc *ci) |
363 | { | 365 | { |
366 | if (ci->platdata->flags & CI_HDRC_OVERRIDE_PHY_CONTROL) | ||
367 | return; | ||
368 | |||
364 | if (ci->phy) { | 369 | if (ci->phy) { |
365 | phy_power_off(ci->phy); | 370 | phy_power_off(ci->phy); |
366 | phy_exit(ci->phy); | 371 | phy_exit(ci->phy); |
@@ -379,6 +384,9 @@ static int ci_usb_phy_init(struct ci_hdrc *ci) | |||
379 | { | 384 | { |
380 | int ret; | 385 | int ret; |
381 | 386 | ||
387 | if (ci->platdata->flags & CI_HDRC_OVERRIDE_PHY_CONTROL) | ||
388 | return 0; | ||
389 | |||
382 | switch (ci->platdata->phy_mode) { | 390 | switch (ci->platdata->phy_mode) { |
383 | case USBPHY_INTERFACE_MODE_UTMI: | 391 | case USBPHY_INTERFACE_MODE_UTMI: |
384 | case USBPHY_INTERFACE_MODE_UTMIW: | 392 | case USBPHY_INTERFACE_MODE_UTMIW: |
@@ -419,13 +427,21 @@ void ci_platform_configure(struct ci_hdrc *ci) | |||
419 | is_device_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_DC; | 427 | is_device_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_DC; |
420 | is_host_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_HC; | 428 | is_host_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_HC; |
421 | 429 | ||
422 | if (is_device_mode && | 430 | if (is_device_mode) { |
423 | (ci->platdata->flags & CI_HDRC_DISABLE_DEVICE_STREAMING)) | 431 | phy_set_mode(ci->phy, PHY_MODE_USB_DEVICE); |
424 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | 432 | |
433 | if (ci->platdata->flags & CI_HDRC_DISABLE_DEVICE_STREAMING) | ||
434 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, | ||
435 | USBMODE_CI_SDIS); | ||
436 | } | ||
437 | |||
438 | if (is_host_mode) { | ||
439 | phy_set_mode(ci->phy, PHY_MODE_USB_HOST); | ||
425 | 440 | ||
426 | if (is_host_mode && | 441 | if (ci->platdata->flags & CI_HDRC_DISABLE_HOST_STREAMING) |
427 | (ci->platdata->flags & CI_HDRC_DISABLE_HOST_STREAMING)) | 442 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, |
428 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | 443 | USBMODE_CI_SDIS); |
444 | } | ||
429 | 445 | ||
430 | if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) { | 446 | if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) { |
431 | if (ci->hw_bank.lpm) | 447 | if (ci->hw_bank.lpm) |
@@ -495,9 +511,12 @@ int hw_device_reset(struct ci_hdrc *ci) | |||
495 | return ret; | 511 | return ret; |
496 | } | 512 | } |
497 | 513 | ||
498 | if (ci->platdata->notify_event) | 514 | if (ci->platdata->notify_event) { |
499 | ci->platdata->notify_event(ci, | 515 | ret = ci->platdata->notify_event(ci, |
500 | CI_HDRC_CONTROLLER_RESET_EVENT); | 516 | CI_HDRC_CONTROLLER_RESET_EVENT); |
517 | if (ret) | ||
518 | return ret; | ||
519 | } | ||
501 | 520 | ||
502 | /* USBMODE should be configured step by step */ | 521 | /* USBMODE should be configured step by step */ |
503 | hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); | 522 | hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); |
@@ -516,38 +535,6 @@ int hw_device_reset(struct ci_hdrc *ci) | |||
516 | return 0; | 535 | return 0; |
517 | } | 536 | } |
518 | 537 | ||
519 | /** | ||
520 | * hw_wait_reg: wait the register value | ||
521 | * | ||
522 | * Sometimes, it needs to wait register value before going on. | ||
523 | * Eg, when switch to device mode, the vbus value should be lower | ||
524 | * than OTGSC_BSV before connects to host. | ||
525 | * | ||
526 | * @ci: the controller | ||
527 | * @reg: register index | ||
528 | * @mask: mast bit | ||
529 | * @value: the bit value to wait | ||
530 | * @timeout_ms: timeout in millisecond | ||
531 | * | ||
532 | * This function returns an error code if timeout | ||
533 | */ | ||
534 | int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask, | ||
535 | u32 value, unsigned int timeout_ms) | ||
536 | { | ||
537 | unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms); | ||
538 | |||
539 | while (hw_read(ci, reg, mask) != value) { | ||
540 | if (time_after(jiffies, elapse)) { | ||
541 | dev_err(ci->dev, "timeout waiting for %08x in %d\n", | ||
542 | mask, reg); | ||
543 | return -ETIMEDOUT; | ||
544 | } | ||
545 | msleep(20); | ||
546 | } | ||
547 | |||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static irqreturn_t ci_irq(int irq, void *data) | 538 | static irqreturn_t ci_irq(int irq, void *data) |
552 | { | 539 | { |
553 | struct ci_hdrc *ci = data; | 540 | struct ci_hdrc *ci = data; |
@@ -601,35 +588,14 @@ static irqreturn_t ci_irq(int irq, void *data) | |||
601 | return ret; | 588 | return ret; |
602 | } | 589 | } |
603 | 590 | ||
604 | static int ci_vbus_notifier(struct notifier_block *nb, unsigned long event, | 591 | static int ci_cable_notifier(struct notifier_block *nb, unsigned long event, |
605 | void *ptr) | 592 | void *ptr) |
606 | { | ||
607 | struct ci_hdrc_cable *vbus = container_of(nb, struct ci_hdrc_cable, nb); | ||
608 | struct ci_hdrc *ci = vbus->ci; | ||
609 | |||
610 | if (event) | ||
611 | vbus->state = true; | ||
612 | else | ||
613 | vbus->state = false; | ||
614 | |||
615 | vbus->changed = true; | ||
616 | |||
617 | ci_irq(ci->irq, ci); | ||
618 | return NOTIFY_DONE; | ||
619 | } | ||
620 | |||
621 | static int ci_id_notifier(struct notifier_block *nb, unsigned long event, | ||
622 | void *ptr) | ||
623 | { | 593 | { |
624 | struct ci_hdrc_cable *id = container_of(nb, struct ci_hdrc_cable, nb); | 594 | struct ci_hdrc_cable *cbl = container_of(nb, struct ci_hdrc_cable, nb); |
625 | struct ci_hdrc *ci = id->ci; | 595 | struct ci_hdrc *ci = cbl->ci; |
626 | 596 | ||
627 | if (event) | 597 | cbl->connected = event; |
628 | id->state = false; | 598 | cbl->changed = true; |
629 | else | ||
630 | id->state = true; | ||
631 | |||
632 | id->changed = true; | ||
633 | 599 | ||
634 | ci_irq(ci->irq, ci); | 600 | ci_irq(ci->irq, ci); |
635 | return NOTIFY_DONE; | 601 | return NOTIFY_DONE; |
@@ -738,27 +704,27 @@ static int ci_get_platdata(struct device *dev, | |||
738 | } | 704 | } |
739 | 705 | ||
740 | cable = &platdata->vbus_extcon; | 706 | cable = &platdata->vbus_extcon; |
741 | cable->nb.notifier_call = ci_vbus_notifier; | 707 | cable->nb.notifier_call = ci_cable_notifier; |
742 | cable->edev = ext_vbus; | 708 | cable->edev = ext_vbus; |
743 | 709 | ||
744 | if (!IS_ERR(ext_vbus)) { | 710 | if (!IS_ERR(ext_vbus)) { |
745 | ret = extcon_get_cable_state_(cable->edev, EXTCON_USB); | 711 | ret = extcon_get_state(cable->edev, EXTCON_USB); |
746 | if (ret) | 712 | if (ret) |
747 | cable->state = true; | 713 | cable->connected = true; |
748 | else | 714 | else |
749 | cable->state = false; | 715 | cable->connected = false; |
750 | } | 716 | } |
751 | 717 | ||
752 | cable = &platdata->id_extcon; | 718 | cable = &platdata->id_extcon; |
753 | cable->nb.notifier_call = ci_id_notifier; | 719 | cable->nb.notifier_call = ci_cable_notifier; |
754 | cable->edev = ext_id; | 720 | cable->edev = ext_id; |
755 | 721 | ||
756 | if (!IS_ERR(ext_id)) { | 722 | if (!IS_ERR(ext_id)) { |
757 | ret = extcon_get_cable_state_(cable->edev, EXTCON_USB_HOST); | 723 | ret = extcon_get_state(cable->edev, EXTCON_USB_HOST); |
758 | if (ret) | 724 | if (ret) |
759 | cable->state = false; | 725 | cable->connected = true; |
760 | else | 726 | else |
761 | cable->state = true; | 727 | cable->connected = false; |
762 | } | 728 | } |
763 | return 0; | 729 | return 0; |
764 | } | 730 | } |
@@ -771,8 +737,8 @@ static int ci_extcon_register(struct ci_hdrc *ci) | |||
771 | id = &ci->platdata->id_extcon; | 737 | id = &ci->platdata->id_extcon; |
772 | id->ci = ci; | 738 | id->ci = ci; |
773 | if (!IS_ERR(id->edev)) { | 739 | if (!IS_ERR(id->edev)) { |
774 | ret = extcon_register_notifier(id->edev, EXTCON_USB_HOST, | 740 | ret = devm_extcon_register_notifier(ci->dev, id->edev, |
775 | &id->nb); | 741 | EXTCON_USB_HOST, &id->nb); |
776 | if (ret < 0) { | 742 | if (ret < 0) { |
777 | dev_err(ci->dev, "register ID failed\n"); | 743 | dev_err(ci->dev, "register ID failed\n"); |
778 | return ret; | 744 | return ret; |
@@ -782,11 +748,9 @@ static int ci_extcon_register(struct ci_hdrc *ci) | |||
782 | vbus = &ci->platdata->vbus_extcon; | 748 | vbus = &ci->platdata->vbus_extcon; |
783 | vbus->ci = ci; | 749 | vbus->ci = ci; |
784 | if (!IS_ERR(vbus->edev)) { | 750 | if (!IS_ERR(vbus->edev)) { |
785 | ret = extcon_register_notifier(vbus->edev, EXTCON_USB, | 751 | ret = devm_extcon_register_notifier(ci->dev, vbus->edev, |
786 | &vbus->nb); | 752 | EXTCON_USB, &vbus->nb); |
787 | if (ret < 0) { | 753 | if (ret < 0) { |
788 | extcon_unregister_notifier(id->edev, EXTCON_USB_HOST, | ||
789 | &id->nb); | ||
790 | dev_err(ci->dev, "register VBUS failed\n"); | 754 | dev_err(ci->dev, "register VBUS failed\n"); |
791 | return ret; | 755 | return ret; |
792 | } | 756 | } |
@@ -795,20 +759,6 @@ static int ci_extcon_register(struct ci_hdrc *ci) | |||
795 | return 0; | 759 | return 0; |
796 | } | 760 | } |
797 | 761 | ||
798 | static void ci_extcon_unregister(struct ci_hdrc *ci) | ||
799 | { | ||
800 | struct ci_hdrc_cable *cable; | ||
801 | |||
802 | cable = &ci->platdata->id_extcon; | ||
803 | if (!IS_ERR(cable->edev)) | ||
804 | extcon_unregister_notifier(cable->edev, EXTCON_USB_HOST, | ||
805 | &cable->nb); | ||
806 | |||
807 | cable = &ci->platdata->vbus_extcon; | ||
808 | if (!IS_ERR(cable->edev)) | ||
809 | extcon_unregister_notifier(cable->edev, EXTCON_USB, &cable->nb); | ||
810 | } | ||
811 | |||
812 | static DEFINE_IDA(ci_ida); | 762 | static DEFINE_IDA(ci_ida); |
813 | 763 | ||
814 | struct platform_device *ci_hdrc_add_device(struct device *dev, | 764 | struct platform_device *ci_hdrc_add_device(struct device *dev, |
@@ -921,6 +871,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
921 | CI_HDRC_IMX28_WRITE_FIX); | 871 | CI_HDRC_IMX28_WRITE_FIX); |
922 | ci->supports_runtime_pm = !!(ci->platdata->flags & | 872 | ci->supports_runtime_pm = !!(ci->platdata->flags & |
923 | CI_HDRC_SUPPORTS_RUNTIME_PM); | 873 | CI_HDRC_SUPPORTS_RUNTIME_PM); |
874 | platform_set_drvdata(pdev, ci); | ||
924 | 875 | ||
925 | ret = hw_device_init(ci, base); | 876 | ret = hw_device_init(ci, base); |
926 | if (ret < 0) { | 877 | if (ret < 0) { |
@@ -928,6 +879,10 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
928 | return -ENODEV; | 879 | return -ENODEV; |
929 | } | 880 | } |
930 | 881 | ||
882 | ret = ci_ulpi_init(ci); | ||
883 | if (ret) | ||
884 | return ret; | ||
885 | |||
931 | if (ci->platdata->phy) { | 886 | if (ci->platdata->phy) { |
932 | ci->phy = ci->platdata->phy; | 887 | ci->phy = ci->platdata->phy; |
933 | } else if (ci->platdata->usb_phy) { | 888 | } else if (ci->platdata->usb_phy) { |
@@ -938,11 +893,15 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
938 | 893 | ||
939 | /* if both generic PHY and USB PHY layers aren't enabled */ | 894 | /* if both generic PHY and USB PHY layers aren't enabled */ |
940 | if (PTR_ERR(ci->phy) == -ENOSYS && | 895 | if (PTR_ERR(ci->phy) == -ENOSYS && |
941 | PTR_ERR(ci->usb_phy) == -ENXIO) | 896 | PTR_ERR(ci->usb_phy) == -ENXIO) { |
942 | return -ENXIO; | 897 | ret = -ENXIO; |
898 | goto ulpi_exit; | ||
899 | } | ||
943 | 900 | ||
944 | if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) | 901 | if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) { |
945 | return -EPROBE_DEFER; | 902 | ret = -EPROBE_DEFER; |
903 | goto ulpi_exit; | ||
904 | } | ||
946 | 905 | ||
947 | if (IS_ERR(ci->phy)) | 906 | if (IS_ERR(ci->phy)) |
948 | ci->phy = NULL; | 907 | ci->phy = NULL; |
@@ -1027,7 +986,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
1027 | } | 986 | } |
1028 | } | 987 | } |
1029 | 988 | ||
1030 | platform_set_drvdata(pdev, ci); | ||
1031 | ret = devm_request_irq(dev, ci->irq, ci_irq, IRQF_SHARED, | 989 | ret = devm_request_irq(dev, ci->irq, ci_irq, IRQF_SHARED, |
1032 | ci->platdata->name, ci); | 990 | ci->platdata->name, ci); |
1033 | if (ret) | 991 | if (ret) |
@@ -1054,11 +1012,12 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
1054 | if (!ret) | 1012 | if (!ret) |
1055 | return 0; | 1013 | return 0; |
1056 | 1014 | ||
1057 | ci_extcon_unregister(ci); | ||
1058 | stop: | 1015 | stop: |
1059 | ci_role_destroy(ci); | 1016 | ci_role_destroy(ci); |
1060 | deinit_phy: | 1017 | deinit_phy: |
1061 | ci_usb_phy_exit(ci); | 1018 | ci_usb_phy_exit(ci); |
1019 | ulpi_exit: | ||
1020 | ci_ulpi_exit(ci); | ||
1062 | 1021 | ||
1063 | return ret; | 1022 | return ret; |
1064 | } | 1023 | } |
@@ -1074,10 +1033,10 @@ static int ci_hdrc_remove(struct platform_device *pdev) | |||
1074 | } | 1033 | } |
1075 | 1034 | ||
1076 | dbg_remove_files(ci); | 1035 | dbg_remove_files(ci); |
1077 | ci_extcon_unregister(ci); | ||
1078 | ci_role_destroy(ci); | 1036 | ci_role_destroy(ci); |
1079 | ci_hdrc_enter_lpm(ci, true); | 1037 | ci_hdrc_enter_lpm(ci, true); |
1080 | ci_usb_phy_exit(ci); | 1038 | ci_usb_phy_exit(ci); |
1039 | ci_ulpi_exit(ci); | ||
1081 | 1040 | ||
1082 | return 0; | 1041 | return 0; |
1083 | } | 1042 | } |
@@ -1125,6 +1084,7 @@ static void ci_controller_suspend(struct ci_hdrc *ci) | |||
1125 | static int ci_controller_resume(struct device *dev) | 1084 | static int ci_controller_resume(struct device *dev) |
1126 | { | 1085 | { |
1127 | struct ci_hdrc *ci = dev_get_drvdata(dev); | 1086 | struct ci_hdrc *ci = dev_get_drvdata(dev); |
1087 | int ret; | ||
1128 | 1088 | ||
1129 | dev_dbg(dev, "at %s\n", __func__); | 1089 | dev_dbg(dev, "at %s\n", __func__); |
1130 | 1090 | ||
@@ -1134,6 +1094,11 @@ static int ci_controller_resume(struct device *dev) | |||
1134 | } | 1094 | } |
1135 | 1095 | ||
1136 | ci_hdrc_enter_lpm(ci, false); | 1096 | ci_hdrc_enter_lpm(ci, false); |
1097 | |||
1098 | ret = ci_ulpi_resume(ci); | ||
1099 | if (ret) | ||
1100 | return ret; | ||
1101 | |||
1137 | if (ci->usb_phy) { | 1102 | if (ci->usb_phy) { |
1138 | usb_phy_set_suspend(ci->usb_phy, 0); | 1103 | usb_phy_set_suspend(ci->usb_phy, 0); |
1139 | usb_phy_set_wakeup(ci->usb_phy, false); | 1104 | usb_phy_set_wakeup(ci->usb_phy, false); |