Esempio n. 1
0
static void mtk_set_vbus(struct musb *musb, int is_on)
{
    DBG(0,"mt65xx_usb20_vbus++,is_on=%d\r\n",is_on);
#ifndef CONFIG_MT6589_FPGA
    if(is_on){
        //power on VBUS, implement later...
    #ifdef MTK_FAN5405_SUPPORT
        fan5405_set_opa_mode(1);
        fan5405_set_otg_pl(1);
        fan5405_set_otg_en(1);
    #elif defined(MTK_BQ24158_SUPPORT)
        bq24158_set_opa_mode(1);
	bq24158_set_otg_pl(1);
	bq24158_set_otg_en(1);
//<2013/1/21-20645-jessicatseng, [Pelican] Intrgrate charging IC BQ24157 for PRE-MP SW
    #elif defined(MTK_BQ24157_SUPPORT)
        bq24157_set_opa_mode(1);
        bq24157_set_otg_pl(1);
        bq24157_set_otg_en(1);
//>2013/1/21-20645-jessicatseng
    #elif defined(MTK_NCP1851_SUPPORT) || defined(MTK_BQ24196_SUPPORT)
        tbl_charger_otg_vbus((work_busy(&musb->id_pin_work.work)<< 8)| 1);
    #else
        mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN,GPIO_OUT_ONE);
        #endif
    } else {
        //power off VBUS, implement later...
    #ifdef MTK_FAN5405_SUPPORT
        fan5405_config_interface_liao(0x01,0x30);
	fan5405_config_interface_liao(0x02,0x8e);
    #elif defined(MTK_BQ24158_SUPPORT)
        bq24158_config_interface_reg(0x01,0x30);
	bq24158_config_interface_reg(0x02,0x8e);
//<2013/1/21-20645-jessicatseng, [Pelican] Intrgrate charging IC BQ24157 for PRE-MP SW
    #elif defined(MTK_BQ24157_SUPPORT)
        bq24157_config_interface_liao(0x01,0x30);
	bq24157_config_interface_liao(0x02,0x8e);
//>2013/1/21-20645-jessicatseng
    #elif defined(MTK_NCP1851_SUPPORT) || defined(MTK_BQ24196_SUPPORT)
        tbl_charger_otg_vbus((work_busy(&musb->id_pin_work.work)<< 8)| 0);
    #else
        mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN,GPIO_OUT_ZERO);
    #endif
    }
#endif
    return;
}
void mt_usb_set_vbus(struct musb *musb, int is_on)
{
    DBG(0,"mt65xx_usb20_vbus++,is_on=%d\r\n",is_on);
#ifndef FPGA_PLATFORM
    if(is_on){
        //power on VBUS, implement later...
    #ifdef MTK_FAN5405_SUPPORT
        fan5405_set_opa_mode(1);
        fan5405_set_otg_pl(1);
        fan5405_set_otg_en(1);
    #elif defined(MTK_BQ24157_SUPPORT)
        bq24157_set_opa_mode(1);
        bq24157_set_otg_pl(1);
        bq24157_set_otg_en(1);
    #elif defined(MTK_BQ24158_SUPPORT)
        bq24158_set_opa_mode(1);
        bq24158_set_otg_pl(1);
        bq24158_set_otg_en(1);
    #elif defined(MTK_NCP1851_SUPPORT) || defined(MTK_BQ24196_SUPPORT)
        tbl_charger_otg_vbus((work_busy(&musb->id_pin_work.work)<< 8)| 1);
    #else
		mt_set_gpio_mode(GPIO_OTG_DRVVBUS_PIN,GPIO_OTG_DRVVBUS_PIN_M_GPIO);
        mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN,GPIO_OUT_ONE);
        #endif
    } else {
        //power off VBUS, implement later...
    #ifdef MTK_FAN5405_SUPPORT
        fan5405_config_interface_liao(0x01,0x30);
		fan5405_config_interface_liao(0x02,0x8e);
    #elif defined(MTK_BQ24157_SUPPORT)		
        bq24157_config_interface_liao(0x01,0x30);
        bq24157_config_interface_liao(0x02,0x8e);
    #elif defined(MTK_BQ24158_SUPPORT)		
        bq24158_config_interface_liao(0x01,0x30);
		bq24158_config_interface_liao(0x02,0x8e);
    #elif defined(MTK_NCP1851_SUPPORT) || defined(MTK_BQ24196_SUPPORT)
        tbl_charger_otg_vbus((work_busy(&musb->id_pin_work.work)<< 8)| 0);
    #else
		mt_set_gpio_mode(GPIO_OTG_DRVVBUS_PIN,GPIO_OTG_DRVVBUS_PIN_M_GPIO);
        mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN,GPIO_OUT_ZERO);
    #endif
    }
