[置顶] mt6577驱动开发 笔记版 转载请注明出处[email protected]




3 Preloader & Uboot

3.1 Preloader




3.1.1Preloader结构
Preloader的主题结构在文件:“alps\mediatek\platform\mt6577\preloader\src\core\main.c”中。


void main(void)
{
//时钟、uart、mcp等初始化
bldr_pre_process();

bldr_handshake(&handler);

//这里加载DSP 3G AP的ROM。

#if CFG_LOAD_UBOOT
addr = CFG_UBOOT_MEMADDR;
//加载uboot
    if (bldr_load_part(PART_UBOOT, bootdev, &addr) != 0)
        goto error;
#endif



//跳转到uboot
bldr_jump(addr, BOOT_ARGUMENT_ADDR, sizeof(boot_arg_t));

}


3.1.2 PLL与Clock
PLL介绍在datasheet 1190
Pll.c中“void mt6577_pll_init(void)”
似乎PLL主要是在preloader里打开的。




//设置的PLL
void mt6577_pll_init(void)
{


}


//根据MCP的型号设置DDR相关时钟
int mt6577_pll_init2 (void)
{
if (mt6577_get_dram_type() == 2)
    {
       …
    }
    else if (mt6577_get_dram_type() == 3)
{

    }
}




3.1.3 DDR的初始化


EMI_SETTINGS emi_settings[]里面定义了KMNJS000ZM_B205 H9TP32A4GDMCPR KMSJS000KM_B308等类型的MCP的配置参数。


在“void mt6577_set_emi (void)”里面会根据“emi_settings[]”的配置初始化MCP控制器。




3.1.4 镜像布局与加载


镜像布局参数被存放在文件:
mediatek/custom/out/mt6577preloader/cust_part.c里
static part_t platform_parts[PART_MAX_COUNT];里面记录每个镜像的长度。






在mediatek/platform/mt6577/preloader/src/core/part.c里
函数int part_init(void)里,依次累加前面所有镜像,算出当前镜像的起始位置。


3.1.5 EMMC 驱动


#define MMC_HOST_ID  0


u32 mmc_init_device(void)
{…
//emmc 零通道
ret = mmc_init(MMC_HOST_ID);

}


//分别初始化host和card
int mmc_init(int id)
{   
    …


    host = &sd_host[id];
    card = &sd_card[id];
    err = mmc_init_host(host, id);
    if (err == MMC_ERR_NONE)
        err = mmc_init_card(host, card);

}


//host初始化
int mmc_init_host(struct mmc_host *host, int id)
{
    memset(host, 0, sizeof(struct mmc_host));


    return msdc_init(host, id);
}


/*
#define MSDC0_BASE          (IO_PHYS + 0x01220000)
#define MSDC1_BASE          (IO_PHYS + 0x01230000)
#define MSDC2_BASE          (IO_PHYS + 0x01250000)
#define MSDC3_BASE          (IO_PHYS + 0x01240000)


#define IO_PHYS             0xC0000000


对于通道0,基地址在MSDC0_BASE即为0xC1220000。其余通道基地址在0xC1230000 0xC1240000  0xC1250000,但是datasheet里只有0通道0xC1220000的信息。


*/




int msdc_init(struct mmc_host *host, int id)
{
u32 baddr[] = {MSDC0_BASE, MSDC1_BASE, MSDC2_BASE, MSDC3_BASE};
//基地址选择0通道
    u32 base = baddr[id];


    //0通道
host->id     = id;
//基地址
    host->base   = base;
host->f_max  = MSDC_MAX_SCLK;

//以下所有对0通道的寄存器操作都是基于这基地址“base”进行的


}


3.3 uboot
Uboot代码:


Generic部分:
Uboot的generic的部分位于“bootable/bootloader/uboot/”


Mt6577相关部分相关位于:
mediatek/platform/mt6577/uboot/
mediatek/custom/out/mt6577/uboot/






