📄 otg_drv.c
字号:
}
}
OTG_STATE OTG_Get_State(void)
{
return g_OtgInfo.otg_state;
}
void OTG_Enable_Device(void)
{
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)|(OTG_CTL_DP_HIGH | OTG_CTL_DM_LOW));
}
/************************************************************
ADC functions
*************************************************************/
static kal_uint32 OTG_Get_VBUS_Volt(void)
{
kal_uint8 adc_channel;
bmt_customized_struct *charing_para;
kal_uint16 adc;
kal_int32 volt;
adc_channel = custom_adc_get_channel(otg_vbus_adc_channel);
charing_para=bmt_get_customized_chr_para();
adc = ADC_GetData(adc_channel);
volt = (kal_int32)((adc_adc2vol(adc_channel, (double)adc)/100)*charing_para->adc_volt_factor[adc_channel]);
return volt;
}
static kal_bool OTG_Is_A_Bus_Valid(void)
{
kal_bool ret = KAL_FALSE;
kal_uint32 volt;
volt = OTG_Get_VBUS_Volt();
if(volt>=4400000)
ret = KAL_TRUE;
return ret;
}
static kal_bool OTG_Is_B_Session_Valid(void)
{
kal_bool ret = KAL_FALSE;
kal_uint32 volt;
volt = OTG_Get_VBUS_Volt();
if(volt>=2100000)
ret = KAL_TRUE;
return ret;
}
static kal_bool OTG_Is_B_Session_End(void)
{
kal_bool ret = KAL_FALSE;
kal_uint32 volt;
volt = OTG_Get_VBUS_Volt();
if(volt<=800000)
ret = KAL_TRUE;
return ret;
}
/************************************************************
Timer functions
*************************************************************/
/* GPT timeout handler */
static void OTG_Timeout_Hdlr(void *parameter)
{
kal_bool b_process_state_machine = KAL_FALSE;
kal_uint32 savedMask;
kal_bool b_dev_unmask_irq = KAL_TRUE;
GPTI_StopItem(g_OtgInfo.gpt_handle);
/* process OTG state machine*/
savedMask = SaveAndSetIRQMask();
g_OtgInfo.timer_out = KAL_TRUE;
if(g_OtgInfo.b_processing == KAL_FALSE)
{
g_OtgInfo.b_processing = KAL_TRUE;
b_process_state_machine = KAL_TRUE;
IRQMask(IRQ_USB_CODE);
}
RestoreIRQMask(savedMask);
if(b_process_state_machine==KAL_TRUE)
{
OTG_State_Machine();
g_OtgInfo.b_processing = KAL_FALSE;
if(g_OtgInfo.host_up==KAL_TRUE)
b_dev_unmask_irq = USB_HCD_Get_UnMask_Irq();
else if(g_OtgInfo.device_up==KAL_TRUE)
b_dev_unmask_irq = USB_Get_UnMask_Irq();
if((g_OtgInfo.b_unmask_irq==KAL_TRUE) && (b_dev_unmask_irq == KAL_TRUE))
IRQUnmask(IRQ_USB_CODE);
}
}
/* The tick uint is ms*/
static void OTG_Start_Timer(OTG_TIMER_TYPE type, kal_uint32 ticks)
{
if(g_OtgInfo.timer_on==KAL_TRUE)
EXT_ASSERT(0, (kal_uint32)g_OtgInfo.timer_on, (kal_uint32)g_OtgInfo.timer_type, (kal_uint32)g_OtgInfo.timer_out);
g_OtgInfo.timer_type = type;
g_OtgInfo.timer_on = KAL_TRUE;
g_OtgInfo.timer_out = KAL_FALSE;
/* If timer is longer than 20 ms, use GPT timer interrupt*/
if(ticks<20)
{
GPT_Start(3);
/* determine the time out value*/
g_OtgInfo.timeout_tick = (kal_uint32)GPT_return_current_count();
g_OtgInfo.timeout_tick+=ticks;
g_OtgInfo.timeout_tick = g_OtgInfo.timeout_tick&0xffff;
DRV_WriteReg8(OTG_INT_EN, DRV_Reg8(OTG_INT_EN)|OTG_INT_ENABLE_1_MSEC);
}
else
{
GPTI_StartItem(g_OtgInfo.gpt_handle, (ticks/10), OTG_Timeout_Hdlr, &g_OtgInfo);
}
}
/* stop the timer */
static void OTG_Stop_Timer(void)
{
DRV_WriteReg8(OTG_INT_EN, DRV_Reg8(OTG_INT_EN)&(~OTG_INT_ENABLE_1_MSEC));
GPT_Stop(3);
GPTI_StopItem(g_OtgInfo.gpt_handle);
g_OtgInfo.timer_on = KAL_FALSE;
g_OtgInfo.timer_out = KAL_FALSE;
g_OtgInfo.timer_type = OTG_TIMER_NONE;
}
/* used by OTG HISR to chek if timer is timeout or not */
static kal_bool OTG_Check_Timer(void)
{
kal_uint32 cur_timer_tick;
kal_bool ret = KAL_FALSE;
if(g_OtgInfo.timer_on==KAL_FALSE)
EXT_ASSERT(0, (kal_uint32)g_OtgInfo.timer_on, (kal_uint32)g_OtgInfo.timer_type, (kal_uint32)g_OtgInfo.timer_out);
cur_timer_tick = (kal_uint32)GPT_return_current_count();
if(cur_timer_tick>=g_OtgInfo.timeout_tick)
{
g_OtgInfo.timer_out = KAL_TRUE;
ret = KAL_TRUE;
}
else
{
ret = KAL_FALSE;
}
return ret;
}
/* return KAL_TRUE if "type" timer is timeout */
static kal_bool OTG_Is_TimerOut(OTG_TIMER_TYPE type)
{
kal_bool ret = KAL_FALSE;
if((g_OtgInfo.timer_out==KAL_TRUE)&&(g_OtgInfo.timer_type==type))
ret = KAL_TRUE;
return ret;
}
/* return if any timer is active*/
static kal_bool OTG_Is_TimerActive(void)
{
kal_bool ret = KAL_FALSE;
if((g_OtgInfo.timer_on == KAL_TRUE) || (g_OtgInfo.timer_out == KAL_TRUE))
ret = KAL_TRUE;
return ret;
}
/* return active timer type */
static OTG_TIMER_TYPE OTG_Get_TimerType(void)
{
return g_OtgInfo.timer_type;
}
/************************************************************
state machine functions
*************************************************************/
static void OTG_Process_A_Vbus_Fail(void)
{
/* Restore interrupt. Enable Attach interrupt only */
DRV_WriteReg8(USB_INT_ENB, VUSB_INT_ENB_ATTACH);
g_OtgInfo.otg_state = OTG_STATE_A_WAIT_VFALL;
/* Turn off VBUS*/
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_VBUS_ON));
if(g_OtgInfo.host_up==KAL_TRUE)
{
g_OtgInfo.host_up = KAL_FALSE;
g_OtgInfo.a_host_stop_hdlr();
g_OtgInfo.host_down_hdlr();
}
if(g_OtgInfo.device_up==KAL_TRUE)
{
g_OtgInfo.device_up = KAL_FALSE;
g_OtgInfo.device_down_hdlr();
}
/* Notify MMI device draws too much current */
g_OtgInfo.a_vrise_fail_hdlr();
}
static void OTG_Process_A_Idle(void)
{
if(OTG_Get_Plug_Type()==OTG_PLUG_B)
{
g_OtgInfo.otg_state = OTG_STATE_B_IDLE;
OTG_Process_B_Idle();
return;
}
if(g_OtgInfo.a_detect_b_data_pls==KAL_TRUE)
{
g_OtgInfo.a_detect_b_data_pls = KAL_FALSE;
g_OtgInfo.a_process_srp = KAL_TRUE;
OTG_Start_Timer(OTG_TIMER_A_DATA_PLS, TA_DATA_PLS);
}
else if(OTG_Is_TimerOut(OTG_TIMER_A_DATA_PLS)==KAL_TRUE)
{
OTG_Stop_Timer();
g_OtgInfo.a_process_srp = KAL_FALSE;
if((DRV_Reg8(USB_CTL)&VUSB_CTL_JSTATE) && (DRV_Reg8(OTG_STATUS)&OTG_STATUS_LINE_STATE_CHANGE))
{
g_OtgInfo.a_detect_b_srp = KAL_TRUE;
g_OtgInfo.a_bus_req = KAL_TRUE;
} /* Endif */
}
if((g_OtgInfo.a_bus_req==KAL_TRUE) || (g_OtgInfo.a_detect_b_srp==KAL_TRUE))
{
/* In case go here and SRP timer is still on*/
OTG_Stop_Timer();
g_OtgInfo.a_detect_b_srp = KAL_FALSE;
/* If device is up, pull it down*/
if(g_OtgInfo.device_up==KAL_TRUE)
{
g_OtgInfo.device_up = KAL_FALSE;
g_OtgInfo.device_down_hdlr();
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&
(~(OTG_CTL_DP_HIGH | OTG_CTL_DM_HIGH | OTG_CTL_DP_LOW |OTG_CTL_DM_LOW)) );
}
/* mask all interrupt in case interrupt happens during wating Vrise
interrupt will be unmasked when Vrise timer expiers*/
DRV_WriteReg8(USB_INT_ENB, 0);
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)|(OTG_CTL_DP_LOW | OTG_CTL_DM_LOW));
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~(OTG_CTL_DP_HIGH | OTG_CTL_DM_HIGH)));
/* Do not detect SRP because this system always provide power*/
/* Turn on VBUS*/
g_OtgInfo.otg_state = OTG_STATE_A_WAIT_VRISE;
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)|OTG_CTL_VBUS_ON);
OTG_Start_Timer(OTG_TIMER_A_WAIT_VRISE, TA_WAIT_VRISE);
OTG_Process_A_Wait_VRise();
}
}
static void OTG_Process_A_Wait_VRise(void)
{
if(OTG_Is_A_Bus_Valid()==KAL_TRUE)
{
OTG_Stop_Timer();
/* wait for B connect forever*/
g_OtgInfo.otg_state = OTG_STATE_A_WAIT_BCON;
if(g_OtgInfo.host_up==KAL_FALSE)
{
g_OtgInfo.host_up = KAL_TRUE;
g_OtgInfo.host_up_hdlr();
}
/* Restore interrupt. Enable Attach interrupt only */
DRV_WriteReg8(USB_INT_ENB, VUSB_INT_ENB_ATTACH);
// USB_Ms_Dbg_Trace(OTG_STATE_A_VRISE_WAIT_B_CON, 0);
}
else
{
if(OTG_Is_TimerOut(OTG_TIMER_A_WAIT_VRISE)==KAL_TRUE)
{
OTG_Stop_Timer();
OTG_Process_A_Vbus_Fail();
return;
}
}
/* Activate check VBUS timer */
if(OTG_Is_TimerActive()==KAL_FALSE)
{
OTG_Start_Timer(OTG_TIMER_A_CHECK_VBUS, TA_CHECK_VBUS);
}
}
static void OTG_Process_A_Wait_BCon(void)
{
/* check whether VBUS is maintained above VBUS threshold */
if(OTG_Is_TimerOut(OTG_TIMER_A_CHECK_VBUS)==KAL_TRUE)
{
OTG_Stop_Timer();
if(OTG_Is_A_Bus_Valid()==KAL_FALSE)
{
OTG_Process_A_Vbus_Fail();
return;
}
}
if (g_OtgInfo.a_detect_b_conn==KAL_TRUE)
{
// USB_Ms_Dbg_Trace(OTG_STATE_A_WAIT_B_CON_HOST, 0);
g_OtgInfo.otg_state = OTG_STATE_A_HOST;
}
/* Activate check VBUS timer */
if(OTG_Is_TimerActive()==KAL_FALSE)
{
OTG_Start_Timer(OTG_TIMER_A_CHECK_VBUS, TA_CHECK_VBUS);
}
}
static void OTG_Process_A_Host(void)
{
/* check whether VBUS is maintained above VBUS threshold */
if(OTG_Is_TimerOut(OTG_TIMER_A_CHECK_VBUS)==KAL_TRUE)
{
OTG_Stop_Timer();
if(OTG_Is_A_Bus_Valid()==KAL_FALSE)
{
OTG_Process_A_Vbus_Fail();
return;
}
}
/*
** If mini B plug is removed RESET (DETACH) interrupt will
** happen on A-Device.The DETACH will processed by the host
** ISR and set a_detect_b_conn to FALSE
*/
if ((g_OtgInfo.a_detect_b_conn==KAL_FALSE) && (g_OtgInfo.a_detect_b_resume ==KAL_FALSE))
{
g_OtgInfo.otg_state = OTG_STATE_A_WAIT_BCON;
if(g_OtgInfo.a_host_stop_hdlr!=NULL)
g_OtgInfo.a_host_stop_hdlr();
// USB_Ms_Dbg_Trace(OTG_STATE_A_HOST_WAIT_B_CON, 0);
}
/************ Starting HNP **************************************
** When the A-device is in the a_host state and has set the dual-role
** B-device's HNP enable bit (b_hnp_enable = TRUE ie, a_suspend_req
** = TRUE) the A-device shall place the connection to the B-device into
** Suspend when it is finished using the bus. We can go to the
** suspend state also if user want to power down.
*/
else if((g_OtgInfo.a_set_b_hnp_enable==KAL_TRUE) && (g_OtgInfo.a_detect_b_resume ==KAL_FALSE))
{
g_OtgInfo.otg_state = OTG_STATE_A_SUSPEND;
USB_HCD_Bus_Control(USB_HCD_BUS_SUSPEND_SOF);
/* stop the regilar check Vbus timer before activate another timer */
if(OTG_Get_TimerType()==OTG_TIMER_A_CHECK_VBUS)
OTG_Stop_Timer();
OTG_Start_Timer(OTG_TIMER_A_IDLE_BDIS, TA_AIDL_BDIS);
g_OtgInfo.a_process_hnp = KAL_TRUE;
}
/* A request to suspend the bus */
else if(g_OtgInfo.a_suspend_req==KAL_TRUE)
{
g_OtgInfo.otg_state = OTG_STATE_A_SUSPEND;
USB_HCD_Bus_Control(USB_HCD_BUS_SUSPEND_SOF);
g_OtgInfo.a_suspend_req = KAL_FALSE;
}
/* This may be because of B device is not supported by this A device */
else if(g_OtgInfo.a_bus_req==KAL_FALSE)
{
g_OtgInfo.otg_state = OTG_STATE_A_WAIT_VFALL;
USB_HCD_Bus_Control(USB_HCD_BUS_SUSPEND_SOF);
/* Turn off VBUS*/
DRV_WriteReg8(OTG_CTRL, DRV_Reg8(OTG_CTRL)&(~OTG_CTL_VBUS_ON));
}
/* OPT remote wakeup timeout*/
else if(OTG_Is_TimerOut(OTG_TIMER_A_REMOTE_WAKEUP) == KAL_TRUE)
{
OTG_Stop_Timer();
g_OtgInfo.a_detect_b_resume = KAL_FALSE;
// USB_Ms_Dbg_Trace(OTG_HOST_DEASSERT_RESUME, 0);
USB_HCD_Bus_Control(USB_HCD_BUS_DEASSERT_RESUME);
}
/* Activate check VBUS timer */
if(OTG_Is_TimerActive()==KAL_FALSE)
{
OTG_Start_Timer(OTG_TIMER_A_CHECK_VBUS, TA_CHECK_VBUS);
}
}
static void OTG_Process_A_Suspend(void)
{
/* check whether VBUS is maintained above VBUS threshold */
if(OTG_Is_TimerOut(OTG_TIMER_A_CHECK_VBUS)==KAL_TRUE)
{
OTG_Stop_Timer();
if(OTG_Is_A_Bus_Valid()==KAL_FALSE)
{
OTG_Process_A_Vbus_Fail();
return;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -