sdk-hwV1.3/lichee/brandy-2.0/spl/common/board_helper.c

241 lines
6.2 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <libfdt.h>
#include <common.h>
#include <boot_param.h>
#define FDT_DEBUG 0
#if FDT_DEBUG
#define FDT_DBG(fmt, arg...) printf("%s()%d - " fmt, __func__, __LINE__, ##arg)
#define FDT_ERR(fmt, arg...) printf("%s()%d - " fmt, __func__, __LINE__, ##arg)
#else
#define FDT_DBG(fmt, arg...)
#define FDT_ERR(fmt, arg...) printf("%s()%d - " fmt, __func__, __LINE__, ##arg)
#endif
#ifdef CFG_SUNXI_SDMMC
extern void mmc_update_config_for_sdly(void);
#endif
#ifndef CFG_SUNXI_ENV
#define ROOTFS_NAME "rootfs@"
#define ROOTFS_BACKUP_NAME "rootfs_backup@"
#define BLOCK_ROOTFS_NUM "root=/dev/"
/* During the first mass production,
* this area of the nor scheme is erased to 1,
* and the mmc scheme is erased to 0
* */
#ifdef CFG_SUNXI_SPINOR
#define USE_BACKUP_BIT_IS_ZERO 0x00
#elif CFG_SUNXI_SDMMC
#define USE_BACKUP_BIT_IS_ZERO 0xFF
#else
#define USE_BACKUP_BIT_IS_ZERO 0x00
#endif
//#define USE_BACKUP_IS_ZERO 0
#define KERNEL_AND_ROOTFS_MASK 0x01
#define ROOTFS_SWITCH_MASK 0x02
#define KERNEL_SWITCH_MASK 0x01
/* switch_flag default -- 0xff,
* value : 1 -- system 0 -- system_backup
* bit 1~7: reserve
* bit 0 : rootfs and kernel
*/
char get_switch_flag(void)
{
#ifdef CFG_BOOT0_LOAD_ISPPARM
char switch_flag = read_switch_flag_from_kernel();
#else
char switch_flag = 0xff;
#endif
switch_flag = (switch_flag && KERNEL_AND_ROOTFS_MASK)^USE_BACKUP_BIT_IS_ZERO;
FDT_DBG("switch_flag = 0x%x\n", switch_flag);
return switch_flag;
}
/* switch_flag default -- 0xff,
* value : 1 -- system 0 -- system_backup
* bit 3~7: reserve
* bit 2 extend partition/usr directory,boot0 not use,system use
* bit 1 : rootfs: 1:system 0:system_backup
* bit 0 : kernel, 1:system 0:system_backup
*/
char get_switch_kernel_flag(void)
{
#ifdef CFG_BOOT0_LOAD_ISPPARM
char switch_flag = read_switch_flag_from_kernel();
#else
char switch_flag = 0xff;
#endif
switch_flag = (switch_flag & KERNEL_SWITCH_MASK)^USE_BACKUP_BIT_IS_ZERO;
printf("switch_kernel_flag = 0x%x\n", switch_flag);
return switch_flag;
}
/* switch_flag default -- 0xff,
* value : 1 -- system 0 -- system_backup
* bit 3~7: reserve
* bit 2 extend partition/usr directory,boot0 not use,system use
* bit 1 : rootfs: 1:system 0:system_backup
* bit 0 : kernel, 1:system 0:system_backup
*/
#ifndef CFG_SUNXI_NO_UPDATE_FDT_CHOSEN
char get_switch_rootfs_flag(void)
{
#ifdef CFG_BOOT0_LOAD_ISPPARM
char switch_flag = read_switch_flag_from_kernel();
#else
char switch_flag = 0xff;
#endif
switch_flag = (switch_flag & ROOTFS_SWITCH_MASK)^USE_BACKUP_BIT_IS_ZERO;
printf("switch_rootfs_flag = 0x%x\n", switch_flag);
return switch_flag;
}
static void sunxi_switch_rootfs(char *rootfs_name)
{
u32 bootargs_node;
int len = 0;
int err;
char *bootargs_str = NULL;
char cmdline[512] = { 0 };
char temp_blocknum[32] = { 0 };
bootargs_node = fdt_path_offset(working_fdt, "/chosen");
bootargs_str = (void *)fdt_getprop(working_fdt, bootargs_node,
"bootargs", &len);
if (!bootargs_str) {
FDT_ERR("bootargs_str is NULL!!!\n");
}
char *rootfs_start = strstr(bootargs_str, rootfs_name);
if (!rootfs_start) {
FDT_ERR("cont find rootfs partition!!!\n");
}
/* The last partition of the sunxi platform is udisk */
char *rootfs_end = strchr(rootfs_start, ':');
if (!rootfs_end) {
FDT_DBG("error:cant find rootfs end\n");
}
char *spacer_symbol = strchr(rootfs_start, '@');
memcpy(temp_blocknum, spacer_symbol + 1,
rootfs_end - spacer_symbol -1);
FDT_DBG("temp_blocknum : %s\n", temp_blocknum);
char *blck_root_start = strstr(bootargs_str, BLOCK_ROOTFS_NUM);
if (!blck_root_start) {
FDT_ERR("cont find rootfs partition!!!\n");
}
char *blck_root_end = strchr(blck_root_start, ' ');
if (!blck_root_end) {
blck_root_end = bootargs_str + strlen(bootargs_str) - 1;
FDT_DBG("error:cant find rootfs end\n");
}
strncat(cmdline, bootargs_str, blck_root_start - bootargs_str);
strncat(cmdline, BLOCK_ROOTFS_NUM, sizeof(BLOCK_ROOTFS_NUM));
strncat(cmdline, temp_blocknum, sizeof(temp_blocknum));
strncat(cmdline, blck_root_end,
bootargs_str + strlen(bootargs_str) - blck_root_end);
FDT_DBG("cmdline:%s\nstrlen(cmdline = %d)\n", cmdline, strlen(cmdline));
err = fdt_setprop(working_fdt, bootargs_node, "bootargs", cmdline,
strlen(cmdline) + 1);
if (err < 0) {
printf("libfdt fdt_setprop(): %s\n", fdt_strerror(err));
return;
}
return;
}
static void sunxi_update_chosen(void)
{
if (get_switch_rootfs_flag()) {
sunxi_switch_rootfs(ROOTFS_NAME);
} else {
sunxi_switch_rootfs(ROOTFS_BACKUP_NAME);
}
}
#endif //CFG_SUNXI_NO_UPDATE_FDT_CHOSEN
#endif //CFG_SUNXI_GPT
__weak void mmc_update_config_for_sdly(void)
{
}
#ifdef CFG_SUNXI_BOOT_PARAM
extern int sprintf(char *buf, const char *fmt, ...);
int update_fdt_dram_para_from_bootpara(void *dtb_base)
{
/*fix dram para*/
int i, nodeoffset = 0;
char dram_str[16] = { 0 };
uint32_t *dram_para = NULL;
typedef_sunxi_boot_param *sunxi_boot_param = sunxi_bootparam_get_buf();
nodeoffset = fdt_path_offset(dtb_base, "/dram");
if (nodeoffset < 0) {
FDT_ERR("## error: %s : %s\n", __func__,
fdt_strerror(nodeoffset));
return -1;
}
dram_para = (uint32_t *)sunxi_boot_param->ddr_info;
memset(dram_str, 0, sizeof(dram_str));
for (i = MAX_DRAMPARA_SIZE - 1; i >= 0; i--) {
sprintf(dram_str, "dram_para[%02d]", i);
fdt_setprop_u32(dtb_base, nodeoffset, dram_str, dram_para[i]);
}
return 0;
}
#endif
int sunxi_update_fdt_para_for_kernel(void)
{
#ifdef CFG_USE_DCACHE
dcache_enable();
#endif
int err = fdt_check_header(working_fdt);
if (err < 0) {
printf("fdt_chosen: %s\n", fdt_strerror(err));
return err;
}
#ifndef CFG_SUNXI_NO_UPDATE_FDT_CHOSEN
sunxi_update_chosen();
#endif
#ifdef CFG_SUNXI_BOOT_PARAM
update_fdt_dram_para_from_bootpara(working_fdt);
#endif
#ifdef CFG_SUNXI_SDMMC
mmc_update_config_for_sdly();
#endif
#ifdef CFG_USE_DCACHE
dcache_disable();
#endif
printf("update dts\n");
return 0;
}
int fdt_enable_node(char *name, int onoff)
{
int nodeoffset = 0;
int ret = 0;
nodeoffset = fdt_path_offset(working_fdt, name);
ret = fdt_set_node_status(working_fdt, nodeoffset,
onoff ? FDT_STATUS_OKAY : FDT_STATUS_DISABLED, 0);
if (ret < 0) {
printf("disable nand error: %s\n", fdt_strerror(ret));
}
return ret;
}