uboot的config:
“alps\mediatek\custom\out\mt6577\uboot\inc\configs\ubconfigs.h”
3.3.1 uboot初始化流程
Uboot初始化主体位于“bootable/bootloader/uboot/arch/arm/lib/board.c”


void start_armboot (void)
{

//执行初始化例程数组
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) 
{
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}

//执行平台相关misc初始化
#if defined(CONFIG_MISC_INIT_R)
/* miscellaneous platform dependent initialisations */
misc_init_r ();
#endif


}


在“bootable/bootloader/uboot/arch/arm/lib/board.c”定义了初始化例程指针数组,其中的各项例程不同的板卡有自己不同的实现:


init_fnc_t *init_sequence[] = {
cpu_init, /* basic cpu dependent setup */
dram_init,              /* configure available RAM banks */ /*  change the original init order */
board_init, /* basic board dependent setup */
interrupt_init, /* set up exceptions */
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
    …
display_dram_config,
NULL,
};






Mt6577的初始化例程的实现位于“mediatek/platform/mt6577/uboot/mt6577_board.c”:


int board_init (void)
{…
mtk_serial_init();

mt6577_pinmux_init();s

pmic6329_init();




}




3.3.2 镜像布局与分区


Uboot在“int misc_init_r (…)”里对镜像分区初始化




int misc_init_r (void)
{…
mt6577_part_init(BLK_NUM(16 * GB));

}


/**********************************************************************/


在“mediatek/custom/out/mt6577/uboot/partition.h”里对分区表定义如下:


#include <common.h>
/*该文件可能就是:
“mediatek/custom/out/mt6577/uboot/inc/mt65xx_partition.h”
*/
#include "mt65xx_partition.h"


part_t partition_layout[] = {
{PART_PRELOADER, PART_BLKS_PRELOADER, PART_FLAG_NONE,0},
{PART_DSP_DL, PART_BLKS_DSP_DL, 0, PART_FLAG_NONE},

};




3.3.3 gpio初始化
DCT工具产生的“cust_gpio_boot.h”被如下文件:
mediatek/platform/mt6577/uboot/mt6577_gpio_init.c 




默认设置的定义:


u16 gpio_init_mode_data[];
u16 gpio_init_dir_data[];
u16 gpio_init_pullen_data[];



设置默认设置
void mt_gpio_set_default(void)






4 Kernel
内核源码


标准内核:
Alps/kernel


Mtk部分内核
Alps/mediatek/source/kernel/
Alps/mediatek/platform/mt6577/kernel
Alps/mediatek/custom/*/kernel下面也有,如
Alps/mediatek/custom/common/kernel
Alps/mediatek/custom/mt6577/kernel




4.1 ARCH初始化


4.1.1 Board支持
在“alps/mediatek/platform/mt6577/kernel/core/core.c”定义


MACHINE_START(MT6577, "MT6577")
    .boot_params    = PHYS_OFFSET + 0x00000100,
    .map_io         = mt6577_map_io,
    .init_irq       = mt_init_irq,
    .timer          = &mt6577_timer,
    .init_machine   = mt6577_init,
    .fixup          = mt6577_fixup
MACHINE_END


在“alps/mediatek/platform/mt6577/kernel/core/mt6577_devs.c”注册device
__init int mt6577_board_init(void)
{

retval = platform_device_register(&mt_hid_dev);
retval = platform_device_register(&mt_device_i2c[i]);
retval = platform_device_register(&AudDrv_device);
retval = platform_device_register(&mt6577_device_fb);
retval = platform_device_register(&mtk_hdmi_dev);
retval = platform_device_register(&mt6577_TVOUT_dev);

}




在“alps/kernel/mediatek/Makefile”里引用“../../mediatek/build/kernel/Makefile”,该文件即为:“alps/mediatek/build/kernel/Makefile”里面定义了相关的mt6577的内核文件:


machine-y       := $(call lc,$(MTK_PLATFORM))
ifeq ($(strip $(KBUILD_OUTPUT_SUPPORT)),yes)
MACHINE          := mediatek/platform/$(call lc,$(MTK_PLATFORM))/kernel/core/
machdirs         := mediatek/platform/$(call lc,$(MTK_PLATFORM))/kernel/core/
else
MACHINE         := $(MTK_PATH_PLATFORM)/core/
machdirs        := $(MTK_PATH_PLATFORM)/core/
endif
platdirs        :=


ifeq ($(strip $(KBUILD_OUTPUT_SUPPORT)),yes)
drivers-y       += mediatek/source/kernel/
drivers-y       += mediatek/custom/out/$(FULL_PROJECT)/kernel/
drivers-y       += mediatek/platform/$(call lc,$(MTK_PLATFORM))/kernel/drivers/
else
drivers-y       += $(MTK_PATH_PLATFORM)/drivers/
drivers-y       += $(MTK_PATH_SOURCE)/
drivers-y       += $(MTK_PATH_CUSTOM)/
endif






4.1.2 PLL与Clock


mt6577_clock_manager.c中“static void mt6577_clock_init(void)”“static void mt6577_pll_init(void)”


mt6577的clock定义如下
enum mt65xx_clock_id {
    /* PERI_GLOBALCON_PDN0 */
    MT65XX_PDN_PERI_NFI                 = 0,
    …
    
    /* PERI_GLOBALCON_PDN1 */
    MT65XX_PDN_PERI_SEJ                 = 32,
    …
    /* MMSYS1 Clock Gating #0 */
MT65XX_PDN_MM_VBUF                  = 64,

    /* MMSYS1 Clock Gating #1 */
    MT65XX_PDN_MM_VRZ1                  = 96,
    …


    /*MMSYS1 Clock Gating #2 */
    MT65XX_PDN_MM_SCAM                  = 128,
    …
    
MT65XX_CLOCK_AUDIO_PDN, /* 32*6 = 192*/
    MT65XX_AUDIO_PDN_END                = MT65XX_PDN_AUDIO_I2S,


    MT65XX_CLOCK_COUNT,
};


按照32,分组,enbale某个clock时,首先找到分组,然后找到组内偏移,针对某个组进行操作。中间根据clock组编号区分出 AP AP1 MM1 MM2等不同始终组,进行特殊操作。


不同的驱动在自己初始化函数里enable自己需要clock id—实际上enable对应的clock组。


int enable_clock(enum mt65xx_clock_id id, char *mod_name)
{
    unsigned long flags;
    int ret = 0;
    int category = id / CLK_REG_WIDTH;
int offset = id % CLK_REG_WIDTH;




if (CATEGORY_AP1(category)) {

}

if (CATEGORY_MM(category)) {

}
if (CATEGORY_AUD(category)) {

}


ret = enable_clock_internal(category, mask);






5 CpuFreq


5.1 初始化


在“static int mtk_cpufreq_init(…)”里根据处理器的版本选择调频表:


static struct mtk_cpu_freq_info mt6575_freqs_e1[] = {
    OP(DVFS_F2_MT6575_E1),
    OP(DVFS_F1_MT6575_E1),
};


/***************************
* MT6575 E2 DVFS Table
****************************/
static struct mtk_cpu_freq_info mt6575_freqs_e2[] = {
    OP(DVFS_F4_MT6575_E2),
    …
};


/***************************
* MT6577 E1 DVFS Table
****************************/
static struct mtk_cpu_freq_info mt6577_freqs_e1[] = {
    OP(DVFS_F6_MT6577_E1),
    …
    OP(DVFS_F1_MT6577_E1),
};


/***************************
* MT6577 E1 TM DVFS Table
****************************/
static struct mtk_cpu_freq_info mt6577_freqs_e1_tm[] = {
    OP(DVFS_F6_MT6577_E1_TM),
    …
    OP(DVFS_F1_MT6577_E1_TM),
};






调频操作在“static int mtk_cpufreq_target()”里完成。




5.2 基本数据结构


调频例程


static struct cpufreq_driver mtk_cpufreq_driver = {
    .verify = mtk_cpufreq_verify,
    .target = mtk_cpufreq_target,
    .init   = mtk_cpufreq_init,
    .get    = mtk_cpufreq_get,
    .name   = "mtk-cpufreq",
};




5.7 调频




/**********************************
* cpufreq target callback function
***********************************/
/*************************************************
* [note]
* 1. handle frequency change request
* 2. call mtk_cpufreq_set to set target frequency
**************************************************/
static int mtk_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation)
{
    …


    /******************************
    * look up the target frequency
    *******************************/
    if (cpufreq_frequency_table_target(policy, mtk_cpu_freqs_table, target_freq, relation, &idx))
        return -EINVAL;


   


//idx是目标调频点索引值


    if (get_chip_ver() >= CHIP_6577_E1)
    {…
    }
    else if (get_chip_ver() >= CHIP_6575_E2)
    {
        next = &mt6575_freqs_e2[idx];
    }
    …
 
// next指向目标调频点
// freqs.old是当前频点,freqs.new是目标频点
    freqs.old = policy->cur;
    freqs.new = next->cpufreq_mhz;
    freqs.cpu = policy->cpu;


    


    #ifndef MTK_DVFS_RANDOM_TEST
    if (mtk_cpufreq_keep_max_freq(freqs.old, freqs.new))
    {
        if ((DRV_Reg32(HW_RESV) & (0x1 << 23)) && ((DRV_Reg32(HW_RESV) & (0x1 << 20)) == 0))
            freqs.new = DVFS_F1_TM;
        else
            freqs.new = DVFS_F1;
    }


    if (freqs.new > g_limited_freq)
    {
        dprintk("CPU frequency has been limited to %d Mhz, request %d Mhz will be limited\n", g_limited_freq / 1000, freqs.new / 1000);
        freqs.new = g_limited_freq;
    }


    if (freqs.new < g_limited_min_freq)
    {
        dprintk("cannot switch CPU frequency to %d Mhz due to voltage limitation\n", g_limited_min_freq / 1000);
        freqs.new = g_limited_min_freq;
    }
    #endif


    /************************************************
    * target frequency == existing frequency, skip it
    *************************************************/
    if (freqs.old == freqs.new)
    {
        dprintk("CPU frequency from %d MHz to %d MHz (skipped) due to same frequency\n", freqs.old / 1000, freqs.new / 1000);
        return 0;
    }


/*调频前对所有ONLINE CPU发出通知*/
    for_each_online_cpu(cpu)
    {
        freqs.cpu = cpu;
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
    }


    spin_lock_irqsave(&mtk_cpufreq_lock, flags);


    /*********************************************
    * update current frequency due to last change
    **********************************************/
    freqs.old = g_cur_freq;


    /******************************
    * set to the target freeuency
*******************************/
//真正的调频操作
    mtk_cpufreq_set(freqs.old, freqs.new);


    spin_unlock_irqrestore(&mtk_cpufreq_lock, flags);




/*调频后对所有ONLINE CPU发出通知*/


    for_each_online_cpu(cpu)
    {
        freqs.cpu = cpu;
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
    }


    return 0;
}








