// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2020 ArtInChip Technology Co.,Ltd * Author: Dehuang Wu */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define usleep_range(a, b) udelay((b)) #define RTC_CMU_REG ((void *)0x18020908) #define RTC_CMU_BUS_EN_MSK (0x1000) #define BASE_RTC ((void *)0x19030000) #define RTC_WRITE_KEY_REG (BASE_RTC + 0x0FC) #define RTC_WRITE_KEY_VALUE (0xAC) #define RTC_BOOTINFO1_REG (BASE_RTC + 0x100) #define BOOTINFO1_REASON_OFF (4) #define BOOTINFO1_REASON_MSK (0xF << 4) #define RTC_REBOOT_REASON_UPGRADE (4) #define RTC_REBOOT_REASON_BL_UPGRADE (5) #define RTC_SYS_BAK_BASE (BASE_RTC + 0x104) #define RTC_SYS_BAK_REG(id) (RTC_SYS_BAK_BASE + (id) * 0x04) #ifdef CONFIG_SPL_SPI_NAND_TINY #include #endif #ifdef CONFIG_AUTO_CALCULATE_PART_CONFIG #include #endif DECLARE_GLOBAL_DATA_PTR; #define MAX_MTDIDS 64 #define MAX_MTDPARTS 256 #define EFUSE_CMU_REG ((void *)0x18020904) #define EFUSE_SHADOW_FEATURE_REG ((void *)0x19010224) #define DDR2_32MB 0xA #define DDR2_64MB 0xB #define DDR3_128MB 0xC #define DDR3_256MB 0xD #ifdef CONFIG_DEBUG_UART_BOARD_INIT #define USE_UART0 #define GPIO_CMU_CFG_REG ((void *)(0x1802083C)) #define CMU_PLL_INT1_CFG_REG ((void *)(0x18020004)) #ifdef USE_UART1 #define UART1_CMU_CFG_REG ((void *)(0x18020844)) #define UART1_LSR_REG ((void *)(0x18711014)) #define UART1_IER_REG ((void *)(0x18711004)) #define GPIO_PA4_PIN_CFG_REG ((void *)0x18700090) #define GPIO_PA5_PIN_CFG_REG ((void *)0x18700094) #endif #ifdef USE_UART0 #define UART0_CMU_CFG_REG ((void *)(0x18020840)) #define UART0_LSR_REG ((void *)(0x18710014)) #define UART0_IER_REG ((void *)(0x18710004)) #define GPIO_PN0_PIN_CFG_REG ((void *)0x18700E80) #define GPIO_PN1_PIN_CFG_REG ((void *)0x18700E84) #endif #define LSR_TX_EMP_BIT BIT(6) void board_debug_uart_init(void) { u32 val = 0; /* Reset and Gating GPIO */ writel(0x3100, GPIO_CMU_CFG_REG); writel(0x88153100, CMU_PLL_INT1_CFG_REG); #ifdef USE_UART1 writel(0x325, GPIO_PA4_PIN_CFG_REG); writel(0x325, GPIO_PA5_PIN_CFG_REG); val = readl(UART1_CMU_CFG_REG); if (val & 0x3100) { /* Wait for UART Tx FIFO to be empty, if UART already enabled */ while ((readl(UART1_LSR_REG) & LSR_TX_EMP_BIT) == 0) ; writel(0, UART1_CMU_CFG_REG); }; /* Reset and Gating UART */ writel(0x3118, UART1_CMU_CFG_REG); #endif #ifdef USE_UART0 writel(0x324, GPIO_PN0_PIN_CFG_REG); writel(0x324, GPIO_PN1_PIN_CFG_REG); val = readl(UART0_CMU_CFG_REG); if (val & 0x3100) { /* Wait for UART Tx FIFO to be empty, if UART already enabled */ while ((readl(UART0_LSR_REG) & LSR_TX_EMP_BIT) == 0) ; writel(0, UART0_CMU_CFG_REG); }; /* Reset and Gating UART */ writel(0x3118, UART0_CMU_CFG_REG); #endif } #endif #if defined(CONFIG_SPL_BUILD) void board_init_f(ulong dummy) { int ret; #ifdef CONFIG_ARTINCHIP_DEBUG_BOOT_TIME u32 *p = (u32 *)BOOT_TIME_SPL_START; /* SPL start time */ *p = aic_timer_get_us(); #endif log_buf_init(); #ifdef CONFIG_DEBUG_UART /* * For SPL, Use DEBUG UART to enable serial output, * don't use dm serial driver, because it spend too much time to * initialize driver. */ log_notice("\nspl:debug uart enabled in %s\n", __func__); #endif ret = spl_early_init(); if (ret) panic("spl_early_init() failed: %d\n", ret); riscv_cpu_setup(NULL, NULL); preloader_console_init(); ret = spl_board_init_f(); if (ret) panic("spl_board_init_f() failed: %d\n", ret); } void spl_board_init(void) { enable_caches(); } void spl_board_prepare_for_linux(void) { usb_dev_connection_check_end(0); } #endif int board_init(void) { return 0; } static void setup_boot_device(void) { enum boot_device bd; /* * Boot ROM detects Boot device and pass it to SPL, * SPL pass it to U-Boot. */ bd = aic_get_boot_device(); switch (bd) { case BD_SDMC0: env_set("boot_device", "mmc"); env_set("boot_devnum", "0"); debug("Booting from eMMC...\n"); break; case BD_SDMC1: env_set("boot_device", "mmc"); env_set("boot_devnum", "1"); debug("Booting from SD Card...\n"); break; case BD_SDFAT32: env_set("boot_device", "fat"); env_set("boot_devnum", "1"); debug("Booting from SD Card FATFS...\n"); break; case BD_SPINOR: env_set("boot_device", "nor"); env_set("boot_devnum", "0"); debug("Booting from SPI NOR...\n"); break; case BD_SPINAND: env_set("boot_device", "nand"); env_set("boot_devnum", "0"); debug("Booting from SPI NAND...\n"); break; case BD_USB: env_set("boot_device", "usb"); env_set("boot_devnum", "0"); debug("Booting from USBUPG...\n"); break; default: pr_err("Unknown boot device id %d...\n", (int)bd); break; } } #if CONFIG_IS_ENABLED(OF_CONTROL) && defined(CONFIG_FIT_SIGNATURE) static int set_dev_part(const void *blob, char *propname) { struct disk_partition info; struct blk_desc *desc; char *media, *devnum, dev_name[16]; const char *part_name; int part, ret; media = env_get("boot_device"); devnum = env_get("boot_devnum"); /* get part name */ part_name = fdtdec_get_chosen_prop(blob, propname); if (part_name) { /* get dev desc */ ret = blk_get_device_by_str(media, devnum, &desc); if (ret < 0) return ret; /* get part number */ part = part_get_info_by_name(desc, part_name, &info); if (part < 0) return -1; snprintf(dev_name, sizeof(dev_name), "/dev/mmcblk%sp%d", devnum, part); env_set(propname, dev_name); } return 0; } static int setup_dm_verity_part(void) { int ret; ret = set_dev_part(gd->fdt_blob, "root_part"); if (ret < 0) return ret; ret = set_dev_part(gd->fdt_blob, "hash_part"); if (ret < 0) return ret; return 0; } #endif #ifdef CONFIG_VIDEO_ARTINCHIP static int board_prepare_logo(struct udevice *dev) { enum boot_device bd; int ret = -EINVAL; bd = aic_get_boot_device(); switch (bd) { case BD_SDMC0: case BD_SDMC1: case BD_SPINAND: case BD_SPINOR: ret = aic_disp_logo("boot", bd); break; case BD_SDFAT32: #ifdef CONFIG_PROGRESS_BAR ret = 0; #else ret = aic_disp_logo("sdburn", bd); #endif break; case BD_BOOTROM: ret = aic_disp_logo("usbburn", bd); break; default: pr_err("Unknown boot device id %d...\n", (int)bd); return ret; } return ret; } static int board_show_logo(void) { struct udevice *dev; int ret; ret = uclass_first_device(UCLASS_VIDEO, &dev); if (ret) { pr_err("Failed to find aicfb udevice\n"); return ret; } #ifdef CONFIG_PROGRESS_BAR struct video_priv *priv = dev_get_uclass_priv(dev); memset(priv->fb, 0xffffff, priv->fb_size); flush_dcache_range((uintptr_t)&priv->fb, (uintptr_t)(&priv->fb_size)); #endif ret = board_prepare_logo(dev); if (!ret) { aicfb_update_ui_layer(dev); aicfb_startup_panel(dev); } return ret; } #endif /* CONFIG_VIDEO_ARTINCHIP */ static u64 efuse_get_ddr_size(void) { u32 val, mem; u64 size = 0; writel(0x1100, EFUSE_CMU_REG); val = readl(EFUSE_SHADOW_FEATURE_REG); mem = (val >> 20) & 0xF; switch (mem) { case DDR2_32MB: pr_info("DDR2 32MB\n"); size = 0x2000000; break; case DDR2_64MB: pr_info("DDR2 64MB\n"); size = 0x4000000; break; case DDR3_128MB: pr_info("DDR3 128MB\n"); size = 0x8000000; break; case DDR3_256MB: pr_info("DDR3 256MB\n"); size = 0x10000000; break; default: pr_info("No DDR info\n"); } return size; } static u64 get_dram_size(void) { const fdt64_t *val; u64 size = 0; int offset; int len; size = efuse_get_ddr_size(); if (size > 0) return size; offset = fdt_path_offset(gd->fdt_blob, "/memory"); if (offset < 0) { pr_err("Get memory node from DTS failed.\n"); return size; } val = fdt_getprop(gd->fdt_blob, offset, "reg", &len); if (len < sizeof(*val) * 2) { pr_err("Get memory size from DTS failed.\n"); return size; } size = (u64)get_unaligned_be64(&val[1]); return size; } int dram_init(void) { gd->ram_size = get_dram_size(); if (gd->ram_size == 0) { pr_err("Get DRAM size failed.\n"); } return 0; } void fdt_fix_mem_size(void *blob) { int len, nodeoffset; const u64 *reg; u64 start[1], size[1]; char *node = "/memory@40000000"; nodeoffset = fdt_path_offset(blob, node); reg = fdt_getprop(blob, nodeoffset, "reg", &len); if (reg) { start[0] = fdt64_to_cpu(reg[0]); size[0] = efuse_get_ddr_size(); if (size[0]) { fdt_fix_memory(blob, start, size, node); } } } #if defined(CONFIG_FIT_SIGNATURE) static int replace_first_str(char *src, char *match_str, char *replace_str) { int str_len; char newstring[1024] = {0}; char *find_pos; if (!match_str || !replace_str) return -1; find_pos = strstr(src, match_str); if (!find_pos) return -1; while (find_pos) { str_len = find_pos - src; strncpy(newstring, src, str_len); strcat(newstring, replace_str); strcat(newstring, find_pos + strlen(match_str)); strcpy(src, newstring); return 0; } return 0; } static int fdt_get_cmdline(void *fdt, char *console, char *cmdline) { int nodeoffset; const char *create, *waitfor, *bootargs, *args; char buf[1024]; /* find or create "/chosen" node. */ nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); if (nodeoffset < 0) return nodeoffset; debug("Get bootargs parameters.\n"); create = fdt_getprop(fdt, nodeoffset, "dm-mod.create", NULL); waitfor = fdt_getprop(fdt, nodeoffset, "dm-mod.waitfor", NULL); bootargs = fdt_getprop(fdt, nodeoffset, "bootargs", NULL); args = fdt_getprop(fdt, nodeoffset, "args", NULL); if (!create || !waitfor || !bootargs || !args) { printf("Get bootargs parameters failed!\n"); printf("If secure boot is not used, "); printf("CONFIG_FIT_SIGNATURE should be disabled!\n"); return -EINVAL; } strcpy(buf, create); if (replace_first_str(buf, "data_dev", env_get("root_part"))) printf("Set data dev failed.\n"); if (replace_first_str(buf, "hash_dev", env_get("hash_part"))) printf("Set hash dev failed.\n"); /* Don't add console= if user already set it */ if (strstr(bootargs, "console=")) snprintf(cmdline, 1024, "%s %s %s %s", bootargs, args, buf, waitfor); else snprintf(cmdline, 1024, "%s %s %s %s %s", console, bootargs, args, buf, waitfor); return 0; } #endif #ifdef CONFIG_OF_BOARD_SETUP char *board_fdt_chosen_bootargs(void) { /* Set up chosen bootargs in ft_board_setup */ return NULL; } static int ft_board_setup_chosen_bootargs(void *fdt) { int err, idx; int nodeoffset; char *str, *s; char cmdline[1024], console[32]; /* find or create "/chosen" node. */ nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); if (nodeoffset < 0) return nodeoffset; err = 0; str = (char *)fdtdec_get_chosen_prop(fdt, "stdout-path"); if (str) { for (s = str; *s; s++) if (isdigit(*s) || *s == ':') break; idx = simple_strtoul(s, NULL, 10); s = strchr(str, ':'); s++; } else { idx = 0; s = "115200n8"; } snprintf(console, 32, "console=ttyS%d,%s", idx, s); #if defined(CONFIG_FIT_SIGNATURE) err = fdt_get_cmdline(fdt, console, cmdline); if (err) return err; #else str = env_get("bootargs"); /* Don't add console= if user already set it */ if (strstr(str, "console=")) snprintf(cmdline, 1024, "%s", str); else snprintf(cmdline, 1024, "%s %s", console, str); #endif if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", cmdline, strlen(cmdline) + 1); if (err < 0) { printf("WARNING: could not set bootargs %s.\n", fdt_strerror(err)); return err; } } return err; } static int fdt_fix_aic_logo_reserved_memory(void *blob) { int ret = 0; #ifdef CONFIG_VIDEO_ARTINCHIP struct fdt_memory logo; struct video_priv *priv; struct udevice *dev; ret = uclass_find_first_device(UCLASS_VIDEO, &dev); if (ret) { pr_err("%s: failed to find aicfb udevice\n", __func__); return ret; } priv = dev_get_uclass_priv(dev); if (IS_ERR_OR_NULL(priv)) { pr_warn("%s: failed to find aic-logo info\n", __func__); return 0; } logo.start = (phys_addr_t)priv->fb; logo.end = (phys_addr_t)priv->fb + priv->fb_size - 1; ret = fdtdec_add_reserved_memory(blob, "aic-logo", &logo, NULL, 0, NULL, false); if (ret < 0 && ret != -FDT_ERR_EXISTS) { pr_err("%s: failed to add reserved memory\n", __func__); return ret; } #endif return ret; } int ft_board_setup(void *blob, struct bd_info *bd) { fdt_fix_mem_size(blob); ft_board_setup_chosen_bootargs(blob); fdt_fix_aic_logo_reserved_memory(blob); return 0; } #endif /* CONFIG_OF_BOARD_SETUP */ int board_late_init(void) { setup_boot_device(); #if defined(CONFIG_FIT_SIGNATURE) setup_dm_verity_part(); #endif #ifdef CONFIG_VIDEO_ARTINCHIP board_show_logo(); #endif #ifdef CONFIG_USERID_SUPPORT enum boot_device bd; bd = aic_get_boot_device(); if (bd != BD_USB && bd != BD_SDFAT32) userid_init(); #endif return 0; } void board_mtdparts_default(const char **mtdids, const char **mtdparts) { static char ids[MAX_MTDIDS]; static char parts[MAX_MTDPARTS]; struct mtd_info *mtd = get_mtd_device(NULL, 0); struct udevice *dev; int pos, ret, cnt; char *p; if (IS_ERR_OR_NULL(mtd)) { ret = uclass_first_device(UCLASS_MTD, &dev); if (ret && !dev) { pr_err("Find MTD device failed.\n"); goto out; } device_probe(dev); mtd = get_mtd_device(NULL, 0); } if (IS_ERR_OR_NULL(mtd)) { pr_err("There is no mtd device.\n"); goto out; } if ((gd->flags & GD_FLG_ENV_READY) == 0) { pr_warn("env is not loaded.\n"); goto out; } p = env_get("MTD"); if (!p) { pr_warn("Get MTD partition table from env failed.\n"); goto out; } memset(ids, 0, MAX_MTDIDS); snprintf(ids, MAX_MTDIDS, "%s=", mtd->name); for (pos = 0; pos < strlen(p); pos++) { if (p[pos] == ':') break; } if (pos == strlen(p)) { pr_err("There is no mtd ids in partition table.\n"); return; } if ((pos + strlen(ids)) >= MAX_MTDIDS) { pr_err("mtd ids is too long.\n"); return; } if (strlen(p) >= MAX_MTDPARTS) { pr_err("mtd partition table is too long\n"); return; } memcpy(ids + strlen(ids), p, pos); strcpy(parts, p); /* Check if it is set minimal boot mtdparts number */ p = env_get("nand_boot_mtdparts_cnt"); if (p) { cnt = simple_strtoul(p, NULL, 10); if (!cnt) goto all; /* Filter minimal parts */ p = parts; while (*p != '\0') { p++; if (*p == ',') cnt--; if (cnt == 0) break; } /* OK, drop not relative mtdparts for u-boot */ if (!cnt && *p == ',') *p = '\0'; } all: *mtdids = ids; *mtdparts = parts; pr_info("U-Boot stage mtdparts: %s\n", parts); return; out: /* ENV is not ready, use default configuratioin if it is provided.*/ #ifdef CONFIG_MTDIDS_DEFAULT *mtdids = CONFIG_MTDIDS_DEFAULT; #endif #ifdef CONFIG_MTDPARTS_DEFAULT *mtdparts = CONFIG_MTDPARTS_DEFAULT; #endif return; } int dram_init_banksize(void) { gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; gd->bd->bi_dram[0].size = gd->ram_size; return 0; } #ifdef CONFIG_SPL_OS_BOOT static int search_boot_os(u8 *env_ram, int len) { int i = 0, cnt = 0; while (i < len) { if (env_ram[i] != 0) cnt = 0; if ((env_ram[i] == 'b') && !memcmp(&env_ram[i], "boot_os=yes", 11)) return 1; else if (env_ram[i] == 0) cnt++; if (cnt >= 2) break; i++; } return 0; } #ifdef CONFIG_SPL_MMC_SUPPORT static int mmc_load_env_simple(int dev, u8 *env_ram) { static struct mmc *mmc; unsigned long count, sector_start, sector_cnt; int err = -1; mmc = find_mmc_device(dev); if (!mmc) return err; sector_start = CONFIG_ENV_OFFSET / mmc->read_bl_len; sector_cnt = CONFIG_ENV_SIZE / mmc->read_bl_len; count = blk_dread(mmc_get_blk_desc(mmc), sector_start, sector_cnt, env_ram); if (count != sector_cnt) return -1; return CONFIG_ENV_SIZE; } #endif #ifdef CONFIG_SPL_SPI_NAND_TINY static int spinand_load_env_simple(u8 *env_ram) { struct spinand_device *spinand; unsigned long offset, remain; size_t rdlen; spinand = spl_spinand_init(); if (IS_ERR_OR_NULL(spinand)) { pr_err("Tiny SPI NAND init failed. ret = %ld\n", PTR_ERR(spinand)); return -1; } offset = CONFIG_ENV_OFFSET; remain = (uint32_t)CONFIG_ENV_SIZE; #ifndef CONFIG_SYS_REDUNDAND_ENVIRONMENT spl_spi_nand_read(spinand, offset, remain, &rdlen, (void *)env_ram); if (remain != rdlen) { pr_err("Tiny SPI NAND read failed.\n"); return -1; } return CONFIG_ENV_SIZE; #else int read1_fail = 0, read2_fail = 0; u8 *buf = env_ram; u8 *buf_redund = (u8 *)CONFIG_ENV_RAM_ADDR + CONFIG_ENV_SIZE; char tmp_env1_flags, tmp_env2_flags; read1_fail = spl_spi_nand_read(spinand, CONFIG_ENV_OFFSET, remain, &rdlen, (void *)buf); read2_fail = spl_spi_nand_read(spinand, CONFIG_ENV_OFFSET_REDUND, remain, &rdlen, (void *)buf_redund); if (read1_fail && read2_fail) { pr_err("Tiny SPI NAND read failed.\n"); return -1; } tmp_env1_flags = buf[4]; tmp_env2_flags = buf_redund[4]; if (tmp_env1_flags == 255 && tmp_env2_flags == 0) memcpy(env_ram, buf_redund, CONFIG_ENV_SIZE); else if (tmp_env2_flags > tmp_env1_flags) memcpy(env_ram, buf_redund, CONFIG_ENV_SIZE); return CONFIG_ENV_SIZE; #endif } #endif #ifdef CONFIG_SPL_SPI_LOAD static int spinor_load_env_simple(u8 *env_ram) { unsigned int bus = CONFIG_SF_DEFAULT_BUS; unsigned int cs = CONFIG_SF_DEFAULT_CS; struct udevice *new, *bus_dev; struct spi_flash *flash; int ret; ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new); if (ret) { pr_err("Failed to find a spi device\n"); return -EINVAL; } flash = dev_get_uclass_priv(new); ret = spi_flash_read(flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, (void *)env_ram); if (ret) { pr_err("Failed to read env from SPINOR.\n"); return -1; } return CONFIG_ENV_SIZE; } #endif static int env_boot_os_flag(enum boot_device bd) { u8 *env_ram = (u8 *)CONFIG_ENV_RAM_ADDR; int size = 0; switch (bd) { #ifdef CONFIG_SPL_MMC_SUPPORT case BD_SDMC0: size = mmc_load_env_simple(0, env_ram); break; case BD_SDMC1: size = mmc_load_env_simple(1, env_ram); break; #endif case BD_SPINAND: #ifdef CONFIG_SPL_SPI_NAND_TINY size = spinand_load_env_simple(env_ram); #endif break; case BD_SPINOR: #ifdef CONFIG_SPL_SPI_LOAD size = spinor_load_env_simple(env_ram); #endif break; default: break; } if (size > 0) return search_boot_os(env_ram, size); return 0; } #ifdef CONFIG_USERID_SUPPORT static int userid_lock_flag(enum boot_device bd) { int ret = 0; u32 flag = 0; ret = userid_init(); if (ret) { return 0; } ret = userid_read("lock", 0, (void *)&flag, 4); if (ret <= 0) return 0; return (flag != 0); } #endif #define START_UNKNOWN -1 #define START_KERNEL 0 #define START_UBOOT 1 extern int aic_upg_mode_detect(void); /* * This API will be called multi-times */ int spl_start_uboot(void) { #ifndef CONFIG_SPL_OS_BOOT /* Falcon mode is not enabled, run u-boot directly */ return START_UBOOT; #else static int start = START_UNKNOWN; static int usb_dev_check; enum boot_device bd; int userid_lock = 0; if (start == START_UBOOT) return start; /* UNKNOWN, START_KERNEL: still need to check */ bd = aic_get_boot_device(); if (bd == BD_USB || bd == BD_SDFAT32) { /* If Boot for image upgrading, force to start U-Boot. */ start = START_UBOOT; puts("Run U-Boot: upgrading mode\n"); goto out; } #ifdef CONFIG_SPL_SERIAL_SUPPORT /* break into full u-boot with CTRL + c/C */ if (serial_tstc() && serial_getc() == CTRL('C')) { start = START_UBOOT; puts("Run U-Boot: got CTRL+C\n"); goto out; } #endif if (start == START_UNKNOWN) { #ifdef CONFIG_CMD_AICUPG if (aic_upg_mode_detect()) { start = START_UBOOT; puts("Run U-Boot: Software reset to enter UPG mode\n"); goto out; } #endif if (env_boot_os_flag(bd) != 1) { start = START_UBOOT; puts("Run U-Boot: boot_os=no in ENV, don't boot os\n"); goto out; } #ifdef CONFIG_UPDATE_UDISK_FATFS_ARTINCHIP /* Check udisk upgrading: * Only check when userid is locked */ if (usb_host_udisk_connection_check()) { /* Device is connecting to UDISK, goto uboot to check * whether it is going to perform UDISK upgrading */ start = START_UBOOT; puts("Run U-Boot: try UDISK upgrading\n"); goto out; } #endif usb_dev_check = 0; #ifdef CONFIG_USERID_SUPPORT userid_lock = userid_lock_flag(bd); #else userid_lock = 1; #endif /* * When userid partition is locked, it is no needed to check * usb connection for userid */ if (!userid_lock) usb_dev_check++; #ifdef CONFIG_AICUPG_FORCE_USBUPG_SUPPORT usb_dev_check++; #endif /* * Switch to Device mode, and check whether USB connecting to PC. * This function should be called once. */ if (usb_dev_check) usb_dev_connection_check_start(0); } /* * Check usb connecton status every time spl_start_uboot is called. */ if (usb_dev_check && usb_dev_connection_check_status(0)) { start = START_UBOOT; usb_dev_connection_check_end(0); puts("Run U-Boot: Device is connecting to PC with USB, try to burn userid\n"); goto out; } start = START_KERNEL; out: return start; #endif } #endif ulong board_spl_fit_size_align(ulong size) { size = ALIGN(size, 0x20); return size; } /* Get the top of usable RAM */ ulong board_get_usable_ram_top(ulong total_size) { u64 dram_size; phys_addr_t top; dram_size = get_dram_size(); top = CONFIG_SYS_SDRAM_BASE + dram_size; /* last region is for OpenSBI */ top = top - CONFIG_SPL_OPENSBI_SIZE; return top; } int board_load_opensbi_to_ram_top(void) { return 1; } void aic_upg_flag_clear(void) { u32 val; val = readl(RTC_CMU_REG); if (!(val & RTC_CMU_BUS_EN_MSK)) writel(RTC_CMU_BUS_EN_MSK, RTC_CMU_REG); writel(RTC_WRITE_KEY_VALUE, RTC_WRITE_KEY_REG); val = readl(RTC_BOOTINFO1_REG); val &= ~BOOTINFO1_REASON_MSK; writel(val, RTC_BOOTINFO1_REG); writel(0, RTC_WRITE_KEY_REG); } static int rtc_upg_flag_check(void) { u32 val; val = readl((void *)RTC_BOOTINFO1_REG); val = (val & BOOTINFO1_REASON_MSK) >> BOOTINFO1_REASON_OFF; if ((val == RTC_REBOOT_REASON_UPGRADE) || (val == RTC_REBOOT_REASON_BL_UPGRADE)) { printf("Software reboot to enter upgrading mode.\n"); return 1; } return 0; } void aic_upg_succ_cnt(void) { u32 val; val = readl(RTC_CMU_REG); if (!(val & RTC_CMU_BUS_EN_MSK)) writel(RTC_CMU_BUS_EN_MSK, RTC_CMU_REG); writel(RTC_WRITE_KEY_VALUE, RTC_WRITE_KEY_REG); val = readl(RTC_SYS_BAK_REG(14)); val += 1; writel(val, RTC_SYS_BAK_REG(14)); writel(0, RTC_WRITE_KEY_REG); printf("Successfully burned %d times.\n", val); } int aic_upg_mode_detect(void) { int ret; ret = rtc_upg_flag_check(); return ret; } #ifndef CONFIG_SPL_BUILD extern int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); void do_brom_upg(char *upg_mode) { u32 val; writel(RTC_WRITE_KEY_VALUE, RTC_WRITE_KEY_REG); val = readl((void *)RTC_BOOTINFO1_REG); val &= ~BOOTINFO1_REASON_MSK; val |= (RTC_REBOOT_REASON_UPGRADE << BOOTINFO1_REASON_OFF); writel(val, (void *)RTC_BOOTINFO1_REG); writel(0, RTC_WRITE_KEY_REG); do_reset(NULL, 0, 0, 0); } #endif