📄 ftc_fotg2xx.c
字号:
DBG_OTG_TRACEC(">>>FOTG2XX_start_hnp()-->mdwOTGC_Control_A_SET_B_HNP_EN_Set\n"); mdwOTGC_Control_A_SET_B_HNP_EN_Set(); mUsbUnPLGClr(); //<4>.A-Host should disconnect the device issue the HNP Host_Disconnect_for_OTG(pFTC_OTG->otg.host,0); //<5>.Waiting for Role Change ==> if fail clear the all the variable wTemp=0; while (pFTC_OTG->otg.state == OTG_STATE_A_HOST) { //Waiting 500ms mdelay(10); wTemp++; if (wTemp>50) {//Time Out for waiting for Rolechange ERROR(pFTC_OTG,"???Waiting for Role Change Fail...\n"); mdwOTGC_Control_A_SET_B_HNP_EN_Clr(); pFTC_OTG->otg.host->b_hnp_enable=0; return(1); } } return 0;}//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------//------------------------- Group-4:OTG Function ------------------------------//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------//*********************************************************// Name: OTG_RoleChange// Description:This function will take care the event about role change.// It will close/init some function.// Input: void// Output:void//*********************************************************void OTG_RoleChange(void){ int wTempCounter; u32 wRole=mdwOTGC_Control_CROLE_Rd();#ifdef OPEN_CRITICAL_MESSAGE DBG_OTG_FUNCC("+(OTG_RoleChange)wRole=%d\n",wRole);#endif if (wRole==0) { //Change to Host if (mdwOTGC_Control_ID_Rd()==0) {//Device-A: change to Host mdwOTGC_Control_A_SET_B_HNP_EN_Clr(); OTGC_enable_vbus_draw(1); OTGP_Close(); OTGH_Open(); pFTC_OTG->otg.state = OTG_STATE_A_HOST; pFTC_OTG->otg.host->is_b_host=0; pFTC_OTG->otg.host->b_hnp_enable=0; if (pFTC_OTG->A_HNP_to_Peripheral>0) { //Device A from Peripheral to Host pFTC_OTG->otg.host->A_Disable_Set_Feature_HNP=1;//Tell to host that 'Do not set feature B_HNP_Enable' mdelay(10); //<1>.Waiting for OPT-B Connect after HNP-2 (200ms) wTempCounter=0; while (mwHost20_PORTSC_ConnectStatus_Rd()==0) { mdelay(1); wTempCounter++; //if (wTempCounter>200) {//Waiting for 200 ms if (wTempCounter>300) {//Waiting for 200 ms INFO(pFTC_OTG,">>> OTG-B do not connect under 200 ms...\n"); break; } } //<2>.If connect => Issue quick reset if (mwHost20_PORTSC_ConnectStatus_Rd()>0) { //mdelay(200);//For OPT-A Test mdelay(300);//For OPT-A Test OTGH_host_quick_Reset(); } //OTGC_AP_Set_to_Idle(); } pFTC_OTG->A_HNP_to_Peripheral=0; } else {//Device-B: Change to Host pFTC_OTG->otg.host->is_b_host=1; OTGP_Close(); OTGH_Open(); mdwOTGC_Control_B_HNP_EN_Clr(); mdwOTGC_Control_B_DSCHG_VBUS_Clr(); pFTC_OTG->otg.state = OTG_STATE_B_HOST; mdwOTGC_Control_B_BUS_REQ_Clr(); } } else { //Change to Peripheral if (mdwOTGC_Control_ID_Rd()==0) { //Device-A: change to Peripheral mdwOTGC_Control_A_SET_B_HNP_EN_Clr(); pFTC_OTG->otg.state = OTG_STATE_A_PERIPHERAL; pFTC_OTG->A_HNP_to_Peripheral=1; } else { //Device-B: Change to Peripheral mdwOTGC_Control_B_BUS_REQ_Clr(); pFTC_OTG->otg.state = OTG_STATE_B_PERIPHERAL; } OTGH_Close(); OTGP_Open(); }}//*********************************************************// Name: OTGC_Init// Description:// 1.Init the OTG Structure Variable// 2.Init the Interrupt register(OTG-Controller layer)// 3.Call the OTG_RoleChange function to init the Host/Peripheral// Input: void// Output:void//*********************************************************void OTGC_Init(void){ DBG_OTG_FUNCC("+(OTGC_Init)\n"); pFTC_OTG->A_HNP_to_Peripheral=0; pFTC_OTG->otg.host->A_Disable_Set_Feature_HNP=1; //<1>.Read the ID if (mdwOTGC_Control_ID_Rd()>0) { //Change to B Type //<1.1>.Init Variable pFTC_OTG->wCurrentInterruptMask=OTGC_INT_B_TYPE; pFTC_OTG->otg.state = OTG_STATE_B_IDLE; mdwOTGC_Control_A_SRP_DET_EN_Clr(); //<1.2>.Init Interrupt mdwOTGC_INT_Enable_Clr(OTGC_INT_A_TYPE); mdwOTGC_INT_Enable_Set(OTGC_INT_B_TYPE); mdwOTGC_GINT_MASK_OTG_Clr(); //<1.3>.Init the Host/Peripheral OTG_RoleChange(); } else { //Changfe to A Type //<2.1>.Init Variable pFTC_OTG->wCurrentInterruptMask=OTGC_INT_A_TYPE; pFTC_OTG->otg.state = OTG_STATE_A_IDLE; pFTC_OTG->otg.default_a=1; //Enable the SRP detect mdwOTGC_Control_A_SRP_RESP_TYPE_Clr(); //<2.2>. Init Interrupt mdwOTGC_INT_Enable_Clr(OTGC_INT_B_TYPE); mdwOTGC_INT_Enable_Set(OTGC_INT_A_TYPE); mdwOTGC_GINT_MASK_OTG_Clr(); //<2.3>.Init the Host/Peripheral OTG_RoleChange(); } DBG_OTG_FUNCC("-(OTGC_Init)\n");}//*********************************************************// Name: OTGC_INT_ISR// Description:This interrupt service routine belongs to the OTG-Controller// <1>.Check for ID_Change// <2>.Check for RL_Change// <3>.Error Detect// Input: wINTStatus// Output:void//*********************************************************void OTGC_INT_ISR(u32 wINTStatus){ int wTempCounter;#ifdef OPEN_CRITICAL_MESSAGE DBG_OTG_FUNCC("+(OTGC_INT_ISR)(0x30=0x%x)\n",mdwFOTGPort(0x30));#endif //<1>.Check for ID_Change if (wINTStatus&OTGC_INT_IDCHG) { OTGC_Init(); } else { //else of " if (wINTStatus&OTGC_INT_IDCHG) " //<2>.Check for RL_Change if (wINTStatus&OTGC_INT_RLCHG) OTG_RoleChange(); //<3>.Error Detect if (wINTStatus&OTGC_INT_AVBUSERR) ERROR(pFTC_OTG,"??? Error:Interrupt OTGC_INT_AVBUSERR=1... \n"); if (wINTStatus&OTGC_INT_OVC) ERROR(pFTC_OTG,"??? Error:Interrupt OTGC_INT_OVC=1... \n"); //<3>.Check for Type-A/Type-B Interrupt if (mdwOTGC_Control_ID_Rd()==0) { //For Type-A Interrupt if (wINTStatus & OTGC_INT_A_TYPE) { if (wINTStatus & OTGC_INT_ASRPDET) { //<1>.SRP detected => then set global variable INFO(pFTC_OTG,">>> OTG-A got the SRP from the DEvice-B ...\n"); //<2>.Turn on the V Bus pFTC_OTG->otg.state = OTG_STATE_A_WAIT_VRISE; OTGC_enable_vbus_draw(1); pFTC_OTG->otg.state = OTG_STATE_A_HOST; //<3>.Should waiting for Device-Connect Wait 300ms INFO(pFTC_OTG,">>> OTG-A Waiting for OTG-B Connect,\n"); wTempCounter=0; while(mwHost20_PORTSC_ConnectStatus_Rd()==0) { mdelay(1); wTempCounter++; if (wTempCounter>300) { //Waiting for 300 ms mdwOTGC_Control_A_SRP_DET_EN_Clr(); INFO(pFTC_OTG,">>> OTG-B do not connect under 300 ms...\n"); break; } } //<4>.If Connect => issue quick Reset if (mwHost20_PORTSC_ConnectStatus_Rd()>0) { mdelay(300);//For OPT-A Test OTGH_host_quick_Reset(); OTGH_Open(); pFTC_OTG->otg.host->A_Disable_Set_Feature_HNP=0; } } } } else { //For Type-B Interrupt } } //end of " if (wINTStatus&OTGC_INT_IDCHG) "}//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------//---------------------- Group-5:Module Function-------------------------------//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------//*********************************************************// Name: FOTG2XX_ISR// Description:// Checking for interrupt source// <1>.OTG Control interrupt event// <2>.Host Mode interrupt event// <3>.Peripheral interrupt event// Input:// Output://*********************************************************static irqreturn_t FOTG2XX_ISR(int irq, void *_dev, struct pt_regs *r){ u32 wINTStatus; struct FTC_OTGC_STS *dev = _dev; int iTimerCounter;#ifdef OPEN_CRITICAL_MESSAGE DBG_OTG_FUNCC("+FOTG2XX_ISR(FOTG2XX_irq)\n");#endif spin_lock(&dev->lock); wINTStatus = mdwOTGC_INT_STS_Rd(); //<1>.Checking the OTG layer interrupt status if (wINTStatus>0) { mdwOTGC_INT_STS_Clr(wINTStatus); if ((pFTC_OTG->wCurrentInterruptMask & wINTStatus)>0) OTGC_INT_ISR(wINTStatus); mdwOTGC_INT_STS_Clr(wINTStatus); } if (mdwOTGC_Control_CROLE_Rd()==0) { //<2>.For Host ISR if (mdwOTGC_GINT_STS_HOST_Rd()>0) pFTC_OTG->otg.host->hcd_isr(pFTC_OTG->otg.host,r); } else { //<3>.For Peripheral ISR if (mdwOTGC_GINT_STS_PERIPHERAL_Rd()>0) { //Here we must to check the HNP enable issue if (mUsbIntSrc2Rd() & BIT1) { //Peripheral Suspend if (pFTC_OTG->otg.gadget->b_hnp_enable==1) { //<2>.Waiting for Role Change interrupt status iTimerCounter=0; while(iTimerCounter<7000) { //Waiting 70ms if ((mdwOTGC_INT_STS_Rd()&OTGC_INT_RLCHG)>0) {//Role Change OK udelay(100); OTGH_host_quick_Reset(); printk(">>> Device-B: Role Change to Host ok & Issue port reset...\n"); pFTC_OTG->otg.gadget->b_hnp_enable=0; OTGP_Close(); goto Irq_Exit; } udelay(10); iTimerCounter++; } printk("??? Device Not Responding...\n"); pFTC_OTG->otg.gadget->b_hnp_enable=0; } //if (pFTC_OTG->otg.gadget->b_hnp_enable==1) } // if (mUsbIntSrc2Rd()&BIT1) pFTC_OTG->otg.gadget->udc_isr(); } //if (mdwOTGC_GINT_STS_PERIPHERAL_Rd()>0) }Irq_Exit: spin_unlock(&dev->lock); return IRQ_RETVAL(0);}/*-------------------------------------------------------------------------*///*********************************************************// Name: FOTG2XX_Remove// Description:Remove the Driver// Input:// Output://*********************************************************/* tear down the binding between this driver and the pci device */static void FOTG2XX_Remove(void){ DBG_OTG_FUNCC("+FOTG2XX_Remove()\n"); pFTC_OTG->otg.state = OTG_STATE_UNDEFINED; if (pFTC_OTG->got_irq) free_irq(IRQ_FOTG200, pFTC_OTG);//Andrew update kfree(pFTC_OTG); //Andrew update pFTC_OTG = 0; INFO(pFTC_OTG,"USB device unbind\n");}//*********************************************************// Name: FOTG2XX_Probe// Description:probe driver// Input: void// Output: int//*********************************************************static int FOTG2XX_Probe(void)//FOTG200.ok{ int retval=0; u8 wFound=0; struct otg_transceiver *the_OTG_controller; DBG_OTG_FUNCC("+FOTG2XX_Probe()\n"); //<1>.Checking FOTG2XX if ((mdwFOTGPort(0x00)==0x01000010) && (mdwFOTGPort(0x04)==0x00000001) && (mdwFOTGPort(0x08)==0x00000006)) wFound=1; DBG_OTG_FUNCC(">>> Checking FOTG2XX ...(Reg 0x00=0x%x)\n",wFOTGPeri_Port(0x00)); if (wFound==1) INFO(pFTC_OTG,">>> Found FOTG2XX ...\n"); else { ERROR(pFTC_OTG,"??? Not Found FOTG2XX ...(Reg 0x00=0x%x)\n",wFOTGPeri_Port(0x00)); return(-EBUSY); } //<2>.Register the Module DBG_OTG_TRACEC("FOTG2XX_Probe()--> devfs_register_chrdev(OTG_MAJOR=%d)\n",OTG_MAJOR); if (devfs_register_chrdev(OTG_MAJOR, "FOTG2XX", &otg_fops)) { err("unable to get major %d for otg devices", OTG_MAJOR); return -EBUSY; } //<3>.Init OTG Structure /* alloc, and start init */ pFTC_OTG = kmalloc (sizeof *pFTC_OTG, SLAB_KERNEL); if (pFTC_OTG == NULL){ ERROR(pFTC_OTG,"enomem FOTG2XX device\n"); retval = -ENOMEM; goto done; } //Bruce;; otg_set_transceiver(&(pFTC_OTG->otg)); xceiv=&(pFTC_OTG->otg); the_OTG_controller=&(pFTC_OTG->otg); //pending;;the_OTG_controller->dev = &(pFTC_OTG); the_OTG_controller->label = driver_name; the_OTG_controller->set_host = FOTG2XX_set_host, the_OTG_controller->set_peripheral = FOTG2XX_set_peripheral, the_OTG_controller->set_power = FOTG2XX_set_power,//Nobody will call this function in FOTG2XX the_OTG_controller->start_srp = FOTG2XX_start_srp,//Peripheral will call this function the_OTG_controller->start_hnp = FOTG2XX_start_hnp,//Peripheral and Host will not call 'start_hnp' //OTGC_AP_Set_to_Idle will call 'FOTG2XX_start_hnp' the_OTG_controller->gadget=0; the_OTG_controller->host=0; pFTC_OTG->otg.state = OTG_STATE_UNDEFINED; //<3>.Init FOTG2XX HW //john0215 for built-in OTG driver, under 2 conditions: //1)as Host, and has plugged in device before system bootup //2)as device, and has plugged into PC before system bootup // should not disable bit 5(Chip enable); otherwise condition 1) will failed // should disable bit 2(Global interrupt enable); otherwise condition 2) will failed // mdwOTGC_ChipEnable_Set(); mdwFOTGPort(0x100) &= ~(BIT2);#ifndef CONFIG_FIC8120_PLATFORM mdwOTGC_GINT_HI_ACTIVE_Set();//Fource FOTG200-Interrupt to High-Active#endif //Disable all the interrupt mdwOTGC_GINT_MASK_HOST_Set(); mdwOTGC_GINT_MASK_OTG_Set(); mdwOTGC_GINT_MASK_PERIPHERAL_Set(); cpe_int_set_irq(IRQ_FOTG200, LEVEL, H_ACTIVE); if (request_irq(IRQ_FOTG200, FOTG2XX_ISR, SA_INTERRUPT /*|SA_SAMPLE_RANDOM*/, driver_name, pFTC_OTG) != 0) { DBG(dev, "request interrupt failed\n"); retval = -EBUSY; pFTC_OTG->got_irq=0; goto done; } pFTC_OTG->got_irq=1; //pFTC_OTG->iTMP_Force_Speed=1;//Default force speed to Full /* done */ return 0;done: if (pFTC_OTG) FOTG2XX_Remove(); return retval;}//*********************************************************// Name: cleanup// Description: init driver// Input: void// Output: int//*********************************************************static int __init init (void){ INFO(pFTC_OTG,"Init FOTG2XX Driver\n"); DBG_OTG_TRACEC("FOTG2XX_BASE_ADDRESS = 0x%x\n", OTG_BASE_ADDRESS); return FOTG2XX_Probe();}module_init (init);//*********************************************************// Name: init// Description: init driver// Input:void// Output: void//*********************************************************static void __exit cleanup (void){ INFO(pFTC_OTG,"Remove FOTG2XX Driver...\n"); return FOTG2XX_Remove();}module_exit (cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -