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

📄 otg_fsm.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
					}else {
						isp1362_kernel_user_mesg("Connected device is not responding");
					}
					fsm_data->tcb.bus_req = 0;
					otgfsm_stop_timer(fsm_data);
					otg_reg_write32(OTG_ALT_TMR_REG, OTG_START_TIMER);
//					otgfsm_fast_discharge(fsm_data, TRUE);
					otg_fsm_state_change(fsm_data,A_WAIT_VFALL);
				}
			} else if( fsm_data->tcb.id == 1 ||  fsm_data->tcb.bus_drop == 1) {

				fsm_data->tcb.bus_req = 0;
				otgfsm_stop_timer(fsm_data);
				otg_fsm_state_change(fsm_data,A_WAIT_VFALL);
				
			} else if ( fsm_data->tcb.a_vbus_vld == 0 ) {
				/* SW patch for VA_VBUS_VLD Bit going to low suddenly */
				isp1362_mdelay(10);	
				otg_reg_read16(OTG_STATUS_REG, &data);
				fsm_data->tcb.a_vbus_vld = (data & 0x02) ? 1: 0;
				if ( fsm_data->tcb.a_vbus_vld == 0 ) {
					otg_fsm_state_change(fsm_data,A_VBUS_ERR);
				}

			} else if (fsm_data->tcb.b_conn == 1) {
					
				if(fsm_data->tcb.TimerId != A_BCON_DEBOUNCE_TIMER_ID) {
					otgfsm_stop_timer(fsm_data);
					otgfsm_start_timer(fsm_data, A_BCON_DEBOUNCE_TIMER_ID, A_BCON_DEBOUNCE_TIMER);
				}
			}
			break;

		case A_HOST:

			otgfsm_local_vbus(fsm_data, TRUE);
			otgfsm_local_pullup(FALSE);
			otgfsm_hc_dc_sel(FALSE);

			if(	fsm_data->tcb.id == 1 || fsm_data->tcb.bus_drop == 1 || 
				fsm_data->tcb.b_conn == 0) {

				otgfsm_start_timer(fsm_data,A_WAIT_BCON_TIMER_ID, A_WAIT_BCON_TIMER);
				phci_otg_port_control(fsm_data->hcd_priv, OTG_PORT_DISCONNECT_PORT, NULL);
				otg_fsm_state_change(fsm_data,A_WAIT_BCON);

			} else if( fsm_data->tcb.a_vbus_vld == 0) {

				/* SW patch for VA_VBUS_VLD Bit going to low suddenly */
				isp1362_mdelay(10);	
				otg_reg_read16(OTG_STATUS_REG, &data);
				fsm_data->tcb.a_vbus_vld = (data & 0x02) ? 1: 0;
				if ( fsm_data->tcb.a_vbus_vld == 0 ) {
					phci_otg_port_control(fsm_data->hcd_priv, OTG_PORT_DISCONNECT_PORT, NULL);
					otg_fsm_state_change(fsm_data,A_VBUS_ERR);
				}

			} else if((fsm_data->tcb.bus_req == 0 && 
					fsm_data->tcb.AllowStateChange == 1) 
					|| fsm_data->tcb.a_suspend_req == 1) {


					otgfsm_rdis_lcon_en(TRUE); 	// if B-device disconnected, then A-device assert pull-up immediately
				otgfsm_start_timer(fsm_data, A_AIDL_BDIS_TIMER_ID, A_AIDL_BDIS_TIMER);
				phci_otg_port_control(fsm_data->hcd_priv, OTG_PORT_SUSPEND, NULL);
				phci_otg_port_control( fsm_data->hcd_priv, 
					OTG_PORT_DISCONNECT_PORT, NULL);
				otg_fsm_state_change(fsm_data,A_SUSPEND);


			}
			break;

		case A_SUSPEND:

			otgfsm_local_vbus(fsm_data, TRUE);
			otgfsm_local_pullup(FALSE);
			otgfsm_hc_dc_sel(FALSE);
			fsm_data->tcb.a_suspend_req = 0;

			if(	fsm_data->tcb.id == 1 || fsm_data->tcb.bus_drop == 1 || 
				fsm_data->tcb.TimeOut == 1) {

				fsm_data->tcb.TimeOut = 0;
				otgfsm_rdis_lcon_en(FALSE);
				otg_fsm_state_change(fsm_data,A_WAIT_VFALL);

			} else if (fsm_data->tcb.a_vbus_vld == 0 ) {

				/* SW patch for VA_VBUS_VLD Bit going to low suddenly */
				isp1362_mdelay(10);	
				otg_reg_read16(OTG_STATUS_REG, &data);
				fsm_data->tcb.a_vbus_vld = (data & 0x02) ? 1: 0;
				if ( fsm_data->tcb.a_vbus_vld == 0 ) {
					otg_fsm_state_change(fsm_data,A_VBUS_ERR);
				}

			} else if ( fsm_data->tcb.b_conn == 0 && fsm_data->tcb.a_set_b_hnp_en == 1) {

				//A-device starts to detect suspend condition after 5ms delay
				otgfsm_start_timer(fsm_data, A_SUSPEND_DET_TIMER_ID, A_SUSPEND_DET_TIMER);     
				fsm_data->tcb.b_bus_suspend = 0;
				pdc_otg_control(NULL, PDC_ENABLE);
				otg_fsm_state_change(fsm_data,A_PERIPHERAL);

			} else if ( fsm_data->tcb.b_conn == 0 && fsm_data->tcb.a_set_b_hnp_en == 0) {

				otgfsm_rdis_lcon_en(FALSE);
				otgfsm_start_timer(fsm_data,A_WAIT_BCON_TIMER_ID,A_WAIT_BCON_TIMER);
				otg_fsm_state_change(fsm_data,A_WAIT_BCON);

			} else if(fsm_data->tcb.bus_req == 1 || fsm_data->tcb.b_bus_resume == 1) {

				otgfsm_rdis_lcon_en(FALSE);
				fsm_data->tcb.AllowStateChange = 0;
				otg_fsm_state_change(fsm_data,A_HOST);
			}
			break;

		case A_PERIPHERAL:

			otgfsm_local_vbus(fsm_data, TRUE);
			otgfsm_local_pullup(TRUE);
			otgfsm_hc_dc_sel(TRUE);

			if( fsm_data->tcb.id == 1|| fsm_data->tcb.bus_drop == 1 )	
					// 0 == RmtSOF is IDLE for at least 3 ms
			{
				pdc_otg_control(NULL,PDC_DISABLE);
				otg_fsm_state_change(fsm_data,A_WAIT_VFALL);

			} else if (fsm_data->tcb.a_vbus_vld == 0 ) {


				/* SW patch for VA_VBUS_VLD Bit going to low suddenly */
				isp1362_mdelay(10);	
				otg_reg_read16(OTG_STATUS_REG, &data);
				fsm_data->tcb.a_vbus_vld = (data & 0x02) ? 1: 0;
				if ( fsm_data->tcb.a_vbus_vld == 0 ) {
					pdc_otg_control(NULL,PDC_DISABLE);
					otg_fsm_state_change(fsm_data,A_VBUS_ERR);
				}
			}
			else if (fsm_data->tcb.b_bus_suspend == 1 && fsm_data->tcb.TimeOut == 1	) // suspend
			{
		        	fsm_data->tcb.err_code = OTG_STATUS_NONE;
				otgfsm_start_timer(fsm_data,A_WAIT_BCON_TIMER_ID,A_WAIT_BCON_TIMER);

				fsm_data->tcb.b_bus_suspend = 0;
				pdc_otg_control(NULL,PDC_DISABLE);
				otg_fsm_state_change(fsm_data,A_WAIT_BCON);
			}
			break;

		case A_WAIT_VFALL:

			otgfsm_local_vbus(fsm_data, FALSE);
