Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
usb
otg
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
;
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 */
117
int
otg_set_state
(
struct
otg_fsm
*fsm,
enum
usb_otg_state
new_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
;
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
);
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
;
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
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
)
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
);
251
else
if
(fsm->
b_sess_vld
&& fsm->
otg
->gadget)
252
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
);
263
else
if
(fsm->
b_bus_req
&& fsm->
otg
->
264
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
) &&
305
fsm->
otg
->host->b_hnp_enable)
306
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
:
313
if
(!fsm->
b_conn
&& fsm->
otg
->host->b_hnp_enable)
314
otg_set_state
(fsm,
OTG_STATE_A_PERIPHERAL
);
315
else
if
(!fsm->
b_conn
&& !fsm->
otg
->host->b_hnp_enable)
316
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
}
Generated on Thu Jan 10 2013 14:37:58 for Linux Kernel by
1.8.2