/*****************************************
* frequency ramp up and ramp down handler
******************************************/
/***********************************************************
* [note]
* 1. frequency ramp up need to wait voltage settle
* 2. frequency ramp down do not need to wait voltage settle
************************************************************/
static void mtk_cpufreq_set(unsigned int freq_old, unsigned int freq_new)
{
    if (freq_new == DVFS_F1 || freq_new == DVFS_F1_TM) /* set ARMPLL divider to 1/1 */
    {
        …
    }
    else if (freq_new == DVFS_F2 || freq_new == DVFS_F2_TM) /* set ARMPLL divider to 5/6 */
    {
        if (freq_new > freq_old)
        {    //升频,先调压再调频
//调压
            #ifdef MTK_BUCK_ADJUST
            DRV_WriteReg32(SC_AP_DVFS_CON, ((DRV_Reg32(SC_AP_DVFS_CON) & 0xFFFFFFFC) | 0x03));


            mb();
            udelay(PMIC_SETTLE_TIME);
            #endif
           
            
            g_cur_freq = freq_new;
//调频
            DRV_WriteReg32(TOP_CKDIV1, 0x19);
        }
        else
        {   //降频,先调频再调压
            //调频
            g_cur_freq = freq_new;
            DRV_WriteReg32(TOP_CKDIV1, 0x19);
            mb();
             
//调压
            #ifdef MTK_BUCK_ADJUST
            DRV_WriteReg32(SC_AP_DVFS_CON, ((DRV_Reg32(SC_AP_DVFS_CON) & 0xFFFFFFFC) | 0x03));
            #endif
        }
    }
    else if (freq_new == DVFS_F3 || freq_new == DVFS_F3_TM) /* set ARMPLL divider to 3/4 */
    {
      
    }
    else if (freq_new == DVFS_F4 || freq_new == DVFS_F4_TM) /* set ARMPLL divider to 2/3 */
    {
    }
    else if (freq_new == DVFS_F5 || freq_new == DVFS_F5_TM) /* set ARMPLL divider to 1/2 */
    {
    }
    else if (freq_new == DVFS_F6 || freq_new == DVFS_F6_TM) /* set ARMPLL divider to 1/4 */
    {
    }
    else if (freq_new == DVFS_F7 || freq_new == DVFS_F7_TM) /* set ARMPLL divider to 1/6 */
    {
    }
   


}