#endif
}
int musb_otg_exec_cmd(unsigned int cmd){

    unsigned char devctl;
    unsigned char intrusb;
    unsigned short intrtx;
    unsigned char power;
    unsigned short csr0;
    unsigned int usb_l1intp;
    unsigned int usb_l1ints;

    unsigned int ret;
    unsigned long timeout;
    bool timeout_flag = false;

    if(!mtk_musb){
        DBG(0,"mtk_musb is NULL,error!\n");
        }

	switch(cmd){
		case HOST_CMD_ENV_INIT:
    		musb_otg_env_init();
			return 0;
		case HOST_CMD_ENV_EXIT:
			musb_otg_env_exit ();
			return 0;
		}

    //init
    musb_writeb(mtk_musb->mregs, MUSB_POWER, 0x21);
    musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);
    msleep(300);

    #ifdef DX_DBG
    devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
    power = musb_readb (mtk_musb->mregs,MUSB_POWER);
    intrusb = musb_readb(mtk_musb->mregs,MUSB_INTRUSB);
    DBG(0,"1:cmd=%d,devctl=0x%x,power=0x%x,intrusb=0x%x\n",cmd,devctl,power,intrusb);
    #endif
    musb_writew(mtk_musb->mregs,MUSB_INTRRX,0xffff);
    musb_writew(mtk_musb->mregs,MUSB_INTRTX,0xffff);
    musb_writeb(mtk_musb->mregs,MUSB_INTRUSB,0xff);
    msleep(10);
    #ifdef DX_DBG
    devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
    power = musb_readb (mtk_musb->mregs,MUSB_POWER);
    intrusb = musb_readb(mtk_musb->mregs,MUSB_INTRUSB);
    DBG(0,"2:cmd=%d,devctl=0x%x,power=0x%x,intrusb=0x%x\n",cmd,devctl,power,intrusb);
    #endif
    high_speed = false;
    g_exec = 1;

	DBG(0,"before exec:cmd=%d\n",cmd);

    switch(cmd){
        //electrical
        case OTG_CMD_E_ENABLE_VBUS:
        		DBG(0,"musb::enable VBUS!\n");
            musb_otg_set_session (true);
	    #ifdef MTK_FAN5405_SUPPORT
	    fan5405_set_opa_mode(1);
	    fan5405_set_otg_pl(1);
	    fan5405_set_otg_en(1);
            #elif defined(MTK_BQ24158_SUPPORT) 
            bq24158_set_opa_mode(1);
	    bq24158_set_otg_pl(1);
	    bq24158_set_otg_en(1);
//<2013/3/4-22419-jessicatseng, [Pelican] Some bq24157 related files are not integrated into JB2
	    #elif defined(MTK_BQ24157_SUPPORT)
	    bq24157_set_opa_mode(1);
	    bq24157_set_otg_pl(1);
	    bq24157_set_otg_en(1);
//>2013/3/4-22419-jessicatseng	    
	    #endif
            while(g_exec)
                msleep(100);
            musb_otg_set_session (false);
	    #ifdef MTK_FAN5405_SUPPORT
	    fan5405_config_interface_liao(0x01,0x30);
	    fan5405_config_interface_liao(0x02,0x8e);
            #elif defined(MTK_BQ24158_SUPPORT)
            bq24158_config_interface_reg(0x01,0x30);
	    bq24158_config_interface_reg(0x02,0x8e);
//<2013/3/4-22419-jessicatseng, [Pelican] Some bq24157 related files are not integrated into JB2
	    #elif defined(MTK_BQ24157_SUPPORT)
	    bq24157_config_interface_liao(0x01,0x30);
	    bq24157_config_interface_liao(0x02,0x8e);
//>2013/3/4-22419-jessicatseng	    
	    #endif
            break;
        case OTG_CMD_E_ENABLE_SRP: //need to clear session?
            DBG(0,"musb::enable srp!\n");
            musb_otg_reset_usb();
            USBPHY_WRITE8 (0x6c, 0x1);
            USBPHY_WRITE8 (0x6d, 0x1);
            musb_writeb(mtk_musb->mregs,0x7B,1);
            musb_otg_set_session (true);
            while(g_exec){
                msleep(100);
                }
            musb_otg_set_session (false);
            break;
        case OTG_CMD_E_START_DET_SRP:
            //need as a A-device
            musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);
            devctl = musb_readb (mtk_musb->mregs, MUSB_DEVCTL);
             while(g_exec&&(devctl & 0x18)){//VBUS[1:0] should be 0, it indicate below SessionEnd
                DBG(0,"musb::not below session end!\n");
                msleep(100);
                devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
                }
            while(g_exec&&(!(devctl & 0x10))){
                DBG(0,"musb::not above session end!\n");
                msleep(100);
                devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
                }
            devctl |= MUSB_DEVCTL_SESSION;
            musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, devctl);
            while(g_exec)
                msleep(100);
            musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);
            break;
        case OTG_CMD_E_START_DET_VBUS:
            usb_l1intp = musb_readl(mtk_musb->mregs,USB_L1INTP);
            usb_l1intp &= ~(1<<10);
            musb_writel(mtk_musb->mregs,USB_L1INTP,usb_l1intp);
            usb_l1ints = musb_readl(mtk_musb->mregs,USB_L1INTS);
            while((usb_l1ints&(1<<8))==0){
                DBG(0,"musb::vbus is 0!\n");
                msleep(100);
                usb_l1ints = musb_readl(mtk_musb->mregs,USB_L1INTS);
                }
            DBG(0,"musb::vbus is detected!\n");
            power = musb_readb (mtk_musb->mregs,MUSB_POWER);
            power |= MUSB_POWER_SOFTCONN;
            musb_writeb(mtk_musb->mregs, MUSB_POWER, power);
            while(g_exec)
                 msleep(100);
            musb_writeb(mtk_musb->mregs, MUSB_POWER, 0x21);
            break;

		case OTG_CMD_P_B_UUT_TD59:
			is_td_59 = true;
			if(is_td_59) DBG(0, "TD5.9 will be tested!\n");
			break;

        //protocal
        case OTG_CMD_P_A_UUT:
			DBG(0,"A-UUT starts...\n");
            //polling the session req from B-OPT and start a new session
            device_enumed = false;
