• mt6577驱动开发 笔记版


    3 Preloader & Uboot
    3.1 Preloader
    3.1.1Preloader结构
    Preloader的主题结构在文件:“alpsmediatekplatformmt6577preloadersrccoremain.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:
    “alpsmediatekcustomoutmt6577ubootincconfigsubconfigs.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 ", 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 ", 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 ", 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(…)”注册自己的中断函数。
    比如“alpsmediatekcustomcommonkernel ouchpanelft5206ft5206_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中断触发。在“alpsmediatekplatformmt6577kernelcoremt6577_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!! ");
    }

    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
    mediateksourcekerneldriversvideo
    static const DISP_DRIVER DSI_DISP_DRV
    const LCM_DRIVER *disp_drv_get_lcm_driver(const char *lcm_name)
    15.2 BL
    mediateksourcekerneldriversledleds.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! ");
                }
                
                rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_div);
                if(rc)
                {
                    LEDS_DEBUG("[LED]device_create_file duty fail! ");
                }
                
                rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_frequency);
                if(rc)
                {
                    LEDS_DEBUG("[LED]device_create_file duty fail! ");
                }
                
       rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_pwm_register);
                if(rc)
                {
                    LEDS_DEBUG("[LED]device_create_file duty fail! ");
                }
    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




    alpsmediatekcustomcommonkernel ouchpanelft5206
    alpsmediatekcustomcommonkernel ouchpanelsrc




    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




    mediatekplatformmt6577kernelcore
    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 ");
    retval = platform_device_register(&mt_device_usb);
    if (retval != 0){
    printk("mt_device_usb register fail ");
            return retval;

    #endif

    }
























    mediateksourcekerneldriversusb20




    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




    alpsmediatekplatformmt6577kernelcoreMt6577_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
    alpsmediatekplatformmt6577kerneldriversi2cI2c.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
    alpsmediatekplatformmt6577kerneldriverspowerpmic_mt6329.c




    i2c_register_board_info 指出mt6329使用2通道








    15.9 emmc & sd








    C:senix dmtk6577source-codesrcalpsmediatekplatformmt6577kernelcore 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 dmtk6577source-codesrcalpsmediatekplatformmt6577kerneldriversmmc-hostsd.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
  • 相关阅读:
    刘备和诸葛亮闹翻:无意说出蜀国灭亡的根源?
    亚马逊为什么能吞噬世界?贝索斯有这么一种独特的战略思维
    现在的社会,能负债的人,一定是有本事的人
    富士康为何转向美国:人口红利消失 炒房带来恶性循环
    中国华为:硅谷风混搭国企作派
    亚马逊拟斥资15亿美元建航空货运中心
    比数字工具更好用的纸和笔
    张小龙的克制 小程序 微信
    阿里前CEO卫哲用自己10余年经历,倾诉B2B的三差、四率、两大坑
    关于自信的励志名言
  • 原文地址:https://www.cnblogs.com/LoongEmbedded/p/5298314.html
Copyright © 2020-2023  润新知