基于IMX6Q的u-boot-2017.11的移植(2)->MMC移植

先观察上次IMX6Q移植uboot后串口打印出的信息:
U-Boot 2017.11 (Jan 04 2018 - 20:58:38 +0800)                                   
                                                                                    
CPU:   Freescale i.MX6Q rev1.5 at 792 MHz                                       
Reset cause: POR                                                                
Board: MX6Q-Armadillo2                                                          
DRAM:  2 GiB                                                                    
MMC:   FSL_SDHC: 0, FSL_SDHC: 1                                                 
MMC Device -1 not found                                                         
*** Warning - No MMC card found, using default environment                      
                                                                                
In:    serial                                                                   
Out:   serial                                                                   
Err:   serial                                                                   
Net:   FEC                                                                      
Error: FEC address not set.                                                     
                                                                                
Hit any key to stop autoboot:  0                                                
switch to partitions #0, OK                                                     
mmc1(part 0) is current device                                                  
switch to partitions #0, OK                                                     
mmc1(part 0) is current device                                                  
** Unable to read file boot.scr **                                              
reading zImage                                                                  
8472784 bytes read in 405 ms (20 MiB/s)                                         
Booting from mmc ...                                                            
** Unable to read file imx6q-arm2.dtb **                                        
Kernel image @ 0x12000000 [ 0x000000 - 0x8148d0 ]                               
                                                                                
Starting kernel ... 
发现:
    MMC:   FSL_SDHC: 0, FSL_SDHC: 1                                                 
    MMC Device -1 not found     
这儿有两个MMC设备,而且下面提示有一个-1的设备没有发现。
所以我们这一步就进行MMC的移植:
    首先找到MMC初始化的位置:common/board_r.c的static int initr_mmc(void)函数,
跟着这个函数下去就找到drivers/mmc/mmc.c里面的函数:static int mmc_probe(bd_t *bis)
函数源代码:
static int mmc_probe(bd_t *bis)
{
	if (board_mmc_init(bis) < 0)
		cpu_mmc_init(bis);

	return 0;
}
这儿的board_mmc_init(bis)就是调用板级的mmc初始化函数,该函数的位置board/freescale/mx6qarm2/mx6qarm2.c
函数源代码为:
int board_mmc_init(bd_t *bis)
{
        int ret;
        u32 index = 0;

        usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
        usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);

        for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) {
                switch (index) {
                case 0:
                        imx_iomux_v3_setup_multiple_pads(
                                usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
                        break;
                case 1:
                        imx_iomux_v3_setup_multiple_pads(
                                usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
                        break;
                default:
                        printf("Warning: you configured more USDHC controllers"
                                "(%d) then supported by the board (%d)\n",
                                index + 1, CONFIG_SYS_FSL_USDHC_NUM);
                        return -EINVAL;
                }

                ret = fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
                if (ret)
                        return ret;
        }

        return 0;
}
这儿的CONFIG_SYS_FSL_USDHC_NUM宏,定义了mmc设备的数量,这儿为2,在include/configs/mx6qarm2.h中定义。
观察这个函数主要是设置引脚复用,通过查看我们目标板的电路图(下图)得知,我们的SD卡挂接在SD2_XX上,SD2_CD(GPIO_4)
eMMC挂接在SD4_XX上。

基于IMX6Q的u-boot-2017.11的移植(2)->MMC移植_第1张图片

基于IMX6Q的u-boot-2017.11的移植(2)->MMC移植_第2张图片

所以修改为:
/* modefied by xcl */
int board_mmc_init(bd_t *bis)
{
	int ret;
	u32 index = 0;

	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
	usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);

	for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) {
		switch (index) {
		case 0:
			imx_iomux_v3_setup_multiple_pads(
				usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
			break;
		case 1:
			imx_iomux_v3_setup_multiple_pads(
				usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
			break;
		default:
			printf("Warning: you configured more USDHC controllers"
				"(%d) then supported by the board (%d)\n",
				index + 1, CONFIG_SYS_FSL_USDHC_NUM);
			return -EINVAL;
		}

		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
		if (ret)
			return ret;
	}

	return 0;
}
把与之相关的变量修改为:
/* modefied by xcl*///SD CARD
iomux_v3_cfg_t const usdhc2_pads[] = {
	MX6_PAD_SD2_CLK__SD2_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD2_CMD__SD2_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_GPIO_4__GPIO1_IO04  | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
};
//eMMC
iomux_v3_cfg_t const usdhc4_pads[] = {
	MX6_PAD_SD4_CLK__SD4_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD4_CMD__SD4_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD4_DAT4__SD4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD4_DAT5__SD4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD4_DAT6__SD4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	MX6_PAD_SD4_DAT7__SD4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
};
/* modefied by xcl */
struct fsl_esdhc_cfg usdhc_cfg[2] = {
	{USDHC2_BASE_ADDR},
	{USDHC4_BASE_ADDR},
};
然后再看该文件(board/freescale/mx6qarm2/mx6qarm2.c)中是否还有与MMC相关的函数
发现:
int board_mmc_get_env_dev(int devno)
{
	return devno - 2;
}
这个函数从函数名看可以看出是得到保存环境变了的设备号的函数,至于返回值暂时不深究。
int board_mmc_getcd(struct mmc *mmc)
{
	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
	int ret;

	if (cfg->esdhc_base == USDHC3_BASE_ADDR) {
		gpio_direction_input(IMX_GPIO_NR(6, 11));
		ret = !gpio_get_value(IMX_GPIO_NR(6, 11));
	} else /* Don't have the CD GPIO pin on board */
		ret = 1;

	return ret;
}
该函数是检测MMC设备的,我们有两个设备,SD卡和eMMC,SD卡在USDHC2上,eMMC在USDHC4上,
且SD卡的CD接在GPIO_4的复用功能GPIO1_4,所以仿照该函数
修改为:
/* modefied by xcl */
int board_mmc_getcd(struct mmc *mmc)
{
	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
	int ret;

	if (cfg->esdhc_base == USDHC2_BASE_ADDR) {
		gpio_direction_input(IMX_GPIO_NR(1, 4));
		ret = !gpio_get_value(IMX_GPIO_NR(1, 4));
	} else if (cfg->esdhc_base == USDHC4_BASE_ADDR){
        ret = 1;/* eMMC is always present */
    }
    else{
		ret = -1;/* Don't have the CD GPIO pin on board */
    }

	return ret;
}
修改完成,编译下载重启......

串口输出为:
U-Boot 2017.11 (Jan 07 2018 - 11:07:54 +0800)                                   
                                                                                
CPU:   Freescale i.MX6Q rev1.5 at 792 MHz                                       
Reset cause: POR                                                                
Board: MX6Q-Armadillo2                                                          
DRAM:  2 GiB                                                                    
MMC:   FSL_SDHC: 0, FSL_SDHC: 1                                                 
MMC Device -1 not found                                                         
*** Warning - No MMC card found, using default environment                      
                                                                                
In:    serial                                                                   
Out:   serial                                                                   
Err:   serial                                                                   
Net:   FEC                                                                      
Error: FEC address not set.                                                     
                                                                                
Hit any key to stop autoboot:  0                                                
=> 
还是有问题
执行指令:                                               
=> mmc dev 0                                                                    
switch to partitions #0, OK                                                     
mmc0 is current device                                                          
=> mmc dev 1                                                                    
switch to partitions #0, OK                                                     
mmc1(part 0) is current device                                                  
=> mmc list                                                                     
FSL_SDHC: 0 (SD)                                                                
FSL_SDHC: 1 (eMMC)                                                              
=> saveenv                                                                      
Saving Environment to MMC...                                                    
MMC Device -1 not found                                                         
!No MMC card found                                                              
=> 
还是有问题。
然后就搜索MMC Device字符串,发现在drivers/mmc/mmc_legacy.c
struct mmc *find_mmc_device(int dev_num)
{
	struct mmc *m;
	struct list_head *entry;
	list_for_each(entry, &mmc_devices) {
		m = list_entry(entry, struct mmc, link);
		if (m->block_dev.devnum == dev_num)
			return m;
	}

#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
	printf("MMC Device %d not found\n", dev_num);
#endif

	return NULL;
}
这个函数中传入了一个参数-1,所以就查找调用该函数的地方,最终找到:env/mmc.c
static int env_mmc_load(void)
{
#if !defined(ENV_IS_EMBEDDED)
        ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
        struct mmc *mmc;
        u32 offset;
        int ret;
        int dev = mmc_get_env_dev();
        const char *errmsg;

        mmc = find_mmc_device(dev);

        errmsg = init_mmc_for_env(mmc);
        if (errmsg) {
                ret = -EIO;
                goto err;
        }

        if (mmc_get_env_addr(mmc, 0, &offset)) {
                ret = -EIO;
                goto fini;
        }

        if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf)) {
                errmsg = "!read failed";
                ret = -EIO;
                goto fini;
        }

        env_import(buf, 1);
        ret = 0;

fini:
        fini_mmc_for_env(mmc);
err:
        if (ret)
                set_default_env(errmsg);
#endif
        return ret;
}
在这个函数中调用mmc_get_env_dev()得到了一个-1,继续跟踪这个函数
最终跟踪到:arch/arm/mach-imx/mx6/soc.c
int mmc_get_env_dev(void)
{
	int devno = mmc_get_boot_dev();

	/* If not boot from sd/mmc, use default value */
	if (devno < 0)
		return CONFIG_SYS_MMC_ENV_DEV;

	return board_mmc_get_env_dev(devno);
}
这个函数就是得到启动MMC设备的设备号,如果不是从MMC设备启动就返回CONFIG_SYS_MMC_ENV_DEV,
该宏定义环境变量保存的设备的设备号,如果是重MMC设备启动,就调用board_mmc_get_env_dev(devno)
而该函数在:board/freescale/mx6qarm2/mx6qarm2.c
int board_mmc_get_env_dev(int devno)
{
	return devno - 2;
}
从这个函数结果得知devno等于1,得知mmc_get_boot_dev()返回值为1,我这儿的SD卡设备号为0,eMMC为1,
我先将环境变量保存到SD卡(启动设备)中,所以改为:
/* modefied by xcl */
int board_mmc_get_env_dev(int devno)
{
	return devno - 1;
}
至于从eMMC启动的时候环境变量能不能保存到eMMC中我不确定,没有仔细去看mmc_get_boot_dev函数的实现。
如果以后从eMMC启动的时候有问题再回来改。

修改完成编译下载重启......
U-Boot 2017.11 (Jan 07 2018 - 11:50:48 +0800)                                   
                                                                                
CPU:   Freescale i.MX6Q rev1.5 at 792 MHz                                       
Reset cause: POR                                                                
Board: MX6Q-Armadillo2                                                          
DRAM:  2 GiB                                                                    
MMC:   FSL_SDHC: 0, FSL_SDHC: 1                                                 
In:    serial                                                                   
Out:   serial                                                                   
Err:   serial                                                                   
Net:   FEC                                                                      
Error: FEC address not set.                                                     
                                                                                
Hit any key to stop autoboot:  0                                                
=>   
命令测试:
=> mmc dev 0                                                                    
switch to partitions #0, OK                                                     
mmc0 is current device                                                          
=> mmc dev 1                                                                    
switch to partitions #0, OK                                                     
mmc1(part 0) is current device                                                  
=> mmc list                                                                     
FSL_SDHC: 0 (SD)                                                                
FSL_SDHC: 1 (eMMC)                                                              
=> saveenv                                                                      
Saving Environment to MMC...                                                    
Writing to MMC(0)... done                                                       
=> mmc read 120000000 1 100                                                     
                                                                                
MMC read: dev # 1, block # 1, count 256 ... 256 blocks read: OK                 
=> mmc write 120000000 1 100                                                    
                                                                                
MMC write: dev # 1, block # 1, count 256 ... 256 blocks written: OK             
=> mmc dev 0                                                                    
switch to partitions #0, OK                                                     
mmc0 is current device                                                          
=> mmc read 120000000 1 100                                                     
                                                                                
MMC read: dev # 0, block # 1, count 256 ... 256 blocks read: OK                 
=> mmc write 120000000 1 100                                                    
                                                                                
MMC write: dev # 0, block # 1, count 256 ... 256 blocks written: OK             
=> 
都OK,这样初步移植mmc完成,如果以后遇到问题再改。


你可能感兴趣的:(uboot)