blob: ade131a8ae5ee6e664ee707034951eaad2db757e [file] [log] [blame]
Li Yang0807c502011-04-18 22:01:59 +02001/*
2 * OTG Finite State Machine from OTG spec
3 *
4 * Copyright (C) 2007,2008 Freescale Semiconductor, Inc.
5 *
6 * Author: Li Yang <LeoLi@freescale.com>
7 * Jerry Huang <Chang-Ming.Huang@freescale.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/kernel.h>
25#include <linux/types.h>
26#include <linux/spinlock.h>
27#include <linux/delay.h>
28#include <linux/usb.h>
29#include <linux/usb/gadget.h>
30#include <linux/usb/otg.h>
Li Yang0807c502011-04-18 22:01:59 +020031
32#include "otg_fsm.h"
33
34/* Change USB protocol when there is a protocol change */
35static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
36{
37 int ret = 0;
38
39 if (fsm->protocol != protocol) {
40 VDBG("Changing role fsm->protocol= %d; new protocol= %d\n",
41 fsm->protocol, protocol);
42 /* stop old protocol */
43 if (fsm->protocol == PROTO_HOST)
44 ret = fsm->ops->start_host(fsm, 0);
45 else if (fsm->protocol == PROTO_GADGET)
46 ret = fsm->ops->start_gadget(fsm, 0);
47 if (ret)
48 return ret;
49
50 /* start new protocol */
51 if (protocol == PROTO_HOST)
52 ret = fsm->ops->start_host(fsm, 1);
53 else if (protocol == PROTO_GADGET)
54 ret = fsm->ops->start_gadget(fsm, 1);
55 if (ret)
56 return ret;
57
58 fsm->protocol = protocol;
59 return 0;
60 }
61
62 return 0;
63}
64
65static int state_changed;
66
67/* Called when leaving a state. Do state clean up jobs here */
68void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
69{
70 switch (old_state) {
71 case OTG_STATE_B_IDLE:
72 otg_del_timer(fsm, b_se0_srp_tmr);
73 fsm->b_se0_srp = 0;
74 break;
75 case OTG_STATE_B_SRP_INIT:
76 fsm->b_srp_done = 0;
77 break;
78 case OTG_STATE_B_PERIPHERAL:
79 break;
80 case OTG_STATE_B_WAIT_ACON:
81 otg_del_timer(fsm, b_ase0_brst_tmr);
82 fsm->b_ase0_brst_tmout = 0;
83 break;
84 case OTG_STATE_B_HOST:
85 break;
86 case OTG_STATE_A_IDLE:
87 break;
88 case OTG_STATE_A_WAIT_VRISE:
89 otg_del_timer(fsm, a_wait_vrise_tmr);
90 fsm->a_wait_vrise_tmout = 0;
91 break;
92 case OTG_STATE_A_WAIT_BCON:
93 otg_del_timer(fsm, a_wait_bcon_tmr);
94 fsm->a_wait_bcon_tmout = 0;
95 break;
96 case OTG_STATE_A_HOST:
97 otg_del_timer(fsm, a_wait_enum_tmr);
98 break;
99 case OTG_STATE_A_SUSPEND:
100 otg_del_timer(fsm, a_aidl_bdis_tmr);
101 fsm->a_aidl_bdis_tmout = 0;
102 fsm->a_suspend_req = 0;
103 break;
104 case OTG_STATE_A_PERIPHERAL:
105 break;
106 case OTG_STATE_A_WAIT_VFALL:
107 otg_del_timer(fsm, a_wait_vrise_tmr);
108 break;
109 case OTG_STATE_A_VBUS_ERR:
110 break;
111 default:
112 break;
113 }
114}
115
116/* Called when entering a state */
117int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
118{
119 state_changed = 1;
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200120 if (fsm->otg->phy->state == new_state)
Li Yang0807c502011-04-18 22:01:59 +0200121 return 0;
122 VDBG("Set state: %s\n", otg_state_string(new_state));
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200123 otg_leave_state(fsm, fsm->otg->phy->state);
Li Yang0807c502011-04-18 22:01:59 +0200124 switch (new_state) {
125 case OTG_STATE_B_IDLE:
126 otg_drv_vbus(fsm, 0);
127 otg_chrg_vbus(fsm, 0);
128 otg_loc_conn(fsm, 0);
129 otg_loc_sof(fsm, 0);
130 otg_set_protocol(fsm, PROTO_UNDEF);
131 otg_add_timer(fsm, b_se0_srp_tmr);
132 break;
133 case OTG_STATE_B_SRP_INIT:
134 otg_start_pulse(fsm);
135 otg_loc_sof(fsm, 0);
136 otg_set_protocol(fsm, PROTO_UNDEF);
137 otg_add_timer(fsm, b_srp_fail_tmr);
138 break;
139 case OTG_STATE_B_PERIPHERAL:
140 otg_chrg_vbus(fsm, 0);
141 otg_loc_conn(fsm, 1);
142 otg_loc_sof(fsm, 0);
143 otg_set_protocol(fsm, PROTO_GADGET);
144 break;
145 case OTG_STATE_B_WAIT_ACON:
146 otg_chrg_vbus(fsm, 0);
147 otg_loc_conn(fsm, 0);
148 otg_loc_sof(fsm, 0);
149 otg_set_protocol(fsm, PROTO_HOST);
150 otg_add_timer(fsm, b_ase0_brst_tmr);
151 fsm->a_bus_suspend = 0;
152 break;
153 case OTG_STATE_B_HOST:
154 otg_chrg_vbus(fsm, 0);
155 otg_loc_conn(fsm, 0);
156 otg_loc_sof(fsm, 1);
157 otg_set_protocol(fsm, PROTO_HOST);
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200158 usb_bus_start_enum(fsm->otg->host,
159 fsm->otg->host->otg_port);
Li Yang0807c502011-04-18 22:01:59 +0200160 break;
161 case OTG_STATE_A_IDLE:
162 otg_drv_vbus(fsm, 0);
163 otg_chrg_vbus(fsm, 0);
164 otg_loc_conn(fsm, 0);
165 otg_loc_sof(fsm, 0);
166 otg_set_protocol(fsm, PROTO_HOST);
167 break;
168 case OTG_STATE_A_WAIT_VRISE:
169 otg_drv_vbus(fsm, 1);
170 otg_loc_conn(fsm, 0);
171 otg_loc_sof(fsm, 0);
172 otg_set_protocol(fsm, PROTO_HOST);
173 otg_add_timer(fsm, a_wait_vrise_tmr);
174 break;
175 case OTG_STATE_A_WAIT_BCON:
176 otg_drv_vbus(fsm, 1);
177 otg_loc_conn(fsm, 0);
178 otg_loc_sof(fsm, 0);
179 otg_set_protocol(fsm, PROTO_HOST);
180 otg_add_timer(fsm, a_wait_bcon_tmr);
181 break;
182 case OTG_STATE_A_HOST:
183 otg_drv_vbus(fsm, 1);
184 otg_loc_conn(fsm, 0);
185 otg_loc_sof(fsm, 1);
186 otg_set_protocol(fsm, PROTO_HOST);
187 /*
188 * When HNP is triggered while a_bus_req = 0, a_host will
189 * suspend too fast to complete a_set_b_hnp_en
190 */
191 if (!fsm->a_bus_req || fsm->a_suspend_req)
192 otg_add_timer(fsm, a_wait_enum_tmr);
193 break;
194 case OTG_STATE_A_SUSPEND:
195 otg_drv_vbus(fsm, 1);
196 otg_loc_conn(fsm, 0);
197 otg_loc_sof(fsm, 0);
198 otg_set_protocol(fsm, PROTO_HOST);
199 otg_add_timer(fsm, a_aidl_bdis_tmr);
200
201 break;
202 case OTG_STATE_A_PERIPHERAL:
203 otg_loc_conn(fsm, 1);
204 otg_loc_sof(fsm, 0);
205 otg_set_protocol(fsm, PROTO_GADGET);
206 otg_drv_vbus(fsm, 1);
207 break;
208 case OTG_STATE_A_WAIT_VFALL:
209 otg_drv_vbus(fsm, 0);
210 otg_loc_conn(fsm, 0);
211 otg_loc_sof(fsm, 0);
212 otg_set_protocol(fsm, PROTO_HOST);
213 break;
214 case OTG_STATE_A_VBUS_ERR:
215 otg_drv_vbus(fsm, 0);
216 otg_loc_conn(fsm, 0);
217 otg_loc_sof(fsm, 0);
218 otg_set_protocol(fsm, PROTO_UNDEF);
219 break;
220 default:
221 break;
222 }
223
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200224 fsm->otg->phy->state = new_state;
Li Yang0807c502011-04-18 22:01:59 +0200225 return 0;
226}
227
228/* State change judgement */
229int otg_statemachine(struct otg_fsm *fsm)
230{
231 enum usb_otg_state state;
232 unsigned long flags;
233
234 spin_lock_irqsave(&fsm->lock, flags);
235
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200236 state = fsm->otg->phy->state;
Li Yang0807c502011-04-18 22:01:59 +0200237 state_changed = 0;
238 /* State machine state change judgement */
239
240 switch (state) {
241 case OTG_STATE_UNDEFINED:
242 VDBG("fsm->id = %d\n", fsm->id);
243 if (fsm->id)
244 otg_set_state(fsm, OTG_STATE_B_IDLE);
245 else
246 otg_set_state(fsm, OTG_STATE_A_IDLE);
247 break;
248 case OTG_STATE_B_IDLE:
249 if (!fsm->id)
250 otg_set_state(fsm, OTG_STATE_A_IDLE);
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200251 else if (fsm->b_sess_vld && fsm->otg->gadget)
Li Yang0807c502011-04-18 22:01:59 +0200252 otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
253 else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp)
254 otg_set_state(fsm, OTG_STATE_B_SRP_INIT);
255 break;
256 case OTG_STATE_B_SRP_INIT:
257 if (!fsm->id || fsm->b_srp_done)
258 otg_set_state(fsm, OTG_STATE_B_IDLE);
259 break;
260 case OTG_STATE_B_PERIPHERAL:
261 if (!fsm->id || !fsm->b_sess_vld)
262 otg_set_state(fsm, OTG_STATE_B_IDLE);
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200263 else if (fsm->b_bus_req && fsm->otg->
Li Yang0807c502011-04-18 22:01:59 +0200264 gadget->b_hnp_enable && fsm->a_bus_suspend)
265 otg_set_state(fsm, OTG_STATE_B_WAIT_ACON);
266 break;
267 case OTG_STATE_B_WAIT_ACON:
268 if (fsm->a_conn)
269 otg_set_state(fsm, OTG_STATE_B_HOST);
270 else if (!fsm->id || !fsm->b_sess_vld)
271 otg_set_state(fsm, OTG_STATE_B_IDLE);
272 else if (fsm->a_bus_resume || fsm->b_ase0_brst_tmout) {
273 fsm->b_ase0_brst_tmout = 0;
274 otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
275 }
276 break;
277 case OTG_STATE_B_HOST:
278 if (!fsm->id || !fsm->b_sess_vld)
279 otg_set_state(fsm, OTG_STATE_B_IDLE);
280 else if (!fsm->b_bus_req || !fsm->a_conn)
281 otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
282 break;
283 case OTG_STATE_A_IDLE:
284 if (fsm->id)
285 otg_set_state(fsm, OTG_STATE_B_IDLE);
286 else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det))
287 otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE);
288 break;
289 case OTG_STATE_A_WAIT_VRISE:
290 if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld ||
291 fsm->a_wait_vrise_tmout) {
292 otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
293 }
294 break;
295 case OTG_STATE_A_WAIT_BCON:
296 if (!fsm->a_vbus_vld)
297 otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
298 else if (fsm->b_conn)
299 otg_set_state(fsm, OTG_STATE_A_HOST);
300 else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout)
301 otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
302 break;
303 case OTG_STATE_A_HOST:
304 if ((!fsm->a_bus_req || fsm->a_suspend_req) &&
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200305 fsm->otg->host->b_hnp_enable)
Li Yang0807c502011-04-18 22:01:59 +0200306 otg_set_state(fsm, OTG_STATE_A_SUSPEND);
307 else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop)
308 otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
309 else if (!fsm->a_vbus_vld)
310 otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
311 break;
312 case OTG_STATE_A_SUSPEND:
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200313 if (!fsm->b_conn && fsm->otg->host->b_hnp_enable)
Li Yang0807c502011-04-18 22:01:59 +0200314 otg_set_state(fsm, OTG_STATE_A_PERIPHERAL);
Heikki Krogerus7e062c02012-02-13 13:24:06 +0200315 else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable)
Li Yang0807c502011-04-18 22:01:59 +0200316 otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
317 else if (fsm->a_bus_req || fsm->b_bus_resume)
318 otg_set_state(fsm, OTG_STATE_A_HOST);
319 else if (fsm->id || fsm->a_bus_drop || fsm->a_aidl_bdis_tmout)
320 otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
321 else if (!fsm->a_vbus_vld)
322 otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
323 break;
324 case OTG_STATE_A_PERIPHERAL:
325 if (fsm->id || fsm->a_bus_drop)
326 otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
327 else if (fsm->b_bus_suspend)
328 otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
329 else if (!fsm->a_vbus_vld)
330 otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
331 break;
332 case OTG_STATE_A_WAIT_VFALL:
333 if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld &&
334 !fsm->b_conn))
335 otg_set_state(fsm, OTG_STATE_A_IDLE);
336 break;
337 case OTG_STATE_A_VBUS_ERR:
338 if (fsm->id || fsm->a_bus_drop || fsm->a_clr_err)
339 otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
340 break;
341 default:
342 break;
343 }
344 spin_unlock_irqrestore(&fsm->lock, flags);
345
346 VDBG("quit statemachine, changed = %d\n", state_changed);
347 return state_changed;
348}