/** NVT evb board file To handle na510xx basic init. @file na510xxevb.c @ingroup @note Copyright Novatek Microelectronics Corp. 2019. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. */ #include #include #include #include #include #include #include DECLARE_GLOBAL_DATA_PTR; extern int nvt_mmc_init(int id); extern int na51089_eth_initialize(bd_t *bis); const char *boardinfo[] = { "Board:"_CHIP_NAME_"EVB\n" }; void reset_cpu(unsigned long ignored) { nvt_ivot_reset_cpu(); } /** * @brief board_early_init_f * * @return 0 */ int board_early_init_f(void) { //nvt_ipc_init(); return 0; } /** * @brief board_init * * @return 0 */ int board_init(void) { int ret = 0; #ifdef CONFIG_NVT_IVOT_BOOT_FAST char command[100] = {0}; sprintf(command, "nvt_uart_disable"); ret = run_command(command, 0); #endif nvt_tm0_cnt_beg = get_nvt_timer0_cnt(); printf("Relocation to 0x%08lx, Offset is 0x%08lx sp at %08lx\n", gd->relocaddr, gd->reloc_off, gd->start_addr_sp); nvt_shminfo_init(); timer_init(); ret = nvt_fdt_init(false); if (ret < 0) { printf("fdt init fail\n"); } #ifdef CONFIG_NVT_FPGA_EMULATION nvt_writel(0xFFFFFFFF, (ulong)0xF0E40048); printf("0xF0E40048 = 0x%08x\r\n", nvt_readl(0xF0E40048)); printf("0xF0E4004C = 0x%08x\r\n", nvt_readl(0xF0E4004C)); #endif ret = nvt_board_init_early(); if (ret < 0) { printf("board init early fail\n"); return 0; } nvt_print_system_info(); return 0; } #ifdef CONFIG_NVT_MMC int board_mmc_init(bd_t *bis) { int ret = 0, i; int CONFIG_NVT_MMC_CHANNEL = 0; #ifdef CONFIG_NVT_MMC_CHANNEL_SDIO1 CONFIG_NVT_MMC_CHANNEL |= 1 << 0; #endif #ifdef CONFIG_NVT_MMC_CHANNEL_SDIO2 CONFIG_NVT_MMC_CHANNEL |= 1 << 1; #endif #ifdef CONFIG_NVT_MMC_CHANNEL_SDIO3 CONFIG_NVT_MMC_CHANNEL |= 1 << 2; #endif for (i = 0; i < CONFIG_NVT_MMC_MAX_NUM; i++) { if((CONFIG_NVT_MMC_CHANNEL >> i) & 0x1) { ret = nvt_mmc_init(i); if(ret) break; } } return ret; } #endif int board_eth_init(bd_t *bis) { int rc = 0; #ifdef CONFIG_ETHNET rc = na51089_eth_initialize(bis); #endif return rc; } #ifdef CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT #define MAKEFOURCC(ch0, ch1, ch2, ch3) ((unsigned int)(unsigned char)(ch0) | ((unsigned int)(unsigned char)(ch1) << 8) | ((unsigned int)(unsigned char)(ch2) << 16) | ((unsigned int)(unsigned char)(ch3) << 24 )) #define WDT_REG_ADDR(ofs) (IOADDR_WDT_REG_BASE+(ofs)) #define WDT_GETREG(ofs) INW(WDT_REG_ADDR(ofs)) #define WDT_SETREG(ofs,value) OUTW(WDT_REG_ADDR(ofs), (value)) typedef enum { WDT_OTA_STS_INVALID = 0, WDT_OTA_STS_LOADER_DETECTING_FW, WDT_OTA_STS_LOADER_DETECTING_FW_AUTO, WDT_OTA_STS_UBOOT_UPDATE_FAILED, WDT_OTA_STS_UBOOT_UPDATE_OPEN_FAILED, WDT_OTA_STS_UBOOT_UPDATE_READ_FAILED, WDT_OTA_STS_UBOOT_UPDATE_NO_NEED, WDT_OTA_STS_UBOOT_UPDATE_UNKNOWN, WDT_OTA_STS_UBOOT_UPDATE_OK, /* uboot stage ok */ WDT_OTA_STS_LINUX_TRIGGER, /* linux stage trigger ota */ WDT_OTA_STS_LINUX_TRIGGER_AUTO, /* linux stage trigger ota */ } WDT_OTA_STS; #define WDT_OTA_MAKEFOURCC(sts) MAKEFOURCC('O','T','A', sts) #define WDT_OTA_SET_STS(sts) WDT_SETREG(0x84, WDT_OTA_MAKEFOURCC(sts)) #define WDT_OTA_GET_STS() WDT_GETREG(0x84) static int nvt_handle_fw_abin(void) { int ret = 0; char cmdline[1024] = {0}; char buf[512] = {0}; int ota_upgrade_sts = 0; int is_ota = 0; if(WDT_OTA_GET_STS() == WDT_OTA_MAKEFOURCC(WDT_OTA_STS_LOADER_DETECTING_FW)) { is_ota = 1; } else if(WDT_OTA_GET_STS() == WDT_OTA_MAKEFOURCC(WDT_OTA_STS_LOADER_DETECTING_FW_AUTO)) { is_ota = 1; #ifdef CONFIG_NVT_DISPLAY_BAR_FWUPDATE //uboot config sf_display_lcd_bl(0); #endif } printf("is_ota: %d\r\n", is_ota); /* To handle firmware update */ ret = nvt_fw_update(false); if (ret < 0) { switch (ret) { case ERR_NVT_UPDATE_FAILED: printf("%sUpdate fail %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET); if(is_ota) WDT_OTA_SET_STS(WDT_OTA_STS_UBOOT_UPDATE_FAILED); return -1; break; case ERR_NVT_UPDATE_OPENFAILED: printf("Open SD fail:%s No SD device? %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET); if(is_ota) WDT_OTA_SET_STS(WDT_OTA_STS_UBOOT_UPDATE_OPEN_FAILED); break; case ERR_NVT_UPDATE_READ_FAILED: printf("%sRead SD fail %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET); if(is_ota) WDT_OTA_SET_STS(WDT_OTA_STS_UBOOT_UPDATE_READ_FAILED); return -1; break; case ERR_NVT_UPDATE_NO_NEED: printf("%sNo need to update (%s) %s\r\n", ANSI_COLOR_YELLOW, get_nvt_bin_name(NVT_BIN_NAME_TYPE_FW), ANSI_COLOR_RESET); if(is_ota) WDT_OTA_SET_STS(WDT_OTA_STS_UBOOT_UPDATE_NO_NEED); break; default: if(is_ota) WDT_OTA_SET_STS(WDT_OTA_STS_UBOOT_UPDATE_UNKNOWN); break; } ret = nvt_fdt_init(true); if (ret < 0) { printf("modelext init fail\n"); } } else{ printf("%s%s:%d Update successfully %s\r\n", ANSI_COLOR_YELLOW, __FUNCTION__, __LINE__, ANSI_COLOR_RESET); if(is_ota) WDT_OTA_SET_STS(WDT_OTA_STS_UBOOT_UPDATE_OK); ota_upgrade_sts = 1; } /* * To handle bootargs expanding for the kernel /proc/cmdline and uboot mtdids env setting */ //printf("%s:%d ota_upgrade_sts:%d\n", __FUNCTION__, __LINE__ ,ota_upgrade_sts); snprintf(buf, sizeof(buf), env_get("bootargs")); //sprintf(buf,"%s ",env_get("bootargs")); //printf("%s:%d ota_upgrade_sts:%d\n", __FUNCTION__, __LINE__ ,ota_upgrade_sts); strcat(cmdline, buf); ret = nvt_part_config((char *)cmdline, NULL); if (ret < 0) return ret; if (ota_upgrade_sts != 0) { strcat(cmdline, "ota_flag=0x1"); } env_set("bootargs",cmdline); return 0; } static int nvt_handle_fw_tbin(void) { int ret = 0; char cmdline[1024] = {0}; char buf[1024] = {0}; ret = nvt_fw_load_tbin(); if (ret < 0) { switch (ret) { case ERR_NVT_UPDATE_OPENFAILED: printf("Open SD fail:%s No SD device? (%s) %s\r\n", ANSI_COLOR_YELLOW, get_nvt_bin_name(NVT_BIN_NAME_TYPE_RUNFW), ANSI_COLOR_RESET); break; case ERR_NVT_UPDATE_NO_NEED: case ERR_NVT_UPDATE_READ_FAILED: printf("%sRead SD fail (%s) %s\r\n", ANSI_COLOR_RED, get_nvt_bin_name(NVT_BIN_NAME_TYPE_RUNFW), ANSI_COLOR_RESET); return -1; break; default: break; } } else printf("%sLoad successfully %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET); ret = nvt_fdt_init(false); if (ret < 0) { printf("modelext init fail\n"); return ret; } /* * To handle bootargs expanding for the kernel /proc/cmdline and uboot mtdids env setting */ sprintf(buf,"%s ",env_get("bootargs")); strcat(cmdline, buf); ret = nvt_part_config((char *)cmdline, NULL); if (ret < 0) return ret; env_set("bootargs",cmdline); return 0; } static int nvt_handle_fw_update_fw(void) { int ret = 0; unsigned long val = 0; printf("%sStarting to update firmware runtime %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET); /* To handle firmware update */ ret = nvt_fw_update(true); if (ret < 0) { printf("%sUpdate fail %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET); val = (nvt_readl((ulong)nvt_shminfo_comm_uboot_boot_func) & ~COMM_UBOOT_BOOT_FUNC_BOOT_DONE_MASK) | COMM_UBOOT_BOOT_FUNC_BOOT_NG; nvt_writel(val, (ulong)nvt_shminfo_comm_uboot_boot_func); flush_dcache_all(); return -1; } else { printf("%sUpdate firmware successfully %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET); // Update finished. val = (nvt_readl((ulong)nvt_shminfo_comm_uboot_boot_func) & ~COMM_UBOOT_BOOT_FUNC_BOOT_DONE_MASK) | COMM_UBOOT_BOOT_FUNC_BOOT_DONE; nvt_writel(val, (ulong)nvt_shminfo_comm_uboot_boot_func); flush_dcache_all(); while(1) { // Waiting for itron trigger reboot. printf("."); mdelay(1000); } } return 0; } static int nvt_handle_update_fw_by_usb_eth(void) { int ret = 0; char cmdline[1024] = {0}; char buf[1024] = {0}; printf("%sStarting to update firmware from USB/ETH%s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET); /* To handle firmware update */ ret = nvt_fw_update(true); if (ret < 0) { printf("%sUpdate fail %s\r\n", ANSI_COLOR_RED, ANSI_COLOR_RESET); return -1; } else { printf("%sUpdate firmware successfully %s\r\n", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET); } /* * To handle bootargs expanding for the kernel /proc/cmdline and uboot mtdids env setting * Continue to boot */ sprintf(buf,"%s ",env_get("bootargs")); strcat(cmdline, buf); ret = nvt_part_config((char *)cmdline, NULL); if (ret < 0) return ret; env_set("bootargs",cmdline); return 0; } static int nvt_handle_format_rw_rootfs(void) { int ret = 0; ret = nvt_process_rootfs_format(); return ret; } static int nvt_handle_recovery_sys(void) { int ret = 0; char cmdline[1024] = {0}; char buf[1024] = {0}; ret = nvt_process_sys_recovery(); /* * To handle bootargs expanding for the kernel /proc/cmdline and uboot mtdids env setting */ sprintf(buf,"%s ",env_get("bootargs")); strcat(cmdline, buf); ret = nvt_part_config((char *)cmdline, NULL); if (ret < 0) return ret; env_set("bootargs",cmdline); return ret; } #ifdef CONFIG_NVT_LINUX_AUTODETECT static int nvt_handle_fw_auto(void) { int ret = 0; unsigned long boot_reason = nvt_readl((ulong)nvt_shminfo_comm_uboot_boot_func) & COMM_UBOOT_BOOT_FUNC_BOOT_REASON_MASK; if (boot_reason == COMM_UBOOT_BOOT_FUNC_BOOT_UPDFIRM) { // Update by itron: firmware will be loaded by itron. ret = nvt_handle_fw_update_fw(); if (ret < 0) return ret; } else if ((boot_reason == COMM_UBOOT_BOOT_FUNC_BOOT_UPD_FRM_USB) || \ (boot_reason == COMM_UBOOT_BOOT_FUNC_BOOT_UPD_FRM_ETH)){ // Update by USB/ETH: firmware will be loaded by loader. ret = nvt_handle_update_fw_by_usb_eth(); if (ret < 0) return ret; } else if (nvt_detect_fw_tbin()) { ret = nvt_handle_fw_tbin(); if (ret < 0) return ret; #ifndef CONFIG_NVT_LINUX_RAMDISK_SUPPORT char cmdline[512] = {0}; char buf[255] = {0}; /* * To handle bootargs expanding for the kernel /proc/cmdline and uboot mtdids env setting */ sprintf(buf,"%s ",env_get("bootargs")); strcat(cmdline, buf); ret = nvt_part_config((char *)cmdline, NULL); if (ret < 0) return ret; env_set("bootargs",cmdline); #endif /* CONFIG_NVT_LINUX_RAMDISK_SUPPORT */ } else if (boot_reason == COMM_UBOOT_BOOT_FUNC_BOOT_FORMAT_ROOTFS){ // Format R/W rootfs, we should check if this partition is existed firstly. ret = nvt_handle_format_rw_rootfs(); if (ret < 0) return ret; } else if (boot_reason == COMM_UBOOT_BOOT_FUNC_BOOT_RECOVERY_SYS){ // Recovery system if loader send event to do system recovery. (EMMC boot only) ret = nvt_handle_recovery_sys(); if (ret < 0) return ret; } else { ret = nvt_handle_fw_abin(); if (ret < 0) return ret; } return 0; } #endif /* CONFIG_NVT_LINUX_AUTODETECT */ #endif /* CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT */ #if defined(CONFIG_NVT_IVOT_EMMC) static int nvt_emmc_init(void) { int ret = 0; char command[128] = {0}; /* Switch to emmc bus and user partition access config */ sprintf(command, "mmc dev %d", CONFIG_NVT_IVOT_EMMC); ret = run_command(command, 0); if (ret < 0) return ret; sprintf(command, "mmc partconf %d 1 1 0", CONFIG_NVT_IVOT_EMMC); ret = run_command(command, 0); return ret; } #elif defined(CONFIG_NVT_SPI_NOR) static int nvt_norflash_init(void) { int ret = 0; char command[128] = {0}; sprintf(command, "sf probe"); ret = run_command(command, 0); if (ret < 0) { nvt_dbg(ERR, "nor flash init failed\n"); } return ret; } #endif /* CONFIG_NVT_LINUX_EMMC_BOOT */ #if 0 static int sf_fw_update_reset(void) { int ret = 0; char command[128] = {0}; printf("[%s:%d] s\n", __FUNCTION__, __LINE__); sprintf(command, "reset"); ret = run_command(command, 0); if (ret < 0) { nvt_dbg(ERR, "sf reset failed\n"); } printf("[%s:%d] %s\n", __FUNCTION__, __LINE__,command); return ret; } #endif /** * @brief misc_init_r - To do nvt update and board init. * * @return 0 */ int misc_init_r(void) { int ret = 0; #ifdef CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT nvt_dbg(FUNC, "%sFirmware name: %s %s %s %s \n", ANSI_COLOR_YELLOW, get_nvt_bin_name(NVT_BIN_NAME_TYPE_FW), get_nvt_bin_name(NVT_BIN_NAME_TYPE_RUNFW), get_nvt_bin_name(NVT_BIN_NAME_TYPE_MODELEXT), ANSI_COLOR_RESET); nvt_dbg(FUNC, "boot time: %lu(us) \n", get_nvt_timer0_cnt()); #endif /* CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT */ #if defined(CONFIG_NVT_IVOT_EMMC) ret = nvt_emmc_init(); if (ret < 0) return 0; #elif defined(CONFIG_NVT_SPI_NOR) ret = nvt_norflash_init(); if (ret < 0) return 0; #endif /* CONFIG_NVT_LINUX_EMMC_BOOT */ #ifdef CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT #ifdef CONFIG_NVT_LINUX_AUTODETECT ret = nvt_handle_fw_auto(); if (ret < 0) return 0; #else /* !CONFIG_NVT_LINUX_AUTODETECT */ #ifdef CONFIG_NVT_LINUX_SPINAND_BOOT ret = nvt_handle_fw_abin(); if (ret < 0) return 0; #else /* !CONFIG_NVT_LINUX_SPINAND_BOOT */ ret = nvt_handle_fw_tbin(); if (ret < 0) return 0; #endif /* CONFIG_NVT_LINUX_SPINAND_BOOT */ #endif /* CONFIG_NVT_LINUX_AUTODETECT */ #else /* !CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT */ /* FIXME: To do customized boot */ ret = nvt_fdt_init(true); if (ret < 0) { printf("modelext init fail\n"); return 0; } #endif /* CONFIG_NVT_IVOT_SOC_FW_UPDATE_SUPPORT */ /* Why to do this again? * This is because modelext maybe updated, we should init again here. */ nvt_dbg(FUNC, "boot time: %lu(us) \n", get_nvt_timer0_cnt()); ret = nvt_board_init(); if (ret < 0) { printf("board init fail\n"); return 0; } nvt_dbg(FUNC, "boot time: %lu(us) \n", get_nvt_timer0_cnt()); //sf_fw_update_reset(); return 0; } /* * dram init. */ int dram_init_banksize(void) { gd->bd->bi_dram[0].start = PHYS_SDRAM_1; gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; return 0; } phys_size_t get_effective_memsize(void) { /* We should report the uboot dram size due to relocate * address will be calculated by this size to get ram top address, * #ifdef CONFIG_SYS_SDRAM_BASE * gd->ram_base = CONFIG_SYS_SDRAM_BASE; * #endif * gd->ram_top = gd->ram_base + get_effective_memsize(); * gd->ram_top = board_get_usable_ram_top(gd->mon_len); * gd->relocaddr = gd->ram_top; */ return CONFIG_SYS_SDRAM_SIZE; } /* * get_board_rev() - get board revision */ u32 get_board_rev(void) { return 0; } int board_late_init(void) { return 0; }