/*****************************************************************************
 function name  : mali_dfs_to_profile
 description    : doing dfs action to target profile
 input vars     : u32 curr
 output vars    : NA
 return value   : int
 calls          :
 called         :

 history        :
  1.data        : 07/05/2014
    author      : s00250033
    modify      : new

*****************************************************************************/
int mali_dfs_set_pll(int target)
{
    u32 i = 0;
    u32 ret = 0;
    if (g_mali_dvfs_profile[target].pllNum != g_mali_dvfs_profile[g_mali_dfs_var.dfs_CurrPrf].pllNum) 
    {
        if (g_mali_dvfs_profile[target].freq > MAX_SFT_FREQ)                                       //ASIC下,GPU频率至少100M
        {
            phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_CLKCFG2_ADDR(0),0,31,DVFS_FREQ_DIV(6));
            for (i = 0; i < MAX_CUNT; i++)
            {
                ret = phy_reg_readl(SOC_MEDIA_SCTRL_BASE_ADDR, SOC_MEDIA_SCTRL_SC_MEDIA_CLKCFG2_ADDR(0), 8, 11);
                if (MID_DIV == ret)
                {
                    break;
                }
                udelay(1);
            }
            if (MAX_CUNT == i)
            {
                MALI_DEBUG_PRINT(1,("mali dfs: ERROR! set mid div %d failed! Current div is %d!\n", g_mali_dvfs_profile[target].div, ret));
                return -1;
            }
        }
        phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_SUBSYS_CTRL5_ADDR(0),1,1,g_mali_dvfs_profile[target].pllNum);
    }
    return 0;
}
예제 #2
0
static int mshci_enable_tuning(struct mshci_host *host, int enable)
{
    int ret;

    if (enable){
        phy_reg_writel(REG_BASE_SC_OFF,
            SOC_SCTRL_SC_PERIPH_CTRL2_ADDR(CALC_REG_OFFSET),
            SOC_SCTRL_SC_PERIPH_CTRL2_mmc_clk_phase_bypass_en_mmc0_START,
            SOC_SCTRL_SC_PERIPH_CTRL2_mmc_clk_phase_bypass_en_mmc0_END, 0);
        ret = clk_enable(host->clk_mmc_high);
        if (ret) {
            printk("%s:failed to enable clock \n", __func__);
            return ret;		
        }
    }
    else{
       /*disable tuning*/
       phy_reg_writel(REG_BASE_SC_OFF,
            SOC_SCTRL_SC_PERIPH_CTRL2_ADDR(CALC_REG_OFFSET),
            SOC_SCTRL_SC_PERIPH_CTRL2_mmc_clk_phase_bypass_en_mmc0_START,
            SOC_SCTRL_SC_PERIPH_CTRL2_mmc_clk_phase_bypass_en_mmc0_END, 1);
       clk_disable(host->clk_mmc_high);
    }
    return 0;
}
/*****************************************************************************
 function name  : mali_domain_powerdown_begin
 description    : powerdown begin with it
 input vars     : void
 output vars    : NA
 return value   : void
 calls          : phy_reg_writel

 called         : mali_platform_powerdown

 history        :
  1.data        : 04/03/2014
    author      : s00250033
    modify      : new

*****************************************************************************/
void mali_domain_powerdown_begin(void)
{   
    MALI_DEBUG_PRINT(3, ("mali power down start! \n"));
    
    phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_RSTEN_ADDR(0),0,0,1);

    phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_CLKDIS_ADDR(0),1,1,1);

    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_CLKDIS0_ADDR(0),1,1,1);

    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_ISOEN0_ADDR(0),1,1,1);

    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_RSTEN0_ADDR(0),1,1,1);
    
    MALI_DEBUG_PRINT(3, ("mali power down end! \n"));
}
예제 #4
0
void modem_wdt_disable(void)
{
    pr_info("Balong_power : modem_wdt_disable.\n");
    /*关闭C核狗的时钟*/
    phy_reg_writel(SOC_SC_ON_BASE_ADDR,
	       SOC_AO_SCTRL_SC_PERIPH_CLKDIS6_ADDR(0), /*only get offset*/
	       SOC_AO_SCTRL_SC_PERIPH_CLKDIS6_periph_clkdis6_watchdog3_pclk_START,
	       SOC_AO_SCTRL_SC_PERIPH_CLKDIS6_periph_clkdis6_watchdog3_START,
	       1);
}
/*****************************************************************************
 function name  : mali_domain_powerup_finish
 description    : powerup finish to run
 input vars     : void
 output vars    : NA
 return value   : void
 calls          : phy_reg_writel

 called         : mali_platform_powerup

 history        :
  1.data        : 04/03/2014
    author      : s00250033
    modify      : new

*****************************************************************************/
void mali_domain_powerup_finish(void)
{
    unsigned int ret = 0;

    MALI_DEBUG_PRINT(3, ("mali power up start! \n"));
    
    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_RSTDIS0_ADDR(0),1,1,1);
    ret = phy_reg_readl(SOC_AO_SCTRL_BASE_ADDR, SOC_AO_SCTRL_SC_PW_RST_STAT0_ADDR(0), 1, 1);
    if(0 != ret)
    {
        MALI_DEBUG_PRINT(2, (" error:  SET SC_PW_RSTDIS0 failed!\n"));
    }

    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_ISODIS0_ADDR(0),1,1,1);
    ret = phy_reg_readl(SOC_AO_SCTRL_BASE_ADDR, SOC_AO_SCTRL_SC_PW_ISO_STAT0_ADDR(0), 1, 1);
    if(0 != ret)
    {
        MALI_DEBUG_PRINT(2, (" error:  SET SC_PW_ISODIS0 failed!\n"));
    }
    
    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_CLKEN0_ADDR(0),1,1,1);
    ret = phy_reg_readl(SOC_AO_SCTRL_BASE_ADDR, SOC_AO_SCTRL_SC_PW_CLK_STAT0_ADDR(0), 1, 1);
    if(1 != ret)
    {
        MALI_DEBUG_PRINT(2, (" error:  SET SC_PW_CLKEN0 failed!\n"));
    }
    
    phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_RSTDIS_ADDR(0),0,0,1);
    ret = phy_reg_readl(SOC_MEDIA_SCTRL_BASE_ADDR, SOC_MEDIA_SCTRL_SC_MEDIA_RST_STAT_ADDR(0), 0, 0);
    if(0 != ret)
    {
        MALI_DEBUG_PRINT(2, (" error:  SET SC_MEDIA_RSTDIS failed!\n"));
    }
    
    MALI_DEBUG_PRINT(3, ("mali power up end! \n"));
}
int mali_dfs_set_div(int target)
{
    u32 i = 0;
    u32 ret = 0;
    phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_CLKCFG2_ADDR(0),0,31,DVFS_FREQ_DIV(g_mali_dvfs_profile[target].div));
    
    for (i = 0; i < MAX_CUNT; i++)
    {
        ret = phy_reg_readl(SOC_MEDIA_SCTRL_BASE_ADDR, SOC_MEDIA_SCTRL_SC_MEDIA_CLKCFG2_ADDR(0), 8, 11);
        if (g_mali_dvfs_profile[target].div == ret)
        {
            return 0;
        }
        udelay(1);
    }
            
    MALI_DEBUG_PRINT(1,("mali dfs: ERROR! target %d  set div %d failed! Current div is %d!\n", target,g_mali_dvfs_profile[target].div, ret));
    return -1;
}
/***************************************************************************
 * FunctionName: ispv1_csi_phy_set;
 * Description : csi phyhardware poweron region set;
 * Input       : csiphy_power_enum;
 * Output      : NA;
 * ReturnValue : NA;
 * Other       : NA;
 ***************************************************************************/