//			otgfsm_fast_discharge(fsm_data, TRUE);
			otgfsm_local_pullup(FALSE);

			otgfsm_hc_dc_sel(FALSE);

			if(fsm_data->tcb.bus_req == 1 || 
			   (fsm_data->tcb.a_sess_vld == 0 && fsm_data->tcb.b_conn == 0) ||
				fsm_data->tcb.id == 1) {
//				otgfsm_fast_discharge(fsm_data, FALSE);
				otgfsm_init_fsm_data(fsm_data);
				otg_fsm_state_change(fsm_data,A_IDLE);

			}
			break;

		case A_VBUS_ERR:


			otgfsm_local_vbus(fsm_data, FALSE);
			otgfsm_local_pullup(FALSE);
			fsm_data->tcb.err_code = OTG_STATUS_VBUS_ERR;		/* Set the VBUS error status */

			otgfsm_hc_dc_sel(FALSE);

			if(fsm_data->tcb.id == 1 || fsm_data->tcb.bus_drop == 1) {

				fsm_data->tcb.bus_drop = 0;
				otg_fsm_state_change(fsm_data,A_WAIT_VFALL);
			}
			break;

		default:
			break;
	}
}

/*----------------------------------------------*/
/* Run the OTG 	FSM								*/
/* ---------------------------------------------*/
void otgfsm_run(otg_fsm_t	*fsm_data) {

	__u8	prev_state = INV_STATE;

	// Get inputs for the FSM
	otgfsm_status_probe(fsm_data);

	// Run the A device FSM until its stebilized
	while(prev_state != fsm_data->tcb.state) {

		prev_state = fsm_data->tcb.state;
		otgfsm_run_Adevice(fsm_data);
	}
	
	prev_state = INV_STATE;

	// Run the B device FSM until its stebilized
	while(prev_state != fsm_data->tcb.state) {

		prev_state = fsm_data->tcb.state;
		otgfsm_run_Bdevice(fsm_data);
	}
}

