diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-10-22 21:24:38 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-10-22 21:24:38 -0400 |
commit | 9e43643b11695911bb1dd585d9a9f758a5ad4d89 (patch) | |
tree | cb9cdcfea0895229fcaceee6bf51d0aa345f5159 /drivers/usb/chipidea | |
parent | a4d8e93c3182a54d8d21a4d1cec6538ae1be9e16 (diff) | |
parent | 851ce932242d5a79bef8fe625fce37cc2f27033e (diff) |
Merge tag 'usb-ci-v4.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb into usb-next
Peter writes:
USB Chipidea updates for v4.4-rc1
- Use extcon framework for VBUS and ID detect
- Add imx6sx and imx7d support
- Other small changes
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r-- | drivers/usb/chipidea/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_imx.c | 11 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_pci.c | 6 | ||||
-rw-r--r-- | drivers/usb/chipidea/core.c | 132 | ||||
-rw-r--r-- | drivers/usb/chipidea/otg.c | 48 | ||||
-rw-r--r-- | drivers/usb/chipidea/usbmisc_imx.c | 66 |
6 files changed, 257 insertions, 7 deletions
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index 5ce3f1d6a6ed..5619b8ca3bf3 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config USB_CHIPIDEA | 1 | config USB_CHIPIDEA |
2 | tristate "ChipIdea Highspeed Dual Role Controller" | 2 | tristate "ChipIdea Highspeed Dual Role Controller" |
3 | depends on ((USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)) && HAS_DMA | 3 | depends on ((USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)) && HAS_DMA |
4 | select EXTCON | ||
4 | help | 5 | help |
5 | Say Y here if your system has a dual role high speed USB | 6 | Say Y here if your system has a dual role high speed USB |
6 | controller based on ChipIdea silicon IP. Currently, only the | 7 | controller based on ChipIdea silicon IP. Currently, only the |
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index dcc50c878159..6ccbf60cdd5c 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c | |||
@@ -56,12 +56,23 @@ static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = { | |||
56 | CI_HDRC_DISABLE_HOST_STREAMING, | 56 | CI_HDRC_DISABLE_HOST_STREAMING, |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static const struct ci_hdrc_imx_platform_flag imx6ul_usb_data = { | ||
60 | .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | | ||
61 | CI_HDRC_TURN_VBUS_EARLY_ON, | ||
62 | }; | ||
63 | |||
64 | static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = { | ||
65 | .flags = CI_HDRC_SUPPORTS_RUNTIME_PM, | ||
66 | }; | ||
67 | |||
59 | static const struct of_device_id ci_hdrc_imx_dt_ids[] = { | 68 | static const struct of_device_id ci_hdrc_imx_dt_ids[] = { |
60 | { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data}, | 69 | { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data}, |
61 | { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data}, | 70 | { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data}, |
62 | { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data}, | 71 | { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data}, |
63 | { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data}, | 72 | { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data}, |
64 | { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data}, | 73 | { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data}, |
74 | { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data}, | ||
75 | { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data}, | ||
65 | { /* sentinel */ } | 76 | { /* sentinel */ } |
66 | }; | 77 | }; |
67 | MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); | 78 | MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); |
diff --git a/drivers/usb/chipidea/ci_hdrc_pci.c b/drivers/usb/chipidea/ci_hdrc_pci.c index 773d150512fa..b59195edf636 100644 --- a/drivers/usb/chipidea/ci_hdrc_pci.c +++ b/drivers/usb/chipidea/ci_hdrc_pci.c | |||
@@ -142,16 +142,16 @@ static const struct pci_device_id ci_hdrc_pci_id_table[] = { | |||
142 | .driver_data = (kernel_ulong_t)&pci_platdata, | 142 | .driver_data = (kernel_ulong_t)&pci_platdata, |
143 | }, | 143 | }, |
144 | { | 144 | { |
145 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811), | 145 | PCI_VDEVICE(INTEL, 0x0811), |
146 | .driver_data = (kernel_ulong_t)&langwell_pci_platdata, | 146 | .driver_data = (kernel_ulong_t)&langwell_pci_platdata, |
147 | }, | 147 | }, |
148 | { | 148 | { |
149 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829), | 149 | PCI_VDEVICE(INTEL, 0x0829), |
150 | .driver_data = (kernel_ulong_t)&penwell_pci_platdata, | 150 | .driver_data = (kernel_ulong_t)&penwell_pci_platdata, |
151 | }, | 151 | }, |
152 | { | 152 | { |
153 | /* Intel Clovertrail */ | 153 | /* Intel Clovertrail */ |
154 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe006), | 154 | PCI_VDEVICE(INTEL, 0xe006), |
155 | .driver_data = (kernel_ulong_t)&penwell_pci_platdata, | 155 | .driver_data = (kernel_ulong_t)&penwell_pci_platdata, |
156 | }, | 156 | }, |
157 | { 0 } /* end: all zeroes */ | 157 | { 0 } /* end: all zeroes */ |
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index bf2599757f55..965d0e240dcb 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/delay.h> | 47 | #include <linux/delay.h> |
48 | #include <linux/device.h> | 48 | #include <linux/device.h> |
49 | #include <linux/dma-mapping.h> | 49 | #include <linux/dma-mapping.h> |
50 | #include <linux/extcon.h> | ||
50 | #include <linux/phy/phy.h> | 51 | #include <linux/phy/phy.h> |
51 | #include <linux/platform_device.h> | 52 | #include <linux/platform_device.h> |
52 | #include <linux/module.h> | 53 | #include <linux/module.h> |
@@ -602,9 +603,45 @@ static irqreturn_t ci_irq(int irq, void *data) | |||
602 | return ret; | 603 | return ret; |
603 | } | 604 | } |
604 | 605 | ||
606 | static int ci_vbus_notifier(struct notifier_block *nb, unsigned long event, | ||
607 | void *ptr) | ||
608 | { | ||
609 | struct ci_hdrc_cable *vbus = container_of(nb, struct ci_hdrc_cable, nb); | ||
610 | struct ci_hdrc *ci = vbus->ci; | ||
611 | |||
612 | if (event) | ||
613 | vbus->state = true; | ||
614 | else | ||
615 | vbus->state = false; | ||
616 | |||
617 | vbus->changed = true; | ||
618 | |||
619 | ci_irq(ci->irq, ci); | ||
620 | return NOTIFY_DONE; | ||
621 | } | ||
622 | |||
623 | static int ci_id_notifier(struct notifier_block *nb, unsigned long event, | ||
624 | void *ptr) | ||
625 | { | ||
626 | struct ci_hdrc_cable *id = container_of(nb, struct ci_hdrc_cable, nb); | ||
627 | struct ci_hdrc *ci = id->ci; | ||
628 | |||
629 | if (event) | ||
630 | id->state = false; | ||
631 | else | ||
632 | id->state = true; | ||
633 | |||
634 | id->changed = true; | ||
635 | |||
636 | ci_irq(ci->irq, ci); | ||
637 | return NOTIFY_DONE; | ||
638 | } | ||
639 | |||
605 | static int ci_get_platdata(struct device *dev, | 640 | static int ci_get_platdata(struct device *dev, |
606 | struct ci_hdrc_platform_data *platdata) | 641 | struct ci_hdrc_platform_data *platdata) |
607 | { | 642 | { |
643 | struct extcon_dev *ext_vbus, *ext_id; | ||
644 | struct ci_hdrc_cable *cable; | ||
608 | int ret; | 645 | int ret; |
609 | 646 | ||
610 | if (!platdata->phy_mode) | 647 | if (!platdata->phy_mode) |
@@ -651,6 +688,10 @@ static int ci_get_platdata(struct device *dev, | |||
651 | if (usb_get_maximum_speed(dev) == USB_SPEED_FULL) | 688 | if (usb_get_maximum_speed(dev) == USB_SPEED_FULL) |
652 | platdata->flags |= CI_HDRC_FORCE_FULLSPEED; | 689 | platdata->flags |= CI_HDRC_FORCE_FULLSPEED; |
653 | 690 | ||
691 | if (of_find_property(dev->of_node, "phy-clkgate-delay-us", NULL)) | ||
692 | of_property_read_u32(dev->of_node, "phy-clkgate-delay-us", | ||
693 | &platdata->phy_clkgate_delay_us); | ||
694 | |||
654 | platdata->itc_setting = 1; | 695 | platdata->itc_setting = 1; |
655 | if (of_find_property(dev->of_node, "itc-setting", NULL)) { | 696 | if (of_find_property(dev->of_node, "itc-setting", NULL)) { |
656 | ret = of_property_read_u32(dev->of_node, "itc-setting", | 697 | ret = of_property_read_u32(dev->of_node, "itc-setting", |
@@ -695,9 +736,91 @@ static int ci_get_platdata(struct device *dev, | |||
695 | platdata->flags |= CI_HDRC_OVERRIDE_RX_BURST; | 736 | platdata->flags |= CI_HDRC_OVERRIDE_RX_BURST; |
696 | } | 737 | } |
697 | 738 | ||
739 | ext_id = ERR_PTR(-ENODEV); | ||
740 | ext_vbus = ERR_PTR(-ENODEV); | ||
741 | if (of_property_read_bool(dev->of_node, "extcon")) { | ||
742 | /* Each one of them is not mandatory */ | ||
743 | ext_vbus = extcon_get_edev_by_phandle(dev, 0); | ||
744 | if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV) | ||
745 | return PTR_ERR(ext_vbus); | ||
746 | |||
747 | ext_id = extcon_get_edev_by_phandle(dev, 1); | ||
748 | if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV) | ||
749 | return PTR_ERR(ext_id); | ||
750 | } | ||
751 | |||
752 | cable = &platdata->vbus_extcon; | ||
753 | cable->nb.notifier_call = ci_vbus_notifier; | ||
754 | cable->edev = ext_vbus; | ||
755 | |||
756 | if (!IS_ERR(ext_vbus)) { | ||
757 | ret = extcon_get_cable_state_(cable->edev, EXTCON_USB); | ||
758 | if (ret) | ||
759 | cable->state = true; | ||
760 | else | ||
761 | cable->state = false; | ||
762 | } | ||
763 | |||
764 | cable = &platdata->id_extcon; | ||
765 | cable->nb.notifier_call = ci_id_notifier; | ||
766 | cable->edev = ext_id; | ||
767 | |||
768 | if (!IS_ERR(ext_id)) { | ||
769 | ret = extcon_get_cable_state_(cable->edev, EXTCON_USB_HOST); | ||
770 | if (ret) | ||
771 | cable->state = false; | ||
772 | else | ||
773 | cable->state = true; | ||
774 | } | ||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static int ci_extcon_register(struct ci_hdrc *ci) | ||
779 | { | ||
780 | struct ci_hdrc_cable *id, *vbus; | ||
781 | int ret; | ||
782 | |||
783 | id = &ci->platdata->id_extcon; | ||
784 | id->ci = ci; | ||
785 | if (!IS_ERR(id->edev)) { | ||
786 | ret = extcon_register_notifier(id->edev, EXTCON_USB_HOST, | ||
787 | &id->nb); | ||
788 | if (ret < 0) { | ||
789 | dev_err(ci->dev, "register ID failed\n"); | ||
790 | return ret; | ||
791 | } | ||
792 | } | ||
793 | |||
794 | vbus = &ci->platdata->vbus_extcon; | ||
795 | vbus->ci = ci; | ||
796 | if (!IS_ERR(vbus->edev)) { | ||
797 | ret = extcon_register_notifier(vbus->edev, EXTCON_USB, | ||
798 | &vbus->nb); | ||
799 | if (ret < 0) { | ||
800 | extcon_unregister_notifier(id->edev, EXTCON_USB_HOST, | ||
801 | &id->nb); | ||
802 | dev_err(ci->dev, "register VBUS failed\n"); | ||
803 | return ret; | ||
804 | } | ||
805 | } | ||
806 | |||
698 | return 0; | 807 | return 0; |
699 | } | 808 | } |
700 | 809 | ||
810 | static void ci_extcon_unregister(struct ci_hdrc *ci) | ||
811 | { | ||
812 | struct ci_hdrc_cable *cable; | ||
813 | |||
814 | cable = &ci->platdata->id_extcon; | ||
815 | if (!IS_ERR(cable->edev)) | ||
816 | extcon_unregister_notifier(cable->edev, EXTCON_USB_HOST, | ||
817 | &cable->nb); | ||
818 | |||
819 | cable = &ci->platdata->vbus_extcon; | ||
820 | if (!IS_ERR(cable->edev)) | ||
821 | extcon_unregister_notifier(cable->edev, EXTCON_USB, &cable->nb); | ||
822 | } | ||
823 | |||
701 | static DEFINE_IDA(ci_ida); | 824 | static DEFINE_IDA(ci_ida); |
702 | 825 | ||
703 | struct platform_device *ci_hdrc_add_device(struct device *dev, | 826 | struct platform_device *ci_hdrc_add_device(struct device *dev, |
@@ -921,6 +1044,10 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
921 | if (ret) | 1044 | if (ret) |
922 | goto stop; | 1045 | goto stop; |
923 | 1046 | ||
1047 | ret = ci_extcon_register(ci); | ||
1048 | if (ret) | ||
1049 | goto stop; | ||
1050 | |||
924 | if (ci->supports_runtime_pm) { | 1051 | if (ci->supports_runtime_pm) { |
925 | pm_runtime_set_active(&pdev->dev); | 1052 | pm_runtime_set_active(&pdev->dev); |
926 | pm_runtime_enable(&pdev->dev); | 1053 | pm_runtime_enable(&pdev->dev); |
@@ -938,6 +1065,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
938 | if (!ret) | 1065 | if (!ret) |
939 | return 0; | 1066 | return 0; |
940 | 1067 | ||
1068 | ci_extcon_unregister(ci); | ||
941 | stop: | 1069 | stop: |
942 | ci_role_destroy(ci); | 1070 | ci_role_destroy(ci); |
943 | deinit_phy: | 1071 | deinit_phy: |
@@ -957,6 +1085,7 @@ static int ci_hdrc_remove(struct platform_device *pdev) | |||
957 | } | 1085 | } |
958 | 1086 | ||
959 | dbg_remove_files(ci); | 1087 | dbg_remove_files(ci); |
1088 | ci_extcon_unregister(ci); | ||
960 | ci_role_destroy(ci); | 1089 | ci_role_destroy(ci); |
961 | ci_hdrc_enter_lpm(ci, true); | 1090 | ci_hdrc_enter_lpm(ci, true); |
962 | ci_usb_phy_exit(ci); | 1091 | ci_usb_phy_exit(ci); |
@@ -996,6 +1125,9 @@ static void ci_controller_suspend(struct ci_hdrc *ci) | |||
996 | { | 1125 | { |
997 | disable_irq(ci->irq); | 1126 | disable_irq(ci->irq); |
998 | ci_hdrc_enter_lpm(ci, true); | 1127 | ci_hdrc_enter_lpm(ci, true); |
1128 | if (ci->platdata->phy_clkgate_delay_us) | ||
1129 | usleep_range(ci->platdata->phy_clkgate_delay_us, | ||
1130 | ci->platdata->phy_clkgate_delay_us + 50); | ||
999 | usb_phy_set_suspend(ci->usb_phy, 1); | 1131 | usb_phy_set_suspend(ci->usb_phy, 1); |
1000 | ci->in_lpm = true; | 1132 | ci->in_lpm = true; |
1001 | enable_irq(ci->irq); | 1133 | enable_irq(ci->irq); |
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index ad6c87a4653c..45f86da1d6d3 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c | |||
@@ -30,7 +30,44 @@ | |||
30 | */ | 30 | */ |
31 | u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) | 31 | u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) |
32 | { | 32 | { |
33 | return hw_read(ci, OP_OTGSC, mask); | 33 | struct ci_hdrc_cable *cable; |
34 | u32 val = hw_read(ci, OP_OTGSC, mask); | ||
35 | |||
36 | /* | ||
37 | * If using extcon framework for VBUS and/or ID signal | ||
38 | * detection overwrite OTGSC register value | ||
39 | */ | ||
40 | cable = &ci->platdata->vbus_extcon; | ||
41 | if (!IS_ERR(cable->edev)) { | ||
42 | if (cable->changed) | ||
43 | val |= OTGSC_BSVIS; | ||
44 | else | ||
45 | val &= ~OTGSC_BSVIS; | ||
46 | |||
47 | cable->changed = false; | ||
48 | |||
49 | if (cable->state) | ||
50 | val |= OTGSC_BSV; | ||
51 | else | ||
52 | val &= ~OTGSC_BSV; | ||
53 | } | ||
54 | |||
55 | cable = &ci->platdata->id_extcon; | ||
56 | if (!IS_ERR(cable->edev)) { | ||
57 | if (cable->changed) | ||
58 | val |= OTGSC_IDIS; | ||
59 | else | ||
60 | val &= ~OTGSC_IDIS; | ||
61 | |||
62 | cable->changed = false; | ||
63 | |||
64 | if (cable->state) | ||
65 | val |= OTGSC_ID; | ||
66 | else | ||
67 | val &= ~OTGSC_ID; | ||
68 | } | ||
69 | |||
70 | return val; | ||
34 | } | 71 | } |
35 | 72 | ||
36 | /** | 73 | /** |
@@ -77,9 +114,12 @@ static void ci_handle_id_switch(struct ci_hdrc *ci) | |||
77 | ci_role(ci)->name, ci->roles[role]->name); | 114 | ci_role(ci)->name, ci->roles[role]->name); |
78 | 115 | ||
79 | ci_role_stop(ci); | 116 | ci_role_stop(ci); |
80 | /* wait vbus lower than OTGSC_BSV */ | 117 | |
81 | hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0, | 118 | if (role == CI_ROLE_GADGET) |
82 | CI_VBUS_STABLE_TIMEOUT_MS); | 119 | /* wait vbus lower than OTGSC_BSV */ |
120 | hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0, | ||
121 | CI_VBUS_STABLE_TIMEOUT_MS); | ||
122 | |||
83 | ci_role_start(ci, role); | 123 | ci_role_start(ci, role); |
84 | } | 124 | } |
85 | } | 125 | } |
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index 5ddab30ee240..fcea4eb36eee 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c | |||
@@ -72,6 +72,14 @@ | |||
72 | 72 | ||
73 | #define VF610_OVER_CUR_DIS BIT(7) | 73 | #define VF610_OVER_CUR_DIS BIT(7) |
74 | 74 | ||
75 | #define MX7D_USBNC_USB_CTRL2 0x4 | ||
76 | #define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK 0x3 | ||
77 | #define MX7D_USB_VBUS_WAKEUP_SOURCE(v) (v << 0) | ||
78 | #define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS MX7D_USB_VBUS_WAKEUP_SOURCE(0) | ||
79 | #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1) | ||
80 | #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2) | ||
81 | #define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3) | ||
82 | |||
75 | struct usbmisc_ops { | 83 | struct usbmisc_ops { |
76 | /* It's called once when probe a usb device */ | 84 | /* It's called once when probe a usb device */ |
77 | int (*init)(struct imx_usbmisc_data *data); | 85 | int (*init)(struct imx_usbmisc_data *data); |
@@ -324,6 +332,55 @@ static int usbmisc_vf610_init(struct imx_usbmisc_data *data) | |||
324 | return 0; | 332 | return 0; |
325 | } | 333 | } |
326 | 334 | ||
335 | static int usbmisc_imx7d_set_wakeup | ||
336 | (struct imx_usbmisc_data *data, bool enabled) | ||
337 | { | ||
338 | struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); | ||
339 | unsigned long flags; | ||
340 | u32 val; | ||
341 | u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE | | ||
342 | MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP); | ||
343 | |||
344 | spin_lock_irqsave(&usbmisc->lock, flags); | ||
345 | val = readl(usbmisc->base); | ||
346 | if (enabled) { | ||
347 | writel(val | wakeup_setting, usbmisc->base); | ||
348 | } else { | ||
349 | if (val & MX6_BM_WAKEUP_INTR) | ||
350 | dev_dbg(data->dev, "wakeup int\n"); | ||
351 | writel(val & ~wakeup_setting, usbmisc->base); | ||
352 | } | ||
353 | spin_unlock_irqrestore(&usbmisc->lock, flags); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int usbmisc_imx7d_init(struct imx_usbmisc_data *data) | ||
359 | { | ||
360 | struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); | ||
361 | unsigned long flags; | ||
362 | u32 reg; | ||
363 | |||
364 | if (data->index >= 1) | ||
365 | return -EINVAL; | ||
366 | |||
367 | spin_lock_irqsave(&usbmisc->lock, flags); | ||
368 | if (data->disable_oc) { | ||
369 | reg = readl(usbmisc->base); | ||
370 | writel(reg | MX6_BM_OVER_CUR_DIS, usbmisc->base); | ||
371 | } | ||
372 | |||
373 | reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); | ||
374 | reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; | ||
375 | writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, | ||
376 | usbmisc->base + MX7D_USBNC_USB_CTRL2); | ||
377 | spin_unlock_irqrestore(&usbmisc->lock, flags); | ||
378 | |||
379 | usbmisc_imx7d_set_wakeup(data, false); | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
327 | static const struct usbmisc_ops imx25_usbmisc_ops = { | 384 | static const struct usbmisc_ops imx25_usbmisc_ops = { |
328 | .init = usbmisc_imx25_init, | 385 | .init = usbmisc_imx25_init, |
329 | .post = usbmisc_imx25_post, | 386 | .post = usbmisc_imx25_post, |
@@ -351,6 +408,11 @@ static const struct usbmisc_ops imx6sx_usbmisc_ops = { | |||
351 | .init = usbmisc_imx6sx_init, | 408 | .init = usbmisc_imx6sx_init, |
352 | }; | 409 | }; |
353 | 410 | ||
411 | static const struct usbmisc_ops imx7d_usbmisc_ops = { | ||
412 | .init = usbmisc_imx7d_init, | ||
413 | .set_wakeup = usbmisc_imx7d_set_wakeup, | ||
414 | }; | ||
415 | |||
354 | int imx_usbmisc_init(struct imx_usbmisc_data *data) | 416 | int imx_usbmisc_init(struct imx_usbmisc_data *data) |
355 | { | 417 | { |
356 | struct imx_usbmisc *usbmisc; | 418 | struct imx_usbmisc *usbmisc; |
@@ -426,6 +488,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = { | |||
426 | .compatible = "fsl,imx6sx-usbmisc", | 488 | .compatible = "fsl,imx6sx-usbmisc", |
427 | .data = &imx6sx_usbmisc_ops, | 489 | .data = &imx6sx_usbmisc_ops, |
428 | }, | 490 | }, |
491 | { | ||
492 | .compatible = "fsl,imx6ul-usbmisc", | ||
493 | .data = &imx6sx_usbmisc_ops, | ||
494 | }, | ||
429 | { /* sentinel */ } | 495 | { /* sentinel */ } |
430 | }; | 496 | }; |
431 | MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); | 497 | MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); |