Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
otg_fsm.c
Go to the documentation of this file.
1 /*
2  * OTG Finite State Machine from OTG spec
3  *
4  * Copyright (C) 2007,2008 Freescale Semiconductor, Inc.
5  *
6  * Author: Li Yang <[email protected]>
7  * Jerry Huang <[email protected]>
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>
31 
32 #include "otg_fsm.h"
33 
34 /* Change USB protocol when there is a protocol change */
35 static 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 
65 static int state_changed;
66 
67 /* Called when leaving a state. Do state clean up jobs here */
68 void 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;
76  fsm->b_srp_done = 0;
77  break;
79  break;
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;
89  otg_del_timer(fsm, a_wait_vrise_tmr);
90  fsm->a_wait_vrise_tmout = 0;
91  break;
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;
100  otg_del_timer(fsm, a_aidl_bdis_tmr);
101  fsm->a_aidl_bdis_tmout = 0;
102  fsm->a_suspend_req = 0;
103  break;
105  break;
107  otg_del_timer(fsm, a_wait_vrise_tmr);
108  break;
110  break;
111  default:
112  break;
113  }
114 }
115 
116 /* Called when entering a state */
118 {
119  state_changed = 1;
120  if (fsm->otg->phy->state == new_state)
121  return 0;
122  VDBG("Set state: %s\n", otg_state_string(new_state));
123  otg_leave_state(fsm, fsm->otg->phy->state);
124  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;
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;
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;
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);
158  usb_bus_start_enum(fsm->otg->host,
159  fsm->otg->host->otg_port);
160  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;
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;
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;
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;
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;
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 
224  fsm->otg->phy->state = new_state;
225  return 0;
226 }
227 
228 /* State change judgement */
229 int 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 
236  state = fsm->otg->phy->state;
237  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)
245  else
247  break;
248  case OTG_STATE_B_IDLE:
249  if (!fsm->id)
251  else if (fsm->b_sess_vld && fsm->otg->gadget)
253  else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp)
255  break;
257  if (!fsm->id || fsm->b_srp_done)
259  break;
261  if (!fsm->id || !fsm->b_sess_vld)
263  else if (fsm->b_bus_req && fsm->otg->
264  gadget->b_hnp_enable && fsm->a_bus_suspend)
266  break;
268  if (fsm->a_conn)
270  else if (!fsm->id || !fsm->b_sess_vld)
272  else if (fsm->a_bus_resume || fsm->b_ase0_brst_tmout) {
273  fsm->b_ase0_brst_tmout = 0;
275  }
276  break;
277  case OTG_STATE_B_HOST:
278  if (!fsm->id || !fsm->b_sess_vld)
280  else if (!fsm->b_bus_req || !fsm->a_conn)
282  break;
283  case OTG_STATE_A_IDLE:
284  if (fsm->id)
286  else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det))
288  break;
290  if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld ||
291  fsm->a_wait_vrise_tmout) {
293  }
294  break;
296  if (!fsm->a_vbus_vld)
298  else if (fsm->b_conn)
300  else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout)
302  break;
303  case OTG_STATE_A_HOST:
304  if ((!fsm->a_bus_req || fsm->a_suspend_req) &&
305  fsm->otg->host->b_hnp_enable)
307  else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop)
309  else if (!fsm->a_vbus_vld)
311  break;
312  case OTG_STATE_A_SUSPEND:
313  if (!fsm->b_conn && fsm->otg->host->b_hnp_enable)
315  else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable)
317  else if (fsm->a_bus_req || fsm->b_bus_resume)
319  else if (fsm->id || fsm->a_bus_drop || fsm->a_aidl_bdis_tmout)
321  else if (!fsm->a_vbus_vld)
323  break;
325  if (fsm->id || fsm->a_bus_drop)
327  else if (fsm->b_bus_suspend)
329  else if (!fsm->a_vbus_vld)
331  break;
333  if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld &&
334  !fsm->b_conn))
336  break;
338  if (fsm->id || fsm->a_bus_drop || fsm->a_clr_err)
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 }