/*----------------------------------------------*/
/* Init	fsm data variables						*/
/* ---------------------------------------------*/
void otgfsm_init_fsm_data(otg_fsm_t	*fsm_data) {

	/* Reset all the fields of fsm_data */
	fsm_data->tcb.bus_req = 0;
	fsm_data->tcb.b_host_pending = 0;
	fsm_data->tcb.a_suspend_req = 0;
	fsm_data->tcb.a_bus_resume = 0;
	fsm_data->tcb.a_bus_suspend = 0;
	fsm_data->tcb.a_bus_reset = 0;
	fsm_data->tcb.b_bus_resume = 0;
	fsm_data->tcb.b_bus_suspend = 0;

	fsm_data->tcb.b_hnp_en = 0;

	fsm_data->tcb.a_set_b_hnp_en = 0;
	fsm_data->tcb.b_hnp_support = 1;
	fsm_data->tcb.a_hnp_support = 0;
	fsm_data->tcb.a_alt_hnp_support = 0;

	/* Stop if any timer is running */
	if(fsm_data->tcb.TimerRunning == 1) otgfsm_stop_timer(fsm_data);

	fsm_data->tcb.TimerRunning = 0;
	fsm_data->tcb.TimeOut = 0;
	fsm_data->tcb.TimerTick = 0;

	fsm_data->tcb.Req4StateChange = 0;
	fsm_data->tcb.AllowStateChange = 0;

	fsm_data->tcb.bus_drop = 0;

	fsm_data->tcb.TimerId = 0;

	isp1362_otg_dev = fsm_data->dev;

	/* Clear all the interrupts in the OTG interrupt register */
	otg_reg_write16(OTG_INT_REG, 0xFFFF);
}

/*----------------------------------------------*/
/* Init	fsm 									*/
/* ---------------------------------------------*/
void otgfsm_init(otg_fsm_t	*fsm_data ) {

	otgfsm_init_fsm_data(fsm_data);

	otgfsm_status_probe(fsm_data);

	/* Enable all possible OTG interrupt sources */
	otg_reg_write16(OTG_INT_ENABLE_REG, OTG_IRQ_MASK);

	switch(fsm_data->tcb.id) {

		case 0:
			fsm_data->tcb.state = A_IDLE;
			fsm_data->tcb.app_state = A_IDLE;
			otgfsm_hc_dc_sel(FALSE);	//default HC

			break;

		case 1:
			fsm_data->tcb.state = B_IDLE;
			fsm_data->tcb.app_state = B_IDLE;
			otgfsm_hc_dc_sel(TRUE);	//default DC

			break;
		default:
			break;
	}

	otgfsm_run(fsm_data);
}

void otgfsm_deinit(otg_fsm_t	*fsm_data ) {

	/* Disable all OTG interrupts */
	otg_reg_write16(OTG_INT_ENABLE_REG, OTG_IRQ_MASK);

	otg_reg_write16(OTG_CONTROL_REG, 0x00C0);
	
	switch (fsm_data->tcb.state) {
		case A_HOST:
		case B_HOST:
			phci_otg_port_control(fsm_data->hcd_priv, OTG_PORT_DISCONNECT_PORT, NULL);

		break;

		case A_PERIPHERAL:
		case B_PERIPHERAL:
	
			pdc_otg_control(NULL, PDC_DISCONNECT);
		
		break;
	}

	return;	
}

/*----------------------------------------------*/
/* Change the FSM state (request from application */
/* ---------------------------------------------*/
void otgfsm_set_state(otg_fsm_t	*fsm_data, __u8	cmd) {

	// Change the FSM variables
	
	fsm_data->tcb.err_code = OTG_STATUS_NONE;

	/* Set the FSM variables based on the command received */
	switch(cmd) {

		case HOST:

			/* Change the state of the FSM to HOST (open OTG session) */
			fsm_data->tcb.bus_req = 1;
			fsm_data->tcb.bus_drop = 0;
			fsm_data->tcb.b_srp_done = 0;
			fsm_data->tcb.a_suspend_req = 0;

			break;
		
		case BUS_DROP:
		
			/* Drop the VBUS */
			fsm_data->tcb.bus_req = 0;
			fsm_data->tcb.bus_drop = 1;

			break;

		case BUS_OPEN:

			/* Allow VBUS to go when required */
			fsm_data->tcb.bus_drop = 0;

			break;

		case IDLE:

			/* Change the state to IDLE (close OTG session) */
			fsm_data->tcb.bus_req = 0;
			if(fsm_data->tcb.id == 0) {
				fsm_data->tcb.a_suspend_req = 1;
			} else if(fsm_data->tcb.b_host_pending == 0) {
				/* There is no host pending, So
				 * Clear the bus request completely
				 */
				fsm_data->tcb.AllowStateChange = 1;
			}
			
			break;

		case PERIPHERAL:

			/* This releases the mastership to other remote OTG device
			 * if applicable otherwise closes the session */
			fsm_data->tcb.bus_req = 0;
			if(fsm_data->tcb.id == 1) {
				fsm_data->tcb.AllowStateChange = 1;
			}

			break;

	}

	// Run the fsm
	otgfsm_run(fsm_data);
}

⌨️ 快捷键说明

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