参考i.MX_6_BSP_Porting_Guide.pdf手册,下载u-boot源码,以下是文档和源码链接。
fsl_yocto-L4.1.15_2.0.0-ga.tar.gz
uboot-imx-imx_v2016.03_4.1.15_2.0.0_ga
cp include/configs/mx6sabresd.h include/configs/mx6q_tqcorec.h
vim arch/arm/cpu/armv7/mx6/Kconfig +100
config TARGET_MX6Q_TQCOREC
bool "mx6q_tqcorec"
select SUPPORT_SPI
select DM
select DM_THERMAL
source "board/freescale/mx6q_tqcorec/Kconfig"
cp -R board/freescale/mx6sabresd board/freescale/mx6q_tqcorec
cd board/freescale/mx6q_tqcorec/
mv mx6sabresd.c mx6q_tqcorec.c
vim Makefile
obj-y := mx6q_tqcorec.o
vim Kconfig
if TARGET_MX6Q_TQCOREC
config SYS_BOARD
default "mx6q_tqcorec"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "mx6q_tqcorec"
endif
vim configs/mx6q_tqcorec_defconfig
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MX6Q_TQCOREC=y
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6q_tqcorec/mx6q_4x_mt41j128.cfg,MX6Q,SYS_USE_SPINOR"
CONFIG_CMD_GPIO=y
其中内存参数是由mx6q_4x_mt41j128.cfg配置文件决定,把天嵌官方文件拷贝过来,或者但采用飞思卡尔的工具配置DCD,下载DDR_Stress_Tester_V1.0.3.zip和I.MX6DQSDL
DDR3 Script Aid V0.10.xlsx两个工具。
查看TQIMX6Q的原理图可知,TQIMX6Q的UART1的TXD和RXD分别接到了UART1_TXD(SD3_DAT7)和UART1_RXD(SD3_DAT6)两个管脚上.
vim board/freescale/mx6q_tqcorec/mx6q_tqcorec.c
static iomux_v3_cfg_t const uart1_pads[] = {
//MX6_PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
//MX6_PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_SD3_DAT7__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_SD3_DAT6__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
由于MX6_PAD_SD3_DAT7、MX6_PAD_SD3_DAT6已经被USDHC3占用
static iomux_v3_cfg_t const usdhc3_pads[] = {
// MX6_PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
// MX6_PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
// MX6_PAD_NANDF_D0__GPIO2_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
};
sd卡槽使用的是USDHC2控制器,并且与sabresd不同的是 该SD CARD电路的CD引脚使用的是GPIO_4.
static iomux_v3_cfg_t const usdhc2_pads[] = {
//MX6_PAD_NANDF_D2__GPIO2_IO02 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
MX6_PAD_GPIO_4__GPIO1_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
};
sd卡槽cd引脚宏定义:
//#define USDHC2_CD_GPIO IMX_GPIO_NR(2, 2)
//#define USDHC3_CD_GPIO IMX_GPIO_NR(2, 0)
#define USDHC2_CD_GPIO IMX_GPIO_NR(1, 4)
int board_mmc_getcd(struct mmc *mmc)
{
......
//ret = !gpio_get_value(USDHC3_CD_GPIO);
}
int board_mmc_init(bd_t *bis)
{
......
//gpio_direction_input(USDHC3_CD_GPIO);
}
查看原理图及IMX6Q芯片手册可以发现UART1和UART2的TXD和RXD与usdhc3_pads的管脚是复用的,因此,MMC初始化时不能将UART相关的引脚初始化为MMC相关引脚,由于这块开发板上没有引出usdhc3,所以不会影响开发板的其它功能。
static iomux_v3_cfg_t const usdhc3_pads[] = {
//MX6_PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
//MX6_PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
}
static const struct boot_mode board_boot_modes[] = {
......
//{"sd3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
}
make mx6q_tqcorec_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
sudo dd if=/dev/zero of=/dev/sdb bs=512 seek=2 count=512
sudo dd if=u-boot.imx of=/dev/sdb bs=512 seek=2
运行开发板报错,以下是log文件:
U-Boot 2016.03 (Aug 27 2018 - 17:38:55 +0800)
CPU: Freescale i.MX6Q rev1.2 996 MHz (running at 792 MHz)
CPU: Extended Commercial temperature grade (-20C to 105C) at 27C
Reset cause: POR
Board: MX6-SabreSD
I2C: ready
DRAM: 2 GiB
Can't find PMIC:PFUZE100
initcall sequence 8ff970d8 failed at call 178041e0 (err=-19)
### ERROR ### Please RESET the board ###
解决问题,solution:
天嵌这块板子没有使用sabresd官方使用的PFUZE100,故要关掉相应驱动。
uboot\include\configs\Mx6q_tqcorec.h:#include "mx6sabre_common.h"
uboot\include\configs\Mx6sabre_common.h:
/* PMIC */
#define CONFIG_POWER
#define CONFIG_POWER_I2C
#define CONFIG_POWER_PFUZE100
#define CONFIG_POWER_PFUZE100_I2C_ADDR 0x08
uboot\include\configs\mx6q_tqcorec.h 添加以下:
#undef CONFIG_POWER_PFUZE100
#undef CONFIG_LDO_BYPASS_CHECK
board/freescale/mx6q_tqcorec/mx6q_tqcorec.c 添加宏定义:
#ifdef CONFIG_POWER_PFUZE100
int power_init_board(void)
{
//..........
}
#endif
重新编译运行,打印
U-Boot 2016.03 (Aug 28 2018 - 10:02:31 +0800)
CPU: Freescale i.MX6Q rev1.2 996 MHz (running at 792 MHz)
CPU: Extended Commercial temperature grade (-20C to 105C) at 33C
Reset cause: POR
Board: MX6-SabreSD
I2C: ready
DRAM: 2 GiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1, FSL_SDHC: 2
*** Warning - bad CRC, using default environment
No panel detected: default to Hannstar-XGA
Display: Hannstar-XGA (1024x768)
In: serial
Out: serial
Err: serial
switch to partitions #0, OK
mmc0 is current device
Net: Board Net Initialization Failed
No ethernet found.
Normal Boot
Hit any key to stop autoboot: 0
switch to partitions #0, OK
mmc0 is current device
reading boot.scr
** Unable to read file boot.scr **
reading zImage
** Unable to read file zImage **
Booting from net ...
No ethernet found.
No ethernet found.
Bad Linux ARM zImage magic!
=>
这里命令行提示符为"=> ",可以将之改为正式些的形式,在include/config_fallbacks.h 行79:
#ifndef CONFIG_SYS_PROMPT
#define CONFIG_SYS_PROMPT "=> "
#endif
uboot\include\configs\mx6q_tqcorec.h 定义命令行提示符:
#define CONFIG_SYS_PROMPT "TQCOREC > "
最后修改下board/freescale/mx6q_tqcorec/mx6q_tqcorec.c 定义Board名称:
int checkboard(void)
{
//puts("Board: MX6-SabreSD\n");
puts("Board: MX6Q_TQCOREC\n");
return 0;
}
根据打印log:
Net: Board Net Initialization Failed
No ethernet found.
问题跟踪:斜体样式
fecmxc_initialize_multi(bd, -1, CONFIG_FEC_MXC_PHYADDR,IMX_FEC_BASE);
int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
base_mii = addr;
bus = fec_get_miibus(base_mii, dev_id);
phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII);//执行到phydev直接返回
以下是log文件:
U-Boot 2016.03 (Aug 28 2018 - 14:22:29 +0800)
CPU: Freescale i.MX6Q rev1.2 996 MHz (running at 792 MHz)
CPU: Extended Commercial temperature grade (-20C to 105C) at 33C
Reset cause: POR
Board: MX6Q_TQCOREC
I2C: ready
DRAM: 2 GiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1, FSL_SDHC: 2
No panel detected: default to Hannstar-XGA
Display: Hannstar-XGA (1024x768)
In: serial
Out: serial
Err: serial
switch to partitions #0, OK
mmc0 is current device
Net: ------[eth_initialize]
--------[board_eth_init]
----------[cpu_eth_init]
------------[fecmxc_initialize]
--------------[fecmxc_initialize_multi]
--------------[fecmxc_initialize_multi] bus:-1896633888
--------------[fecmxc_initialize_multi] phydev:0
Board Net Initialization Failed
No ethernet found.
Normal Boot
Hit any key to stop autoboot: 0
TQCOREC >
解决问题:
在include/configs/mx6sabre_common.h 修改地址:
#define CONFIG_FEC_MXC_PHYADDR 0
setenv ethact FEC
setenv ethaddr 12:32:43:34:21:43
setenv ethprime FEC
setenv ipaddr 192.168.1.103
setenv netmask 255.255.255.0
setenv serverip 192.168.1.235
saveenv
LCD屏:TN92_7LCD_V1.02
AT070TN92 F(V02)_1103.pdf
board/freescale/mx6q_tqcorec/mx6q_tqcorec.c
struct display_info_t const displays[] = {
{
.bus = 0,
.addr = 0,
.pixfmt = IPU_PIX_FMT_RGB24,
.detect = NULL,
.enable = enable_rgb,
.mode = {
.name = "CLAA-WVGA",
.refresh = 57,
.xres = 800,
.yres = 480,
.pixclock = 37037,
.left_margin = 25,
.right_margin = 75,
.upper_margin = 10,
.lower_margin = 10,
.hsync_len = 20,
.vsync_len = 10,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED
} }
};
在board_video_skip中获取panel环境变量 arch/arm/imx-common/video.c:18:int board_video_skip(void)
setenv panel CLAA-WVGA
saveenv
现象:屏幕上显示logo,但是也显示了一个字符串:U-boot 2016.03 (Aug 28 2018 - 15:38:16 +0800)
问题跟踪:
uboot\drivers\video\cfb_console.c
static void *video_logo(void) {
sprintf(info, " %s", version_string);
video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);
}
解决问题:
#ifdef DISP_VERSION_STRING_ON_LCD
sprintf(info, " %s", version_string);
//......
video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);
#endif
include/configs/mx6q_tqcorec.h :
#undef DISP_VERSION_STRING_ON_LCD
以上工作之后的log文件:
U-Boot 2016.03 (Aug 28 2018 - 16:10:34 +0800)
CPU: Freescale i.MX6Q rev1.2 996 MHz (running at 792 MHz)
CPU: Extended Commercial temperature grade (-20C to 105C) at 32C
Reset cause: POR
Board: MX6Q_TQCOREC
I2C: ready
DRAM: 2 GiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1, FSL_SDHC: 2
Display: SEIKO-WVGA (800x480)
In: serial
Out: serial
Err: serial
switch to partitions #0, OK
mmc0 is current device
Net: FEC [PRIME]
Normal Boot
Hit any key to stop autoboot: 0
TQCOREC >
uboot的logo文件: tools/logos/freescale.bmp
emmc及启动情况
MMC初始化的位置: uboot\common\board_r.c
static int initr_mmc(void)
puts("MMC: ");
mmc_initialize(gd->bd); //uboot\drivers\mmc\mmc.c
ret = mmc_probe(bis);
if (board_mmc_init(bis) < 0) //board\freescale\mx6q_tqcorec\mx6q_tqcorec.c
cpu_mmc_init(bis);
board_mmc_init:
/*
* According to the board_mmc_init() the following map is done:
* (U-Boot device node) (Physical Port)
* mmc0 SD2
* mmc1 SD3
* mmc2 eMMC
*/
定义了mmc设备的数量: uboot\include\configs\mx6q_tqcorec.h
#define CONFIG_SYS_FSL_USDHC_NUM 3
主要是设置引脚复用,通过查看我们目标板的电路图得知,
我们的SD卡挂接在SD2_XX上,SD2_CD(GPIO_4)eMMC挂接在SD4_XX上。
static iomux_v3_cfg_t const usdhc2_pads[]
static iomux_v3_cfg_t const usdhc3_pads[] =
static iomux_v3_cfg_t const usdhc4_pads[] =
struct fsl_esdhc_cfg usdhc_cfg[3]:
USDHC2_BASE_ADDR
USDHC3_BASE_ADDR
USDHC4_BASE_ADDR
根据mmc_get_boot_dev的返回值指定mmcx设备,
例如mmc_get_boot_dev返回1,则是对应mmc0
int board_mmc_get_env_dev(int devno)
{
return devno - 1;
}
检测哪个mmc设备在使用
int board_mmc_getcd(struct mmc *mmc)
void env_relocate_spec(void) //uboot\common\env_mmc.c
int dev = mmc_get_env_dev();
mmc = find_mmc_device(dev);
errmsg = init_mmc_for_env(mmc);
mmc_get_env_addr(mmc, 0, &offset)
read_env(mmc, CONFIG_ENV_SIZE, offset, buf)
env_import(buf, 1);
查找mmc设备: uboot\drivers\mmc\mmc.c
struct mmc *find_mmc_device(int dev_num)
list_for_each(entry, &mmc_devices) {
m = list_entry(entry, struct mmc, link);
if (m->block_dev.dev == dev_num)
return m;
uboot\arch\arm\cpu\armv7\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);// 函数体内是return devno - 1;
}
uboot\arch\arm\cpu\armv7\mx6\soc.c
static int mmc_get_boot_dev(void):
/* BOOT_CFG2[3] and BOOT_CFG2[4] */
devno = (soc_sbmr & 0x00001800) >> 11;
return devno;//SD2启动返回1; EMMC启动返回3
BOOT_CFG2[4] BOOT_CFG2[3] MODE
0 1 SD2_BOOT
1 1 EMMC_BOOT
0 0 DownLoad
uboot网卡
uboot(2016.03)网卡移植(AR8035) UBOOT支持AR8035网卡
#define CONFIG_FEC_MXC //mx6sabre_common.h
obj-$(CONFIG_FEC_MXC) += fec_mxc.o //drivers/net/Makefile
board_init_r //arch/arm/lib/crt0.S
initr_net //CONFIG_CMD_NET //common/board_r.c
eth_initialize //net/eth_legacy.c
board_eth_init //board/freescale/mx6q_tqcorec/mx6q_tqcorec.c
cpu_eth_init //CONFIG_FEC_MXC //arch/arm/imx-common/cpu.c
fecmxc_initialize //CONFIG_FEC_MXC_PHYADDR //drivers/net/fec_mxc.c
fecmxc_initialize_multi //CONFIG_FEC_MXC_PHYADDR IMX_FEC_BASE
在eth_initialize中调用eth_common_init,eth_current_changed,board_eth_init。
eth_common_init中调用miiphy_init和phy_init。
miiphy_init需要定义defined(CONFIG_MII) || defined(CONFIG_CMD_MII) ||
defined(CONFIG_PHYLIB)
phy_init需要定义CONFIG_PHYLIB,其中phy_atheros_init需要定义CONFIG_PHY_ATHEROS
miiphy_init():初始化mii_devs链表,该列表中是一系列象征mac控制器,每个miid_dev表示一条mdio总线,可挂载多个phy设备。
phy_init():根据宏定义(例如CONFIG_PHY_REALTEK、CONFIG_PHY_ATHEROS等)初始化相应一个或多个系列网卡,
其中就有我们使用的aheros(AR8035)系列网卡。
eth_current_changed():初始化关于eth的一些uboot环境变量,这里我们不需要关心。
board_eth_init():网卡的板级初始化。
board_eth_init()中会执行setup_iomux_enet(),setup_pcie(),cpu_eth_init()三个函数。
其中setup_iomux_enet()函数配置网卡的rgmii接口,一般不用动这部分代码。
setup_pcie()配置板子pcie总线,具体这里也不用管。
cpu_eth_init()函数会做些网卡的芯片级初始化。
cpu_eth_init()只是调用了fecmx_initialize()函数,该函数中则只调用了fecmxc_initialize_multi(bd, -1, CONFIG_FEC_MXC_PHYADDR,
IMX_FEC_BASE);函数,该函数原型为int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr);
作用是初始化挂载在器件地址为phy_id的mdio上的所有phy芯片,具体实现颇复杂但也比较有意思,有兴趣的可以自行研究下,
这里我们知道这些就已经足够了,如此看来似乎phy_id这个参数名如果改为phy_addr会更容易理解些。
到这里我们也就已经获得了移植AR8035网卡所需要的所有信息,这里做个总结:
由步骤2得知为了注册AR8035的驱动,需要定义CONFIG_PHY_REALTEK宏,为了探测到MDIO上我们的phy芯片(AR8035),需要用调用fecmxc_initialize_multi(bd,-1,CONFIG_FEC_MXC_PHYADDR,IMX_FEC_BASE),
这里CONFIG_FEC_MXC_PHYADDR就是我们的网卡芯片的器件地址,可通过电路图得知我们的地址为0,也就是说需要把CONFIG_FEC_MXC_PHYADDR宏定义为数值0。