⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 otg_fsm.c

📁 linux下的usb开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	} else {		// Disable local connection		otg_reg_read16(REG_OTG_CONTROL, &wTemp);		otg_reg_write16(REG_OTG_CONTROL, (wTemp&(~OTG_A_RDIS_LCON_EN)));	}}void otgfsm_rcon_lse0_en(__u8 ctrl_flag) {	__u16   wTemp;	if(ctrl_flag == TRUE) {		otg_reg_read16(REG_OTG_CONTROL, &wTemp);		otg_reg_write16(REG_OTG_CONTROL, (wTemp|OTG_B_RCON_LSE0_EN));	} else {		otg_reg_read16(REG_OTG_CONTROL, &wTemp);		otg_reg_write16(REG_OTG_CONTROL, (wTemp&(~OTG_B_RCON_LSE0_EN)));	}}/*----------------------------------------------*//* control local V Bus line						*//* For B device, VBus pulsing					*//* For A device VBus driving					*//* ---------------------------------------------*/void otgfsm_local_vbus(otg_fsm_t	*fsm_data, __u8 ctrl_flag) {	__u16	wTemp;	if(fsm_data->tcb.id == 1) {		// B device	vbus pulsing		if( ctrl_flag == TRUE ) {			otg_reg_read16(REG_OTG_CONTROL, &wTemp);			otg_reg_write16(REG_OTG_CONTROL, (wTemp|OTG_CHRG_VBUS));			} else {			otg_reg_read16(REG_OTG_CONTROL, &wTemp);			otg_reg_write16(REG_OTG_CONTROL, (wTemp&(~OTG_CHRG_VBUS)));		}	} else {		// A device driving VBUS line		if(ctrl_flag == TRUE ) {			otg_reg_read16(REG_OTG_CONTROL, &wTemp);			otg_reg_write16(REG_OTG_CONTROL, (wTemp|OTG_DRV_VBUS));		} else {			otg_reg_read16(REG_OTG_CONTROL, &wTemp);			otg_reg_write16(REG_OTG_CONTROL, (wTemp&(~OTG_DRV_VBUS)));		}	}}/*----------------------------------------------*//* Read and update OTG status information 		*//* ---------------------------------------------*/void otgfsm_status_probe(otg_fsm_t	*fsm_data) {	__u16	data = 0;	otg_reg_read16(REG_OTG_STATUS,&data);		// Read Status Register	fsm_data->regs.status_port.data = data;#ifdef CONFIG_DETAIL_DEBUG	otgfsm_print_status(fsm_data);		// Print OTG status #endif /* CONFIG_DETAIL_DEBUG */	// Copy Status and Interrupt registers info to FSM data 		fsm_data->tcb.id = fsm_data->regs.status_port.bitmap.ID;	fsm_data->tcb.a_vbus_vld = fsm_data->regs.status_port.bitmap.a_vbus_vld;	fsm_data->tcb.a_sess_vld = fsm_data->regs.status_port.bitmap.a_sess_vld;	fsm_data->tcb.b_conn = fsm_data->regs.status_port.bitmap.rmt_conn;	fsm_data->tcb.b_bus_resume = fsm_data->regs.int_port.bitmap.bus_resume;	fsm_data->tcb.a_srp_det = fsm_data->regs.int_port.bitmap.a_srp_det;	fsm_data->tcb.b_sess_end = fsm_data->regs.status_port.bitmap.b_sess_end;	fsm_data->tcb.b_sess_vld = fsm_data->regs.status_port.bitmap.b_sess_vld;	fsm_data->tcb.a_conn = fsm_data->regs.status_port.bitmap.rmt_conn;	fsm_data->tcb.b_se0_srp = fsm_data->regs.int_port.bitmap.b_se0_srp;	if(fsm_data->tcb.TimerRunning) {		// Update timeout info, if timer is running		fsm_data->tcb.TimeOut = fsm_data->regs.int_port.bitmap.otg_tmr_tmout;		if(fsm_data->tcb.TimeOut) {			fsm_data->tcb.TimerRunning = 0;		}	}}/*----------------------------------------------*//* Start timer for OTG fsm throug HW timer reg	*//* Timer resolution is 0.01 milliseconds		*//* the variable time is in milli seconds		*//* ---------------------------------------------*/void otgfsm_start_timer(otg_fsm_t	*fsm_data, __u8	timer_id, __u16	time ) {		__u32	data;		fsm_data->tcb.TimerRunning = 0;	fsm_data->tcb.TimeOut = 0;	fsm_data->tcb.TimerTick = time;			//Timer interrupt @time ms	fsm_data->tcb.TimerRunning = 1;	fsm_data->tcb.TimerId = timer_id;	otg_reg_write32(REG_OTG_TMR, 0);		// Stop the timer first	data = OTG_START_TIMER;	data |= (time*OTG_TMR_RESOLUTION);						otg_reg_write32(REG_OTG_TMR, data);	// Start the timer}/*----------------------------------------------*//* stop the timer for OTG fsm 					*//* ---------------------------------------------*/void otgfsm_stop_timer(otg_fsm_t	*fsm_data) {	fsm_data->tcb.TimerRunning = 0;	fsm_data->tcb.TimerId = 0;	otg_reg_write32(REG_OTG_TMR, 0);		// Stop the timer first}/*----------------------------------------------*//* Run the B device FSM							*//* ---------------------------------------------*/void otgfsm_run_Bdevice(otg_fsm_t	*fsm_data) {	__u32	port_data;	switch (fsm_data->tcb.state) {		// B StateMachine		case B_IDLE:			fsm_data->tcb.b_hnp_en = 0;			otgfsm_local_vbus(fsm_data, FALSE);			otgfsm_local_pullup(FALSE);			otgfsm_local_pulldown(TRUE);			otgfsm_hc_dc_sel(TRUE);	//default is DC			if(	fsm_data->tcb.id == 0 ) {				otgfsm_init_fsm_data(fsm_data);				otg_fsm_state_change(fsm_data,A_IDLE);			} else if ( fsm_data->tcb.bus_req == 1 &&					  fsm_data->tcb.b_sess_end == 1 && 					  fsm_data->tcb.b_srp_done == 0) {					// start VBus Pulsing 					otgfsm_local_pullup(TRUE);					otgfsm_start_timer(fsm_data,B_DATA_PLS_TIMER_ID,									B_DATA_PLS_TIMER);								otg_fsm_state_change(fsm_data,B_SRP_INIT);			} else if ( fsm_data->tcb.b_sess_vld == 1 ) {				pdc_otg_control(NULL, PDC_ENABLE);				otg_fsm_state_change(fsm_data,B_PERIPHERAL);							} else if ( fsm_data->tcb.TimeOut == 1) {		        fsm_data->tcb.err_code = OTG_STATUS_TIMEOUT;				fsm_data->tcb.b_srp_done = 0;				fsm_data->tcb.bus_req = 0;//				fsm_data->tcb.err_code = OTG_ERR_SRP_FAIL;			}			break;		case B_SRP_INIT:			if( fsm_data->tcb.TimeOut == 1 && 				fsm_data->tcb.TimerId == B_DATA_PLS_TIMER_ID) {					otgfsm_local_pullup(FALSE);                    // VBUS Pulsing                    otgfsm_local_vbus(fsm_data, TRUE);					otgfsm_start_timer(fsm_data,B_VBUS_PLS_TIMER_ID,									B_VBUS_PLS_TIMER);			} else if(fsm_data->tcb.TimeOut == 1 &&					  fsm_data->tcb.TimerId == B_VBUS_PLS_TIMER_ID) {                    otgfsm_local_vbus(fsm_data, FALSE);                    fsm_data->tcb.b_srp_done = 1;			} #if 0			/* Not needed */			else if ( fsm_data->tcb.b_sess_vld == 1 ) {				if(fsm_data->tcb.TimerId == B_DATA_PLS_TIMER_ID) {					otgfsm_local_pullup(FALSE);				} else {                    otgfsm_local_vbus(fsm_data, FALSE);				}				otgfsm_stop_timer(fsm_data);                fsm_data->tcb.b_srp_done = 0;				pdc_otg_control(NULL, PDC_ENABLE);				otg_fsm_state_change(fsm_data,B_PERIPHERAL);				break;			}#endif									if(	fsm_data->tcb.id == 0 || fsm_data->tcb.b_srp_done == 1 ) {				//Allow 5s for A-device responding SRP				otgfsm_start_timer(fsm_data, B_BUS_REQ_TIMER_ID, B_BUS_REQ_TIMER);					otg_fsm_state_change(fsm_data,B_IDLE);			}			break;		case B_PERIPHERAL:			otgfsm_local_pullup(TRUE);			otgfsm_hc_dc_sel(TRUE);			if( fsm_data->tcb.b_sess_vld == 0 || fsm_data->tcb.id == 0) {				pdc_otg_control(NULL,PDC_DISABLE);				otg_fsm_state_change(fsm_data,B_IDLE);			} else if ( fsm_data->tcb.bus_req == 1 && 					fsm_data->tcb.b_hnp_en == 1 && 					( fsm_data->tcb.a_bus_suspend == 1) ) { 				otgfsm_rcon_lse0_en(TRUE);				fsm_data->tcb.a_bus_suspend = 0;				fsm_data->tcb.b_hnp_en = 0;				otgfsm_start_timer(fsm_data,B_ASE0_BRST_TIMER_ID,							  B_ASE0_BRST_TIMER);	//5ms (3.125-10ms)				pdc_otg_control(NULL,PDC_DISABLE);				otg_fsm_state_change(fsm_data,B_WAIT_ACON);			}			break;		case B_WAIT_ACON:			otgfsm_local_pullup(FALSE);			otgfsm_hc_dc_sel(FALSE);			if(	fsm_data->tcb.b_sess_vld == 0 || fsm_data->tcb.id == 0 ) {				otgfsm_rcon_lse0_en(FALSE);				otgfsm_stop_timer(fsm_data);				otg_fsm_state_change(fsm_data,B_IDLE);			} else if( fsm_data->tcb.a_conn == 1 ) {				otgfsm_rcon_lse0_en(FALSE);				otgfsm_stop_timer(fsm_data);								port_data = USB_OTG_ENUMERATE_DEV;				phci_otg_port_control( fsm_data->hcd_priv, 					OTG_PORT_OPEN_PORT_IMM, &port_data);				otg_fsm_state_change(fsm_data,B_HOST);			}			else if( fsm_data->tcb.TimeOut == 1 || fsm_data->tcb.a_bus_resume ==  1)			{				if( fsm_data->tcb.TimeOut == 1) {		        	fsm_data->tcb.err_code = OTG_STATUS_TIMEOUT;					fsm_data->tcb.TimeOut = 0;					fsm_data->tcb.a_bus_reset = 1;	//SE0 >5ms should be taken as bus reset//					fsm_data->tcb.err_code = OTG_ERR_B_ASE0_BRST_TMOUT;				} else {					fsm_data->tcb.a_bus_resume = 0;				}				otgfsm_rcon_lse0_en(FALSE);				otg_fsm_state_change(fsm_data,B_PERIPHERAL);			}			break;		case B_HOST:			otgfsm_local_pullup(FALSE);			otgfsm_hc_dc_sel(FALSE);			if(	fsm_data->tcb.b_sess_vld == 0 || fsm_data->tcb.id == 0 ) {				// This might be a case of cable removal, and connection again,				// so clear bus request				fsm_data->tcb.bus_req = 0;				phci_otg_port_control(fsm_data->hcd_priv, OTG_PORT_DISCONNECT_PORT, NULL);				otg_fsm_state_change(fsm_data,B_IDLE);			} else if( (fsm_data->tcb.a_conn == 0 || fsm_data->tcb.bus_req == 0)					&& fsm_data->tcb.AllowStateChange == 1 ) {				fsm_data->tcb.AllowStateChange = 0;				phci_otg_port_control(fsm_data->hcd_priv, OTG_PORT_DISCONNECT_PORT, NULL);				pdc_otg_control(NULL, PDC_ENABLE);				otg_fsm_state_change(fsm_data,B_PERIPHERAL);			}			break;		default:			break;	}}/*----------------------------------------------*//* Run the A device FSM							*//* ---------------------------------------------*/void otgfsm_run_Adevice(otg_fsm_t	*fsm_data) {	__u16	data;	__u32	port_data;	switch (fsm_data->tcb.state)	{		// A_device statemachine		case A_IDLE:			fsm_data->tcb.a_set_b_hnp_en = 0;			otgfsm_local_vbus(fsm_data, FALSE);			otgfsm_local_pullup(FALSE);			otgfsm_local_pulldown(TRUE);			otgfsm_hc_dc_sel(FALSE);     //default HC			otgfsm_srp_det_en(TRUE);	//enable SRP detection			if( fsm_data->tcb.id == 1 ) {				otgfsm_srp_det_en(FALSE);  //Disable SRP detection				fsm_data->tcb.a_srp_det = 0;				otg_fsm_state_change(fsm_data,B_IDLE);			} else if( (fsm_data->tcb.bus_req == 1 || fsm_data->tcb.a_sess_vld == 1) 					&& fsm_data->tcb.bus_drop  == 0) {				otgfsm_srp_det_en(FALSE);				fsm_data->tcb.a_srp_det = 0;				otgfsm_start_timer(fsm_data, A_WAIT_VRISE_TIMER_ID,							  A_WAIT_VRISE_TIMER);				otg_fsm_state_change(fsm_data,A_WAIT_VRISE);			}			break;		case A_WAIT_VRISE:			otgfsm_local_vbus(fsm_data, TRUE);			otgfsm_local_pullup(FALSE);			otgfsm_hc_dc_sel(FALSE);			if (((fsm_data->tcb.a_sess_vld == 1) && (fsm_data->tcb.b_sess_vld == 1) && (fsm_data->tcb.a_vbus_vld == 1)) || (fsm_data->tcb.TimeOut == 1)) {				otgfsm_start_timer(fsm_data, A_WAIT_BCON_TIMER_ID, A_WAIT_BCON_TIMER);				otg_fsm_state_change(fsm_data,A_WAIT_BCON);			}			break;		case A_WAIT_BCON:			otgfsm_local_vbus(fsm_data, TRUE);			otgfsm_local_pullup(FALSE);			otgfsm_hc_dc_sel(FALSE);			if(	fsm_data->tcb.TimeOut == 1) 			{				if((fsm_data->tcb.b_conn == 1) && (fsm_data->tcb.TimerId == A_BCON_DEBOUNCE_TIMER_ID)) {				fsm_data->tcb.AllowStateChange = 0;								port_data = USB_OTG_GET_OTG_DESC;				if(fsm_data->tcb.bus_req == 1) port_data |= USB_OTG_ENUMERATE_DEV;				phci_otg_port_control(fsm_data->hcd_priv, OTG_PORT_OPEN_PORT_IMM, &port_data);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -