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驱动开发 笔记版的更多相关文章

  1. 嵌入式linux驱动开发 笔记

    @ 目录 首个驱动hellodrv 1.编写源码 2.编译模块 3.加载驱动 首个驱动hellodrv 3.如果下载不到,就自己编写,并编译驱动. 1.编写源码 2.编译模块 1.先写makefile ...

  2. 精通linux设备驱动开发 笔记

      3.2.7 错误处理   #include <linux/err.h> char * collect_data(char *userbuffer) { char *buffer; /* ...

  3. Windows驱动开发工具 WDK 学习笔记(1)

    目标:能够把电脑当作一个集成有高性能处理器的开发板用起来,当然,还自带了一个高级的操作系统Windows(必须的).总之,就是在一个带了操作系统的高性能开发板上的驱动程序开发. 性质:纯属业余爱好 1 ...

  4. Android驱动开发5-8章读书笔记

    Android驱动开发读书笔记                                                              第五章 S5PV210是一款32位处理器,具有 ...

  5. 第一章 Andorid系统移植与驱动开发概述 - 读书笔记

    Android驱动月考1 第一章 Andorid系统移植与驱动开发概述 - 读书笔记 1.Android系统的架构: (1)Linux内核,Android是基于Linux内核的操作系统,并且开源,所以 ...

  6. 驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址

    驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址 最近重新看了乾龙_Heron的<ARM 上电启动及 Uboot 代码分析>(下简称<代码分析>) ...

  7. 驱动开发学习笔记. 0.06 嵌入式linux视频开发之预备知识

    驱动开发读书笔记. 0.06  嵌入式linux视频开发之预备知识 由于毕业设计选择了嵌入式linux视频开发相关的项目,于是找了相关的资料,下面是一下预备知识 UVC : UVC,全称为:USB v ...

  8. 驱动开发学习笔记. 0.05 linux 2.6 platform device register 平台设备注册 2/2 共2篇

    驱动开发读书笔记. 0.05 linux 2.6 platform device register 平台设备注册 2/2 共2篇 下面这段摘自 linux源码里面的文档 : 内核版本2.6.22Doc ...

  9. 驱动开发学习笔记. 0.04 linux 2.6 platform device register 平台设备注册 1/2 共2篇

    驱动开发读书笔记. 0.04  linux 2.6 platform device register 平台设备注册  1/2 共2篇下面这段摘自 linux源码里面的文档 : Documentatio ...

随机推荐

  1. 用户创建,删除and并发注册and系统登陆的API研究(学习汇总网上资料)

    一.系统登陆链接实现 比如有一个外围支持系统,用户需要在外围系统登录之后点个link就可以登录到Oracle ERP系统中,那么我们需要先把外围系统的用户创建在Oracle ERP中,并且分配职责给他 ...

  2. Gazebo機器人仿真學習探索筆記(四)模型編輯

    模型編輯主要是自定義編輯物體模型構建環境,也可以將多種模型組合爲新模型等,支持外部模型導入, 需要注意的導入模型格式有相應要求,否在無法導入成功, COLLADA (dae), STereoLitho ...

  3. iOS集合视图单元格高亮和选中的区别

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交 ...

  4. Sybase - tempdb

    前沿:换了新公司,公司使用的Sybase数据库.现在开始学习Sybase数据库了.希望未来的几个月能对Sybase由浅入深的了解和研究. Tempdb的作用 sybase server端内部使用 排序 ...

  5. Fork And Join框架初探

    首先,关于Fork And Join框架的入门资料我觉得最好的是: Java线程(十一):Fork/Join-Java并行计算框架 本文参考了这篇文章 Fork/Join框架的核心类是ForkJoin ...

  6. 套接字输入缓冲装置——InternalInputBuffer

    互联网的世界很复杂,信息从一端传向另一端过程也相当复杂,中间可能通过若干个硬件,为了提高发送和接收效率,在发送端及接收端都将引入缓冲区,所以两端的套接字都拥有各自的缓冲区,当然这种缓冲区的引入也带来了 ...

  7. 02-Git简单使用

    Git安装(windows) https://code.google.com/p/msysgit/downloads/list 我们使用版本Git-1.7.9版本 百度网盘下载:链接:http://p ...

  8. (八十九)用AutoLayout实现动画和Label根据内容自动调整

    [AutoLayout动画] 对于storyboard每个约束,都可以像控件那样通过拖线的方式来建立和代码的连接. 约束是一个对象,通过这个对象的constant属性可以修改约束的点数. 在修改之后, ...

  9. (八十)MapKit放置系统默认大头针和自定义大头针

    有关MapView的显示和定位在上一节已经说明,这一节说明如何在地图上放置大头针,以及设置点击大头针的视图. [系统默认大头针] mapView上放置大头针的方法是调用其addAnnotation:方 ...

  10. Mybatis源码之Statement处理器SimpleStatementHandler(四)

    SimpleStatementHandler就是使用基本的Statement来执行query.batch.update等操作,其实现还是比较简单的,当然在执行过程中会涉及keyGenerator和Re ...