diff options
Diffstat (limited to 'drivers/usb/chipidea/otg.c')
-rw-r--r-- | drivers/usb/chipidea/otg.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index 39bd7ec8bf75..a048b08b9d4d 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c | |||
@@ -11,8 +11,8 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * This file mainly handles otgsc register, it may include OTG operation | 14 | * This file mainly handles otgsc register, OTG fsm operations for HNP and SRP |
15 | * in the future. | 15 | * are also included. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/usb/otg.h> | 18 | #include <linux/usb/otg.h> |
@@ -22,6 +22,26 @@ | |||
22 | #include "ci.h" | 22 | #include "ci.h" |
23 | #include "bits.h" | 23 | #include "bits.h" |
24 | #include "otg.h" | 24 | #include "otg.h" |
25 | #include "otg_fsm.h" | ||
26 | |||
27 | /** | ||
28 | * hw_read_otgsc returns otgsc register bits value. | ||
29 | * @mask: bitfield mask | ||
30 | */ | ||
31 | u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) | ||
32 | { | ||
33 | return hw_read(ci, OP_OTGSC, mask); | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * hw_write_otgsc updates target bits of OTGSC register. | ||
38 | * @mask: bitfield mask | ||
39 | * @data: to be written | ||
40 | */ | ||
41 | void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data) | ||
42 | { | ||
43 | hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data); | ||
44 | } | ||
25 | 45 | ||
26 | /** | 46 | /** |
27 | * ci_otg_role - pick role based on ID pin state | 47 | * ci_otg_role - pick role based on ID pin state |
@@ -29,8 +49,7 @@ | |||
29 | */ | 49 | */ |
30 | enum ci_role ci_otg_role(struct ci_hdrc *ci) | 50 | enum ci_role ci_otg_role(struct ci_hdrc *ci) |
31 | { | 51 | { |
32 | u32 sts = hw_read(ci, OP_OTGSC, ~0); | 52 | enum ci_role role = hw_read_otgsc(ci, OTGSC_ID) |
33 | enum ci_role role = sts & OTGSC_ID | ||
34 | ? CI_ROLE_GADGET | 53 | ? CI_ROLE_GADGET |
35 | : CI_ROLE_HOST; | 54 | : CI_ROLE_HOST; |
36 | 55 | ||
@@ -39,14 +58,10 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci) | |||
39 | 58 | ||
40 | void ci_handle_vbus_change(struct ci_hdrc *ci) | 59 | void ci_handle_vbus_change(struct ci_hdrc *ci) |
41 | { | 60 | { |
42 | u32 otgsc; | ||
43 | |||
44 | if (!ci->is_otg) | 61 | if (!ci->is_otg) |
45 | return; | 62 | return; |
46 | 63 | ||
47 | otgsc = hw_read(ci, OP_OTGSC, ~0); | 64 | if (hw_read_otgsc(ci, OTGSC_BSV)) |
48 | |||
49 | if (otgsc & OTGSC_BSV) | ||
50 | usb_gadget_vbus_connect(&ci->gadget); | 65 | usb_gadget_vbus_connect(&ci->gadget); |
51 | else | 66 | else |
52 | usb_gadget_vbus_disconnect(&ci->gadget); | 67 | usb_gadget_vbus_disconnect(&ci->gadget); |
@@ -76,6 +91,11 @@ static void ci_otg_work(struct work_struct *work) | |||
76 | { | 91 | { |
77 | struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work); | 92 | struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work); |
78 | 93 | ||
94 | if (ci_otg_is_fsm_mode(ci) && !ci_otg_fsm_work(ci)) { | ||
95 | enable_irq(ci->irq); | ||
96 | return; | ||
97 | } | ||
98 | |||
79 | if (ci->id_event) { | 99 | if (ci->id_event) { |
80 | ci->id_event = false; | 100 | ci->id_event = false; |
81 | ci_handle_id_switch(ci); | 101 | ci_handle_id_switch(ci); |
@@ -102,6 +122,9 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci) | |||
102 | return -ENODEV; | 122 | return -ENODEV; |
103 | } | 123 | } |
104 | 124 | ||
125 | if (ci_otg_is_fsm_mode(ci)) | ||
126 | return ci_hdrc_otg_fsm_init(ci); | ||
127 | |||
105 | return 0; | 128 | return 0; |
106 | } | 129 | } |
107 | 130 | ||
@@ -115,6 +138,9 @@ void ci_hdrc_otg_destroy(struct ci_hdrc *ci) | |||
115 | flush_workqueue(ci->wq); | 138 | flush_workqueue(ci->wq); |
116 | destroy_workqueue(ci->wq); | 139 | destroy_workqueue(ci->wq); |
117 | } | 140 | } |
118 | ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS); | 141 | /* Disable all OTG irq and clear status */ |
119 | ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS); | 142 | hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS, |
143 | OTGSC_INT_STATUS_BITS); | ||
144 | if (ci_otg_is_fsm_mode(ci)) | ||
145 | ci_hdrc_otg_fsm_remove(ci); | ||
120 | } | 146 | } |