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

241 lines
6.2 KiB
C
Raw Normal View History

2024-05-07 10:09:20 +00:00
#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;
}