最近移植了下u-boot-2014.10到tq335x,如果基于am335x evm进行移植,需要修改的地方并不多。
由于ti的am335x evm开发使用了一个eeprom保存了板载配置信息,用来区分不同板子的型号的,而tq335x没有这个eeprom,因此,需要修改eeprom相关的部分,使u-boot适应tq335x开发板。
使用source insight查看代码,很容易发现,所有获取板载配置的部分都是通过读取eeprom获得的,因此,首选修改read_eeprom(board/ti/am335x/board.c)函数,具体的修改如下:
static int read_eeprom(struct am335x_baseboard_id *header)
{
#if 1
strcpy(header->name, "tq335x");
#else
/* check if baseboard eeprom is available */
if (i2c_probe(config_sys_i2c_eeprom_addr)) {
puts("could not probe the eeprom; something fundamentally "
"wrong on the i2c bus.\n");
return -enodev;
}
/* read the eeprom using i2c */
if (i2c_read(config_sys_i2c_eeprom_addr, 0, 2, (uchar *)header,
sizeof(struct am335x_baseboard_id))) {
puts("could not read the eeprom; something fundamentally"
" wrong on the i2c bus.\n");
return -eio;
if (header->magic != 0xee3355aa) {
/*
* read the eeprom using i2c again,
* but use only a 1 byte address
*/
if (i2c_read(config_sys_i2c_eeprom_addr, 0, 1, (uchar *)header,
sizeof(struct am335x_baseboard_id))) {
puts("could not read the eeprom; something "
"fundamentally wrong on the i2c bus.\n");
return -eio;
}
if (header->magic != 0xee3355aa) {
printf("incorrect magic number (0x%x) in eeprom\n",
header->magic);
return -einval;
#endif
return 0;
}
通过上述修改,u-boot不去读取eeprom,而是直接将header的name赋值为"tq335x",后面可以根据这一配置区分是否为tq335x开发板。
然后是修改get_dpll_ddr_params(board/ti/am335x/board.c)函数,具体的修改内容如下:
const struct dpll_params *get_dpll_ddr_params(void)
struct am335x_baseboard_id header;
enable_i2c0_pin_mux();
i2c_init(config_sys_omap24_i2c_speed, config_sys_omap24_i2c_slave);
if (read_eeprom(&header) < 0)
puts("could not get board id.\n");
if (board_is_tq335x(&header) || board_is_evm_sk(&header))
return &dpll_ddr_evm_sk;
else if (board_is_bone_lt(&header))
return &dpll_ddr_bone_black;
else if (board_is_evm_15_or_later(&header))
else
return &dpll_ddr;
然后是修改sdram_init(board/ti/am335x/board.c)函数,具体的修改内容如下:
void sdram_init(void)
__maybe_unused struct am335x_baseboard_id header;
if (board_is_evm_sk(&header)) {
* evm sk 1.2a and later use gpio0_7 to enable ddr3.
* this is safe enough to do on older revs.
gpio_request(gpio_ddr_vtt_en, "ddr_vtt_en");
gpio_direction_output(gpio_ddr_vtt_en, 1);
if (board_is_evm_sk(&header) || board_is_tq335x(&header))
config_ddr(303, &ioregs_evmsk, &ddr3_data,
&ddr3_cmd_ctrl_data, &ddr3_emif_reg_data, 0);
config_ddr(400, &ioregs_bonelt,
&ddr3_beagleblack_data,
&ddr3_beagleblack_cmd_ctrl_data,
&ddr3_beagleblack_emif_reg_data, 0);
config_ddr(303, &ioregs_evm15, &ddr3_evm_data,
&ddr3_evm_cmd_ctrl_data, &ddr3_evm_emif_reg_data, 0);
config_ddr(266, &ioregs, &ddr2_data,
&ddr2_cmd_ctrl_data, &ddr2_emif_reg_data, 0);
然后添加board_is_tq335x函数的具体实现,参考其它类似函数实现即可,由于我们的read_eeprom仅读到了name,其内容是"tq335x",故可如下实现,在board/ti/am335x/board.h中添加如下内容:
static inline int board_is_tq335x(struct am335x_baseboard_id *header)
return !strncmp(header->name, "tq335x", hdr_name_len);
最后是修改enable_board_pin_mux(board/ti/am335x/mux.c)函数,具体的修改内容如下:
void enable_board_pin_mux(struct am335x_baseboard_id *header)
/* do board-specific muxes. */
if (board_is_bone(header) || board_is_tq335x(header)) {
/* beaglebone pinmux */
configure_module_pin_mux(i2c1_pin_mux);
configure_module_pin_mux(mii1_pin_mux);
configure_module_pin_mux(mmc0_pin_mux);
#if defined(config_nand)
configure_module_pin_mux(nand_pin_mux);
#elif defined(config_nor)
configure_module_pin_mux(bone_norcape_pin_mux);
configure_module_pin_mux(mmc1_pin_mux);
} else if (board_is_gp_evm(header)) {
/* general purpose evm */
unsigned short profile = detect_daughter_board_profile();
configure_module_pin_mux(rgmii1_pin_mux);
/* in profile #2 i2c1 and spi0 conflict. */
if (profile & ~profile_2)
configure_module_pin_mux(i2c1_pin_mux);
/* profiles 2 & 3 don't have nand */
#ifdef config_nand
if (profile & ~(profile_2 | profile_3))
configure_module_pin_mux(nand_pin_mux);
else if (profile == profile_2) {
configure_module_pin_mux(mmc1_pin_mux);
configure_module_pin_mux(spi0_pin_mux);
} else if (board_is_idk(header)) {
/* industrial motor control (idk) */
configure_module_pin_mux(mmc0_no_cd_pin_mux);
} else if (board_is_evm_sk(header)) {
/* starter kit evm */
configure_module_pin_mux(gpio0_7_pin_mux);
configure_module_pin_mux(mmc0_pin_mux_sk_evm);
} else if (board_is_bone_lt(header)) {
/* beaglebone lt pinmux */
} else {
puts("unknown board, cannot configure pinmux.");
hang();
另外,这个版本的u-boot有个bug,需要修改fat_register_device(fs/fat/fat.c)函数:
int fat_register_device(block_dev_desc_t *dev_desc, int part_no)
disk_partition_t info;
/* first close any currently found fat filesystem */
cur_dev = null;
/* read the partition table, if present */
if (get_partition_info(dev_desc, part_no, &info)) {
/*if (part_no != 0) {
printf("** partition %d not valid on device %d **\n",
part_no, dev_desc->dev);
return -1;
}*/
info.start = 0;
info.size = dev_desc->lba;
info.blksz = dev_desc->blksz;
info.name[0] = 0;
info.type[0] = 0;
info.bootable = 0;
#ifdef config_partition_uuids
info.uuid[0] = 0;
return fat_set_blk_dev(dev_desc, &info);
至此,u-boot就已经可以启动了,但是有多余的步骤和log,不过可以去掉,修改file_fat_read_at(fs/fat/fat.c)函数:
long file_fat_read_at(const char *filename, unsigned long pos, void *buffer,
unsigned long maxsize)
debug("reading %s\n", filename);
return do_fat_read_at(filename, pos, buffer, maxsize, ls_no, 0);
最后,tq335x是mlo启动u-boot,然后u-boot去启动内核,故可以去掉配置项config_spl_os_boot,具体的修改文件include/configs/ti_armv7_common.h:
#if defined(config_spl_os_boot_enable)
#define config_spl_os_boot
至此,u-boot的移植工作就完成了,编译方法如下:
make arch=arm cross_compile=arm-linux-gnueabi- am335x_evm_defconfig
make arch=arm cross_compile=arm-linux-gnueabi- -j8
其中,arm-linux-gnueabi-需要根据自己的交叉编译工具链前缀进行修改。完成u-boot的移植工作后我们来研究如何启动内核。
源码下载地址:
<a target="_blank" href="http://download.csdn.net/detail/girlkoo/8316233">u-boot-2014.10 for tq335x/tq3358(sd卡启动)</a>