static void ispv1_csi_phy_set(camera_power_state type, csi_index_t index)
{
    if (POWER_ON == type) {
        if (index == CSI_INDEX_0) {
            /* CSI PHY0 RSTDIS */
            phy_reg_writel(SOC_SC_ON_BASE_ADDR,
                           SOC_AO_SCTRL_SC_PW_RSTDIS0_ADDR(0),
                           SOC_AO_SCTRL_SC_PW_RSTDIS0_pw_rstdis0_22cs0phy_START,
                           SOC_AO_SCTRL_SC_PW_RSTDIS0_pw_rstdis0_22cs0phy_END,
                           0x1);

            /* CSI PHY0 CLKREG ENABLE */
            phy_reg_writel(SOC_SC_ON_BASE_ADDR,
                           SOC_AO_SCTRL_SC_PW_CLKEN0_ADDR(0),
                           SOC_AO_SCTRL_SC_PW_CLKEN0_pw_clken0_22cs0phy_START,
                           SOC_AO_SCTRL_SC_PW_CLKEN0_pw_clken0_22cs0phy_END,
                           0x1);
        } else {
            /* CSI PHY2 RSTDIS */
            phy_reg_writel(SOC_SC_ON_BASE_ADDR,
                           SOC_AO_SCTRL_SC_PW_RSTDIS0_ADDR(0),
                           SOC_AO_SCTRL_SC_PW_RSTDIS0_pw_rstdis0_24cs2phy_START,
                           SOC_AO_SCTRL_SC_PW_RSTDIS0_pw_rstdis0_24cs2phy_END,
                           0x1);

            /* CSI PHY2 CLKREG ENABLE */
            phy_reg_writel(SOC_SC_ON_BASE_ADDR,
                           SOC_AO_SCTRL_SC_PW_CLKEN0_ADDR(0),
                           SOC_AO_SCTRL_SC_PW_CLKEN0_pw_clken0_24cs2phy_START,
                           SOC_AO_SCTRL_SC_PW_CLKEN0_pw_clken0_24cs2phy_END,
                           0x1);
        }
    } else if (POWER_OFF == type) {
        if (index == CSI_INDEX_0) {
            /* CSI PHY0 CLKREG DISABLE */
            phy_reg_writel(SOC_SC_ON_BASE_ADDR,
                           SOC_AO_SCTRL_SC_PW_CLKDIS0_ADDR(0),
                           SOC_AO_SCTRL_SC_PW_CLKDIS0_pw_clkdis0_22cs0phy_START,
                           SOC_AO_SCTRL_SC_PW_CLKDIS0_pw_clkdis0_22cs0phy_END,
                           0x1);

            /* CSI PHY0 RST ENABLE */
            phy_reg_writel(SOC_SC_ON_BASE_ADDR,
                           SOC_AO_SCTRL_SC_PW_RSTEN0_ADDR(0),
                           SOC_AO_SCTRL_SC_PW_RSTEN0_pw_rsten0_22cs0phy_START,
                           SOC_AO_SCTRL_SC_PW_RSTEN0_pw_rsten0_22cs0phy_END,
                           0x1);
        } else {
            /* CSI PHY2 CLKREG DISABLE */
            phy_reg_writel(SOC_SC_ON_BASE_ADDR,
                           SOC_AO_SCTRL_SC_PW_CLKDIS0_ADDR(0),
                           SOC_AO_SCTRL_SC_PW_CLKDIS0_pw_clkdis0_24cs2phy_START,
                           SOC_AO_SCTRL_SC_PW_CLKDIS0_pw_clkdis0_24cs2phy_END,
                           0x1);

            /* CSI PHY2 RST ENABLE */
            phy_reg_writel(SOC_SC_ON_BASE_ADDR,
                           SOC_AO_SCTRL_SC_PW_RSTEN0_ADDR(0),
                           SOC_AO_SCTRL_SC_PW_RSTEN0_pw_rsten0_24cs2phy_START,
                           SOC_AO_SCTRL_SC_PW_RSTEN0_pw_rsten0_24cs2phy_END,
                           0x1);
        }
    } else {
        print_error("%s, ispv1_power_enum input error:%d", __func__, type);
    }

    return;
}
int video_harden_video_noc_disable(video_harden_dev_id_enum dev_id)
{
	int ret = 0;
    unsigned int reg_val = 0;
    unsigned int count = 0;

    printk(KERN_INFO "%s, dev_id is %d.\n", __func__, dev_id);

    ret = video_harden_device_id_check(dev_id);
    if (ret != 0) {
        return -1;
    }

    ret = down_interruptible(&video_harden_busy_lock);
	if (0 != ret) {
		printk(KERN_ERR "%s, video_harden_busy_lock failed.\n", __func__);
		return -1;
	}

    switch (dev_id) {
        case VIDEO_HARDEN_DEV_ID_VCODEC: /* VCODEC */
            video_harden_video_noc_vote.vcodec_bit = 0;
            break;

        case VIDEO_HARDEN_DEV_ID_JPEG: /* JPEG */
            video_harden_video_noc_vote.jpeg_bit = 0;
            break;

        case VIDEO_HARDEN_DEV_ID_ISP: /* ISP */
            video_harden_video_noc_vote.isp_bit = 0;
            break;

        default:
            break;
    }

    if ((0 == video_harden_video_noc_vote.vcodec_bit)
        && (0 == video_harden_video_noc_vote.jpeg_bit)
        && (0 == video_harden_video_noc_vote.isp_bit)) {

        /* AO_SC PW CTRL1[0x8C8]: video noc power idle req, BIT[30][14] */
        phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,
                       SOC_AO_SCTRL_SC_PW_CTRL1_ADDR(CALC_REG_OFFSET),
                       SOC_AO_SCTRL_SC_PW_CTRL1_acpu_sft_fiq_req_START,
                       SOC_AO_SCTRL_SC_PW_CTRL1_ade_domain_idlereq_msk_END,
                       0x40004000);

        /* AO_SC PW STAT1[0x854]: video noc stat */
        do {
            reg_val = phy_reg_readl(SOC_AO_SCTRL_BASE_ADDR,
                SOC_AO_SCTRL_SC_PW_STAT1_ADDR(CALC_REG_OFFSET),
                SOC_AO_SCTRL_SC_PW_STAT1_video_domain_idleack_START,
                SOC_AO_SCTRL_SC_PW_STAT1_video_domain_idle_END);
            printk(KERN_INFO "%s, SC_PW_STAT1_video_domain_idleack&idle = 0x%0x \n", __func__, reg_val);
            udelay(10);
            count ++;
            if (count >= 10) {
        		printk(KERN_ERR "%s, video noc stat is not expect.\n", __func__);
        		ret = -1;
                break;
            }
        } while (reg_val != 0x3);

        printk(KERN_INFO "%s, video noc disable is sucessful.\n", __func__);
    } else {
        printk(KERN_INFO "%s, video noc is already disabled!. \n", __func__);
    }

    up(&video_harden_busy_lock);

    printk(KERN_INFO "%s, video_noc_vote is 0x%x.\n",
        __func__, *((unsigned int *)&video_harden_video_noc_vote));

    return ret;
}
int video_harden_clkdis_isoen_rsten(video_harden_dev_id_enum dev_id)
{
    int ret = 0;

    printk(KERN_INFO "dev_id is %d.\n", dev_id);

    ret = video_harden_device_id_check(dev_id);
    if (ret != 0) {
        return -1;
    }

    if ((video_harden_rst_iso_clk_vote.vcodec_bit == 0)
        && (video_harden_rst_iso_clk_vote.jpeg_bit == 0)
        && (video_harden_rst_iso_clk_vote.isp_bit == 0)) {
        printk(KERN_ERR "video_harden_clkdis_isoen_rsten is already done!\n");
        return -1;
    }

    ret = down_interruptible(&video_harden_busy_lock);
	if (0 != ret) {
		printk(KERN_ERR "video_harden_busy_lock failed\n");
		return -1;
	}

    switch (dev_id) {
        case VIDEO_HARDEN_DEV_ID_VCODEC: /* VCODEC */
            video_harden_rst_iso_clk_vote.vcodec_bit    = 0;
            break;

        case VIDEO_HARDEN_DEV_ID_JPEG: /* JPEG */
            video_harden_rst_iso_clk_vote.jpeg_bit      = 0;
            break;

        case VIDEO_HARDEN_DEV_ID_ISP: /* ISP */
            video_harden_rst_iso_clk_vote.isp_bit       = 0;
            break;

        default:
            break;
    }

    if ( (video_harden_rst_iso_clk_vote.vcodec_bit == 0)
        && (video_harden_rst_iso_clk_vote.jpeg_bit == 0)
        && (video_harden_rst_iso_clk_vote.isp_bit == 0)) {
        /* AO_SC SOC_AO_SCTRL_SC_PW_CLKDIS0_ADDR [0x804] */
        phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,
                       SOC_AO_SCTRL_SC_PW_CLKDIS0_ADDR(CALC_REG_OFFSET),
                       SOC_AO_SCTRL_SC_PW_CLKDIS0_pw_clkdis0_2codecisp_START,
                       SOC_AO_SCTRL_SC_PW_CLKDIS0_pw_clkdis0_2codecisp_END,
                       0x1);

        /* AO_SC SC_PW_ISOEN0 [0x820] */
        phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,
                       SOC_AO_SCTRL_SC_PW_ISOEN0_ADDR(CALC_REG_OFFSET),
                       SOC_AO_SCTRL_SC_PW_ISOEN0_pw_isoen0_2codecisp_START,
                       SOC_AO_SCTRL_SC_PW_ISOEN0_pw_isoen0_2codecisp_END,
                       0x1);

        /* AO_SC SC_PW_RSTEN0 [0x810] */
        phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,
                      SOC_AO_SCTRL_SC_PW_RSTEN0_ADDR(CALC_REG_OFFSET),
                      SOC_AO_SCTRL_SC_PW_RSTEN0_pw_rsten0_2codecisp_START,
                      SOC_AO_SCTRL_SC_PW_RSTEN0_pw_rsten0_2codecisp_END,
                      0x1);

        printk(KERN_INFO "video harden clkdis_isoen_rsten is sucessful.\n");
    } else {
        printk(KERN_INFO "video_harden_clkdis_isoen_rsten is already done!.\n");
    }

    up(&video_harden_busy_lock);

    printk(KERN_INFO "video_harden_rst_iso_clk_vote is 0x%x.\n",
        *((unsigned int *)&video_harden_rst_iso_clk_vote));

    return ret;
}
/*****************************************************************************
 function name  : init_mali_clock_regulator
 description    : mali clk and regulator init
 input vars     : void
 output vars    : NA
 return value   : mali_bool
 calls          : mali_clk_get

 called         : mali_platform_init

 history        :
  1.data        : 04/03/2014
    author      : s00250033
    modify      : new

*****************************************************************************/
static mali_bool init_mali_clock_regulator(struct platform_device *pdev)
{
    mali_bool ret       = MALI_TRUE;

    g_swGpuPowerState   = MALI_TRUE;

    /* regulator init */
    mali_regulator  = regulator_get(&pdev->dev, "G3D_PD_VDD");

    if (IS_ERR(mali_regulator))
    {
        MALI_PRINT( ("MALI Error : failed to get G3D_PD_VDD\n"));
        return MALI_FALSE;
    }

    mali_regulator_enable();

    /* clk init */

    if (mali_clock != 0)
    {
        return ret;
    }
    
    if (!mali_clk_get(pdev))
    {
        MALI_PRINT(("MALI Error: Failed to get Mali clock\n"));
        return MALI_FALSE;
    }

 
    /*使能媒体外设时钟*/
    ret = phy_reg_readl(SOC_PERI_SCTRL_BASE_ADDR, SOC_PERI_SCTRL_SC_PERIPH_CLKSTAT12_ADDR(0), 10, 10);
    if(1 != ret)
    {
        phy_reg_writel(SOC_PERI_SCTRL_BASE_ADDR,SOC_PERI_SCTRL_SC_PERIPH_CLKEN12_ADDR(0),10,10,1);
        ret = phy_reg_readl(SOC_PERI_SCTRL_BASE_ADDR, SOC_PERI_SCTRL_SC_PERIPH_CLKSTAT12_ADDR(0), 10, 10);
        if(1 != ret)
        {
            MALI_DEBUG_PRINT(2, (" error:  SET SC_PERIPH_CLKEN12 failed!\n"));
        }            
    }
    
    /* CLK on and set rate */
    mali_clock_on();

    MALI_DEBUG_PRINT(2, (" init mali clock regulator ok\n"));

    /*时钟有效指示*/
    phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_CLKCFG2_ADDR(0),15,15,1);
    ret = phy_reg_readl(SOC_MEDIA_SCTRL_BASE_ADDR, SOC_MEDIA_SCTRL_SC_MEDIA_CLKCFG2_ADDR(0), 15, 15);
    if(1 != ret)
    {
        MALI_DEBUG_PRINT(2, (" error:  SET SC_MEDIA_CLKCFG2 failed!\n"));
    }
    
    mali_domain_powerup_finish();
    
    return MALI_TRUE;

}
static void mali_platform_powerup_no_drv(void)
{
    MALI_DEBUG_PRINT(2, ("mali_platform_powerup_no_drv start!\n"));

    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_MTCMOS_EN0_ADDR(0),1,1,1);

    phy_reg_writel(SOC_PERI_SCTRL_BASE_ADDR,SOC_PERI_SCTRL_SC_PERIPH_CLKEN12_ADDR(0),0,31,0x400);
    
    phy_reg_writel(SOC_PMCTRL_BASE_ADDR,SOC_PMCTRL_GPUPLLCTRL_ADDR(0),0,31,0x7801);

    phy_reg_writel(SOC_PMCTRL_BASE_ADDR,SOC_PMCTRL_SYSPLLCTRL_ADDR(0),0,31,0x7801);

    phy_reg_writel(SOC_PMCTRL_BASE_ADDR,SOC_PMCTRL_MEDPLLCTRL_ADDR(0),0,31,0x7801);

    phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_CLKCFG2_ADDR(0),0,31,0x8100);

    phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_CLKCFG0_ADDR(0),0,31,0x84);//0x84
    
    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_RSTDIS0_ADDR(0),1,1,1);

    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_ISODIS0_ADDR(0),1,1,1);

    phy_reg_writel(SOC_AO_SCTRL_BASE_ADDR,SOC_AO_SCTRL_SC_PW_CLKEN0_ADDR(0),1,1,1);

    phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_RSTDIS_ADDR(0),0,0,1);

    phy_reg_writel(SOC_MEDIA_SCTRL_BASE_ADDR,SOC_MEDIA_SCTRL_SC_MEDIA_CLKEN_ADDR(0),0,31,0x20002);

    MALI_DEBUG_PRINT(2, ("mali_platform_powerup_no_drv end!\n"));
}