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 <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
>
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