TD_4_6:
            musb_otg_reset_usb();
			DBG(0,"A-UUT reset success\n");
            timeout = jiffies + 5*HZ;
            musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);
            devctl = musb_readb (mtk_musb->mregs, MUSB_DEVCTL);
            while(g_exec&&(devctl & 0x18)){//VBUS[1:0] should be 0, it indicate below SessionEnd
                DBG(0,"musb::not below session end!\n");
                msleep(100);
                if(time_after(jiffies,timeout)){
                    timeout_flag = true;
                    break;
                    }
                devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
                }
            if(timeout_flag){
                timeout_flag = false;
                musb_otg_reset_usb();
                DBG(0,"timeout for below session end, after reset usb, devctl=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_DEVCTL));
                }
            DBG(0,"polling session request,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_SESSREQ);
            DBG(0,"polling session request,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            musb_otg_set_session(true);//session is set and VBUS will be out.
            #if 1
            power = musb_readb(mtk_musb->mregs,MUSB_POWER);
            power &= ~MUSB_POWER_SOFTCONN;
            musb_writeb(mtk_musb->mregs,MUSB_POWER,power);
            #endif
            //polling the connect interrupt from B-OPT
            DBG(0,"polling connect interrupt,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_CONNECT);
            DBG(0,"polling connect interrupt,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            if(DEV_NOT_CONNECT == ret){
                DBG(0,"device is not connected in 15s\n");
                g_otg_message.msg = OTG_MSG_DEV_NOT_RESPONSE;
                break;
                }
            DBG(0,"musb::connect interrupt is detected!\n");
            msleep(100);//the test is fail beacuse the reset starts less than100 ms from the B-OPT connect. the IF test needs
            //reset the bus,check whether it is a hs device
            musb_h_reset();//should last for more than 50ms, TD.4.2
            musb_h_enumerate();
            //suspend the bus
            csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0);
            DBG(0,"after enum B-OPT,csr0=0x%x\n",csr0);
            musb_h_suspend();

            //polling the disconnect interrupt from B-OPT, and remote wakeup(TD.4.8)
            DBG(0,"polling disconnect or remote wakeup,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_DISCONNECT|MUSB_INTR_RESUME);
            DBG(0,"polling disconnect or remote wakeup,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            if(MUSB_INTR_RESUME == ret){
                //for TD4.8
                musb_h_remote_wakeup();
                //maybe need to access the B-OPT, get device descriptor
                if(g_exec)
                    wait_for_completion (&stop_event);
                break;
                }
            //polling the reset interrupt from B-OPT
            if(!(ret & MUSB_INTR_RESET)){
                DBG(0,"polling reset for B-OPT,begin\n");
                ret = musb_polling_bus_interrupt(MUSB_INTR_RESET);
                DBG(0,"polling reset for B-OPT,done,ret=0x%x\n",ret);
                if(TEST_IS_STOP == ret) break;
                if(DEV_NOT_RESET == ret){
                    if(g_exec)
                        wait_for_completion (&stop_event);
                    break;
                    }
                }

            DBG(0,"after receive reset,devctl=0x%x,csr0=0x%x\n",musb_readb(mtk_musb->mregs, MUSB_DEVCTL),musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0));

            //enumerate and polling the suspend interrupt form B-OPT

            do{
                intrtx = musb_readw(mtk_musb->mregs, MUSB_INTRTX);
                mb();
                musb_writew(mtk_musb->mregs, MUSB_INTRTX, intrtx);
                intrusb = musb_readb(mtk_musb->mregs, MUSB_INTRUSB);
                mb();
                musb_writeb(mtk_musb->mregs, MUSB_INTRUSB,intrusb);
                if(intrtx || (intrusb&MUSB_INTR_SUSPEND)){
                    if(intrtx){
                        if(intrtx&0x1)
                            musb_d_enumerated();
                        }
                    if(intrusb){
                        if(intrusb&MUSB_INTR_SUSPEND){//maybe receive disconnect interrupt when the session is end
                            if(device_enumed){
                                break;//return form the while loop
                                }
                            else{//TD.4.6
                                musb_d_soft_connect (false);
                                goto TD_4_6;
                                }
                            }
                        }
                    }
                else
                    wait_for_completion_timeout(&stop_event,1);
                }
            while(g_exec);//the enum will be repeated for 5 times
            if(!g_exec){
                break;//return form the switch-case
                }
            DBG(0,"polling connect form B-OPT,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_CONNECT);//B-OPT will connect again 100ms after A disconnect
            DBG(0,"polling connect form B-OPT,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            musb_h_reset();//should reset bus again, TD.4.7
            wait_for_completion (&stop_event);
            DBG(0,"the test as A-UUT is done\n");
            break;

        case OTG_CMD_P_B_UUT:
            musb_otg_reset_usb();
            //The B-UUT issues an SRP to start a session with the A-OPT
            musb_otg_set_session (true);
            //100ms after VBUS begins to decay the A-OPT powers VBUS
            timeout = jiffies + 5 * HZ;
            devctl = musb_readb (mtk_musb->mregs, MUSB_DEVCTL);

            while(((devctl & MUSB_DEVCTL_VBUS)>>MUSB_DEVCTL_VBUS_SHIFT)<0x3){
                if(time_after(jiffies, timeout)){
                    timeout_flag = true;
                    break;
                    }
                msleep(100);
                devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
                }
            if(timeout_flag){
				DBG(0,"B-UUT set vbus timeout\n");
                g_otg_message.msg = OTG_MSG_DEV_NOT_RESPONSE;
                timeout_flag = false;
                break;
                }

            //After detecting the VBUS, B-UUT should connect to the A_OPT
            power = musb_readb(mtk_musb->mregs, MUSB_POWER);
            power |= MUSB_POWER_HSENAB;
            musb_writeb(mtk_musb->mregs, MUSB_POWER,power);
//TD5_5:
            musb_d_soft_connect(true);

            device_enumed = false;
            //polling the reset single form the A-OPT
            DBG(0,"polling reset form A-OPT,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_RESET);
            DBG(0,"polling reset form A-OPT,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            power = musb_readb(mtk_musb->mregs,MUSB_POWER);
            if(power & MUSB_POWER_HSMODE){
                high_speed = true;
            	}
            else
                high_speed = false;
            //The A-OPT enumerates the B-UUT
TD6_13:     do{
                intrtx = musb_readw(mtk_musb->mregs, MUSB_INTRTX);
                mb();
                musb_writew(mtk_musb->mregs, MUSB_INTRTX,intrtx);
                intrusb = musb_readb(mtk_musb->mregs, MUSB_INTRUSB);
                mb();
                musb_writeb(mtk_musb->mregs, MUSB_INTRUSB,intrusb);
                if(intrtx || (intrusb & 0xf7)){
                    if(intrtx){
                        //DBG(0,"B-enum,intrtx=0x%x\n",intrtx);
                        if(intrtx&0x1)
                            DBG(0,"ep0 interrupt\n");
                            musb_d_enumerated();
                        }
                    if(intrusb){
                        if(intrusb & 0xf7)
                            DBG(0,"B-enum,intrusb=0x%x,power=0x%x\n",intrusb,musb_readb(mtk_musb->mregs,MUSB_POWER));
                        if((device_enumed)&&(intrusb & MUSB_INTR_SUSPEND)){
                            DBG(0,"suspend interrupt is received,power=0x%x,devctl=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_POWER),musb_readb(mtk_musb->mregs,MUSB_DEVCTL));
                            break;
                            }
                        }
                    }
                else{
                    DBG(0,"power=0x%x,devctl=0x%x,intrtx=0x%x,intrusb=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_POWER),musb_readb(mtk_musb->mregs,MUSB_DEVCTL),musb_readw(mtk_musb->mregs,MUSB_INTRTX),musb_readb(mtk_musb->mregs,MUSB_INTRUSB));
                    wait_for_completion_timeout (&stop_event,1);
                    }
                }
            while(g_exec);
            if(!g_exec) break;
            DBG(0,"hnp start\n");
            if(intrusb & MUSB_INTR_RESUME)
                goto TD6_13;
            if(!(intrusb & MUSB_INTR_CONNECT)){
                //polling the connect from A-OPT, the UUT acts as host
                DBG(0,"polling connect or resume form A-OPT,begin\n");
                ret = musb_polling_bus_interrupt(MUSB_INTR_CONNECT|MUSB_INTR_RESUME);
                DBG(0,"polling connect or resume form A-OPT,done,ret=0x%x\n",ret);
                if(TEST_IS_STOP == ret) break;
                if(MUSB_INTR_RESUME == ret){
                    goto TD6_13;
                    }
                if(DEV_HNP_TIMEOUT == ret){
					DBG(0,"B-UUT HNP timeout\n");
                    devctl = musb_readb(mtk_musb->mregs,MUSB_DEVCTL);
                    //DBG(0,"hnp timeout,power=0x%x,devctl=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_POWER),devctl);
                    devctl &= ~MUSB_DEVCTL_HR;
                    musb_writeb(mtk_musb->mregs,MUSB_DEVCTL,devctl);
					if(is_td_59)
						g_otg_message.msg = OTG_MSG_DEV_NOT_RESPONSE;
                    break;
                    }
                }
            //reset the bus and check whether it is a hs device
            musb_h_reset();
            musb_h_enumerate();
            //suspend the bus
            musb_h_suspend();
            //polling the disconnect interrupt from A-OPT
            DBG(0,"polling disconnect form A-OPT,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_DISCONNECT);
            DBG(0,"polling disconnect form A-OPT,done,ret=0x%x\n",ret);
            //DBG(0,"power=0x%x,devctl=0x%x,intrusb=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_POWER),musb_readb(mtk_musb->mregs,MUSB_DEVCTL),musb_readb(mtk_musb->mregs,MUSB_INTRUSB));
            if(TEST_IS_STOP == ret) break;
            DBG(0,"A-OPT is disconnected, UUT will be back to device\n");
            if(!(ret & MUSB_INTR_RESET)){
                musb_d_soft_connect(true);
                //polling the reset single form the A-OPT
                DBG(0,"polling reset form A-OPT,begin\n");
                ret = musb_polling_bus_interrupt(MUSB_INTR_RESET);
                //musb_d_reset ();
                DBG(0,"polling reset form A-OPT,done,ret=0x%x\n",ret);
                if(TEST_IS_STOP == ret) break;
                }
            device_enumed = false;
            if(g_exec)
                goto TD6_13;//TD5_5
            wait_for_completion(&stop_event);
            DBG(0,"test as B_UUT is done\n");
            break;

       	case HOST_CMD_TEST_SE0_NAK:
       	case HOST_CMD_TEST_J:
       	case HOST_CMD_TEST_K:
       	case HOST_CMD_TEST_PACKET:
       	case HOST_CMD_SUSPEND_RESUME:
       	case HOST_CMD_GET_DESCRIPTOR:
       	case HOST_CMD_SET_FEATURE:
       		musb_host_test_mode(cmd);
       		while(g_exec)
                msleep(100);
       		break;
        }
    DBG(0,"musb_otg_exec_cmd--\n");
    return 0;

}