6 IRQ


6.1 中断体系
根据arm gic规范,
0-15 SGI
16-31 PPP
32以上 SPI




6.3 外部中断




typedef struct 
{
    void (*eint_func[EINT_MAX_CHANNEL])(void);
    unsigned int eint_auto_umask[EINT_MAX_CHANNEL];
} eint_func;




通过“void mt65xx_eint_registration(…)”注册自己的中断函数。


比如“alps\mediatek\custom\common\kernel\touchpanel\ft5206\ft5206_driver.c”通过该函数注册自己的中断处理函数:


    mt65xx_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_EN, CUST_EINT_POLARITY_HIGH, tpd_eint_interrupt_handler, 1);






外部中断的入口是“static irqreturn_t mt65xx_eint_isr(int irq, void *dev_id)”,该函数会检查“eint_func”数组里的处理函数。而整个外部中断入口是由EINT_IRQ中断触发。在“alps\mediatek\platform\mt6577\kernel\core\mt6577_eint.c”将EINT_IRQ中断挂入6577的中断体系。


if (request_irq(EINT_IRQ, mt65xx_eint_isr, IRQF_TRIGGER_HIGH, "EINT", NULL)) {
        printk(KERN_ERR "EINT IRQ LINE NOT AVAILABLE!!\n");
}


6.4 wakeup
static u16 sc_wake_irq[NUM_WAKE_SRC] = {
[2] = MT6577_KP_IRQ_ID,
[3] = MT6577_MSDC1_IRQ_ID,
[5] = MT6577_EINT_IRQ_ID,
[6] = MT6577_RTC_IRQ_ID,
[7] = MT6577_AP_CCIF_IRQ_ID,
[8] = MT6577_ACCDET_IRQ_ID,
};


15 Driver




15.1 LCM
修改lps/mediatek/config/common/ProjectConfig.mk”里的“CUSTOM_KERNEL_LCM”和 “CUSTOM_UBOOT_LCM”选项将影响到文件“alps/mediatek/config/out/mt6577/ProjectConfig.mk”


将上述两项CUSTOM_KERNEL_LCM=hx8369_6575  CUSTOM_UBOOT_LCM=hx8369_6575


导致


alps/mediatek/custom/common/kernel/lcm/hx8369_6575/hx8369_6575.c拷到如下两个目录




alps/mediatek/custom/out/mt6577/kernel/lcm


alps/mediatek/custom/out/mt6577/uboot/lcm






mediatek\source\kernel\drivers\video


static const DISP_DRIVER DSI_DISP_DRV








const LCM_DRIVER *disp_drv_get_lcm_driver(const char *lcm_name)






15.2 BL
mediatek\source\kernel\drivers\led\leds.c
{


if(strcmp(g_leds_data[i]->cdev.name,"lcd-backlight") == 0)
{
rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_duty);
            if(rc)
            {
                LEDS_DEBUG("[LED]device_create_file duty fail!\n");
            }
            
            rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_div);
            if(rc)
            {
                LEDS_DEBUG("[LED]device_create_file duty fail!\n");
            }
            
            rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_frequency);
            if(rc)
            {
                LEDS_DEBUG("[LED]device_create_file duty fail!\n");
            }
            
   rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_pwm_register);
            if(rc)
            {
                LEDS_DEBUG("[LED]device_create_file duty fail!\n");
            }
bl_setting = &g_leds_data[i]->cust;
}




}
static DEVICE_ATTR(duty, 0664, show_duty, store_duty);


g_leds_data






[   40.450409] (0)[313:ScreenOffThread][LED]Set Backlight directly 102 at time 4294941336
[   40.451398] (0)[313:ScreenOffThread]mt65xx_leds_set_cust: set brightness, name:lcd-backlight, mode:3, level:102
[   40.452744] (0)[313:ScreenOffThread]brightness_set_pmic1[LED]PMIC#3:102
[   40.454159] (0)[313:ScreenOffThread]brightness_set_pmic3 2




brightness_set_pmic


mt65xx_leds_brightness_set


led_brightness_set




15.3 TP


alps\mediatek\custom\common\kernel\touchpanel\ft5206
alps\mediatek\custom\common\kernel\touchpanel\src


15.5 Musb


15.5.1 配置
尽管在
mediatek/config/mt6577/autoconfig/kconfig/platform
CONFIG_USB_MTK_HDRC_HCD is not set
CONFIG_USB_MTK_OTG is not set


但是在
mediatek/config/mt6577/autoconfig/kconfig/project
CONFIG_USB_MTK_HDRC_HCD=y
CONFIG_USB_MTK_OTG=y




15.5.2 Platform device & driver


mediatek\platform\mt6577\kernel\core
struct platform_device mt_device_usb = {
.name  = "mt_usb",
.id  = -1,
.dev = {                
//.platform_data          = &usb_data_mt65xx,     
.dma_mask               = &usb_dmamask,
.coherent_dma_mask      = DMA_BIT_MASK(32), 
//.release=musbfsh_hcd_release,    
},
};






__init int mt6577_board_init(void)
{



#if defined(CONFIG_USB_MTK_HDRC)
printk("mt_device_usb register\n");
retval = platform_device_register(&mt_device_usb);
if (retval != 0){
printk("mt_device_usb register fail\n");
        return retval;
}
#endif

}












mediatek\source\kernel\drivers\usb20


static struct platform_driver musb_driver = {
.driver = {
.name = (char *)musb_driver_name,
.owner = THIS_MODULE,
},
.remove = __exit_p(musb_remove),
.shutdown = musb_shutdown,
.probe = musb_probe,
};
















data_array[0]=0x00103902;
        data_array[1]=0x032000B2;
        data_array[2]=0xFF007003;
        data_array[3]=0x00000000;
        data_array[4]=0x01000303;
        dsi_set_cmdq(&data_array, 5, 1);


  data_array[0] 为packet head  定义为:第一个字节为 WC1,第二个字节WC0,第三个字节DT (命令类型)第四个字节为控制类型。


  data_array[1],data_array[2],data_array[3],data_array[4],为初始化的相应数据。








15.6 GPIO




GPIO初始化在uboot里完成




GPIO在内核的定义:
cust_gpio_usage.h






GPIO在内核的设置
mt_set_gpio_mode


15.7 IIC
15.7.1  adapter device


alps\mediatek\platform\mt6577\kernel\core\Mt6577_devs.c


