先观察上次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上。
所以修改为:
/* 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完成,如果以后遇到问题再改。