mt6577驱动开发 笔记版

来源:互联网 发布:php 多级分销商城源码 编辑:程序博客网 时间:2024/05/04 01:42
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
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 京东虚拟单被骗怎么办 网络公选课挂科怎么办 淘宝评论被商家关闭怎么办? 皇冠车钥匙丢了怎么办 皇冠行李箱钥匙丢了怎么办 淘宝主推产品扣两分怎么办 淘宝直通车宝贝排查下架怎么办 滴滴车龄超过8年怎么办 购物车超120了怎么办 没发货申请退款卖家不处理怎么办 淘宝卖家帐号被骗了怎么办 淘宝网下单忘了用返利网怎么办 该地域无法观看此直播怎么办 宝宝喝了有活虫的奶粉怎么办 淘宝商家店铺状态异常怎么办 淘宝购物提示买家信息错误怎么办 苹果淘宝占用空间大怎么办 苹果手机淘宝占内存太大怎么办 苹果手机淘宝图标找不到了怎么办 苹果手机看淘宝很卡怎么办 苹果手机淘宝忘了密码怎么办 苹果手机更新后淘宝打不开怎么办 淘宝买到苹果翻新机怎么办 淘宝网密码忘了怎么办 淘宝改密码要拍摄脸部怎么办 苹果一体机键盘没反应怎么办 淘宝买东西退货卖家拒绝怎么办? 淘宝被限制下单怎么办 淘宝扫码登录后怎么办 花呗选项被隐藏怎么办 新换手机支付宝怎么办 ih5点击按钮跳转页面怎么办 sap点安装程序没反应怎么办 淘宝店账号忘了怎么办 点击电脑桌面图标没反应怎么办 为什么淘宝打不开已停止运行怎么办 移动宽带打不开淘宝网怎么办 淘宝发布宝贝没有品牌怎么办 烫了卷发显老怎么办 唯品会商品不支持退换货怎么办 京东没有自提怎么办