/*
 * emi_bwl_mod_init: module init function.
 */
static int __init emi_bwl_mod_init(void)
{
    int ret;
    if(get_ddr_type() == 1) //DDR1
    {
        //write overhead value
        writel(0x090B0B10, EMI_CONB);	//read  overhead for 4~1
        writel(0x09090909, EMI_CONC);	//read  overhead for 8~5
        writel(0x0B0E1013, EMI_COND);	//write overhead for 4~1
        writel(0x0909090A, EMI_CONE);   //write overhead for 8~5
    }
    else if(get_ddr_type() == 2) //DDR2
    {
        //write overhead value
        writel(0x0B0B0E17, EMI_CONB);	//read  overhead for 4~1
        writel(0x0B0B0B0B, EMI_CONC);	//read  overhead for 8~5
        writel(0x1012161E, EMI_COND);	//write overhead for 4~1
        writel(0x0B0B0D0E, EMI_CONE);   //write overhead for 8~5
    }
    else if(get_ddr_type() == 3) //DDR3
    {
        writel(0x2B2C2C2E, EMI_CONB);	//read  overhead for 4~1
        writel(0x2627292B, EMI_CONC);	//read  overhead for 8~5
        writel(0x2B2C2C2E, EMI_COND);	//write overhead for 4~1
        writel(0x2627292B, EMI_CONE);       //write overhead for 8~5
    }
    
    //write Filter Priority Encode
#if 0    
    writel(0x00112480, EMI_ARBI);	//distant=0, urgent=1, miss=1, hit=2, limit=4, age=8, ultra=0
#else

#ifdef MTK_DISPLAY_HIGH_RESOLUTION
        writel(0x01812484, EMI_ARBI);  	//degrade ultra-high priority from 8 to 4 when enable MM ultra-high
#else 
        writel(0x01812488, EMI_ARBI);
#endif

#endif

    ret = mtk_mem_bw_ctrl(CON_SCE_NORMAL, ENABLE_CON_SCE);
    if (ret) {
        xlog_printk(ANDROID_LOG_ERROR, "EMI/BWL", "fail to set EMI bandwidth limiter\n");
    }

    ret = platform_driver_register(&mem_bw_ctrl);
    if (ret) {
        xlog_printk(ANDROID_LOG_ERROR, "EMI/BWL", "fail to register EMI_BW_LIMITER driver\n");
    }

    ret = driver_create_file(&mem_bw_ctrl.driver, &driver_attr_concurrency_scenario);
    if (ret) {
        xlog_printk(ANDROID_LOG_ERROR, "EMI/BWL", "fail to create EMI_BW_LIMITER sysfs file\n");
    }

    return 0;
}
static int __init init_fliper(void)
{
    struct proc_dir_entry *pe;
    int DRAM_Type=get_ddr_type();

    pe = proc_create("fliper", 0664, NULL, &mt_fliper_fops);
    if (!pe)
        return -ENOMEM;

    printk("prepare mt pp transfer: jiffies:%lu-->%lu\n",jiffies, jiffies + msecs_to_jiffies(5000));
    printk("-  next jiffies:%lu >>> %lu\n",jiffies, jiffies + msecs_to_jiffies(X_ms));
    mod_timer(&mt_pp_transfer_timer, jiffies + msecs_to_jiffies(5000));
    return 0;
}
/*
 * mtk_mem_bw_ctrl: set EMI bandwidth limiter for memory bandwidth control
 * @sce: concurrency scenario ID
 * @op: either ENABLE_CON_SCE or DISABLE_CON_SCE
 * Return 0 for success; return negative values for failure.
 */
int mtk_mem_bw_ctrl(int sce, int op)
{
    int i, highest;

    if (sce >= NR_CON_SCE) {
        return -1;
    }
    if (op != ENABLE_CON_SCE && op != DISABLE_CON_SCE) {
        return -1;
    }
    if (in_interrupt()) {
        return -1;
    }

    down(&emi_bwl_sem);

    if (op == ENABLE_CON_SCE) {
        ctrl_tbl[sce].ref_cnt++;
    } else if (op == DISABLE_CON_SCE) {
        if (ctrl_tbl[sce].ref_cnt != 0) {
            ctrl_tbl[sce].ref_cnt--;
        } 
    }

    /* find the scenario with the highest priority */
    highest = -1;
    for (i = 0; i < NR_CON_SCE; i++) {
        if (ctrl_tbl[i].ref_cnt != 0) {
            highest = i;
            break;
        }
    }
    if (highest == -1) {
        highest = CON_SCE_NORMAL;
    }

    /* set new EMI bandwidth limiter value */
    if (highest != cur_con_sce) {
        if(get_ddr_type() == 1)
        {
            writel(emi_arba_val[highest], EMI_ARBA);
            writel(emi_arbc_val[highest], EMI_ARBC);
            writel(emi_arbd_val[highest], EMI_ARBD);
            writel(emi_arbe_val[highest], EMI_ARBE);
            writel(emi_arbf_val[highest], EMI_ARBF);
            mt65xx_reg_sync_writel(emi_arbg_val[highest], EMI_ARBG);
        }
        else if(get_ddr_type() == 2)
        {
            writel(emi_arba_ddr2_val[highest], EMI_ARBA);
            writel(emi_arbc_ddr2_val[highest], EMI_ARBC);
            writel(emi_arbd_ddr2_val[highest], EMI_ARBD);
            writel(emi_arbe_ddr2_val[highest], EMI_ARBE);
            writel(emi_arbf_ddr2_val[highest], EMI_ARBF);
            mt65xx_reg_sync_writel(emi_arbg_ddr2_val[highest], EMI_ARBG);           
        }
        else if(get_ddr_type() == 3)
        {
            writel(emi_arba_ddr3_val[highest], EMI_ARBA);
            writel(emi_arbc_ddr3_val[highest], EMI_ARBC);
            writel(emi_arbd_ddr3_val[highest], EMI_ARBD);
            writel(emi_arbe_ddr3_val[highest], EMI_ARBE);
            writel(emi_arbf_ddr3_val[highest], EMI_ARBF);
            mt65xx_reg_sync_writel(emi_arbg_ddr3_val[highest], EMI_ARBG);           
        }
        cur_con_sce = highest;
    }

    up(&emi_bwl_sem);

    return 0;
}