2017-11-03 11:28:30 +01:00
// SPDX-License-Identifier: GPL-2.0+
2011-04-18 22:01:59 +02:00
/*
* OTG Finite State Machine from OTG spec
*
* Copyright ( C ) 2007 , 2008 Freescale Semiconductor , Inc .
*
* Author : Li Yang < LeoLi @ freescale . com >
* Jerry Huang < Chang - Ming . Huang @ freescale . com >
*/
2016-06-14 14:14:35 +08:00
# include <linux/module.h>
2011-04-18 22:01:59 +02:00
# include <linux/kernel.h>
# include <linux/types.h>
2013-11-26 11:46:05 +09:00
# include <linux/mutex.h>
2011-04-18 22:01:59 +02:00
# include <linux/delay.h>
# include <linux/usb.h>
# include <linux/usb/gadget.h>
# include <linux/usb/otg.h>
2013-11-26 11:47:02 +09:00
# include <linux/usb/otg-fsm.h>
2011-04-18 22:01:59 +02:00
2017-03-30 09:46:41 +03:00
# ifdef VERBOSE
# define VDBG(fmt, args...) pr_debug("[%s] " fmt, \
__func__ , # # args )
# else
# define VDBG(stuff...) do {} while (0)
# endif
2011-04-18 22:01:59 +02:00
/* Change USB protocol when there is a protocol change */
static int otg_set_protocol ( struct otg_fsm * fsm , int protocol )
{
int ret = 0 ;
if ( fsm - > protocol ! = protocol ) {
VDBG ( " Changing role fsm->protocol= %d; new protocol= %d \n " ,
fsm - > protocol , protocol ) ;
/* stop old protocol */
if ( fsm - > protocol = = PROTO_HOST )
2013-10-03 12:42:04 +09:00
ret = otg_start_host ( fsm , 0 ) ;
2011-04-18 22:01:59 +02:00
else if ( fsm - > protocol = = PROTO_GADGET )
2013-10-03 12:42:04 +09:00
ret = otg_start_gadget ( fsm , 0 ) ;
2011-04-18 22:01:59 +02:00
if ( ret )
return ret ;
/* start new protocol */
if ( protocol = = PROTO_HOST )
2013-10-03 12:42:04 +09:00
ret = otg_start_host ( fsm , 1 ) ;
2011-04-18 22:01:59 +02:00
else if ( protocol = = PROTO_GADGET )
2013-10-03 12:42:04 +09:00
ret = otg_start_gadget ( fsm , 1 ) ;
2011-04-18 22:01:59 +02:00
if ( ret )
return ret ;
fsm - > protocol = protocol ;
return 0 ;
}
return 0 ;
}
/* Called when leaving a state. Do state clean up jobs here */
2013-12-21 15:20:08 +05:30
static void otg_leave_state ( struct otg_fsm * fsm , enum usb_otg_state old_state )
2011-04-18 22:01:59 +02:00
{
switch ( old_state ) {
case OTG_STATE_B_IDLE :
2013-10-03 12:42:04 +09:00
otg_del_timer ( fsm , B_SE0_SRP ) ;
2011-04-18 22:01:59 +02:00
fsm - > b_se0_srp = 0 ;
2013-10-03 12:42:04 +09:00
fsm - > adp_sns = 0 ;
fsm - > adp_prb = 0 ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_B_SRP_INIT :
2013-10-03 12:42:04 +09:00
fsm - > data_pulse = 0 ;
2011-04-18 22:01:59 +02:00
fsm - > b_srp_done = 0 ;
break ;
case OTG_STATE_B_PERIPHERAL :
2016-02-19 10:04:42 +08:00
if ( fsm - > otg - > gadget )
fsm - > otg - > gadget - > host_request_flag = 0 ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_B_WAIT_ACON :
2013-10-03 12:42:04 +09:00
otg_del_timer ( fsm , B_ASE0_BRST ) ;
2011-04-18 22:01:59 +02:00
fsm - > b_ase0_brst_tmout = 0 ;
break ;
case OTG_STATE_B_HOST :
break ;
case OTG_STATE_A_IDLE :
2013-10-03 12:42:04 +09:00
fsm - > adp_prb = 0 ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_WAIT_VRISE :
2013-10-03 12:42:04 +09:00
otg_del_timer ( fsm , A_WAIT_VRISE ) ;
2011-04-18 22:01:59 +02:00
fsm - > a_wait_vrise_tmout = 0 ;
break ;
case OTG_STATE_A_WAIT_BCON :
2013-10-03 12:42:04 +09:00
otg_del_timer ( fsm , A_WAIT_BCON ) ;
2011-04-18 22:01:59 +02:00
fsm - > a_wait_bcon_tmout = 0 ;
break ;
case OTG_STATE_A_HOST :
2013-10-03 12:42:04 +09:00
otg_del_timer ( fsm , A_WAIT_ENUM ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_SUSPEND :
2013-10-03 12:42:04 +09:00
otg_del_timer ( fsm , A_AIDL_BDIS ) ;
2011-04-18 22:01:59 +02:00
fsm - > a_aidl_bdis_tmout = 0 ;
2013-10-03 12:42:04 +09:00
fsm - > a_suspend_req_inf = 0 ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_PERIPHERAL :
2013-10-03 12:42:04 +09:00
otg_del_timer ( fsm , A_BIDL_ADIS ) ;
fsm - > a_bidl_adis_tmout = 0 ;
2016-02-19 10:04:42 +08:00
if ( fsm - > otg - > gadget )
fsm - > otg - > gadget - > host_request_flag = 0 ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_WAIT_VFALL :
2013-10-03 12:42:04 +09:00
otg_del_timer ( fsm , A_WAIT_VFALL ) ;
fsm - > a_wait_vfall_tmout = 0 ;
2013-10-03 12:42:04 +09:00
otg_del_timer ( fsm , A_WAIT_VRISE ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_VBUS_ERR :
break ;
default :
break ;
}
}
2016-02-19 10:04:42 +08:00
static void otg_hnp_polling_work ( struct work_struct * work )
{
struct otg_fsm * fsm = container_of ( to_delayed_work ( work ) ,
struct otg_fsm , hnp_polling_work ) ;
struct usb_device * udev ;
enum usb_otg_state state = fsm - > otg - > state ;
u8 flag ;
int retval ;
if ( state ! = OTG_STATE_A_HOST & & state ! = OTG_STATE_B_HOST )
return ;
udev = usb_hub_find_child ( fsm - > otg - > host - > root_hub , 1 ) ;
if ( ! udev ) {
dev_err ( fsm - > otg - > host - > controller ,
" no usb dev connected, can't start HNP polling \n " ) ;
return ;
}
* fsm - > host_req_flag = 0 ;
/* Get host request flag from connected USB device */
retval = usb_control_msg ( udev ,
usb_rcvctrlpipe ( udev , 0 ) ,
USB_REQ_GET_STATUS ,
USB_DIR_IN | USB_RECIP_DEVICE ,
0 ,
OTG_STS_SELECTOR ,
fsm - > host_req_flag ,
1 ,
USB_CTRL_GET_TIMEOUT ) ;
if ( retval ! = 1 ) {
dev_err ( & udev - > dev , " Get one byte OTG status failed \n " ) ;
return ;
}
flag = * fsm - > host_req_flag ;
if ( flag = = 0 ) {
/* Continue HNP polling */
schedule_delayed_work ( & fsm - > hnp_polling_work ,
msecs_to_jiffies ( T_HOST_REQ_POLL ) ) ;
return ;
} else if ( flag ! = HOST_REQUEST_FLAG ) {
dev_err ( & udev - > dev , " host request flag %d is invalid \n " , flag ) ;
return ;
}
/* Host request flag is set */
if ( state = = OTG_STATE_A_HOST ) {
/* Set b_hnp_enable */
if ( ! fsm - > otg - > host - > b_hnp_enable ) {
retval = usb_control_msg ( udev ,
usb_sndctrlpipe ( udev , 0 ) ,
USB_REQ_SET_FEATURE , 0 ,
USB_DEVICE_B_HNP_ENABLE ,
0 , NULL , 0 ,
USB_CTRL_SET_TIMEOUT ) ;
if ( retval > = 0 )
fsm - > otg - > host - > b_hnp_enable = 1 ;
}
fsm - > a_bus_req = 0 ;
} else if ( state = = OTG_STATE_B_HOST ) {
fsm - > b_bus_req = 0 ;
}
otg_statemachine ( fsm ) ;
}
static void otg_start_hnp_polling ( struct otg_fsm * fsm )
{
/*
* The memory of host_req_flag should be allocated by
* controller driver , otherwise , hnp polling is not started .
*/
if ( ! fsm - > host_req_flag )
return ;
2021-07-17 21:21:27 +03:00
if ( ! fsm - > hnp_work_inited ) {
INIT_DELAYED_WORK ( & fsm - > hnp_polling_work , otg_hnp_polling_work ) ;
fsm - > hnp_work_inited = true ;
}
2016-02-19 10:04:42 +08:00
schedule_delayed_work ( & fsm - > hnp_polling_work ,
msecs_to_jiffies ( T_HOST_REQ_POLL ) ) ;
}
2011-04-18 22:01:59 +02:00
/* Called when entering a state */
2013-12-21 15:20:08 +05:30
static int otg_set_state ( struct otg_fsm * fsm , enum usb_otg_state new_state )
2011-04-18 22:01:59 +02:00
{
2014-10-30 18:41:13 +01:00
if ( fsm - > otg - > state = = new_state )
2011-04-18 22:01:59 +02:00
return 0 ;
2013-03-07 10:39:57 +02:00
VDBG ( " Set state: %s \n " , usb_otg_state_string ( new_state ) ) ;
2014-10-30 18:41:13 +01:00
otg_leave_state ( fsm , fsm - > otg - > state ) ;
2011-04-18 22:01:59 +02:00
switch ( new_state ) {
case OTG_STATE_B_IDLE :
otg_drv_vbus ( fsm , 0 ) ;
otg_chrg_vbus ( fsm , 0 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 0 ) ;
2013-10-03 12:42:04 +09:00
/*
* Driver is responsible for starting ADP probing
* if ADP sensing times out .
*/
otg_start_adp_sns ( fsm ) ;
2011-04-18 22:01:59 +02:00
otg_set_protocol ( fsm , PROTO_UNDEF ) ;
2013-10-03 12:42:04 +09:00
otg_add_timer ( fsm , B_SE0_SRP ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_B_SRP_INIT :
otg_start_pulse ( fsm ) ;
otg_loc_sof ( fsm , 0 ) ;
otg_set_protocol ( fsm , PROTO_UNDEF ) ;
2013-10-03 12:42:04 +09:00
otg_add_timer ( fsm , B_SRP_FAIL ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_B_PERIPHERAL :
otg_chrg_vbus ( fsm , 0 ) ;
otg_loc_sof ( fsm , 0 ) ;
otg_set_protocol ( fsm , PROTO_GADGET ) ;
2015-03-12 09:47:53 +08:00
otg_loc_conn ( fsm , 1 ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_B_WAIT_ACON :
otg_chrg_vbus ( fsm , 0 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 0 ) ;
otg_set_protocol ( fsm , PROTO_HOST ) ;
2013-10-03 12:42:04 +09:00
otg_add_timer ( fsm , B_ASE0_BRST ) ;
2011-04-18 22:01:59 +02:00
fsm - > a_bus_suspend = 0 ;
break ;
case OTG_STATE_B_HOST :
otg_chrg_vbus ( fsm , 0 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 1 ) ;
otg_set_protocol ( fsm , PROTO_HOST ) ;
2012-02-13 13:24:06 +02:00
usb_bus_start_enum ( fsm - > otg - > host ,
fsm - > otg - > host - > otg_port ) ;
2016-02-19 10:04:42 +08:00
otg_start_hnp_polling ( fsm ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_IDLE :
otg_drv_vbus ( fsm , 0 ) ;
otg_chrg_vbus ( fsm , 0 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 0 ) ;
2013-10-03 12:42:04 +09:00
otg_start_adp_prb ( fsm ) ;
2011-04-18 22:01:59 +02:00
otg_set_protocol ( fsm , PROTO_HOST ) ;
break ;
case OTG_STATE_A_WAIT_VRISE :
otg_drv_vbus ( fsm , 1 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 0 ) ;
otg_set_protocol ( fsm , PROTO_HOST ) ;
2013-10-03 12:42:04 +09:00
otg_add_timer ( fsm , A_WAIT_VRISE ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_WAIT_BCON :
otg_drv_vbus ( fsm , 1 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 0 ) ;
otg_set_protocol ( fsm , PROTO_HOST ) ;
2013-10-03 12:42:04 +09:00
otg_add_timer ( fsm , A_WAIT_BCON ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_HOST :
otg_drv_vbus ( fsm , 1 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 1 ) ;
otg_set_protocol ( fsm , PROTO_HOST ) ;
/*
* When HNP is triggered while a_bus_req = 0 , a_host will
* suspend too fast to complete a_set_b_hnp_en
*/
2013-10-03 12:42:04 +09:00
if ( ! fsm - > a_bus_req | | fsm - > a_suspend_req_inf )
2013-10-03 12:42:04 +09:00
otg_add_timer ( fsm , A_WAIT_ENUM ) ;
2016-02-19 10:04:42 +08:00
otg_start_hnp_polling ( fsm ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_SUSPEND :
otg_drv_vbus ( fsm , 1 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 0 ) ;
otg_set_protocol ( fsm , PROTO_HOST ) ;
2013-10-03 12:42:04 +09:00
otg_add_timer ( fsm , A_AIDL_BDIS ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_PERIPHERAL :
otg_loc_sof ( fsm , 0 ) ;
otg_set_protocol ( fsm , PROTO_GADGET ) ;
otg_drv_vbus ( fsm , 1 ) ;
2015-03-12 09:47:53 +08:00
otg_loc_conn ( fsm , 1 ) ;
2013-10-03 12:42:04 +09:00
otg_add_timer ( fsm , A_BIDL_ADIS ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_WAIT_VFALL :
otg_drv_vbus ( fsm , 0 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 0 ) ;
otg_set_protocol ( fsm , PROTO_HOST ) ;
2013-10-03 12:42:04 +09:00
otg_add_timer ( fsm , A_WAIT_VFALL ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_VBUS_ERR :
otg_drv_vbus ( fsm , 0 ) ;
otg_loc_conn ( fsm , 0 ) ;
otg_loc_sof ( fsm , 0 ) ;
otg_set_protocol ( fsm , PROTO_UNDEF ) ;
break ;
default :
break ;
}
2014-10-30 18:41:13 +01:00
fsm - > otg - > state = new_state ;
2016-03-30 12:56:29 +03:00
fsm - > state_changed = 1 ;
2011-04-18 22:01:59 +02:00
return 0 ;
}
/* State change judgement */
int otg_statemachine ( struct otg_fsm * fsm )
{
enum usb_otg_state state ;
2013-11-26 11:46:05 +09:00
mutex_lock ( & fsm - > lock ) ;
2011-04-18 22:01:59 +02:00
2014-10-30 18:41:13 +01:00
state = fsm - > otg - > state ;
2016-03-30 12:56:29 +03:00
fsm - > state_changed = 0 ;
2011-04-18 22:01:59 +02:00
/* State machine state change judgement */
switch ( state ) {
case OTG_STATE_UNDEFINED :
VDBG ( " fsm->id = %d \n " , fsm - > id ) ;
if ( fsm - > id )
otg_set_state ( fsm , OTG_STATE_B_IDLE ) ;
else
otg_set_state ( fsm , OTG_STATE_A_IDLE ) ;
break ;
case OTG_STATE_B_IDLE :
if ( ! fsm - > id )
otg_set_state ( fsm , OTG_STATE_A_IDLE ) ;
2012-02-13 13:24:06 +02:00
else if ( fsm - > b_sess_vld & & fsm - > otg - > gadget )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_B_PERIPHERAL ) ;
2013-10-03 12:42:04 +09:00
else if ( ( fsm - > b_bus_req | | fsm - > adp_change | | fsm - > power_up ) & &
fsm - > b_ssend_srp & & fsm - > b_se0_srp )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_B_SRP_INIT ) ;
break ;
case OTG_STATE_B_SRP_INIT :
if ( ! fsm - > id | | fsm - > b_srp_done )
otg_set_state ( fsm , OTG_STATE_B_IDLE ) ;
break ;
case OTG_STATE_B_PERIPHERAL :
if ( ! fsm - > id | | ! fsm - > b_sess_vld )
otg_set_state ( fsm , OTG_STATE_B_IDLE ) ;
2012-02-13 13:24:06 +02:00
else if ( fsm - > b_bus_req & & fsm - > otg - >
2011-04-18 22:01:59 +02:00
gadget - > b_hnp_enable & & fsm - > a_bus_suspend )
otg_set_state ( fsm , OTG_STATE_B_WAIT_ACON ) ;
break ;
case OTG_STATE_B_WAIT_ACON :
if ( fsm - > a_conn )
otg_set_state ( fsm , OTG_STATE_B_HOST ) ;
else if ( ! fsm - > id | | ! fsm - > b_sess_vld )
otg_set_state ( fsm , OTG_STATE_B_IDLE ) ;
else if ( fsm - > a_bus_resume | | fsm - > b_ase0_brst_tmout ) {
fsm - > b_ase0_brst_tmout = 0 ;
otg_set_state ( fsm , OTG_STATE_B_PERIPHERAL ) ;
}
break ;
case OTG_STATE_B_HOST :
if ( ! fsm - > id | | ! fsm - > b_sess_vld )
otg_set_state ( fsm , OTG_STATE_B_IDLE ) ;
2013-10-03 12:42:04 +09:00
else if ( ! fsm - > b_bus_req | | ! fsm - > a_conn | | fsm - > test_device )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_B_PERIPHERAL ) ;
break ;
case OTG_STATE_A_IDLE :
if ( fsm - > id )
otg_set_state ( fsm , OTG_STATE_B_IDLE ) ;
2013-10-03 12:42:04 +09:00
else if ( ! fsm - > a_bus_drop & & ( fsm - > a_bus_req | |
fsm - > a_srp_det | | fsm - > adp_change | | fsm - > power_up ) )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_A_WAIT_VRISE ) ;
break ;
case OTG_STATE_A_WAIT_VRISE :
2014-03-13 15:22:50 +08:00
if ( fsm - > a_vbus_vld )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_A_WAIT_BCON ) ;
2014-03-13 15:22:50 +08:00
else if ( fsm - > id | | fsm - > a_bus_drop | |
fsm - > a_wait_vrise_tmout )
otg_set_state ( fsm , OTG_STATE_A_WAIT_VFALL ) ;
2011-04-18 22:01:59 +02:00
break ;
case OTG_STATE_A_WAIT_BCON :
if ( ! fsm - > a_vbus_vld )
otg_set_state ( fsm , OTG_STATE_A_VBUS_ERR ) ;
else if ( fsm - > b_conn )
otg_set_state ( fsm , OTG_STATE_A_HOST ) ;
2014-03-13 15:22:51 +08:00
else if ( fsm - > id | | fsm - > a_bus_drop | | fsm - > a_wait_bcon_tmout )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_A_WAIT_VFALL ) ;
break ;
case OTG_STATE_A_HOST :
2014-02-27 07:38:19 +08:00
if ( fsm - > id | | fsm - > a_bus_drop )
otg_set_state ( fsm , OTG_STATE_A_WAIT_VFALL ) ;
else if ( ( ! fsm - > a_bus_req | | fsm - > a_suspend_req_inf ) & &
2012-02-13 13:24:06 +02:00
fsm - > otg - > host - > b_hnp_enable )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_A_SUSPEND ) ;
2014-02-27 07:38:19 +08:00
else if ( ! fsm - > b_conn )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_A_WAIT_BCON ) ;
else if ( ! fsm - > a_vbus_vld )
otg_set_state ( fsm , OTG_STATE_A_VBUS_ERR ) ;
break ;
case OTG_STATE_A_SUSPEND :
2012-02-13 13:24:06 +02:00
if ( ! fsm - > b_conn & & fsm - > otg - > host - > b_hnp_enable )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_A_PERIPHERAL ) ;
2012-02-13 13:24:06 +02:00
else if ( ! fsm - > b_conn & & ! fsm - > otg - > host - > b_hnp_enable )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_A_WAIT_BCON ) ;
else if ( fsm - > a_bus_req | | fsm - > b_bus_resume )
otg_set_state ( fsm , OTG_STATE_A_HOST ) ;
else if ( fsm - > id | | fsm - > a_bus_drop | | fsm - > a_aidl_bdis_tmout )
otg_set_state ( fsm , OTG_STATE_A_WAIT_VFALL ) ;
else if ( ! fsm - > a_vbus_vld )
otg_set_state ( fsm , OTG_STATE_A_VBUS_ERR ) ;
break ;
case OTG_STATE_A_PERIPHERAL :
if ( fsm - > id | | fsm - > a_bus_drop )
otg_set_state ( fsm , OTG_STATE_A_WAIT_VFALL ) ;
2013-10-03 12:42:04 +09:00
else if ( fsm - > a_bidl_adis_tmout | | fsm - > b_bus_suspend )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_A_WAIT_BCON ) ;
else if ( ! fsm - > a_vbus_vld )
otg_set_state ( fsm , OTG_STATE_A_VBUS_ERR ) ;
break ;
case OTG_STATE_A_WAIT_VFALL :
2014-02-27 07:38:19 +08:00
if ( fsm - > a_wait_vfall_tmout )
2011-04-18 22:01:59 +02:00
otg_set_state ( fsm , OTG_STATE_A_IDLE ) ;
break ;
case OTG_STATE_A_VBUS_ERR :
if ( fsm - > id | | fsm - > a_bus_drop | | fsm - > a_clr_err )
otg_set_state ( fsm , OTG_STATE_A_WAIT_VFALL ) ;
break ;
default :
break ;
}
2013-12-20 19:06:24 +09:00
mutex_unlock ( & fsm - > lock ) ;
2011-04-18 22:01:59 +02:00
2016-03-30 12:56:29 +03:00
VDBG ( " quit statemachine, changed = %d \n " , fsm - > state_changed ) ;
return fsm - > state_changed ;
2011-04-18 22:01:59 +02:00
}
2014-04-23 15:56:43 +08:00
EXPORT_SYMBOL_GPL ( otg_statemachine ) ;
2016-06-14 14:14:35 +08:00
MODULE_LICENSE ( " GPL " ) ;