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

📄 otg_fsm.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	otg_reg_read32(HC_FM_REM_REG, &fn_rem);
	printk("%s fn = %x, fn_rem = %x\n",mesg, fn, fn_rem);
}

void otgfsm_fast_discharge(otg_fsm_t	*fsm_data, __u8 ctrl_flag) {

	__u16	wTemp;

	if(ctrl_flag == TRUE ) {
		// Discharge VBUS fastly
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp|OTG_DISCHRG_VBUS));
	} else {
		// Remove Discharfe fast path
		otgfsm_print_fn(fsm_data, "fast discharge disable");
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp&(~OTG_DISCHRG_VBUS)));
	}
}

/*----------------------------------------------*/
/* 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(OTG_CONTROL_REG, &wTemp);
			otg_reg_write16(OTG_CONTROL_REG, (wTemp|OTG_CHRG_VBUS));
	
		} else {

			otg_reg_read16(OTG_CONTROL_REG, &wTemp);
			otg_reg_write16(OTG_CONTROL_REG, (wTemp&(~OTG_CHRG_VBUS)));
		}
	} else {
		// A device driving VBUS line
		if(ctrl_flag == TRUE ) {

			otg_reg_read16(OTG_CONTROL_REG, &wTemp);
			otg_reg_write16(OTG_CONTROL_REG, (wTemp|OTG_DRV_VBUS));
		} else {
			otg_reg_read16(OTG_CONTROL_REG, &wTemp);
			otg_reg_write16(OTG_CONTROL_REG, (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(OTG_STATUS_REG,&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.status_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(OTG_TMR_REG, 0);		// Stop the timer first

	data = OTG_START_TIMER;
	data |= (time*OTG_TMR_RESOLUTION);					

	otg_reg_write32(OTG_TMR_REG, 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(OTG_TMR_REG, 0);		// Stop the timer first
}

/*----------------------------------------------*/
/* Run the B device FSM							*/
/* ---------------------------------------------*/
void otgfsm_run_Bdevice(otg_fsm_t	*fsm_data) {

	__u32	port_data;
	__u32	rem_time;

	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_se0_srp == 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) {

				isp1362_kernel_user_mesg("Unable to communicate with the device");
		        fsm_data->tcb.err_code = OTG_STATUS_TIMEOUT;
				fsm_data->tcb.b_srp_done = 0;
				fsm_data->tcb.bus_req = 0;
				fsm_data->tcb.b_host_pending = 0;

				/* Inform application about timeout */
				otg_fsm_state_change(fsm_data,B_IDLE);
			}
			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(	fsm_data->tcb.id == 0 || fsm_data->tcb.b_srp_done == 1 ) {

				//Allow 5s for A-device responding SRP
				fsm_data->tcb.b_host_pending = 1;
				otg_reg_write32(OTG_ALT_TMR_REG, OTG_START_TIMER);
				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.TimeOut == 1) {
 
				if(fsm_data->tcb.TimerId == B_BUS_REQ_TIMER_ID) {
					/* Bus is Still in hold by the A-HOST */
					isp1362_kernel_user_mesg("Unable to communicate with the connecetd device");
		        	fsm_data->tcb.err_code = OTG_STATUS_TIMEOUT;
					fsm_data->tcb.b_srp_done = 0;
					fsm_data->tcb.bus_req = 0;
					fsm_data->tcb.TimeOut = 0;
					/* Inform application about timeout */
					otg_fsm_state_change(fsm_data,B_PERIPHERAL);
				} else {
					fsm_data->tcb.TimeOut = 0;
					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);
					pdc_otg_control(NULL,PDC_DISABLE);
					otg_fsm_state_change(fsm_data,B_WAIT_ACON);
				}
			} else if ((fsm_data->tcb.bus_req == 1 || fsm_data->tcb.b_host_pending) && 
					fsm_data->tcb.b_hnp_en == 1 && 
					( fsm_data->tcb.a_bus_suspend == 1) ) {		/* OTG1.0A fix */
				fsm_data->tcb.b_host_pending = 0;
				otgfsm_start_timer(fsm_data,B_AIDL_BDIS_TIMER_ID,
							  B_AIDL_BDIS_TIMER);
			}
			break;

		case B_WAIT_ACON:

			otgfsm_local_pullup(FALSE);
			isp1362_udelay(150);		/* RCON_LSE0 fix */
			otgfsm_hc_dc_sel(FALSE);

			if(	fsm_data->tcb.b_sess_vld == 0 || fsm_data->tcb.id == 0 ) {

				isp1362_kernel_user_mesg("Unable to communicate with the connected device");
				fsm_data->tcb.b_host_pending = 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);
				fsm_data->tcb.b_host_pending = 0;
				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) {

					isp1362_kernel_user_mesg("Unable to communicate with the connected device");
		        	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);
				pdc_otg_control(NULL, PDC_ENABLE);
				otg_reg_read32(OTG_ALT_TMR_REG, &rem_time);
				rem_time &= 0x00FFFFFF;	/* Mask the start-stop and reserved bits */
				otgfsm_start_timer(fsm_data, B_BUS_REQ_TIMER_ID, (B_BUS_REQ_TIMER - rem_time/OTG_TMR_RESOLUTION));
				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
				isp1362_kernel_user_mesg("Unable to communicate with the connected device");
				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 ) {

				if(fsm_data->tcb.a_conn == 0) isp1362_kernel_user_mesg("Unable to communicate with the connected device");
				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;
					phci_otg_port_control(fsm_data->hcd_priv, OTG_PORT_OPEN_PORT_IMM, &port_data);
					otg_fsm_state_change(fsm_data,A_HOST);
				} else {
		        	if(fsm_data->tcb.bus_req == 1) {
						fsm_data->tcb.err_code = OTG_STATUS_TIMEOUT;

⌨️ 快捷键说明

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