sdk-hwV1.3/lichee/brandy-2.0/u-boot-2018/board/sunxi/board_helper.c

1210 lines
32 KiB
C

/* SPDX-License-Identifier: GPL-2.0+
* (C) Copyright 2018-2020
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* wangwei <wangwei@allwinnertech.com>
*
* Some init for sunxi platform.
*/
#include <common.h>
#include <asm/io.h>
#include <sunxi_board.h>
#include <sunxi_flash.h>
#include <fdt_support.h>
#include <fs.h>
#include <blk.h>
#include <part.h>
#include <asm/arch/rtc.h>
#include <asm/arch/dram.h>
#include <private_uboot.h>
#include <asm/arch/efuse.h>
#include <sunxi_nand.h>
#include <android_misc.h>
#include <android_ab.h>
#include <sys_partition.h>
#include <sys_config.h>
#include <sunxi-ir.h>
#include <smc.h>
#include <mmc.h>
#include <linux/mtd/aw-spinand.h>
#include <boot_gui.h>
#include "../../drivers/spi/spi-sunxi.h"
#include "../../drivers/spi/spif-sunxi.h"
#include <asm/arch/ce.h>
#ifdef CONFIG_SUNXI_PMU_EXT
#include <sunxi_power/power_manage.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
/*define ir or key mode value*/
#define EFEX_VALUE (0x81)
#define SPRITE_RECOVERY_VALUE (0X82)
#define BOOT_RECOVERY_VALUE (0x83)
#define BOOT_FACTORY_VALUE (0x84)
#define PARTITION_SETS_MAX_SIZE 1024
#define PARTITION_NAME_MAX_SIZE 16
#define ROOT_PART_NAME_MAX_SIZE (PARTITION_NAME_MAX_SIZE + 5)
#define DEV_PART_NAME_MAX_SIZE (PARTITION_NAME_MAX_SIZE + sizeof("/dev/"))
/* only 32 bytes len supported only*/
#define CE_TRNG_32BYTE_ALIGNED 32
int __attribute__((weak)) update_pmu_ext_info_to_kernel()
{
return 0;
}
int __attribute__((weak)) update_no_ext_info_to_kernel()
{
return 0;
}
int disp_lcd_param_update_to_kernel(void);
int update_fdt_dram_para(void *dtb_base)
{
/*fix dram para*/
int i, nodeoffset = 0;
char dram_str[16] = {0};
uint32_t *dram_para = NULL;
dram_para = (uint32_t *)uboot_spare_head.boot_data.dram_para;
pr_msg("(weak)update dtb dram start\n");
gd->bd->bi_dram[0].size = (phys_size_t)uboot_spare_head.boot_data.dram_scan_size * 1024 * 1024;
if (arch_fixup_fdt(dtb_base) < 0) {
printf("ERROR: arch-specific fdt fixup failed\n");
return -1;
}
nodeoffset = fdt_path_offset(dtb_base, "/dram");
if (nodeoffset < 0) {
pr_err("## error: %s : %s\n", __func__, fdt_strerror(nodeoffset));
return -1;
}
for (i = 31; i >= 0; i--) {
sprintf(dram_str, "dram_para[%02d]", i);
fdt_setprop_u32(dtb_base, nodeoffset, dram_str, dram_para[i]);
}
pr_msg("update dtb dram end\n");
return 0;
}
static 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;
}
int disp_fat_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
loff_t read;
loff_t read_len = 0;
ulong addr = 0;
if (argc < 5)
return -1;
if (argc >= 6)
read_len = simple_strtoul(argv[5], NULL, 16);
addr = simple_strtoul(argv[3], NULL, 16);
fs_set_blk_dev(argv[1], argv[2], FS_TYPE_FAT);
return fs_read(argv[4], (ulong)addr, 0, read_len, &read);
}
void sunxi_dump(void *addr, unsigned int size)
{
#if 1
print_buffer((ulong)addr, addr, 1, ALIGN(size, 16)/1, 16/1);
#else
int i, j;
char *buf = (char *)addr;
for (j = 0; j < size; j += 16) {
for (i = 0; (i < 16 && i < size); i++) {
printf("%02x ", buf[j + i] & 0xff);
}
printf("\n");
}
printf("\n");
#endif
return;
}
/*
* name : sunxi_str_replace
* fucntion: replace a word in string which separated by a space
* note : sunxi_str_replace("abc def gh", "def", "replace") get "abc replace gh"
*/
static int sunxi_str_replace(char *dest_buf, char *goal, char *replace)
{
char tmp[128];
char tmp_str[16];
int goal_len, rep_len, dest_len;
int i, j, k;
if( (goal == NULL) || (dest_buf == NULL))
return -1;
memset(tmp, 0, 128);
strcpy(tmp, dest_buf);
goal_len = strlen(goal);
dest_len = strlen(dest_buf);
if(replace != NULL)
rep_len = strlen(replace);
else
rep_len = 0;
j = 0;
for(i=0;tmp[i];) {
k = 0;
while(((tmp[i] != ' ') && (tmp[i] != 0) )|| (tmp[i+1] == ' '))
{
tmp_str[k++] = tmp[i];
i ++;
if(i >= dest_len)
break;
}
i ++;
tmp_str[k] = 0;
if(!strcmp(tmp_str, goal))
{
if(rep_len)
{
strcpy(dest_buf + j, replace);
if(tmp[j + goal_len])
{
memcpy(dest_buf + j + rep_len, tmp + j + goal_len, dest_len - j - goal_len);
dest_buf[dest_len - goal_len + rep_len] = 0;
}
}
else
{
if(tmp[j + goal_len])
{
memcpy(dest_buf + j, tmp + j + goal_len, dest_len - j - goal_len);
dest_buf[dest_len - goal_len + rep_len] = 0;
}
}
return 0;
}
j = i;
}
return 0;
}
int sunxi_str_replace_all(char *dest_buf, char *goal, char *replace)
{
char tmp[128];
char tmp_str[16];
int goal_len, rep_len, dest_len;
int i, j = 0, k;
char first_flag = 0;
if ((goal == NULL) || (dest_buf == NULL)) {
return -1;
}
memset(tmp, 0, 128);
strcpy(tmp, dest_buf);
goal_len = strlen(goal);
dest_len = strlen(dest_buf);
if (replace != NULL) {
rep_len = strlen(replace);
} else {
rep_len = 0;
}
for (i = 0 ; tmp[i] ;) {
k = 0;
while (((tmp[i] != ' ') && (tmp[i] != ';') && (tmp[i] != 0)) || (tmp[i+1] == ' ')) {
tmp_str[k++] = tmp[i];
i++;
if (i >= dest_len)
break;
}
i++;
tmp_str[k] = 0;
if (!strcmp(tmp_str, goal)) {
if (rep_len != 0 && first_flag == 1)
j += (rep_len - goal_len);
if (rep_len) {
strcpy(dest_buf + j, replace);
if (tmp[j + goal_len]) {
memcpy(dest_buf + j + rep_len, tmp + j + goal_len, dest_len - j - goal_len);
dest_buf[dest_len - goal_len + rep_len] = 0;
}
} else {
if (tmp[j + goal_len]) {
memcpy(dest_buf + j, tmp + j + goal_len, dest_len - j - goal_len);
dest_buf[dest_len - goal_len + rep_len] = 0;
}
}
first_flag = 1;
}
j = i;
}
return 0;
}
static int write_recovery_msg_to_misc(char *recovery_msg)
{
u32 misc_offset = 0;
char misc_args[2048];
static struct bootloader_message *misc_message;
int ret;
memset(misc_args, 0x0, 2048);
misc_message = (struct bootloader_message *)misc_args;
misc_offset = sunxi_partition_get_offset_byname("misc");
if (!misc_offset) {
printf("no misc partition\n");
return 0;
}
ret = sunxi_flash_read(misc_offset, 2048 / 512, misc_args);
if (!ret) {
printf("error: read misc partition\n");
return 0;
}
if (!strcmp("ir-or-key-recovery", (const char *)recovery_msg)) {
strcpy(misc_message->command, "boot-recovery");
} else if (!strcmp("ir-factory", (const char *)recovery_msg)) {
strcpy(misc_message->command, "boot-recovery");
strcpy(misc_message->recovery,
"recovery\n--wipe_data\n--locale=zh_CN\n");
} else if (!strcmp("ir-efex", (const char *)recovery_msg)) {
strcpy(misc_message->command, "efex");
} else if (!strcmp("sysrecovery", (const char *)recovery_msg)) {
strcpy(misc_message->command, "sysrecovery");
/* strcpy(misc_message->recovery, "sysrecovery"); */
} else if (!strcmp("erase_misc", (const char *)recovery_msg)) {
memset(misc_args, 0x0, 2048);
}
sunxi_flash_write(misc_offset, 2048 / 512, misc_args);
return 0;
}
#ifdef CONFIG_RECOVERY_KEY
#define RECOVERY_KEY_EFEX_MODE (0x0)
#define RECOVERY_KEY_ONEKEY_SPRITE_RECOVERY_MODE (0x1)
#define RECOVERY_KEY_RECOVERY_MODE (0x2)
#define RECOVERY_KEY_FACTORY_MODE (0x3)
#define RECOVERY_KEY_EFEX_VALUE (0x81)
#define RECOVERY_KEY_SPRITE_RECOVERY_VALUE (0X82)
#define RECOVERY_KEY_BOOT_RECOVERY_VALUE (0x83)
#define RECOVERY_KEY_BOOT_FACTORY_VALUE (0x84)
#define KEY_PRESS_MODE_DISABLE (0X0)
#define KEY_PRESS_MODE_ENABLE (0x1)
#define KEY_BOOT_RECOVERY "/soc/key_boot_recovery"
#ifdef RECOVERY_KEY_DEBUG
#define key_info(fmt...) tick_printf(fmt)
#else
#define key_info(fmt...)
#endif
int check_recovery_key(void)
{
user_gpio_set_t gpio_recovery;
__u32 gpio_hd;
int ret;
int gpio_value = 0;
int used = 0;
int mode = 0;
int press_mode = 0;
int press_time = 0;
if (get_boot_work_mode() == WORK_MODE_BOOT) {
/*check physical gpio pin*/
ret = script_parser_fetch(KEY_BOOT_RECOVERY, "recovery_key_used",
(int *)&used, sizeof(int) / 4);
if (ret || !used) {
key_info("[key recovery] no use\n");
return 0;
}
ret = fdt_get_one_gpio(KEY_BOOT_RECOVERY, "recovery_key", &gpio_recovery);
if (ret) {
key_info("[key recovery] can't find recovery_key config.\n");
return 0;
}
gpio_recovery.mul_sel = 0; /*forced to input*/
gpio_hd = sunxi_gpio_request(&gpio_recovery, 1);
if (!gpio_hd) {
pr_error("[key recovery] gpio request fail!\n");
return 0;
/*gpio request fail,just return.*/
}
int time;
gpio_value = 0;
for (time = 0; time < 5; time++) {
gpio_value += gpio_read_one_pin_value(gpio_hd, 0);
mdelay(1);
}
if (gpio_value) {
key_info("[key recovery] no key press.\n");
return 0;
/*no recovery key was pressed, just return.*/
}
key_info("[key recovery] find the key\n");
script_parser_fetch(KEY_BOOT_RECOVERY, "press_mode_enable",
(int *)&press_mode, sizeof(int) / 4);
if (press_mode == KEY_PRESS_MODE_DISABLE) {
script_parser_fetch(KEY_BOOT_RECOVERY, "key_work_mode",
(int *)&mode, sizeof(int) / 4);
key_info("[key recovery] do not use prese mode, \
key_work_mode = %d\n", mode);
} else if (press_mode == KEY_PRESS_MODE_ENABLE) {
script_parser_fetch(KEY_BOOT_RECOVERY, "key_press_time",
(int *)&press_time, sizeof(int) / 4);
key_info("[key recovery] use prese mode, \
and key_press_time = %d ms\n", press_time);
gpio_value = 0;
for (time = press_time; time > 0; time -= 100) {
mdelay(100); /*detect key value per 100ms*/
gpio_value += gpio_read_one_pin_value(gpio_hd, 0);
/*key was loosed during press time,will not detect key value any more*/
if (gpio_value)
break;
}
/*key was lossed during press time, so use short_press_mode*/
if (gpio_value) {
script_parser_fetch(KEY_BOOT_RECOVERY, "short_press_mode",
(int *)&mode, sizeof(int) / 4);
key_info("[key recovery] key short press, short_press_mode = %d\n", mode);
} else {
/*key was always pressed in key_press_time, so use long_press_mode*/
script_parser_fetch(KEY_BOOT_RECOVERY, "long_press_mode",
(int *)&mode, sizeof(int) / 4);
key_info("[key recovery] key long press, long_press_mode = %d\n", mode);
}
}
switch (mode) {
case RECOVERY_KEY_EFEX_MODE:
gd->key_pressd_value = RECOVERY_KEY_EFEX_VALUE;
break;
case RECOVERY_KEY_ONEKEY_SPRITE_RECOVERY_MODE:
gd->key_pressd_value = RECOVERY_KEY_SPRITE_RECOVERY_VALUE;
break;
case RECOVERY_KEY_RECOVERY_MODE:
gd->key_pressd_value = RECOVERY_KEY_BOOT_RECOVERY_VALUE;
break;
case RECOVERY_KEY_FACTORY_MODE:
gd->key_pressd_value = RECOVERY_KEY_BOOT_FACTORY_VALUE;
break;
default:
gd->key_pressd_value = RECOVERY_KEY_BOOT_RECOVERY_VALUE;
break;
}
}
return 0;
}
#endif
void sunxi_respond_ir_key_action(void)
{
int key_value;
#ifdef CONFIG_IR_BOOT_RECOVERY
int ir_time_out = get_timer_masked();
while (get_timer_masked() - ir_time_out < 200) {
if (gd->ir_detect_status != IR_DETECT_NULL)
break;
}
ir_disable();
#endif
key_value = gd->key_pressd_value;
/* //ir factory or key factory */
if (key_value == 0) {
return;
} else if (key_value == BOOT_FACTORY_VALUE) {
printf("[boot factory] set misc : boot factory and wipe data\n");
write_recovery_msg_to_misc("ir-factory");
} else if (key_value == EFEX_VALUE) {
/* //ir efex or key efex */
printf("[boot efex] set misc : boot efex\n");
write_recovery_msg_to_misc("ir-efex");
} else if (key_value == SPRITE_RECOVERY_VALUE) {
/* //ir sprite recovery */
printf("[ir sysrecovery] set misc : boot recovery and sysrecovery \n");
write_recovery_msg_to_misc("sysrecovery");
} else if (key_value == BOOT_RECOVERY_VALUE) {
/* //ir recovery or key recovery */
printf("[boot recovery] set misc : boot recovery\n");
write_recovery_msg_to_misc("ir-or-key-recovery");
}
}
#ifndef CONFIG_BOOTCMD_SKIP_RTC
static int sunxi_get_bootcmd_from_rtc(void)
{
u8 bootmode_flag = 0;
bootmode_flag = rtc_get_bootmode_flag();
/*clear rtc*/
rtc_set_bootmode_flag(0);
switch (bootmode_flag) {
case SUNXI_EFEX_CMD_FLAG:
return SUNXI_EFEX_CMD_FLAG;
case SUNXI_BOOT_RECOVERY_FLAG:
return SUNXI_BOOT_RECOVERY_FLAG;
case SUNXI_FASTBOOT_FLAG:
return SUNXI_FASTBOOT_FLAG;
case SUNXI_UBOOT_FLAG:
return SUNXI_UBOOT_FLAG;
default:
return 0;
break;
}
}
#endif
#ifndef CONFIG_BOOTCMD_SKIP_ADCKEY
static int sunxi_get_bootcmd_from_adckey(void)
{
typedef struct adc_key_info {
char *key_type;
u32 key_flag;
} _adc_key_info;
int key_high, key_low;
int keyvalue, i;
char key_mode[16] = {0};
_adc_key_info key_info_table[] = {
{"recovery", SUNXI_BOOT_RECOVERY_FLAG},
{"fastboot", SUNXI_FASTBOOT_FLAG},
{"fel", SUNXI_EFEX_CMD_FLAG},
};
keyvalue = uboot_spare_head.boot_data.key_input;
pr_msg("key %d\n", keyvalue);
if (keyvalue) {
for (i = 0; i < sizeof(key_info_table)/sizeof(key_info_table[0]); i++) {
sprintf(key_mode, "/soc/%s_key", key_info_table[i].key_type);
script_parser_fetch(key_mode, "key_max", &key_high, 0);
script_parser_fetch(key_mode, "key_min", &key_low, 0);
if (key_high || key_low) {
pr_notice("%s key high %d, low %d\n", key_info_table[i].key_type, key_high, key_low);
if ((keyvalue >= key_low) && (keyvalue <= key_high)) {
pr_notice("key found, android %s\n", key_info_table[i].key_type);
return key_info_table[i].key_flag;
}
}
}
}
return 0;
}
#endif
#ifndef CONFIG_BOOTCMD_SKIP_MISC
static int sunxi_get_bootcmd_from_misc(void)
{
u32 misc_offset = 0;
char misc_args[2048];
char misc_fill[2048];
struct bootloader_message *misc_message;
int misc_mode;
misc_message = (struct bootloader_message *)misc_args;
memset(misc_args, 0x0, 2048);
memset(misc_fill, 0xff, 2048);
misc_offset = sunxi_partition_get_offset_byname("misc");
if (!misc_offset) {
pr_msg("no misc partition is found\n");
return 0;
} else {
pr_msg("misc partition found\n");
sunxi_flash_read(misc_offset, 2048 / 512, misc_args);
}
if (strstr((const char *)misc_message->command, "efex")) {
misc_mode = SUNXI_EFEX_CMD_FLAG;
/*"sysrecovery" must judge before "recovery" !!!*/
} else if (strstr((const char *)misc_message->command, "sysrecovery")) {
misc_mode = SUNXI_SYS_RECOVERY_FLAG;
} else if (strstr((const char *)misc_message->command, "recovery")) {
misc_mode = SUNXI_BOOT_RECOVERY_FLAG;
} else if (strstr((const char *)misc_message->command, "bootloader")) {
misc_mode = SUNXI_FASTBOOT_FLAG;
} else if (strstr((const char *)misc_message->command, "uboot")) {
misc_mode = SUNXI_UBOOT_FLAG;
} else {
misc_mode = 0;
}
if ((misc_mode) || *(misc_message->recovery))
print_buffer((ulong)misc_args, misc_args, 4, 0x50, 4);
if (strstr((const char *)misc_message->recovery, "update_package") ==
NULL) {
memset(misc_message->command, 0x0,
sizeof(misc_message->command));
sunxi_flash_write(misc_offset, 2048 / 512, misc_args);
sunxi_flash_flush();
}
return misc_mode;
}
#endif
int sunxi_set_bootcmd(char *bootcmd)
{
int i, bootmode[4] = {0};
env_set_hex("force_normal_boot", 1);
#ifndef CONFIG_BOOTCMD_SKIP_ADCKEY
bootmode[1] = sunxi_get_bootcmd_from_adckey();
#endif
#ifndef CONFIG_BOOTCMD_SKIP_RTC
bootmode[2] = sunxi_get_bootcmd_from_rtc();
#endif
#ifndef CONFIG_BOOTCMD_SKIP_MISC
bootmode[3] = sunxi_get_bootcmd_from_misc();
#endif
for (i = 1; i < sizeof(bootmode)/sizeof(bootmode[0]); i++) {
if (bootmode[i]) {
bootmode[0] = bootmode[i];
tick_printf("bootmode[%d]:0x%x\n", i, bootmode[i]);
break;
}
}
switch (bootmode[0]) {
case SUNXI_EFEX_CMD_FLAG:
sunxi_board_run_fel();
break;
case SUNXI_SYS_RECOVERY_FLAG:
set_boot_work_mode(WORK_MODE_SPRITE_RECOVERY);
env_set("sysrecovery", "sprite_test");
strncpy(bootcmd, "run sysrecovery",
sizeof("run sysrecovery"));
break;
case SUNXI_BOOT_RECOVERY_FLAG:
if (sunxi_partition_get_offset_byname("recovery")) {
sunxi_str_replace(bootcmd, "boot_normal", "boot_recovery");
}
env_set_hex("force_normal_boot", 0);
break;
case SUNXI_FASTBOOT_FLAG:
sunxi_str_replace(bootcmd, "boot_normal", "boot_fastboot");
break;
case SUNXI_UBOOT_FLAG:
sunxi_set_uboot_shell(1);
break;
default:
break;
}
return 0;
}
int sunxi_update_bootcmd(void)
{
char boot_commond[128];
int storage_type = get_boot_storage_type();
memset(boot_commond, 0x0, 128);
strncpy(boot_commond, env_get("bootcmd"), sizeof(boot_commond)-1);
debug("base bootcmd=%s\n", boot_commond);
if ((storage_type == STORAGE_SD) || (storage_type == STORAGE_EMMC) ||
(storage_type == STORAGE_EMMC3) || (storage_type == STORAGE_EMMC0)) {
sunxi_str_replace(boot_commond, "setargs_nand", "setargs_mmc");
debug("bootcmd set setargs_mmc\n");
} else if (storage_type == STORAGE_NOR) {
sunxi_str_replace(boot_commond, "setargs_nand", "setargs_nor");
} else if (storage_type == STORAGE_NAND) {
#ifdef CONFIG_SUNXI_UBIFS
#ifndef CONFIG_MACH_SUN8IW18
if (nand_use_ubi()) {
sunxi_str_replace(boot_commond, "setargs_nand", "setargs_nand_ubi");
debug("bootcmd set setargs_nand_ubi\n");
}
#endif
#else
debug("bootcmd set setargs_nand\n");
#endif
}
sunxi_set_bootcmd(boot_commond);
env_set("bootcmd", boot_commond);
#ifdef CONFIG_ANDROID_AB
/*determine whether it is ab-system according to the boot_a partition*/
if (sunxi_partition_get_offset_byname("boot_a")) {
if (ab_select_slot_from_partname("misc") == 1) {
env_set("slot_suffix", "_b");
} else {
env_set("slot_suffix", "_a");
}
}
#endif
debug("to be run cmd=%s\n", boot_commond);
tick_printf("update bootcmd\n");
return 0;
}
struct os_memory_info_t {
uint64_t shm_base;
uint32_t shm_size;
uint64_t ta_ram_base;
uint32_t ta_ram_size;
uint64_t tee_ram_base;
uint32_t tee_ram_size;
} static os_memory_info;
int secure_os_memory_init(void)
{
//some platforms uboot and kernel use different fdt
//so dont add reserve memory until we are updating
//kernel fdt, save the values for now
#if defined(CONFIG_SUNXI_EXTERN_SECURE_MM_LAYOUT)
script_parser_fetch("/firmware/optee", "shm_base",
(int *)&os_memory_info.shm_base, 0);
script_parser_fetch("/firmware/optee", "shm_size",
(int *)&os_memory_info.shm_size, 0);
script_parser_fetch("/firmware/optee", "ta_ram_base",
(int *)&os_memory_info.ta_ram_base, 0);
script_parser_fetch("/firmware/optee", "ta_ram_size",
(int *)&os_memory_info.ta_ram_size, 0);
#endif
script_parser_fetch("/firmware/optee", "tee_ram_base",
(int *)&os_memory_info.tee_ram_base, 0);
script_parser_fetch("/firmware/optee", "tee_ram_size",
(int *)&os_memory_info.tee_ram_size, 0);
return 0;
}
#if defined CONFIG_SUN50IW9_AUTOPRINT
int check_printmode(void)
{
u32 reg, data;
reg = readl(0x0300B0B4);
data = reg & (0x7 << 16);
data |= reg & (0x7 << 8);
/* if PF2 --> TX, PF4 --> RX */
if (data == 0x00030300) {
pr_info(" card print\n");
return 1;
}
return 0;
}
int open_autoprint(void)
{
int nodeoffset, err;
nodeoffset = fdt_path_offset(working_fdt, "/soc/auto_print");
if (nodeoffset < 0) {
pr_err("libfdt fdt_path_offset() returned %s\n",
fdt_strerror(nodeoffset));
return -1;
}
err = fdt_setprop_string(working_fdt, nodeoffset, "status", "okay");
if (err < 0) {
pr_warn("WARNING: fdt_setprop can't set %s from node %s: %s\n",
"compatible", "status", fdt_strerror(err));
return -1;
}
return 0;
}
#endif
#ifdef CONFIG_SUNXI_KASLR_SEED
int update_fdt_kaslr_seed(void *dtb_base)
{
int nodeoffset = 0;
u64 *temp64;
int err;
//===========update================
u32 src[8];
sunxi_ss_open();
sunxi_trng_gen((u8 *)src, CE_TRNG_32BYTE_ALIGNED);
/* sunxi_dump((u8 *)src, CE_TRNG_32BYTE_ALIGNED); */
nodeoffset = fdt_find_or_add_subnode(dtb_base, 0, "chosen");
if (nodeoffset < 0) {
pr_err("## error: %s \n", __func__);
return nodeoffset;
}
temp64 = (u64 *)src;
err = fdt_setprop_u64(dtb_base, nodeoffset, "kaslr-seed", *temp64);
if (err < 0) {
pr_err("WARNING: could not set kaslr-seed %s.\n",
fdt_strerror(err));
return err;
}
return 0;
}
void board_kaslr_seed(void)
{
tick_printf("update_fdt_kaslr_seed\n");
update_fdt_kaslr_seed(working_fdt);
}
#endif
int get_dragonboard_test(struct fdt_header *point_fdt,
uint32_t *dragon_board_test)
{
int nodeoffset, err;
nodeoffset = fdt_path_offset(point_fdt, "/soc/platform");
if (nodeoffset < 0) {
pr_err("libfdt fdt_path_offset() returned %s\n",
fdt_strerror(nodeoffset));
return -1;
}
err = fdt_getprop_u32(point_fdt, nodeoffset, "dragonboard_test",
dragon_board_test);
if (err < 0) {
printf("get value error\n");
return -1;
}
return 0;
}
int sunxi_update_fdt_para_for_kernel(void)
{
uint storage_type = 0;
__maybe_unused int ret = 0;
#ifdef CONFIG_SUNXI_SDMMC
struct mmc *mmc = NULL;
int dev_num = 0;
#endif
storage_type = get_boot_storage_type_ext();
#ifdef CONFIG_SUNXI_SDMMC
/* update sdhc dbt para */
if (storage_type == STORAGE_EMMC || storage_type == STORAGE_EMMC3
|| (storage_type == STORAGE_EMMC0)) {
if (storage_type == STORAGE_EMMC)
dev_num = 2;
else if (storage_type == STORAGE_EMMC0)
dev_num = 0;
else
dev_num = 3;
// dev_num = (storage_type == STORAGE_EMMC) ? 2 : 3;
mmc = find_mmc_device(dev_num);
if (mmc == NULL) {
printf("can't find valid mmc %d\n", dev_num);
return -1;
}
if (mmc->cfg->sample_mode == AUTO_SAMPLE_MODE) {
mmc_update_config_for_sdly(mmc);
}
}
#endif
/* creat udc dbt para when in charger_mode */
if (gd->chargemode == 1) {
fdt_find_and_setprop(working_fdt, "/soc/udc-controller",
"charger_mode", NULL, 0, 1);
}
/* fix nand&sdmmc */
switch (storage_type) {
case STORAGE_NAND:
fdt_enable_node("nand0", 1);
fdt_enable_node("spi0", 0);
break;
case STORAGE_SPI_NAND:
#ifdef CONFIG_SUNXI_UBIFS
#ifdef CONFIG_MACH_SUN8IW18
if (nand_use_ubi() == 0) {
/* sun8iw18 aw-nftl config */
fdt_enable_node("spinand", 1);
fdt_enable_node("spi0", 0);
}
#else
/* sun50iw11 config */
fdt_enable_node("spi0", 1);
fdt_enable_node("/soc/spi/spi-nand", 1);
#endif
#else
/* legacy config */
fdt_enable_node("spinand", 1);
fdt_enable_node("spi0", 0);
#endif
break;
case STORAGE_EMMC:
fdt_enable_node("mmc2", 1);
fdt_enable_node("sunxi-mmc2", 1);
#ifdef CONFIG_SUNXI_SDMMC
mmc_set_mmcblckx("sunxi-mmc2");
#endif
break;
case STORAGE_EMMC0:
fdt_enable_node("mmc0", 1);
fdt_enable_node("sunxi-mmc0", 1);
break;
case STORAGE_EMMC3:
fdt_enable_node("mmc3", 1);
fdt_enable_node("sunxi-mmc3", 1);
break;
case STORAGE_SD:
fdt_enable_node("mmc0", 1);
fdt_enable_node("sunxi-mmc0", 1);
{
uint32_t dragonboard_test = 0;
uint32_t uboot_dragon_board_test = 0;
//Compatible with old platforms
get_dragonboard_test(
(struct fdt_header *)gd->uboot_fdt_blob,
&uboot_dragon_board_test);
script_parser_fetch("/soc/target", "dragonboard_test",
(int *)&dragonboard_test, 0);
if (uboot_dragon_board_test == 1 ||
dragonboard_test == 1) {
if (uboot_dragon_board_test == 1) {
fdt_enable_node("nand0", 0);
fdt_enable_node("mmc2", 0);
fdt_enable_node("sunxi-mmc2", 0);
if (get_board_flash_type_exist(
STORAGE_NAND))
fdt_enable_node("nand0", 1);
if (get_board_flash_type_exist(
STORAGE_EMMC)) {
fdt_enable_node("mmc2", 1);
fdt_enable_node("sunxi-mmc2",
1);
}
} else {
fdt_enable_node("mmc2", 1);
fdt_enable_node("sunxi-mmc2", 1);
printf("warning:The flash on the test board is not supported as nand");
}
#ifdef CONFIG_SUNXI_SDMMC
mmc_update_config_for_dragonboard(2);
#ifdef CONFIG_MMC3_SUPPORT
mmc_update_config_for_dragonboard(3);
#endif
#endif
#ifdef CONFIG_SUNXI_UBIFS
#ifdef CONFIG_MACH_SUN8IW18
if (nand_use_ubi() == 0) {
/* sun8iw18 aw-nftl config */
fdt_enable_node("spinand", 1);
fdt_enable_node("spi0", 0);
}
#else
/* sun50iw11 config */
fdt_enable_node("spi0", 1);
fdt_enable_node("/soc/spi/spi-nand", 1);
#endif
#else
/* legacy config */
fdt_enable_node("spinand", 1);
fdt_enable_node("spi0", 0);
#endif
}
}
#ifdef CONFIG_SUNXI_SDMMC
mmc_set_mmcblckx("sunxi-mmc0");
#endif
break;
case STORAGE_NOR:
#ifdef CONFIG_SUNXI_SPIF
fdt_enable_node("/soc/spif", 1);
fdt_enable_node("/soc/spif/spif-nor", 1);
fdt_enable_node("/soc/spi", 0);
fdt_enable_node("/soc/spi/spi_board0", 0);
#else
fdt_enable_node("/soc/spi", 1);
fdt_enable_node("/soc/spi/spi_board0", 1);
fdt_enable_node("/soc/spif", 0);
fdt_enable_node("/soc/spif/spif-nor", 0);
#endif
break;
default:
break;
}
#if defined(CONFIG_SUNXI_DRM_SUPPORT)
ulong drm_base = 0, drm_size = 0;
if (gd->securemode == SUNXI_SECURE_MODE_WITH_SECUREOS) {
if (!smc_tee_probe_drm_configure(&drm_base, &drm_size)) {
pr_msg("drm_base=0x%lx\n", drm_base);
pr_msg("drm_size=0x%lx\n", drm_size);
ret = fdt_add_mem_rsv(working_fdt, drm_base, drm_size);
if (ret)
pr_err("##add mem rsv error: %s : %s\n",
__func__, fdt_strerror(ret));
}
}
#endif
#if defined(CONFIG_SUNXI_EXTERN_SECURE_MM_LAYOUT)
if (os_memory_info.shm_size) {
pr_msg("shm_base=0x%lx\n", os_memory_info.shm_base);
pr_msg("shm_size=0x%lx\n", os_memory_info.shm_size);
ret = fdt_add_mem_rsv(working_fdt, os_memory_info.shm_base,
os_memory_info.shm_size);
if (ret)
pr_err("##add mem rsv error: %s : %s\n", __func__,
fdt_strerror(ret));
}
if (os_memory_info.ta_ram_size) {
pr_msg("ta_ram_base=0x%lx\n", os_memory_info.ta_ram_base);
pr_msg("ta_ram_size=0x%lx\n", os_memory_info.ta_ram_size);
ret = fdt_add_mem_rsv(working_fdt, os_memory_info.ta_ram_base,
os_memory_info.ta_ram_size);
if (ret)
pr_err("##add mem rsv error: %s : %s\n", __func__,
fdt_strerror(ret));
}
#endif
if (os_memory_info.tee_ram_size) {
pr_msg("tee_ram_base=0x%lx\n", os_memory_info.tee_ram_base);
pr_msg("tee_ram_size=0x%lx\n", os_memory_info.tee_ram_size);
ret = fdt_add_mem_rsv(working_fdt, os_memory_info.tee_ram_base,
os_memory_info.tee_ram_size);
if (ret)
pr_err("##add mem rsv error: %s : %s\n", __func__,
fdt_strerror(ret));
}
#ifdef CONFIG_SPI_SAMP_DL_EN
int nodeoffset = 0;
nodeoffset = fdt_path_offset(working_fdt, "spi0");
if (nodeoffset < 0) {
pr_err("## error: %s : %s\n", __func__,
fdt_strerror(nodeoffset));
return -1;
}
switch (storage_type) {
case STORAGE_NOR:
#ifdef CONFIG_SUNXI_SPINOR
{
#ifdef CONFIG_SUNXI_SPIF
struct sunxi_spif_slave *sspi = get_sspif();
nodeoffset = fdt_path_offset(working_fdt, "spif0");
if (nodeoffset < 0) {
pr_err("## error: %s : %s\n", __func__,
fdt_strerror(nodeoffset));
return -1;
}
#else
struct sunxi_spi_slave *sspi = get_sspi(0);
#endif
fdt_setprop_u32(working_fdt, nodeoffset,
"sample_mode", sspi->right_sample_mode);
fdt_setprop_u32(working_fdt, nodeoffset,
"sample_delay", sspi->right_sample_delay);
pr_msg("spinor update sample_mode:%x right_sample_mod:%x\n",
sspi->right_sample_mode,
sspi->right_sample_delay);
}
#endif
break;
case STORAGE_SPI_NAND:
#ifdef CONFIG_SUNXI_NAND
{
struct aw_spinand *spinand = get_spinand();
fdt_setprop_u32(working_fdt, nodeoffset,
"sample_mode", spinand->right_sample_mode);
fdt_setprop_u32(working_fdt, nodeoffset,
"sample_delay", spinand->right_sample_delay);
pr_msg("spinand update sample_mode:%x right_sample_mod:%x\n",
spinand->right_sample_mode,
spinand->right_sample_delay);
}
#endif
break;
default:
pr_err("The storage not support sample function\n");
break;
}
#endif /* CONFIG_SPI_SAMP_DL_EN */
/* fix dram para */
update_fdt_dram_para(working_fdt);
#ifdef CONFIG_SUNXI_SPINOR_JPEG
int save_jpg_logo_to_kernel(void);
save_jpg_logo_to_kernel();
#endif
#ifdef CONFIG_SUNXI_SPINOR_BMP
int save_bmp_logo_to_kernel(void);
save_bmp_logo_to_kernel();
#endif
#ifdef CONFIG_BOOT_GUI
save_disp_cmd();
disp_lcd_param_update_to_kernel();
#endif
#ifdef CONFIG_SUNXI_MAC
extern int update_sunxi_mac(void);
update_sunxi_mac();
#endif
#if defined(CONFIG_SUN50IW9_AUTOPRINT)
if (check_printmode()) {
open_autoprint();
}
#endif
#ifdef CONFIG_SUNXI_KASLR_SEED
board_kaslr_seed();
#endif
#ifdef CONFIG_SUNXI_PMU_EXT
if (pmu_ext_get_exist()) {
update_pmu_ext_info_to_kernel();
} else {
update_no_ext_info_to_kernel();
}
#endif
tick_printf("update dts\n");
return 0;
}
int sunxi_update_partinfo(void)
{
int index, ret;
char partition_sets[PARTITION_SETS_MAX_SIZE];
char part_name[PARTITION_NAME_MAX_SIZE];
char root_part_name[ROOT_PART_NAME_MAX_SIZE];
char *root_partition;
char blkoops_part_name[DEV_PART_NAME_MAX_SIZE];
char *blkoops_partition;
char *partition_index = partition_sets;
int offset = 0;
int temp_offset = 0;
int storage_type = get_boot_storage_type();
struct blk_desc *desc;
disk_partition_t info = { 0 };
memset(root_part_name, 0, ROOT_PART_NAME_MAX_SIZE);
root_partition = env_get("root_partition");
if (root_partition)
printf("root_partition is %s\n", root_partition);
memset(blkoops_part_name, 0, DEV_PART_NAME_MAX_SIZE);
blkoops_partition = env_get("blkoops_partition");
if (blkoops_partition)
printf("blkoops_partition is %s\n", blkoops_partition);
memset(partition_sets, 0, PARTITION_SETS_MAX_SIZE);
desc = blk_get_devnum_by_typename("sunxi_flash", 0);
if (desc == NULL)
return -ENODEV;
for (index = 1;; index++) {
#if defined (CONFIG_ENABLE_MTD_CMDLINE_PARTS_BY_ENV) /*Get partitiones by env*/
extern int sunxi_partition_parse_get_info(int index, disk_partition_t *info);
ret = sunxi_partition_parse_get_info(index, &info);
#else /* Get partitiones by GPT */
ret = part_get_info(desc, index, &info);
debug("%s: try part %d, ret = %d\n", __func__, index, ret);
#endif
if (ret < 0)
break;
memset(part_name, 0, PARTITION_NAME_MAX_SIZE);
if (storage_type == STORAGE_NAND) {
sprintf(part_name, "nand0p%d", index);
} else if (storage_type == STORAGE_NOR) {
sprintf(part_name, "mtdblock%d", index);
} else {
sprintf(part_name, "mmcblk0p%d", index);
}
temp_offset = strlen((char*)info.name) + strlen(part_name) + 2;
if (temp_offset >= PARTITION_SETS_MAX_SIZE) {
printf("partition_sets is too long, please reduces "
"partition name\n");
break;
}
sprintf(partition_index, "%s@%s:", info.name, part_name);
if (root_partition && strncmp(root_partition, (char *)info.name, sizeof(info.name)) == 0)
sprintf(root_part_name, "/dev/%s", part_name);
if (blkoops_partition && strncmp(blkoops_partition, (char *)info.name, sizeof(info.name)) == 0)
sprintf(blkoops_part_name, "/dev/%s", part_name);
offset += temp_offset;
partition_index = partition_sets + offset;
}
partition_sets[offset - 1] = '\0';
partition_sets[PARTITION_SETS_MAX_SIZE - 1] = '\0';
env_set("partitions", partition_sets);
#ifdef CONFIG_SUNXI_DM_VERITY
if (*root_part_name != 0) {
printf("set root to dm-0\n");
env_set("verity_dev", root_part_name);
if (storage_type == STORAGE_NAND)
env_set("nand_root", "/dev/dm-0");
else if (storage_type == STORAGE_NOR)
env_set("nor_root", "/dev/dm-0");
else
env_set("mmc_root", "/dev/dm-0");
}
#else
if (*root_part_name != 0) {
printf("set root to %s\n", root_part_name);
if (storage_type == STORAGE_NAND)
env_set("nand_root", root_part_name);
else if (storage_type == STORAGE_NOR)
env_set("nor_root", root_part_name);
else
env_set("mmc_root", root_part_name);
}
#endif
if (*blkoops_part_name != 0) {
printf("set blkoops_blkdev to %s\n", blkoops_part_name);
env_set("blkoops_blkdev", blkoops_part_name);
}
tick_printf("update part info\n");
return 0;
}
int sunxi_force_rotpk(void)
{
return ((uboot_spare_head.boot_data.func_mask &
UBOOT_FUNC_MASK_BIT_FORCE_ROTPK) ==
UBOOT_FUNC_MASK_BIT_FORCE_ROTPK);
}
int sunxi_update_rotpk_info(void)
{
char rotpk_status[16] = "";
int ret;
ret = sunxi_efuse_get_rotpk_status();
if (ret >= 0) {
sprintf(rotpk_status, "%d", ret);
env_set("rotpk_status", rotpk_status);
}
if (sunxi_force_rotpk()) {
if (ret < 1) {
pr_err("rotpk required but not burned\n");
return -1;
}
}
return 0;
}