TERES/SOFTWARE/A64-TERES/u-boot_new/board/sunxi/common/board_common.c
Dimitar Gamishev 093685c7d8 u-boot
2017-10-13 14:02:55 +03:00

570 lines
14 KiB
C

#include <common.h>
#include <spare_head.h>
#include <sunxi_mbr.h>
#include <boot_type.h>
#include <sys_partition.h>
#include <sys_config.h>
#include <sunxi_board.h>
#include <fastboot.h>
#include <android_misc.h>
#include <power/sunxi/pmu.h>
#include "debug_mode.h"
#include "sunxi_string.h"
#include "sunxi_serial.h"
#include "pine64_model.h"
#include "olimex_model.h"
#include <fdt_support.h>
#include <arisc.h>
DECLARE_GLOBAL_DATA_PTR;
#define PARTITION_SETS_MAX_SIZE 1024
void sunxi_update_subsequent_processing(int next_work)
{
printf("next work %d\n", next_work);
switch(next_work)
{
case SUNXI_UPDATE_NEXT_ACTION_REBOOT:
case SUNXI_UPDATA_NEXT_ACTION_SPRITE_TEST:
printf("SUNXI_UPDATE_NEXT_ACTION_REBOOT\n");
sunxi_board_restart(0);
break;
case SUNXI_UPDATE_NEXT_ACTION_SHUTDOWN:
printf("SUNXI_UPDATE_NEXT_ACTION_SHUTDOWN\n");
sunxi_board_shutdown();
break;
case SUNXI_UPDATE_NEXT_ACTION_REUPDATE:
printf("SUNXI_UPDATE_NEXT_ACTION_REUPDATE\n");
sunxi_board_run_fel();
break;
case SUNXI_UPDATE_NEXT_ACTION_BOOT:
case SUNXI_UPDATE_NEXT_ACTION_NORMAL:
default:
printf("SUNXI_UPDATE_NEXT_ACTION_NULL\n");
break;
}
return ;
}
void sunxi_fastboot_init(void)
{
struct fastboot_ptentry fb_part;
int index, part_total;
char partition_sets[PARTITION_SETS_MAX_SIZE];
char part_name[16];
char *partition_index = partition_sets;
int offset = 0;
int temp_offset = 0;
int storage_type = uboot_spare_head.boot_data.storage_type;
printf("--------fastboot partitions--------\n");
part_total = sunxi_partition_get_total_num();
if((part_total <= 0) || (part_total > SUNXI_MBR_MAX_PART_COUNT))
{
printf("mbr not exist\n");
return ;
}
printf("-total partitions:%d-\n", part_total);
printf("%-12s %-12s %-12s\n", "-name-", "-start-", "-size-");
memset(partition_sets, 0, PARTITION_SETS_MAX_SIZE);
for(index = 0; index < part_total && index < SUNXI_MBR_MAX_PART_COUNT; index++)
{
sunxi_partition_get_name(index, &fb_part.name[0]);
fb_part.start = sunxi_partition_get_offset(index) * 512;
fb_part.length = sunxi_partition_get_size(index) * 512;
fb_part.flags = 0;
printf("%-12s: %-12x %-12x\n", fb_part.name, fb_part.start, fb_part.length);
memset(part_name, 0, 16);
if(!storage_type)
{
sprintf(part_name, "nand%c", 'a' + index);
}
else
{
if(index == 0)
{
strcpy(part_name, "mmcblk0p2");
}
else if( (index+1)==part_total)
{
strcpy(part_name, "mmcblk0p1");
}
else
{
sprintf(part_name, "mmcblk0p%d", index + 4);
}
}
temp_offset = strlen(fb_part.name) + strlen(part_name) + 2;
if(temp_offset >= PARTITION_SETS_MAX_SIZE)
{
printf("partition_sets is too long, please reduces partition name\n");
break;
}
//fastboot_flash_add_ptn(&fb_part);
sprintf(partition_index, "%s@%s:", fb_part.name, part_name);
offset += temp_offset;
partition_index = partition_sets + offset;
}
partition_sets[offset-1] = '\0';
partition_sets[PARTITION_SETS_MAX_SIZE - 1] = '\0';
printf("-----------------------------------\n");
setenv("partitions", partition_sets);
}
#define ANDROID_NULL_MODE 0
#define ANDROID_FASTBOOT_MODE 1
#define ANDROID_RECOVERY_MODE 2
#define USER_SELECT_MODE 3
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
static int detect_other_boot_mode(void)
{
int ret1, ret2;
uint32_t key_high, key_low;
int keyvalue;
int nodeoffset;
keyvalue = gd->key_pressd_value;
printf("key %d\n", keyvalue);
char buf[8];
sprintf(buf, "%d", keyvalue);
setenv("boot_key", buf);
//check recovery key
nodeoffset = fdt_path_offset(working_fdt,FDT_PATH_RECOVERY_KEY);
if(nodeoffset >= 0)
{
ret1 = fdt_getprop_u32(working_fdt, nodeoffset, "key_max", &key_high);
ret2 = fdt_getprop_u32(working_fdt, nodeoffset, "key_min", &key_low);
if((ret1<0) || (ret2<0))
{
printf("recovery key:cant find key_max or key_min\n");
}
else
{
printf("recovery key high %d, low %d\n", key_high, key_low);
if((keyvalue >= key_low) && (keyvalue <= key_high))
{
printf("key found, android recovery\n");
return ANDROID_RECOVERY_MODE;
}
}
}
else
{
printf("cant find recovery value\n");
}
//check fast boot key
nodeoffset = fdt_path_offset(working_fdt,FDT_PATH_FASTBOOT_KEY);
if(nodeoffset >= 0)
{
ret1 = fdt_getprop_u32(working_fdt, nodeoffset, "key_max", &key_high);
ret2 = fdt_getprop_u32(working_fdt, nodeoffset, "key_min", &key_low);
if((ret1<0) || (ret2<0))
{
printf("fastboot key:cant find key_max or key_min\n");
}
else
{
printf("fastboot key high %d, low %d\n", key_high, key_low);
if((keyvalue >= key_low) && (keyvalue <= key_high))
{
printf("key found, android fastboot\n");
return ANDROID_FASTBOOT_MODE;
}
}
}
else
{
printf("cant find fastboot value\n");
}
return ANDROID_NULL_MODE;
}
int update_bootcmd(void)
{
int mode;
int pmu_value;
u32 misc_offset = 0;
char misc_args[2048];
char misc_fill[2048];
char boot_commond[256];
static struct bootloader_message *misc_message;
if(gd->force_shell)
{
char delaytime[8];
sprintf(delaytime, "%d", 3);
setenv("bootdelay", delaytime);
}
memset(boot_commond, 0x0, 128);
strcpy(boot_commond, getenv("bootcmd"));
printf("base bootcmd=%s\n", boot_commond);
if((uboot_spare_head.boot_data.storage_type == 1) || (uboot_spare_head.boot_data.storage_type == 2))
{
sunxi_str_replace(boot_commond, "setargs_nand", "setargs_mmc");
printf("bootcmd set setargs_mmc\n");
}
else
{
printf("bootcmd set setargs_nand\n");
}
//user enter debug mode by plug usb up to 3 times
if(debug_mode_get())
{
//if enter debug mode,set loglevel = 8
debug_mode_update_info();
return 0;
}
misc_message = (struct bootloader_message *)misc_args;
memset(misc_args, 0x0, 2048);
memset(misc_fill, 0xff, 2048);
mode = detect_other_boot_mode();
switch(mode)
{
case ANDROID_RECOVERY_MODE:
strcpy(misc_message->command, "boot-recovery");
break;
case ANDROID_FASTBOOT_MODE:
strcpy(misc_message->command, "bootloader");
break;
case ANDROID_NULL_MODE:
{
pmu_value = axp_probe_pre_sys_mode();
if(pmu_value == PMU_PRE_FASTBOOT_MODE)
{
puts("PMU : ready to enter fastboot mode\n");
strcpy(misc_message->command, "bootloader");
}
else if(pmu_value == PMU_PRE_RECOVERY_MODE)
{
puts("PMU : ready to enter recovery mode\n");
strcpy(misc_message->command, "boot-recovery");
}
else
{
misc_offset = sunxi_partition_get_offset_byname("misc");
debug("misc_offset = %x\n",misc_offset);
if(!misc_offset)
{
printf("no misc partition is found\n");
}
else
{
printf("misc partition found\n");
//read misc partition data
sunxi_flash_read(misc_offset, 2048/512, misc_args);
}
}
}
break;
}
if(!strcmp(misc_message->command, "efex"))
{
/* there is a recovery command */
puts("find efex cmd\n");
sunxi_flash_write(misc_offset, 2048/512, misc_fill);
sunxi_board_run_fel();
return 0;
}
else if(!strcmp(misc_message->command, "boot-resignature"))
{
puts("error: find boot-resignature cmd,but this cmd not implement\n");
//sunxi_flash_write(misc_offset, 2048/512, misc_fill);
//sunxi_oem_op_lock(SUNXI_LOCKING, NULL, 1);
}
else if(!strcmp(misc_message->command, "boot-recovery"))
{
if(!strcmp(misc_message->recovery, "sysrecovery"))
{
puts("recovery detected, will sprite recovery\n");
strncpy(boot_commond, "sprite_recovery", sizeof("sprite_recovery"));
sunxi_flash_write(misc_offset, 2048/512, misc_fill);
}
else
{
puts("Recovery detected, will boot recovery\n");
sunxi_str_replace(boot_commond, "boot_normal", "boot_recovery");
}
/* android recovery will clean the misc */
}
else if(!strcmp(misc_message->command, "bootloader"))
{
puts("Fastboot detected, will boot fastboot\n");
sunxi_str_replace(boot_commond, "boot_normal", "boot_fastboot");
if(misc_offset)
sunxi_flash_write(misc_offset, 2048/512, misc_fill);
}
else if(!strcmp(misc_message->command, "usb-recovery"))
{
puts("Recovery detected, will usb recovery\n");
sunxi_str_replace(boot_commond, "boot_normal", "boot_recovery");
}
else if(!strcmp(misc_message->command ,"debug_mode"))
{
puts("debug_mode detected ,will enter debug_mode");
if(0 == debug_mode_set())
{
debug_mode_update_info();
}
sunxi_flash_write(misc_offset,2048/512,misc_fill);
}
else
{
}
setenv("bootcmd", boot_commond);
printf("to be run cmd=%s\n", boot_commond);
return 0;
}
int update_fdt_para_for_kernel(void* dtb_base)
{
int ret;
int nodeoffset = 0;
int nodeoffset_emmc = 0;
int nodeoffset_nand = 0;
uint storage_type = 0;
//fix memory
ret = fdt_fixup_memory(dtb_base, gd->bd->bi_dram[0].start ,gd->bd->bi_dram[0].size);
if(ret < 0)
{
return -1;
}
storage_type = uboot_spare_head.boot_data.storage_type;
nodeoffset_emmc = fdt_path_offset(dtb_base, "mmc2");
nodeoffset_nand = fdt_path_offset(dtb_base, "nand0");
if(nodeoffset_emmc < 0 || nodeoffset_nand < 0)
{
printf("emmc or nand path error: %s\n", fdt_strerror(ret));
return -1;
}
//fix nand&sdmmc
if(storage_type == STORAGE_NAND)
{
ret = fdt_set_node_status(dtb_base,nodeoffset_emmc,FDT_STATUS_DISABLED,0);
if(ret < 0)
{
printf("disable emmc error: %s\n", fdt_strerror(ret));
return -1;
}
}
else if(storage_type == STORAGE_EMMC)
{
ret = fdt_set_node_status(dtb_base,nodeoffset_nand,FDT_STATUS_DISABLED,0);
if(ret < 0)
{
printf("disable nand error: %s\n", fdt_strerror(ret));
return -1;
}
}
else if(storage_type == STORAGE_SD)
{
uint32_t nand0_dragonboard = 0;
ret = fdt_getprop_u32(dtb_base,nodeoffset_nand,"nand0_dragonboard",&nand0_dragonboard);
if(ret<0 || nand0_dragonboard != 1)
{
ret = fdt_set_node_status(dtb_base,nodeoffset_nand,FDT_STATUS_DISABLED,0);
if(ret < 0)
{
printf("diable nand error: %s\n", fdt_strerror(ret));
return -1;
}
}
ret = fdt_set_node_status(dtb_base,nodeoffset_emmc,FDT_STATUS_DISABLED,0);
if(ret < 0)
{
printf("diable emmc error: %s\n", fdt_strerror(ret));
return -1;
}
}
//fix dram para
uint32_t *dram_para = NULL;
dram_para = (uint32_t *)uboot_spare_head.boot_data.dram_para;
puts("update dtb dram start\n");
nodeoffset = fdt_path_offset(dtb_base, "/dram");
if(nodeoffset<0)
{
printf("## error: %s : %s\n", __func__,fdt_strerror(ret));
return -1;
}
fdt_setprop_u32(dtb_base,nodeoffset, "dram_clk", dram_para[0]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_type", dram_para[1]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_zq", dram_para[2]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_odt_en", dram_para[3]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_para1", dram_para[4]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_para2", dram_para[5]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_mr0", dram_para[6]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_mr1", dram_para[7]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_mr2", dram_para[8]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_mr3", dram_para[9]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr0", dram_para[10]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr1", dram_para[11]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr2", dram_para[12]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr3", dram_para[13]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr4", dram_para[14]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr5", dram_para[15]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr6", dram_para[16]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr7", dram_para[17]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr8", dram_para[18]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr9", dram_para[19]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr10", dram_para[20]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr11", dram_para[21]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr12", dram_para[22]);
fdt_setprop_u32(dtb_base,nodeoffset, "dram_tpr13", dram_para[23]);
puts("update dtb dram end\n");
return 0;
}
int get_boot_work_mode(void)
{
return uboot_spare_head.boot_data.work_mode;
}
int get_boot_storage_type(void)
{
return uboot_spare_head.boot_data.storage_type;
}
/*
************************************************************************************************************
*
* function
*
* name : get_debugmode_flag
*
* parmeters :
*
* return :
*
* note : guoyingyang@allwinnertech.com
*
*
************************************************************************************************************
*/
int get_debugmode_flag(void)
{
int debug_mode = 0;
int nodeoffset;
if(get_boot_work_mode() != WORK_MODE_BOOT)
{
gd->debug_mode = 1;
return 0;
}
nodeoffset = fdt_path_offset(working_fdt, FDT_PATH_PLATFORM);
if(fdt_getprop_u32(working_fdt,nodeoffset,"debug_mode",(uint32_t*)&debug_mode) > 0)
{
gd->debug_mode = debug_mode;
}
else
{
gd->debug_mode = 1;
}
return 0;
}
static void sunxi_set_boot_disk(void)
{
switch(get_boot_storage_type())
{
case STORAGE_SD:
setenv("boot_disk", "0");
setenv("boot_part", "0:1");
break;
case STORAGE_EMMC:
setenv("boot_disk", "2");
setenv("boot_part", "2:1");
break;
default:
printf("storage not supported\n");
break;
}
}
int board_late_init(void)
{
int ret = 0;
if(get_boot_work_mode() == WORK_MODE_BOOT)
{
sunxi_fastboot_init();
sunxi_set_boot_disk();
update_bootcmd();
ret = update_fdt_para_for_kernel(working_fdt);
#ifdef CONFIG_SUNXI_SERIAL
sunxi_set_serial_num();
#endif
#ifdef CONFIG_PINE64_MODEL
pine64_set_model();
#endif
#ifdef CONFIG_OLIMEX_MODEL
olimex_set_model();
#endif
return 0;
}
else if(uboot_spare_head.boot_data.work_mode == 0x55)
{
printf("Running USB mass storage\n");
setenv("bootcmd", "sunxi_ums");
}
else if(uboot_spare_head.boot_data.work_mode == 0x56)
{
printf("Running USB mass storage\n");
setenv("bootcmd", "efex");
}
return ret;
}