Commit | Line | Data |
---|---|---|
0807c500 LY |
1 | /* Copyright (C) 2007,2008 Freescale Semiconductor, Inc. |
2 | * | |
3 | * This program is free software; you can redistribute it and/or modify it | |
4 | * under the terms of the GNU General Public License as published by the | |
5 | * Free Software Foundation; either version 2 of the License, or (at your | |
6 | * option) any later version. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, but | |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | * General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License along | |
14 | * with this program; if not, write to the Free Software Foundation, Inc., | |
15 | * 675 Mass Ave, Cambridge, MA 02139, USA. | |
16 | */ | |
17 | ||
d49dd788 AT |
18 | #ifndef __LINUX_USB_OTG_FSM_H |
19 | #define __LINUX_USB_OTG_FSM_H | |
20 | ||
16e569e9 | 21 | #include <linux/mutex.h> |
cc9d9ccf FB |
22 | #include <linux/errno.h> |
23 | ||
0807c500 LY |
24 | #undef VERBOSE |
25 | ||
0807c500 | 26 | #ifdef VERBOSE |
523e531e GKH |
27 | #define VDBG(fmt, args...) pr_debug("[%s] " fmt , \ |
28 | __func__, ## args) | |
0807c500 LY |
29 | #else |
30 | #define VDBG(stuff...) do {} while (0) | |
31 | #endif | |
32 | ||
33 | #ifdef VERBOSE | |
34 | #define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__) | |
35 | #else | |
36 | #define MPC_LOC do {} while (0) | |
37 | #endif | |
38 | ||
39 | #define PROTO_UNDEF (0) | |
40 | #define PROTO_HOST (1) | |
41 | #define PROTO_GADGET (2) | |
42 | ||
ae57e97a LJ |
43 | #define OTG_STS_SELECTOR 0xF000 /* OTG status selector, according to |
44 | * OTG and EH 2.0 Chapter 6.2.3 | |
45 | * Table:6-4 | |
46 | */ | |
47 | ||
48 | #define HOST_REQUEST_FLAG 1 /* Host request flag, according to | |
49 | * OTG and EH 2.0 Charpter 6.2.3 | |
50 | * Table:6-5 | |
51 | */ | |
52 | ||
53 | #define T_HOST_REQ_POLL (1500) /* 1500ms, HNP polling interval */ | |
54 | ||
f6de27ee | 55 | enum otg_fsm_timer { |
3294908b | 56 | /* Standard OTG timers */ |
f6de27ee | 57 | A_WAIT_VRISE, |
3294908b | 58 | A_WAIT_VFALL, |
f6de27ee AT |
59 | A_WAIT_BCON, |
60 | A_AIDL_BDIS, | |
61 | B_ASE0_BRST, | |
3294908b | 62 | A_BIDL_ADIS, |
9c527f49 | 63 | B_AIDL_BDIS, |
3294908b AT |
64 | |
65 | /* Auxiliary timers */ | |
f6de27ee AT |
66 | B_SE0_SRP, |
67 | B_SRP_FAIL, | |
68 | A_WAIT_ENUM, | |
2f8a467a LJ |
69 | B_DATA_PLS, |
70 | B_SSEND_SRP, | |
3294908b | 71 | |
f6de27ee AT |
72 | NUM_OTG_FSM_TIMERS, |
73 | }; | |
74 | ||
fa59507f RQ |
75 | /** |
76 | * struct otg_fsm - OTG state machine according to the OTG spec | |
77 | * | |
78 | * OTG hardware Inputs | |
79 | * | |
80 | * Common inputs for A and B device | |
81 | * @id: TRUE for B-device, FALSE for A-device. | |
82 | * @adp_change: TRUE when current ADP measurement (n) value, compared to the | |
83 | * ADP measurement taken at n-2, differs by more than CADP_THR | |
84 | * @power_up: TRUE when the OTG device first powers up its USB system and | |
85 | * ADP measurement taken if ADP capable | |
86 | * | |
87 | * A-Device state inputs | |
88 | * @a_srp_det: TRUE if the A-device detects SRP | |
89 | * @a_vbus_vld: TRUE when VBUS voltage is in regulation | |
90 | * @b_conn: TRUE if the A-device detects connection from the B-device | |
91 | * @a_bus_resume: TRUE when the B-device detects that the A-device is signaling | |
92 | * a resume (K state) | |
93 | * B-Device state inputs | |
94 | * @a_bus_suspend: TRUE when the B-device detects that the A-device has put the | |
95 | * bus into suspend | |
96 | * @a_conn: TRUE if the B-device detects a connection from the A-device | |
97 | * @b_se0_srp: TRUE when the line has been at SE0 for more than the minimum | |
98 | * time before generating SRP | |
99 | * @b_ssend_srp: TRUE when the VBUS has been below VOTG_SESS_VLD for more than | |
100 | * the minimum time before generating SRP | |
101 | * @b_sess_vld: TRUE when the B-device detects that the voltage on VBUS is | |
102 | * above VOTG_SESS_VLD | |
103 | * @test_device: TRUE when the B-device switches to B-Host and detects an OTG | |
104 | * test device. This must be set by host/hub driver | |
105 | * | |
106 | * Application inputs (A-Device) | |
107 | * @a_bus_drop: TRUE when A-device application needs to power down the bus | |
108 | * @a_bus_req: TRUE when A-device application wants to use the bus. | |
109 | * FALSE to suspend the bus | |
110 | * | |
111 | * Application inputs (B-Device) | |
112 | * @b_bus_req: TRUE during the time that the Application running on the | |
113 | * B-device wants to use the bus | |
114 | * | |
115 | * Auxilary inputs (OTG v1.3 only. Obsolete now.) | |
116 | * @a_sess_vld: TRUE if the A-device detects that VBUS is above VA_SESS_VLD | |
117 | * @b_bus_suspend: TRUE when the A-device detects that the B-device has put | |
118 | * the bus into suspend | |
119 | * @b_bus_resume: TRUE when the A-device detects that the B-device is signaling | |
120 | * resume on the bus | |
121 | * | |
122 | * OTG Output status. Read only for users. Updated by OTG FSM helpers defined | |
123 | * in this file | |
124 | * | |
125 | * Outputs for Both A and B device | |
126 | * @drv_vbus: TRUE when A-device is driving VBUS | |
127 | * @loc_conn: TRUE when the local device has signaled that it is connected | |
128 | * to the bus | |
129 | * @loc_sof: TRUE when the local device is generating activity on the bus | |
130 | * @adp_prb: TRUE when the local device is in the process of doing | |
131 | * ADP probing | |
132 | * | |
133 | * Outputs for B-device state | |
134 | * @adp_sns: TRUE when the B-device is in the process of carrying out | |
135 | * ADP sensing | |
136 | * @data_pulse: TRUE when the B-device is performing data line pulsing | |
137 | * | |
138 | * Internal Variables | |
139 | * | |
140 | * a_set_b_hnp_en: TRUE when the A-device has successfully set the | |
141 | * b_hnp_enable bit in the B-device. | |
142 | * Unused as OTG fsm uses otg->host->b_hnp_enable instead | |
143 | * b_srp_done: TRUE when the B-device has completed initiating SRP | |
144 | * b_hnp_enable: TRUE when the B-device has accepted the | |
145 | * SetFeature(b_hnp_enable) B-device. | |
146 | * Unused as OTG fsm uses otg->gadget->b_hnp_enable instead | |
147 | * a_clr_err: Asserted (by application ?) to clear a_vbus_err due to an | |
148 | * overcurrent condition and causes the A-device to transition | |
149 | * to a_wait_vfall | |
150 | */ | |
0807c500 LY |
151 | struct otg_fsm { |
152 | /* Input */ | |
4662e5ef | 153 | int id; |
ec04996a AT |
154 | int adp_change; |
155 | int power_up; | |
4662e5ef AT |
156 | int a_srp_det; |
157 | int a_vbus_vld; | |
158 | int b_conn; | |
0807c500 LY |
159 | int a_bus_resume; |
160 | int a_bus_suspend; | |
161 | int a_conn; | |
0807c500 | 162 | int b_se0_srp; |
68041785 | 163 | int b_ssend_srp; |
0807c500 | 164 | int b_sess_vld; |
fa59507f RQ |
165 | int test_device; |
166 | int a_bus_drop; | |
167 | int a_bus_req; | |
168 | int b_bus_req; | |
169 | ||
4662e5ef AT |
170 | /* Auxilary inputs */ |
171 | int a_sess_vld; | |
172 | int b_bus_resume; | |
173 | int b_bus_suspend; | |
174 | ||
175 | /* Output */ | |
4662e5ef AT |
176 | int drv_vbus; |
177 | int loc_conn; | |
178 | int loc_sof; | |
179 | int adp_prb; | |
180 | int adp_sns; | |
fa59507f | 181 | int data_pulse; |
0807c500 LY |
182 | |
183 | /* Internal variables */ | |
184 | int a_set_b_hnp_en; | |
185 | int b_srp_done; | |
186 | int b_hnp_enable; | |
cff4dab4 | 187 | int a_clr_err; |
0807c500 | 188 | |
fa59507f | 189 | /* Informative variables. All unused as of now */ |
4662e5ef AT |
190 | int a_bus_drop_inf; |
191 | int a_bus_req_inf; | |
192 | int a_clr_err_inf; | |
193 | int b_bus_req_inf; | |
194 | /* Auxilary informative variables */ | |
195 | int a_suspend_req_inf; | |
196 | ||
0807c500 LY |
197 | /* Timeout indicator for timers */ |
198 | int a_wait_vrise_tmout; | |
3294908b | 199 | int a_wait_vfall_tmout; |
0807c500 LY |
200 | int a_wait_bcon_tmout; |
201 | int a_aidl_bdis_tmout; | |
202 | int b_ase0_brst_tmout; | |
3294908b | 203 | int a_bidl_adis_tmout; |
0807c500 | 204 | |
0807c500 | 205 | struct otg_fsm_ops *ops; |
7e062c0f | 206 | struct usb_otg *otg; |
0807c500 LY |
207 | |
208 | /* Current usb protocol used: 0:undefine; 1:host; 2:client */ | |
209 | int protocol; | |
16e569e9 | 210 | struct mutex lock; |
ae57e97a LJ |
211 | u8 *host_req_flag; |
212 | struct delayed_work hnp_polling_work; | |
4e332df6 | 213 | bool state_changed; |
0807c500 LY |
214 | }; |
215 | ||
216 | struct otg_fsm_ops { | |
da8cc167 AT |
217 | void (*chrg_vbus)(struct otg_fsm *fsm, int on); |
218 | void (*drv_vbus)(struct otg_fsm *fsm, int on); | |
219 | void (*loc_conn)(struct otg_fsm *fsm, int on); | |
220 | void (*loc_sof)(struct otg_fsm *fsm, int on); | |
221 | void (*start_pulse)(struct otg_fsm *fsm); | |
ec04996a AT |
222 | void (*start_adp_prb)(struct otg_fsm *fsm); |
223 | void (*start_adp_sns)(struct otg_fsm *fsm); | |
f6de27ee AT |
224 | void (*add_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer); |
225 | void (*del_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer); | |
0807c500 LY |
226 | int (*start_host)(struct otg_fsm *fsm, int on); |
227 | int (*start_gadget)(struct otg_fsm *fsm, int on); | |
228 | }; | |
229 | ||
230 | ||
737cc66e | 231 | static inline int otg_chrg_vbus(struct otg_fsm *fsm, int on) |
0807c500 | 232 | { |
737cc66e AT |
233 | if (!fsm->ops->chrg_vbus) |
234 | return -EOPNOTSUPP; | |
da8cc167 | 235 | fsm->ops->chrg_vbus(fsm, on); |
737cc66e | 236 | return 0; |
0807c500 LY |
237 | } |
238 | ||
737cc66e | 239 | static inline int otg_drv_vbus(struct otg_fsm *fsm, int on) |
0807c500 | 240 | { |
737cc66e AT |
241 | if (!fsm->ops->drv_vbus) |
242 | return -EOPNOTSUPP; | |
0807c500 LY |
243 | if (fsm->drv_vbus != on) { |
244 | fsm->drv_vbus = on; | |
da8cc167 | 245 | fsm->ops->drv_vbus(fsm, on); |
0807c500 | 246 | } |
737cc66e | 247 | return 0; |
0807c500 LY |
248 | } |
249 | ||
737cc66e | 250 | static inline int otg_loc_conn(struct otg_fsm *fsm, int on) |
0807c500 | 251 | { |
737cc66e AT |
252 | if (!fsm->ops->loc_conn) |
253 | return -EOPNOTSUPP; | |
0807c500 LY |
254 | if (fsm->loc_conn != on) { |
255 | fsm->loc_conn = on; | |
da8cc167 | 256 | fsm->ops->loc_conn(fsm, on); |
0807c500 | 257 | } |
737cc66e | 258 | return 0; |
0807c500 LY |
259 | } |
260 | ||
737cc66e | 261 | static inline int otg_loc_sof(struct otg_fsm *fsm, int on) |
0807c500 | 262 | { |
737cc66e AT |
263 | if (!fsm->ops->loc_sof) |
264 | return -EOPNOTSUPP; | |
0807c500 LY |
265 | if (fsm->loc_sof != on) { |
266 | fsm->loc_sof = on; | |
da8cc167 | 267 | fsm->ops->loc_sof(fsm, on); |
0807c500 | 268 | } |
737cc66e | 269 | return 0; |
0807c500 LY |
270 | } |
271 | ||
737cc66e | 272 | static inline int otg_start_pulse(struct otg_fsm *fsm) |
0807c500 | 273 | { |
737cc66e AT |
274 | if (!fsm->ops->start_pulse) |
275 | return -EOPNOTSUPP; | |
ec04996a AT |
276 | if (!fsm->data_pulse) { |
277 | fsm->data_pulse = 1; | |
278 | fsm->ops->start_pulse(fsm); | |
279 | } | |
280 | return 0; | |
281 | } | |
282 | ||
283 | static inline int otg_start_adp_prb(struct otg_fsm *fsm) | |
284 | { | |
285 | if (!fsm->ops->start_adp_prb) | |
286 | return -EOPNOTSUPP; | |
287 | if (!fsm->adp_prb) { | |
288 | fsm->adp_sns = 0; | |
289 | fsm->adp_prb = 1; | |
290 | fsm->ops->start_adp_prb(fsm); | |
291 | } | |
292 | return 0; | |
293 | } | |
294 | ||
295 | static inline int otg_start_adp_sns(struct otg_fsm *fsm) | |
296 | { | |
297 | if (!fsm->ops->start_adp_sns) | |
298 | return -EOPNOTSUPP; | |
299 | if (!fsm->adp_sns) { | |
300 | fsm->adp_sns = 1; | |
301 | fsm->ops->start_adp_sns(fsm); | |
302 | } | |
737cc66e | 303 | return 0; |
0807c500 LY |
304 | } |
305 | ||
f6de27ee | 306 | static inline int otg_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer) |
0807c500 | 307 | { |
737cc66e AT |
308 | if (!fsm->ops->add_timer) |
309 | return -EOPNOTSUPP; | |
da8cc167 | 310 | fsm->ops->add_timer(fsm, timer); |
737cc66e | 311 | return 0; |
0807c500 LY |
312 | } |
313 | ||
f6de27ee | 314 | static inline int otg_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer) |
0807c500 | 315 | { |
737cc66e AT |
316 | if (!fsm->ops->del_timer) |
317 | return -EOPNOTSUPP; | |
da8cc167 | 318 | fsm->ops->del_timer(fsm, timer); |
737cc66e | 319 | return 0; |
0807c500 LY |
320 | } |
321 | ||
425d7101 AT |
322 | static inline int otg_start_host(struct otg_fsm *fsm, int on) |
323 | { | |
324 | if (!fsm->ops->start_host) | |
325 | return -EOPNOTSUPP; | |
326 | return fsm->ops->start_host(fsm, on); | |
327 | } | |
328 | ||
329 | static inline int otg_start_gadget(struct otg_fsm *fsm, int on) | |
330 | { | |
331 | if (!fsm->ops->start_gadget) | |
332 | return -EOPNOTSUPP; | |
333 | return fsm->ops->start_gadget(fsm, on); | |
334 | } | |
335 | ||
0807c500 | 336 | int otg_statemachine(struct otg_fsm *fsm); |
d49dd788 AT |
337 | |
338 | #endif /* __LINUX_USB_OTG_FSM_H */ |