static struct platform_device mt_device_i2c[] = {
    {
        .name           = "mt-i2c",
        .id             = 0,
        .num_resources  = ARRAY_SIZE(mt_resource_i2c1),
        .resource       = mt_resource_i2c1,
    },

    {
        .name           = "mt-i2c",
        .id             = 2,
        .num_resources  = ARRAY_SIZE(mt_resource_i2c3),
        .resource       = mt_resource_i2c3,
    },
};


15.7.2 adapter driver
alps\mediatek\platform\mt6577\kernel\drivers\i2c\I2c.c




static struct platform_driver mt_i2c_driver = {
    .probe = mt_i2c_probe,
    .remove = mt_i2c_remove,
#ifdef CONFIG_PM
    .suspend = mt_i2c_suspend,
    .resume = mt_i2c_resume,
#endif
    .driver  = {
        .name  = DRV_NAME,
        .owner = THIS_MODULE,
    },
};




15.7.3 匹配IIC通道


i2c_register_board_info




15.8 PMIC MT6329
alps\mediatek\platform\mt6577\kernel\drivers\power\pmic_mt6329.c


i2c_register_board_info 指出mt6329使用2通道




15.9 emmc & sd




C:\senix\rd\mtk\6577\source-code\src\alps\mediatek\platform\mt6577\kernel\core\ mt6577_devs.c


static struct platform_device mt6577_device_sd[] =
{
#if defined(CFG_DEV_MSDC0)
    {
        .name           = "mtk-sd",
        .id             = 0,
        .num_resources  = ARRAY_SIZE(mt6577_resource_sd0),
        .resource       = mt6577_resource_sd0,
        .dev = {
            .platform_data = &msdc0_hw,
        },
    },
#endif
#if defined(CFG_DEV_MSDC1)
    {
        .name           = "mtk-sd",
        .id             = 1,
        .num_resources  = ARRAY_SIZE(mt6577_resource_sd1),
        .resource       = mt6577_resource_sd1,
        .dev = {
            .platform_data = &msdc1_hw,
        },
    },
#endif
#if defined(CFG_DEV_MSDC2)
    {
        .name           = "mtk-sd",
        .id             = 2,
        .num_resources  = ARRAY_SIZE(mt6577_resource_sd2),
        .resource       = mt6577_resource_sd2,
        .dev = {
            .platform_data = &msdc2_hw,
        },
    },
#endif
#if defined(CFG_DEV_MSDC3)
    {
        .name           = "mtk-sd",
        .id             = 3,
        .num_resources  = ARRAY_SIZE(mt6577_resource_sd3),
        .resource       = mt6577_resource_sd3,
        .dev = {
            .platform_data = &msdc3_hw,
        },
    },
#endif
};




驱动
c:\senix\rd\mtk\6577\source-code\src\alps\mediatek\platform\mt6577\kernel\drivers\mmc-host\sd.c




EMMC数据线定义
struct msdc_hw msdc0_hw = {
   .clk_src        = 1,
   .cmd_edge       = MSDC_SMPL_FALLING,
   .data_edge      = MSDC_SMPL_FALLING,
   …
   .data_pins      = 8,
   .data_offset    = 0,
#ifdef MTK_EMMC_SUPPORT
   .flags          = MSDC_SYS_SUSPEND | MSDC_HIGHSPEED,
#else
   .flags          = MSDC_SDCARD_FLAG,
#endif
};






static struct mmc_host_ops mt_msdc_ops = {
    .request         = msdc_ops_request,
    .set_ios         = msdc_ops_set_ios,
    .get_ro          = msdc_ops_get_ro,
    .get_cd          = msdc_ops_get_cd,
    .enable_sdio_irq = msdc_ops_enable_sdio_irq,
    .start_signal_voltage_switch = msdc_ops_switch_volt,
};




Host
Mmc card device
Mmc card driver


mmc_rescan 扫描mmc 家里mmc设备


mmc_init_card




mmc_blk_probe
add_disk


你可能感兴趣的:(驱动开发,mt6577)