需要两方面处理:
 
一  根据原理图配置好GPIO


二 修改代码,有如下几只文件需要修改:
 

1     alps/mediatek/config/{project}/ProjectConfig.mk添加如下option:

 CUSTOM_HAL_COMBO=mt6630

 CUSTOM_HAL_ANT=mt6630_ant_m1

 MTK_COMBO_CORE_DUMP_SUPPORT=no

 MTK_COMBO_QUICK_SLEEP_SUPPORT=no

 MTK_COMBO_CHIP = MT6630     

 MTK_WLAN_CHIP=MT6630     

 MTK_BT_CHIP = MTK_MT6630     

 MTK_GPS_CHIP = MTK_GPS_MT6630

        MTK_FM_CHIP=MT6630_FM


   (注意:最好double check原ProjectConfig文件是否已经存在某项option,如果存在且取值一样,则不需要添加;如果只是值不同,则修改为上述值)
 
 
2     alps/mediatek/config/{project}/init.project.rc  factory_init.project.rc  meta_init.project.rc这三只文件
    统一作如下2处修改:
     
service conn_launcher /system/bin/logwrapper /system/bin/6620_launcher -p /system/etc/firmware/
改为:
service 66xx_launcher /system/bin/logwrapper /system/bin/6620_launcher -m 4 -p /system/etc/firmware/
 
在文件末尾添加:

service autokd /system/bin/autokd

     class core

     user system

     group nvram system

  

  

 3    alps\mediatek\config\{project}\autoconfig\kconfig\project文件末尾添加:

   

 CONFIG_SDIOAUTOK_SUPPORT=y

  

  

 4     alps\mediatek\custom\{project}\kernel\core\src\board-custom.h文件作如下3处改动:

    

 //#define CFG_DEV_MSDC3

 改为:

 #define CFG_DEV_MSDC3

  

 #define CONFIG_MTK_COMBO_SDIO_SLOT  (3)

 改为:

 #define CONFIG_MTK_WCN_CMB_SDIO_SLOT  (3)

  

 #undef CONFIG_MTK_COMBO_SDIO_SLOT

 改为:

 #undef CONFIG_MTK_WCN_CMB_SDIO_SLOT

  

 5     alps\mediatek\custom\{project}\kernel\core\src\board.c文件,因改动内容较多,

    最好整个将文件替换为如下内容:

 /* system header files */

 #include <linux/kernel.h>

 #include <linux/mm.h>

 #include <linux/interrupt.h>

 #include <linux/init.h>

 #include <linux/module.h>

 #include <linux/device.h>

 #include <linux/delay.h>

 #include <linux/pm.h>

 #include <linux/mutex.h>

 #include <linux/uaccess.h>

 #include <linux/syscalls.h>

 #include <linux/mtd/nand.h>

 #include <asm/irq.h>

 #include <asm/io.h>

 //#include <asm/mach-types.h>

 //#include <asm/mach/arch.h>

 //#include <asm/mach/irq.h>

 //#include <asm/mach/map.h>

 //#include <asm/mach/time.h>

 //#include <asm/setup.h>

 #include <mach/system.h>

 #include <mach/board.h>

 #include <mach/hardware.h>

 #include <mach/mt_gpio.h>

 #include <mach/mt_bt.h>

 #include <mach/eint.h>

 #include <mach/mtk_rtc.h>

 #include <mach/mt_typedefs.h>

 // Fix-me: marked for early porting

 #include <cust_gpio_usage.h>

 #include <cust_eint.h>

 #define CONFIG_EINT_DEVICE_TREE 0

 #if CONFIG_EINT_DEVICE_TREE

 #include <linux/of.h>

 #include <linux/of_irq.h>

 #include <linux/irqreturn.h>

 static atomic_t wifi_irq_flag;

 static unsigned int wifi_irq = 0;

 #endif

 #include "board-custom.h"

 #if defined(CONFIG_MTK_COMBO) || defined(CONFIG_MTK_COMBO_MODULE)

 #include <mach/mtk_wcn_cmb_stub.h>

 #endif

 #if defined(CONFIG_MTK_WCN_CMB_SDIO_SLOT)

 static sdio_irq_handler_t mtk_wcn_cmb_sdio_eirq_handler = NULL;

 int mtk_wcn_sdio_irq_flag_set (int falg);

 static atomic_t sdio_irq_enable_flag;

 static pm_callback_t mtk_wcn_cmb_sdio_pm_cb = NULL;

 static void *mtk_wcn_cmb_sdio_pm_data = NULL;

 static void *mtk_wcn_cmb_sdio_eirq_data = NULL;

 const static u32 mtk_wcn_cmb_sdio_eint_pin = GPIO_WIFI_EINT_PIN;

 const static u32 mtk_wcn_cmb_sdio_eint_num = CUST_EINT_WIFI_NUM;

 const static u32 mtk_wcn_cmb_sdio_eint_m_eint = GPIO_WIFI_EINT_PIN_M_EINT;

 const static u32 mtk_wcn_cmb_sdio_eint_m_gpio = GPIO_WIFI_EINT_PIN_M_GPIO;

 /*

 index: port number of combo chip (1:SDIO1, 2:SDIO2, no SDIO0)

 value: slot power status of  (0:off, 1:on, 0xFF:invalid)

 */

     #if (CONFIG_MTK_WCN_CMB_SDIO_SLOT == 0)

         static unsigned char combo_port_pwr_map[4] = {0x0, 0xFF, 0xFF, 0xFF};

     #elif (CONFIG_MTK_WCN_CMB_SDIO_SLOT == 1)

         static unsigned char combo_port_pwr_map[4] = {0xFF, 0x0, 0xFF, 0xFF};

     #elif (CONFIG_MTK_WCN_CMB_SDIO_SLOT == 2)

         static unsigned char combo_port_pwr_map[4] = {0xFF, 0xFF, 0x0, 0xFF};

     #elif (CONFIG_MTK_WCN_CMB_SDIO_SLOT == 3)

         static unsigned char combo_port_pwr_map[4] = {0xFF, 0xFF, 0xFF, 0x0};

     #else

         #error "unsupported CONFIG_MTK_WCN_CMB_SDIO_SLOT" CONFIG_MTK_WCN_CMB_SDIO_SLOT

     #endif

 #else

  /*standalone chip's structure should be add here*/

 #endif

 /*=======================================================================*/

 /* Board Specific Devices Power Management                               */

 /*=======================================================================*/

 extern kal_bool pmic_chrdet_status(void);

 void mt_power_off(void)

 {

  printk("mt_power_off\n");

  /* pull PWRBB low */

  /*Hong-Rong: FIXME for early porting*/

  rtc_bbpu_power_down();

  while (1) {

 #if defined(CONFIG_POWER_EXT)

   //EVB

   printk("EVB without charger\n");

 #else 

   //Phone 

   printk("Phone with charger\n");

   if (pmic_chrdet_status() == KAL_TRUE)

    arch_reset(0, "power_off_with_charger");

 #endif

     }

 }

 /*=======================================================================*/

 /* Board Specific Devices                                                */

 /*=======================================================================*/

 /*GPS driver*/

 /*FIXME: remove mt3326 notation */

 struct mt3326_gps_hardware mt3326_gps_hw = {

     .ext_power_on =  NULL,

     .ext_power_off = NULL,

 };



 #if defined(CONFIG_MTK_WCN_CMB_SDIO_SLOT)

 static void mtk_wcn_cmb_sdio_enable_eirq(void)

 {

 #if CONFIG_EINT_DEVICE_TREE

  if(!atomic_read(&wifi_irq_flag))

  {

   printk(KERN_DEBUG "wifi eint has been enabled\n");;

  }

  else

  {

   enable_irq(wifi_irq);

   atomic_dec(&wifi_irq_flag);

   //printk(KERN_DEBUG " enable WIFI EINT irq %d !!\n",wifi_irq);

  }

 #else

     mt_eint_unmask(mtk_wcn_cmb_sdio_eint_num);/* CUST_EINT_WIFI_NUM */

 #endif

 }



 static void mtk_wcn_cmb_sdio_disable_eirq(void)

 {

 #if CONFIG_EINT_DEVICE_TREE

  if(atomic_read(&wifi_irq_flag))

  {

   printk(KERN_DEBUG "wifi eint has been disabled!\n");;

  }

  else

  {

   disable_irq_nosync(wifi_irq);

   atomic_inc(&wifi_irq_flag);

   //printk(KERN_DEBUG "disable WIFI EINT irq %d !!\n",wifi_irq);

  }

 #else

     mt_eint_mask(mtk_wcn_cmb_sdio_eint_num); /* CUST_EINT_WIFI_NUM */

 #endif

 }

 #if CONFIG_EINT_DEVICE_TREE

 irqreturn_t mtk_wcn_cmb_sdio_eirq_handler_stub(int irq,void *data)

 {

     if ((NULL != mtk_wcn_cmb_sdio_eirq_handler) && (0 != atomic_read(&sdio_irq_enable_flag))) {

         mtk_wcn_cmb_sdio_eirq_handler(mtk_wcn_cmb_sdio_eirq_data);

     }

  return IRQ_HANDLED;

 }

 #else

 static void mtk_wcn_cmb_sdio_eirq_handler_stub(void)

 {

     if ((NULL != mtk_wcn_cmb_sdio_eirq_handler) && (0 != atomic_read(&sdio_irq_enable_flag))) {

         mtk_wcn_cmb_sdio_eirq_handler(mtk_wcn_cmb_sdio_eirq_data);

     }

 }

 #endif

 static void mtk_wcn_cmb_sdio_request_eirq(sdio_irq_handler_t irq_handler, void *data)

 {

 #if CONFIG_EINT_DEVICE_TREE

  struct device_node *node;

  u32 ints[2] = {0,0};

  int ret = -EINVAL;

 #endif

     printk( KERN_INFO "enter %s\n", __func__);

     mtk_wcn_sdio_irq_flag_set (0);

     mtk_wcn_cmb_sdio_eirq_data    = data;

     mtk_wcn_cmb_sdio_eirq_handler = irq_handler;

     #if 1

 #if CONFIG_EINT_DEVICE_TREE

  node = of_find_compatible_node(NULL, NULL, "mediatek, WIFI-eint");

  if(node) {

   of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints));

   mt_gpio_set_debounce(ints[0], ints[1]);

   wifi_irq = irq_of_parse_and_map(node, 0);

   ret = request_irq(wifi_irq, mtk_wcn_cmb_sdio_eirq_handler_stub, IRQF_TRIGGER_NONE,"WIFI-eint", NULL);

   printk(KERN_DEBUG "WIFI EINT irq %d !!\n",wifi_irq);

   atomic_set(&wifi_irq_flag, 0);/*default: irq enable*/

   if(ret)

    printk(KERN_ERR "WIFI EINT IRQ LINE NOT AVAILABLE!!\n");

   else {

    mtk_wcn_cmb_sdio_disable_eirq();/*not ,chip state is power off*/

   }

  }

  else

   printk(KERN_ERR "[%s] can't find wifi eint compatible node\n",__func__);

 #else

     mt_eint_registration(mtk_wcn_cmb_sdio_eint_num,

               CUST_EINT_WIFI_TYPE,

                 mtk_wcn_cmb_sdio_eirq_handler_stub,

                 0);

 #endif

     #else

  {

   int i_ret = 0;

   i_ret = request_irq(mtk_wcn_cmb_sdio_eint_num,

     (irq_handler_t)mtk_wcn_cmb_sdio_eirq_handler_stub,

     IRQF_TRIGGER_LOW,

     "SDIO_EXT_IRQ",

     NULL);

   if (i_ret)

       printk( KERN_ERR "request_irq for SDIO ext IRQ failed, i_ret(%d)\n", i_ret);

   else

       printk( KERN_ERR "request_irq for SDIO ext IRQ succeed, i_ret(%d)\n", i_ret);

  }

     #endif

     

 #if CONFIG_EINT_DEVICE_TREE

 #else

     mt_eint_mask(mtk_wcn_cmb_sdio_eint_num);/*CUST_EINT_WIFI_NUM */

 #endif

  printk(KERN_INFO "exit %s\n", __func__);

 }

 static void mtk_wcn_cmb_sdio_register_pm(pm_callback_t pm_cb, void *data)

 {

     printk( KERN_INFO "mtk_wcn_cmb_sdio_register_pm (0x%p, 0x%p)\n", pm_cb, data);

     /* register pm change callback */

     mtk_wcn_cmb_sdio_pm_cb = pm_cb;

     mtk_wcn_cmb_sdio_pm_data = data;

 }

 static void mtk_wcn_cmb_sdio_on (int sdio_port_num) {

     pm_message_t state = { .event = PM_EVENT_USER_RESUME };

     printk(KERN_INFO "mtk_wcn_cmb_sdio_on (%d) \n", sdio_port_num);

     /* 1. disable sdio eirq */

     mtk_wcn_cmb_sdio_disable_eirq();

     mt_set_gpio_pull_enable(mtk_wcn_cmb_sdio_eint_pin, GPIO_PULL_DISABLE); /* GPIO_WIFI_EINT_PIN */

     mt_set_gpio_mode(mtk_wcn_cmb_sdio_eint_pin, mtk_wcn_cmb_sdio_eint_m_eint); /* EINT mode */

     /* 2. call sd callback */

     if (mtk_wcn_cmb_sdio_pm_cb) {

         //printk(KERN_INFO "mtk_wcn_cmb_sdio_pm_cb(PM_EVENT_USER_RESUME, 0x%p, 0x%p) \n", mtk_wcn_cmb_sdio_pm_cb, mtk_wcn_cmb_sdio_pm_data);

         mtk_wcn_cmb_sdio_pm_cb(state, mtk_wcn_cmb_sdio_pm_data);

     }

     else {

         printk(KERN_WARNING "mtk_wcn_cmb_sdio_on no sd callback!!\n");

     }

 }

 static void mtk_wcn_cmb_sdio_off (int sdio_port_num) {

     pm_message_t state = { .event = PM_EVENT_USER_SUSPEND };

     printk(KERN_INFO "mtk_wcn_cmb_sdio_off (%d) \n", sdio_port_num);

     /* 1. call sd callback */

     if (mtk_wcn_cmb_sdio_pm_cb) {

         //printk(KERN_INFO "mtk_wcn_cmb_sdio_off(PM_EVENT_USER_SUSPEND, 0x%p, 0x%p) \n", mtk_wcn_cmb_sdio_pm_cb, mtk_wcn_cmb_sdio_pm_data);

         mtk_wcn_cmb_sdio_pm_cb(state, mtk_wcn_cmb_sdio_pm_data);

     }

     else {

         printk(KERN_WARNING "mtk_wcn_cmb_sdio_off no sd callback!!\n");

     }

     /* 2. disable sdio eirq */

     mtk_wcn_cmb_sdio_disable_eirq();

     /*printk(KERN_INFO "[mt6620] set WIFI_EINT input pull down\n");*/

     mt_set_gpio_mode(mtk_wcn_cmb_sdio_eint_pin, mtk_wcn_cmb_sdio_eint_m_gpio); /* GPIO mode */

     mt_set_gpio_dir(mtk_wcn_cmb_sdio_eint_pin, GPIO_DIR_IN);

     mt_set_gpio_pull_select(mtk_wcn_cmb_sdio_eint_pin, GPIO_PULL_UP);

     mt_set_gpio_pull_enable(mtk_wcn_cmb_sdio_eint_pin, GPIO_PULL_ENABLE);

 }

 int board_sdio_ctrl (unsigned int sdio_port_num, unsigned int on) {

 #if defined(CONFIG_MTK_WCN_CMB_SDIO_SLOT)

    sdio_port_num = CONFIG_MTK_WCN_CMB_SDIO_SLOT;

    printk(KERN_WARNING "mt_combo_sdio_ctrl: force set sdio port to (%d)\n", sdio_port_num);

 #endif

     if ((sdio_port_num >= 4) || (combo_port_pwr_map[sdio_port_num] == 0xFF) ) {

         /* invalid sdio port number or slot mapping */

         printk(KERN_WARNING "mt_mtk_wcn_cmb_sdio_ctrl invalid port(%d, %d)\n", sdio_port_num, combo_port_pwr_map[sdio_port_num]);

         return -1;

     }

     /*printk(KERN_INFO "mt_mtk_wcn_cmb_sdio_ctrl (%d, %d)\n", sdio_port_num, on);*/

     if (!combo_port_pwr_map[sdio_port_num] && on) {

      #if 1

        printk(KERN_WARNING  "board_sdio_ctrl force off before on\n");

         mtk_wcn_cmb_sdio_off(sdio_port_num);

       #else

        printk(KERN_WARNING  "skip sdio off before on\n");

       #endif

         combo_port_pwr_map[sdio_port_num] = 0;

         /* off -> on */

         mtk_wcn_cmb_sdio_on(sdio_port_num);

         combo_port_pwr_map[sdio_port_num] = 1;

     }

     else if (combo_port_pwr_map[sdio_port_num] && !on) {

         /* on -> off */

         mtk_wcn_cmb_sdio_off(sdio_port_num);

         combo_port_pwr_map[sdio_port_num] = 0;

     }

     else {

         return -2;

     }

     return 0;

 }

 EXPORT_SYMBOL(board_sdio_ctrl);

 int mtk_wcn_sdio_irq_flag_set (int flag)

 {

     if (0 != flag)

     {

         atomic_set(&sdio_irq_enable_flag, 1);

     }

     else

     {

         atomic_set(&sdio_irq_enable_flag, 0);

     }

     printk(KERN_INFO  "sdio_irq_enable_flag:%d\n", atomic_read(&sdio_irq_enable_flag));

     return atomic_read(&sdio_irq_enable_flag);

 }

 EXPORT_SYMBOL(mtk_wcn_sdio_irq_flag_set);

 //#endif /* end of  defined(CONFIG_MTK_COMBO) || defined(CONFIG_MTK_COMBO_MODULE) */

 #endif /* end of defined(CONFIG_MTK_WCN_CMB_SDIO_SLOT) */

 /*=======================================================================*/

 /* Board Specific Devices Init                                           */

 /*=======================================================================*/

 #if defined(CONFIG_WLAN)

 int mt_wifi_resume(pm_message_t state)

 {

     int evt = state.event;

     if (evt != PM_EVENT_USER_RESUME && evt != PM_EVENT_RESUME) {

         return -1;

     }

     /*printk(KERN_INFO "[WIFI] %s Resume\n", evt == PM_EVENT_RESUME ? "PM":"USR");*/

     return 0;

 }

 int mt_wifi_suspend(pm_message_t state)

 {

     int evt = state.event;



     if (evt != PM_EVENT_USER_SUSPEND && evt != PM_EVENT_SUSPEND) {

         return -1;

     }

     return 0;

 }

 void mt_wifi_power_on(void)

 {

     pm_message_t state = { .event = PM_EVENT_USER_RESUME };

     (void)mt_wifi_resume(state);

 }

 EXPORT_SYMBOL(mt_wifi_power_on);

 void mt_wifi_power_off(void)

 {

     pm_message_t state = { .event = PM_EVENT_USER_SUSPEND };

     (void)mt_wifi_suspend(state);

 }

 EXPORT_SYMBOL(mt_wifi_power_off);

 #endif /* end of defined(CONFIG_WLAN) */

 /* Board Specific Devices                                                */

 /*=======================================================================*/

 /*=======================================================================*/

 /* Board Specific Devices Init                                           */

 /*=======================================================================*/

 /*=======================================================================*/

 /* Board Devices Capability                                              */

 /*=======================================================================*/

 #define MSDC_SDIO_FLAG    (MSDC_EXT_SDIO_IRQ | MSDC_HIGHSPEED | MSDC_UHS1)

 #if defined(CFG_DEV_MSDC0)

 #if defined(CONFIG_MTK_WCN_CMB_SDIO_SLOT) && (CONFIG_MTK_WCN_CMB_SDIO_SLOT == 0)

 struct msdc_hw msdc0_hw = {

         .clk_src        = MSDC30_CLKSRC_200MHZ,

         .cmd_edge       = MSDC_SMPL_FALLING,

         .rdata_edge     = MSDC_SMPL_FALLING,

         .wdata_edge     = MSDC_SMPL_FALLING,

         .clk_drv        = 1,

         .cmd_drv        = 1,

         .dat_drv        = 1,

         .data_pins      = 4,

         .data_offset    = 0,

         //MT6630 use External IRQ, wifi uses high speed. here wifi manage his own suspend and resume, does not support hot plug

         .flags          = MSDC_SDIO_FLAG,//MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE,

         .dat0rddly      = 0,

         .dat1rddly      = 0,

         .dat2rddly      = 0,

         .dat3rddly      = 0,

         .dat4rddly      = 0,

         .dat5rddly      = 0,

         .dat6rddly      = 0,

         .dat7rddly      = 0,

         .datwrddly      = 0,

         .cmdrrddly      = 0,

         .cmdrddly       = 0,

         .cmdrtactr_sdr50        = 0x1,

         .wdatcrctactr_sdr50     = 0x1,

         .intdatlatcksel_sdr50   = 0x0,

         .cmdrtactr_sdr200       = 0x3,

         .wdatcrctactr_sdr200    = 0x3,

         .intdatlatcksel_sdr200  = 0x0,

         .ett_count              = 0, //should be same with ett_settings array size

         .host_function = MSDC_SDIO,

         .boot           = 0,

         .request_sdio_eirq = mtk_wcn_cmb_sdio_request_eirq,

         .enable_sdio_eirq  = mtk_wcn_cmb_sdio_enable_eirq,

         .disable_sdio_eirq = mtk_wcn_cmb_sdio_disable_eirq,

         .register_pm       = mtk_wcn_cmb_sdio_register_pm,

     };

 #else

   #if defined(MTK_EMMC_SUPPORT)

     struct msdc_ett_settings msdc0_ett_settings[] = {

         /* common ett settings */

         { MSDC_HS200_MODE, 0xb0,  (0x7 << 7), 0x0 }, //PATCH_BIT0[MSDC_PB0_INT_DAT_LATCH_CK_SEL]

         { MSDC_HS200_MODE, 0xb0,  (0x1f<<10), 0x0 }, //PATCH_BIT0[MSDC_PB0_CKGEN_MSDC_DLY_SEL]

         { MSDC_HS400_MODE, 0xb0,  (0x7 << 7), 0x0 }, //PATCH_BIT0[MSDC_PB0_INT_DAT_LATCH_CK_SEL]

         { MSDC_HS400_MODE, 0xb0,  (0x1f<<10), 0x0 }, //PATCH_BIT0[MSDC_PB0_CKGEN_MSDC_DLY_SEL]

         { MSDC_HS400_MODE, 0x188, (0x1f<< 2), 0x0 /*0x7*/ }, //EMMC50_PAD_DS_TUNE[MSDC_EMMC50_PAD_DS_TUNE_DLY1]

         { MSDC_HS400_MODE, 0x188, (0x1f<<12), 0x13 /*0x18*/}, //EMMC50_PAD_DS_TUNE[MSDC_EMMC50_PAD_DS_TUNE_DLY3]

         /* command & resp ett settings */

         { MSDC_HS200_MODE, 0xb4,  (0x7 << 3), 0x1 }, //PATCH_BIT1[MSDC_PB1_CMD_RSP_TA_CNTR]

         { MSDC_HS200_MODE, 0x4,   (0x1 << 1), 0x1 }, //MSDC_IOCON[MSDC_IOCON_RSPL]

         { MSDC_HS200_MODE, 0xec,  (0x1f<<16), 0xf }, //PAD_TUNE[MSDC_PAD_TUNE_CMDRDLY]

         { MSDC_HS200_MODE, 0xec,  (0x1f<<22), 0x0 }, //PAD_TUNE[MSDC_PAD_TUNE_CMDRRDLY]

         { MSDC_HS400_MODE, 0xb4,  (0x7 << 3), 0x1 }, //PATCH_BIT1[MSDC_PB1_CMD_RSP_TA_CNTR]

         { MSDC_HS400_MODE, 0x4,   (0x1 << 1), 0x0 }, //MSDC_IOCON[MSDC_IOCON_RSPL]

         { MSDC_HS400_MODE, 0xec,  (0x1f<<16), 0xf }, //PAD_TUNE[MSDC_PAD_TUNE_CMDRDLY]

         { MSDC_HS400_MODE, 0xec,  (0x1f<<22), 0x0 /*0x3*/ }, //PAD_TUNE[MSDC_PAD_TUNE_CMDRRDLY]

         /* write ett settings */

         { MSDC_HS200_MODE, 0xb4,  (0x7 << 0), 0x1 }, //PATCH_BIT1[MSDC_PB1_WRDAT_CRCS_TA_CNTR]

         { MSDC_HS200_MODE, 0xec,  (0x1f<< 0), 0xf }, //PAD_TUNE[MSDC_PAD_TUNE_DATWRDLY]

         { MSDC_HS200_MODE, 0x4,   (0x1 <<10), 0x1 }, //MSDC_IOCON[MSDC_IOCON_W_D0SPL]

         { MSDC_HS200_MODE, 0xf0,  (0x1f<<24), 0xf }, //DAT_RD_DLY0[MSDC_DAT_RDDLY0_D0]

         /* read ett settings */

         { MSDC_HS200_MODE, 0xec,  (0x1f<< 8), 0x16}, //PAD_TUNE[MSDC_PAD_TUNE_DATRRDLY]

         { MSDC_HS200_MODE, 0x4,   (0x1 << 2), 0x0 }, //MSDC_IOCON[MSDC_IOCON_R_D_SMPL]

     }; 

     struct msdc_hw msdc0_hw = {

         .clk_src        = MSDC50_CLKSRC_200MHZ,

         .cmd_edge       = MSDC_SMPL_FALLING,

         .rdata_edge    = MSDC_SMPL_FALLING,

         .wdata_edge    = MSDC_SMPL_FALLING,

         .clk_drv        = 2,

         .cmd_drv        = 2,

         .dat_drv        = 2,

         .rst_drv        = 2,

         .ds_drv         = 2,

         .data_pins      = 8,

         .data_offset    = 0,

     #ifndef CONFIG_MTK_EMMC_CACHE

         .flags          = MSDC_SYS_SUSPEND | MSDC_HIGHSPEED | MSDC_UHS1 |MSDC_DDR | MSDC_HS400,

     #else

         .flags          = MSDC_SYS_SUSPEND | MSDC_HIGHSPEED | MSDC_CACHE | MSDC_UHS1 |MSDC_DDR | MSDC_HS400, 

     #endif

         .dat0rddly      = 0,

         .dat1rddly      = 0,

         .dat2rddly      = 0,

         .dat3rddly      = 0,

         .dat4rddly      = 0,

         .dat5rddly      = 0,

         .dat6rddly      = 0,

         .dat7rddly      = 0,

         .datwrddly      = 0,

         .cmdrrddly      = 0,

         .cmdrddly       = 0,

         .ett_count      = 20, //should be same with ett_settings array size

         .ett_settings   = (struct msdc_ett_settings *)msdc0_ett_settings,

         .host_function = MSDC_EMMC,

         .boot           = MSDC_BOOT_EN,

     };

   #else

     struct msdc_hw msdc0_hw = {

         .clk_src              = MSDC50_CLKSRC_200MHZ,

         .cmd_edge             = MSDC_SMPL_FALLING,

         .rdata_edge           = MSDC_SMPL_FALLING,

         .wdata_edge           = MSDC_SMPL_FALLING,

         .clk_drv              = 1,

         .cmd_drv              = 1,

         .dat_drv              = 1,

         .clk_drv_sd_18        = 1,         /* sdr104 mode */

         .cmd_drv_sd_18        = 1,

         .dat_drv_sd_18        = 1,

         .clk_drv_sd_18_sdr50 = 1,         /* sdr50 mode */

         .cmd_drv_sd_18_sdr50 = 1,

         .dat_drv_sd_18_sdr50 = 1,

         .clk_drv_sd_18_ddr50 = 1,         /* ddr50 mode */

         .cmd_drv_sd_18_ddr50 = 1,

         .dat_drv_sd_18_ddr50 = 1,

         .data_pins            = 4,

         .data_offset          = 0,

       //#ifdef CUST_EINT_MSDC1_INS_NUM

       #if 0

         .flags                = MSDC_SYS_SUSPEND | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED | MSDC_UHS1 |MSDC_DDR,    

       #else

         .flags                = MSDC_SYS_SUSPEND | MSDC_HIGHSPEED | MSDC_UHS1 |MSDC_DDR,   

       #endif

         .dat0rddly            = 0,

         .dat1rddly            = 0,

         .dat2rddly            = 0,

         .dat3rddly            = 0,

         .dat4rddly            = 0,

         .dat5rddly            = 0,

         .dat6rddly            = 0,

         .dat7rddly            = 0,

         .datwrddly            = 0,

         .cmdrrddly            = 0,

         .cmdrddly             = 0,

         .ett_count            = 0, //should be same with ett_settings array size

         .host_function        = MSDC_SD,

         .boot                 = 0,

         .cd_level             = MSDC_CD_LOW,

     };

   #endif

 #endif

 #endif

 #if defined(CFG_DEV_MSDC1)

 #if defined(CONFIG_MTK_WCN_CMB_SDIO_SLOT) && (CONFIG_MTK_WCN_CMB_SDIO_SLOT == 1)

     struct msdc_hw msdc1_hw = {     

         .clk_src        = MSDC30_CLKSRC_200MHZ,

         .cmd_edge       = MSDC_SMPL_FALLING,

         .rdata_edge     = MSDC_SMPL_FALLING,

         .wdata_edge     = MSDC_SMPL_FALLING,

         .clk_drv        = 1,

         .cmd_drv        = 1,

         .dat_drv        = 1,

         .data_pins      = 4,

         .data_offset    = 0,

         //MT6620 use External IRQ, wifi uses high speed. here wifi manage his own suspend and resume, does not support hot plug

         .flags          = MSDC_SDIO_FLAG,//MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE,

         .dat0rddly      = 0,

         .dat1rddly      = 0,

         .dat2rddly      = 0,

         .dat3rddly      = 0,

         .dat4rddly      = 0,

         .dat5rddly      = 0,

         .dat6rddly      = 0,

         .dat7rddly      = 0,

         .datwrddly      = 0,

         .cmdrrddly      = 0,

         .cmdrddly       = 0,

         .host_function = MSDC_SDIO,

         .boot           = 0,

         .request_sdio_eirq = mtk_wcn_cmb_sdio_request_eirq,

         .enable_sdio_eirq  = mtk_wcn_cmb_sdio_enable_eirq,

         .disable_sdio_eirq = mtk_wcn_cmb_sdio_disable_eirq,

         .register_pm       = mtk_wcn_cmb_sdio_register_pm,

     };

 #else

     struct msdc_hw msdc1_hw = {

         .clk_src              = MSDC30_CLKSRC_200MHZ,

         .cmd_edge             = MSDC_SMPL_FALLING,

         .rdata_edge           = MSDC_SMPL_FALLING,

         .wdata_edge           = MSDC_SMPL_FALLING,

         .clk_drv              = 3,

         .cmd_drv              = 3,

         .dat_drv              = 3,

         .clk_drv_sd_18        = 3,         /* sdr104 mode */

         .cmd_drv_sd_18        = 2,

         .dat_drv_sd_18        = 2,

         .clk_drv_sd_18_sdr50 = 3,         /* sdr50 mode */

         .cmd_drv_sd_18_sdr50 = 2,

         .dat_drv_sd_18_sdr50 = 2,

         .clk_drv_sd_18_ddr50 = 3,         /* ddr50 mode */

         .cmd_drv_sd_18_ddr50 = 2,

         .dat_drv_sd_18_ddr50 = 2,

         .data_pins            = 4,

         .data_offset          = 0,

     #ifdef CUST_EINT_MSDC1_INS_NUM

         .flags                = MSDC_SYS_SUSPEND | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED | MSDC_UHS1 |MSDC_DDR,    

     #else

         .flags                = MSDC_SYS_SUSPEND | MSDC_HIGHSPEED | MSDC_UHS1 |MSDC_DDR,   

     #endif

         .dat0rddly            = 0,

         .dat1rddly            = 0,

         .dat2rddly            = 0,

         .dat3rddly            = 0,

         .dat4rddly            = 0,

         .dat5rddly            = 0,

         .dat6rddly            = 0,

         .dat7rddly            = 0,

         .datwrddly            = 0,

         .cmdrrddly            = 0,

         .cmdrddly             = 0,

         .ett_count            = 0, //should be same with ett_settings array size

         .host_function        = MSDC_SD,

         .boot                 = 0,

         .cd_level             = MSDC_CD_LOW,

     };

 #endif

 #endif

 #if defined(CFG_DEV_MSDC2)

 #if defined(CONFIG_MTK_WCN_CMB_SDIO_SLOT) && (CONFIG_MTK_WCN_CMB_SDIO_SLOT == 2)

     /* MSDC2 settings for MT66xx combo connectivity chip */

     struct msdc_hw msdc2_hw = {     

         .clk_src        = MSDC30_CLKSRC_200MHZ,

         .cmd_edge       = MSDC_SMPL_FALLING,

         .rdata_edge     = MSDC_SMPL_FALLING,

         .wdata_edge     = MSDC_SMPL_FALLING,

         .clk_drv        = 1,

         .cmd_drv        = 1,

         .dat_drv        = 1,

         .data_pins      = 4,

         .data_offset    = 0,

         //MT6620 use External IRQ, wifi uses high speed. here wifi manage his own suspend and resume, does not support hot plug

         .flags          = MSDC_SDIO_FLAG,//MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE,

         .dat0rddly      = 0,

         .dat1rddly      = 0,

         .dat2rddly      = 0,

         .dat3rddly      = 0,

         .dat4rddly      = 0,

         .dat5rddly      = 0,

         .dat6rddly      = 0,

         .dat7rddly      = 0,

         .datwrddly      = 0,

         .cmdrrddly      = 0,

         .cmdrddly       = 0,

         .host_function = MSDC_SDIO,

         .boot           = 0,

         .request_sdio_eirq = mtk_wcn_cmb_sdio_request_eirq,

         .enable_sdio_eirq  = mtk_wcn_cmb_sdio_enable_eirq,

         .disable_sdio_eirq = mtk_wcn_cmb_sdio_disable_eirq,

         .register_pm       = mtk_wcn_cmb_sdio_register_pm,

     };

 #else

     struct msdc_hw msdc2_hw = {

         .clk_src              = MSDC30_CLKSRC_200MHZ,

         .cmd_edge             = MSDC_SMPL_FALLING,

         .rdata_edge           = MSDC_SMPL_FALLING,

         .wdata_edge           = MSDC_SMPL_FALLING,

         .clk_drv              = 3,

         .cmd_drv              = 3,

         .dat_drv              = 3,

         .clk_drv_sd_18        = 3,         /* sdr104 mode */

         .cmd_drv_sd_18        = 2,

         .dat_drv_sd_18        = 2,

         .clk_drv_sd_18_sdr50 = 3,         /* sdr50 mode */

         .cmd_drv_sd_18_sdr50 = 2,

         .dat_drv_sd_18_sdr50 = 2,

         .clk_drv_sd_18_ddr50 = 3,         /* ddr50 mode */

         .cmd_drv_sd_18_ddr50 = 2,

         .dat_drv_sd_18_ddr50 = 2,

         .data_pins            = 4,

         .data_offset          = 0,

         .flags                = MSDC_SYS_SUSPEND | MSDC_HIGHSPEED | MSDC_UHS1 |MSDC_DDR,  

         .dat0rddly           = 0,

         .dat1rddly           = 0,

         .dat2rddly           = 0,

         .dat3rddly           = 0,

         .dat4rddly           = 0,

         .dat5rddly           = 0,

         .dat6rddly           = 0,

         .dat7rddly           = 0,

         .datwrddly           = 0,

         .cmdrrddly           = 0,

         .cmdrddly             = 0,

         .ett_count            = 0, //should be same with ett_settings array size

         .host_function        = MSDC_SD,

         .boot                 = 0,

         .cd_level             = MSDC_CD_LOW,

 };

 #endif

 #endif

 #if defined(CFG_DEV_MSDC3)

 #if defined(CONFIG_MTK_WCN_CMB_SDIO_SLOT) && (CONFIG_MTK_WCN_CMB_SDIO_SLOT == 3)

     /* MSDC3 settings for MT66xx combo connectivity chip */

     struct msdc_hw msdc3_hw = {

         .clk_src        = MSDC30_CLKSRC_200MHZ,

         .cmd_edge       = MSDC_SMPL_FALLING,

         .rdata_edge     = MSDC_SMPL_FALLING,

         .wdata_edge     = MSDC_SMPL_FALLING,

         .clk_drv        = 4,

         .cmd_drv        = 4,

         .dat_drv        = 4,

         .clk_drv_sd_18  = 4,

         .cmd_drv_sd_18  = 4,

         .dat_drv_sd_18  = 4,

         .data_pins      = 4,

         .data_offset    = 0,

         //MT6620 use External IRQ, wifi uses high speed. here wifi manage his own suspend and resume, does not support hot plug

         .flags          = MSDC_SDIO_FLAG | MSDC_UHS1,//MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE,

         .dat0rddly      = 0,

         .dat1rddly      = 0,

         .dat2rddly      = 0,

         .dat3rddly      = 0,

         .dat4rddly      = 0,

         .dat5rddly      = 0,

         .dat6rddly      = 0,

         .dat7rddly      = 0,

         .datwrddly      = 0,

         .cmdrrddly      = 0,

         .cmdrddly       = 0,

         .cmdrtactr_sdr50        = 0x3,

         .wdatcrctactr_sdr50     = 0x1,

         .intdatlatcksel_sdr50   = 0x0,

         .cmdrtactr_sdr200       = 0x4,

         .wdatcrctactr_sdr200    = 0x2,

         .intdatlatcksel_sdr200  = 0x0,

         .ett_count              = 0, //should be same with ett_settings array size

         .host_function = MSDC_SDIO,

         .boot           = 0,

         .request_sdio_eirq = mtk_wcn_cmb_sdio_request_eirq,

         .enable_sdio_eirq  = mtk_wcn_cmb_sdio_enable_eirq,

         .disable_sdio_eirq = mtk_wcn_cmb_sdio_disable_eirq,

         .register_pm       = mtk_wcn_cmb_sdio_register_pm,

  };

 #else

 struct msdc_hw msdc3_hw;

 #endif

 #endif

 /* MT6575 NAND Driver */

 #if defined(CONFIG_MTK_MTD_NAND)

 struct mt6575_nand_host_hw mt6575_nand_hw = {

     .nfi_bus_width          = 8,

  .nfi_access_timing  = NFI_DEFAULT_ACCESS_TIMING,

  .nfi_cs_num    = NFI_CS_NUM,

  .nand_sec_size   = 512,

  .nand_sec_shift   = 9,

  .nand_ecc_size   = 2048,

  .nand_ecc_bytes   = 32,

  .nand_ecc_mode   = NAND_ECC_HW,

 };

 #endif