This patch adds OTG fsm timers initialization, which use controller's 1ms interrupt as time out counter, also adds some local timers which are not in otg_fsm_timer list. Signed-off-by: Li Jun <b47624@xxxxxxxxxxxxx> --- drivers/usb/chipidea/otg_fsm.c | 111 +++++++++++++++++++++++++++++++++++++++- drivers/usb/chipidea/otg_fsm.h | 65 +++++++++++++++++++++++ 2 files changed, 175 insertions(+), 1 deletions(-) diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index 31a046d..86bed68 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -33,7 +33,23 @@ static struct list_head active_timers; /* FSM timers */ struct ci_otg_fsm_timer *a_wait_vrise_tmr, *a_wait_vfall_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr, *a_bidl_adis_tmr, *b_ase0_brst_tmr, - *b_se0_srp_tmr, *b_srp_fail_tmr, *b_data_pulse_tmr; + *b_se0_srp_tmr, *b_srp_fail_tmr, *b_data_pulse_tmr, + *b_ssend_srp_tmr, *b_sess_vld_tmr; + +inline struct ci_otg_fsm_timer *otg_timer_initializer +(void (*function)(void *, unsigned long), unsigned long expires, + unsigned long data) +{ + struct ci_otg_fsm_timer *timer; + + timer = kmalloc(sizeof(struct ci_otg_fsm_timer), GFP_KERNEL); + if (!timer) + return NULL; + timer->function = function; + timer->expires = expires; + timer->data = data; + return timer; +} /* Add timer to timer list */ void ci_otg_add_timer(struct ci_hdrc *ci, struct ci_otg_fsm_timer *gtimer) @@ -170,6 +186,89 @@ int ci_otg_tick_timer(struct ci_hdrc *ci) return expired; } +/* The timeout callback function to set time out bit */ +void set_tmout(void *ptr, unsigned long indicator) +{ + *(int *)indicator = 1; +} + +/* Initialize timers */ +int ci_otg_init_timers(struct otg_fsm *fsm) +{ + /* FSM used timers */ + a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, + (unsigned long)&fsm->a_wait_vrise_tmout); + if (a_wait_vrise_tmr == NULL) + return -ENOMEM; + + a_wait_vfall_tmr = otg_timer_initializer(&set_tmout, + TA_WAIT_VFALL, (unsigned long)&fsm->a_wait_vfall_tmout); + if (a_wait_vfall_tmr == NULL) + return -ENOMEM; + + a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, + TA_WAIT_BCON, (unsigned long)&fsm->a_wait_bcon_tmout); + if (a_wait_bcon_tmr == NULL) + return -ENOMEM; + + a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, + TA_AIDL_BDIS, (unsigned long)&fsm->a_aidl_bdis_tmout); + if (a_aidl_bdis_tmr == NULL) + return -ENOMEM; + + a_bidl_adis_tmr = otg_timer_initializer(&set_tmout, + TA_BIDL_ADIS, (unsigned long)&fsm->a_bidl_adis_tmout); + if (a_bidl_adis_tmr == NULL) + return -ENOMEM; + + b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST, + (unsigned long)&fsm->b_ase0_brst_tmout); + if (b_ase0_brst_tmr == NULL) + return -ENOMEM; + + b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, + (unsigned long)&fsm->b_se0_srp); + if (b_se0_srp_tmr == NULL) + return -ENOMEM; + + b_ssend_srp_tmr = otg_timer_initializer(&set_tmout, + TB_SSEND_SRP, (unsigned long)&fsm->b_ssend_srp); + if (b_ssend_srp_tmr == NULL) + return -ENOMEM; + + b_srp_fail_tmr = otg_timer_initializer(&set_tmout, + TB_SRP_FAIL, (unsigned long)&fsm->b_srp_done); + if (b_srp_fail_tmr == NULL) + return -ENOMEM; + + b_data_pulse_tmr = otg_timer_initializer(&set_tmout, TB_DATA_PLS, 0); + if (b_data_pulse_tmr == NULL) + return -ENOMEM; + + b_sess_vld_tmr = otg_timer_initializer(&set_tmout, TB_SESS_VLD, 0); + if (b_sess_vld_tmr == NULL) + return -ENOMEM; + + return 0; +} + +/* Uninitialize timers */ +void ci_otg_uninit_timers(void) +{ + /* FSM used timers */ + kfree(a_wait_vrise_tmr); + kfree(a_wait_vfall_tmr); + kfree(a_wait_bcon_tmr); + kfree(a_aidl_bdis_tmr); + kfree(a_bidl_adis_tmr); + kfree(b_ase0_brst_tmr); + kfree(b_se0_srp_tmr); + kfree(b_ssend_srp_tmr); + kfree(b_srp_fail_tmr); + kfree(b_data_pulse_tmr); + kfree(b_sess_vld_tmr); +} + /* -------------------------------------------------------------*/ /* Operations that will be called from OTG Finite State Machine */ @@ -337,6 +436,8 @@ static struct otg_fsm_ops ci_otg_ops = { int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) { + int retval = 0; + if (ci->transceiver == NULL) return -EPROBE_DEFER; @@ -366,6 +467,14 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) mutex_init(&ci->fsm->lock); + INIT_LIST_HEAD(&active_timers); + retval = ci_otg_init_timers(ci->fsm); + if (retval) { + dev_err(ci->dev, "Couldn't init OTG timers\n"); + ci_otg_uninit_timers(); + return retval; + } + /* enable ID and A vbus valid irq */ hw_write(ci, OP_OTGSC, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS, OTGSC_IDIE | OTGSC_AVVIE); diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h index e1b45d7..6e8226a 100644 --- a/drivers/usb/chipidea/otg_fsm.h +++ b/drivers/usb/chipidea/otg_fsm.h @@ -11,6 +11,71 @@ #ifndef __DRIVERS_USB_CHIPIDEA_OTG_FSM_H #define __DRIVERS_USB_CHIPIDEA_OTG_FSM_H +/* + * A-DEVICE timing constants + */ + +/* Wait for VBUS Rise */ +#define TA_WAIT_VRISE (100) /* a_wait_vrise 100 ms, section: 6.6.5.1 */ + +/* Wait for VBUS Fall */ +#define TA_WAIT_VFALL (1000) /* a_wait_vfall: Used by A device to wait + * Vbus to fall below Votg_bus_lkg 7.4.5.2 + * TSSEND_LKG 1 sec */ +/* Wait for B-Connect */ +#define TA_WAIT_BCON (10000) /* a_wait_bcon > 1 sec, section: 6.6.5.2 + * This is only used to get out of + * OTG_STATE_A_WAIT_BCON state if there was + * no connection for these many milliseconds + */ + +/* A-Idle to B-Disconnect */ +/* It is necessary for this timer to be more than 750 ms because of a bug in OPT + * test 5.4 in which B OPT disconnects after 750 ms instead of 75ms as stated + * in the test description + */ +#define TA_AIDL_BDIS (5000) /* a_suspend minimum 200 ms, section: 6.6.5.3 */ + +/* B-Idle to A-Disconnect */ +#define TA_BIDL_ADIS (500) /* 3 to 200 ms */ + +/* B-device timing constants */ + + +/* Data-Line Pulse Time*/ +#define TB_DATA_PLS (10) /* b_srp_init,continue 5~10ms, section:5.3.3 */ +#define TB_DATA_PLS_MIN (5) /* minimum 5 ms */ +#define TB_DATA_PLS_MAX (10) /* maximum 10 ms */ + +/* SRP Initiate Time */ +#define TB_SRP_INIT (100) /* b_srp_init,maximum 100 ms, section:5.3.8 */ + +/* SRP Fail Time */ +#define TB_SRP_FAIL (7000) /* b_srp_init,Fail time 5~30s, section:6.8.2.2*/ + +/* SRP result wait time */ +#define TB_SRP_WAIT (60) + +/* VBus time */ +#define TB_VBUS_PLS (30) /* time to keep vbus pulsing asserted */ + +/* Discharge time */ +/* This time should be less than 10ms. It varies from system to system. */ +#define TB_VBUS_DSCHRG (8) + +/* A-SE0 to B-Reset */ +#define TB_ASE0_BRST (20) /* b_wait_acon, mini 3.125 ms,section:6.8.2.4 */ + +/* A bus suspend timer before we can switch to b_wait_aconn */ +#define TB_A_SUSPEND (7) +#define TB_BUS_RESUME (12) + +/* SE0 Time Before SRP */ +#define TB_SE0_SRP (2) /* b_idle,minimum 2 ms, section:5.3.2 */ +/* SSEND time before SRP, 1.5 sec min */ +#define TB_SSEND_SRP (1500) /* Table 5-1, Session end to SRP init */ +#define TB_SESS_VLD (1000) + struct ci_otg_fsm_timer { unsigned long expires; /* Number of count increase to timeout */ unsigned long count; /* Tick counter */ -- 1.7.8 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html