/* * hi3518ev300.c * * The board init for hisilicon * * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_AUTO_OTA_UPDATE #include #endif /* CONFIG_AUTO_OTA_UPDATE */ #ifndef CONFIG_SYS_DCACHE_OFF void enable_caches(void) { /* Enable D-cache. I-cache is already enabled in start.S */ dcache_enable(); } #endif static int boot_media = BOOT_MEDIA_UNKNOWN; int get_boot_media(void) { unsigned int reg_val, boot_mode, spi_device_mode; int boot_media = BOOT_MEDIA_UNKNOWN; reg_val = readl(SYS_CTRL_REG_BASE + REG_SYSSTAT); boot_mode = get_sys_boot_mode(reg_val); switch (boot_mode) { case BOOT_FROM_SPI: spi_device_mode = get_spi_device_type(reg_val); if (spi_device_mode) boot_media = BOOT_MEDIA_NAND; else boot_media = BOOT_MEDIA_SPIFLASH; break; case BOOT_FROM_EMMC: boot_media = BOOT_MEDIA_EMMC; break; default: boot_media = BOOT_MEDIA_UNKNOWN; break; } return boot_media; } #if defined(CONFIG_SHOW_BOOT_PROGRESS) void show_boot_progress(int progress) { printf("Boot reached stage %d\n", progress); } #endif #define COMP_MODE_ENABLE ((unsigned int)0x0000EAEF) static inline void delay(unsigned long loops) { __asm__ volatile("1:\n" "subs %0, %1, #1\n" "bne 1b" : "=r"(loops) : "0"(loops)); } int get_text_base(void) { return CONFIG_SYS_TEXT_BASE; } static void boot_flag_init(void) { unsigned int reg, boot_mode, spi_device_mode; /* get boot mode */ reg = __raw_readl(SYS_CTRL_REG_BASE + REG_SYSSTAT); boot_mode = get_sys_boot_mode(reg); switch (boot_mode) { case BOOT_FROM_SPI: spi_device_mode = get_spi_device_type(reg); if (spi_device_mode) boot_media = BOOT_MEDIA_NAND; else boot_media = BOOT_MEDIA_SPIFLASH; break; case BOOT_FROM_EMMC: /* emmc mode */ boot_media = BOOT_MEDIA_EMMC; break; default: boot_media = BOOT_MEDIA_UNKNOWN; break; } } int board_early_init_f(void) { return 0; } #define UBOOT_DATA_ADDR 0x41000000UL #define UBOOT_DATA_SIZE 0x80000UL int data_to_spiflash(void) { static struct spi_flash *flash = NULL; void *buf = NULL; unsigned int val; /* 0:bus; 0:cs; 1000000:max_hz; 0x3:spi_mode */ flash = spi_flash_probe(0, 0, 1000000, 0x3); if (!flash) { printf("Failed to initialize SPI flash\n"); return -1; /* -1:failed */ } /* erase the address range. */ printf("Spi flash erase...\n"); val = spi_flash_erase(flash, NUM_0, UBOOT_DATA_SIZE); if (val) { printf("SPI flash sector erase failed\n"); return 1; /* 1:failed */ } buf = map_physmem((unsigned long)UBOOT_DATA_ADDR, UBOOT_DATA_SIZE, MAP_WRBACK); if (!buf) { puts("Failed to map physical memory\n"); return 1; /* 1:failed */ } /* copy the data from RAM to FLASH */ printf("Spi flash write...\n"); val = flash->write(flash, NUM_0, UBOOT_DATA_SIZE, buf); if (val) { printf("SPI flash write failed, return %u\n", val); unmap_physmem(buf, UBOOT_DATA_SIZE); return 1; /* 1:failed */ } unmap_physmem(buf, UBOOT_DATA_SIZE); return 0; /* 0:success */ } int data_to_nandflash(void) { struct mtd_info *nand_flash = NULL; void *buf = NULL; size_t length = UBOOT_DATA_SIZE; unsigned int val; nand_flash = nand_info[0]; printf("Nand flash erase...\n"); val = nand_erase(nand_flash, 0, UBOOT_DATA_SIZE); if (val) { printf("Nand flash erase failed\n"); return 1; } buf = map_physmem((unsigned long)UBOOT_DATA_ADDR, UBOOT_DATA_SIZE, MAP_WRBACK); if (!buf) { puts("Failed to map physical memory\n"); return 1; } printf("Nand flash write...\n"); val = nand_write(nand_flash, 0, &length, buf); if (val) { printf("Nand flash write failed, return %u\n", val); unmap_physmem(buf, UBOOT_DATA_SIZE); return 1; } unmap_physmem(buf, UBOOT_DATA_SIZE); return 0; } int data_to_emmc(void) { struct mmc *mmc = find_mmc_device(0); void *buf = NULL; if (!mmc) return 1; (void)mmc_init(mmc); buf = map_physmem((unsigned long)UBOOT_DATA_ADDR, UBOOT_DATA_SIZE, MAP_WRBACK); if (!buf) { puts("Failed to map physical memory\n"); return 1; } printf("MMC write...\n"); blk_dwrite(mmc_get_blk_desc(mmc), 0, (UBOOT_DATA_SIZE >> NUM_9), buf); unmap_physmem(buf, UBOOT_DATA_SIZE); return 0; } int save_bootdata_to_flash(void) { unsigned int sd_update_flag = 0; int ret = 0; sd_update_flag = readl(REG_BASE_SCTL + REG_SC_GEN4); if (sd_update_flag == START_MAGIC) { #if defined(CONFIG_HIFMC) if (boot_media == BOOT_MEDIA_SPIFLASH) { ret = data_to_spiflash(); if (ret != 0) return ret; } if (boot_media == BOOT_MEDIA_NAND) { ret = data_to_nandflash(); if (ret != 0) return ret; } #endif #if defined(CONFIG_SUPPORT_EMMC_BOOT) if (boot_media == BOOT_MEDIA_EMMC) { ret = data_to_emmc(); if (ret != 0) return ret; } #endif printf("update success!\n"); } return 0; } int auto_update_flag = 0; int bare_chip_program = 0; #define REG_BASE_GPIO0 0x120b0000 #define GPIO0_0_DATA_OFST 0x4 #define GPIO_DIR_OFST 0x400 /** upgrade status register address */ #define UPGRADE_STATUS_REG_ADDR 0x120F0048 typedef enum tagUPGRADE_STATUS_E { UPGRADE_STATUS_IDLE = 0, UPGRADE_STATUS_PROCESSING, UPGRADE_STATUS_FINISH, UPGRADE_STATUS_BUTT } upgrade_status_e; int is_bare_program(void) { return 1; } #ifdef CONFIG_AUTO_OTA_UPDATE static bool is_mmc_valid(void) { struct mmc *mmc = NULL; int dev_num = -1; #ifdef CONFIG_EMMC dev_num = 1; #else dev_num = 0; #endif mmc = find_mmc_device(dev_num); if (mmc == NULL) { printf("No mmc %d driver found!\n", dev_num); return false; } if (((unsigned long)mmc->block_dev.vendor[0] == 0) || ((unsigned long)mmc->block_dev.product[0] == 0)) { printf("No SD card found!\n"); return false; } return true; } static bool is_ota_tag_valid(const char *path) { char buf[64] = {0}; /* 32bytes for max in OTA_TAG_FILE */ const char *info = "package_type:ota"; const int len = strlen(info); long sz = file_fat_read(path, (void *)buf, sizeof(buf)); if (sz < len) { printf("%s: not exist, or len %ld invalid\n", path, sz); return false; } if (strncmp(info, buf, len) != 0) { printf("%s info invalid\n", path); return false; } return true; } static bool is_ota(void) { char name[] = "mmc"; int dev = 0; struct blk_desc *stor_dev = NULL; bool valid = false; if (!is_mmc_valid()) { printf("MMC not valid\n"); return false; } stor_dev = blk_get_dev(name, dev); if (stor_dev == NULL) { printf("Unknow device type!\n"); return false; } if (fat_register_device(stor_dev, 1) != 0) { printf("Unable to use %s for fat\n", name); return false; } if (file_fat_detectfs() != 0) { printf("Fat-detectfs failed\n"); return false; } valid = is_ota_tag_valid("/update/OTA.tag"); printf("OTA.tag valid %d\n", valid); return valid; } #endif /* CONFIG_AUTO_OTA_UPDATE */ int is_auto_update(void) { #ifdef CONFIG_AUTO_OTA_UPDATE if (is_ota()) return 1; #else #if (defined CONFIG_AUTO_SD_UPDATE) || (defined CONFIG_AUTO_USB_UPDATE) /* to add some judgement if neccessary */ unsigned int val[NUM_3]; unsigned int *puregval = (unsigned int *)UPGRADE_STATUS_REG_ADDR; if (((*puregval) & (UPGRADE_STATUS_PROCESSING)) != 0) return 1; /* update enable */ writel(0, REG_BASE_GPIO0 + GPIO_DIR_OFST); val[NUM_0] = readl(REG_BASE_GPIO0 + GPIO0_0_DATA_OFST); if (val[NUM_0]) return 0; udelay(10000); /* delay 10000 us */ val[NUM_1] = readl(REG_BASE_GPIO0 + GPIO0_0_DATA_OFST); udelay(10000); /* delay 10000 us */ val[NUM_2] = readl(REG_BASE_GPIO0 + GPIO0_0_DATA_OFST); udelay(10000); /* delay 10000 us */ if (val[NUM_0] == val[NUM_1] && val[NUM_1] == val[NUM_2] && val[NUM_0] == NUM_0) return 1; /* update enable */ else return 0; #endif #endif /* CONFIG_AUTO_OTA_UPDATE */ return 0; } void select_upgrade_dev(void) { #ifdef CONFIG_EMMC unsigned int uval = readl(UPGRADE_STATUS_REG_ADDR); unsigned int stor_dev = 0; unsigned int stor_paration = 0; stor_dev = (uval >> 16) & 0x03; /* 16,0x03: store dev */ stor_paration = (uval >> 18) & 0x1f; /* 18,0x1f: store paration */ if (((uval) & (UPGRADE_STATUS_PROCESSING)) != NUM_0) { /* the upgrade startup by linux application */ if (stor_dev == NUM_0) { /* emmc */ target_dev = NUM_0; target_paratition = stor_paration; } else { /* sd */ target_dev = NUM_1; } } else { /* the upgrade startup by upgrade key on the board, os defaule upgrade style */ target_dev = NUM_1; } printf("update dev is %d: paratition is %d\n", target_dev, target_paratition); #endif return; } int misc_init_r(void) { #ifdef CONFIG_RANDOM_ETHADDR random_init_r(); #endif env_set("verify", "n"); #if (CONFIG_AUTO_UPDATE == 1) /* auto update flag */ if (is_auto_update()) auto_update_flag = NUM_1; else auto_update_flag = NUM_0; /* bare chip program flag */ if (is_bare_program()) bare_chip_program = NUM_1; else bare_chip_program = NUM_0; #ifdef CFG_MMU_HANDLEOK dcache_stop(); #endif #ifdef CFG_MMU_HANDLEOK dcache_start(); #endif #endif #if (CONFIG_AUTO_UPDATE == 1) int update_flag = -1; /* -1:default failed */ if (auto_update_flag) { select_upgrade_dev(); update_flag = do_auto_update(); unsigned int *puregval = (unsigned int *)UPGRADE_STATUS_REG_ADDR; if (((*puregval) & (UPGRADE_STATUS_PROCESSING)) && (update_flag == NUM_0)) { printf("upgrade status: finish\n"); *puregval = UPGRADE_STATUS_FINISH; } } if (bare_chip_program && !auto_update_flag) save_bootdata_to_flash(); if (update_flag == NUM_0) do_reset(NULL, 0, 0, NULL); #endif return 0; } int board_init(void) { DECLARE_GLOBAL_DATA_PTR; gd->bd->bi_arch_number = MACH_TYPE_HI3518EV300; gd->bd->bi_boot_params = CFG_BOOT_PARAMS; boot_flag_init(); return 0; } int dram_init(void) { DECLARE_GLOBAL_DATA_PTR; gd->ram_size = PHYS_SDRAM_1_SIZE; return 0; } void reset_cpu(ulong addr) { /* 0x12345678:writing any value will cause a reset. */ writel(0x12345678, REG_BASE_SCTL + REG_SC_SYSRES); while (1); } int timer_init(void) { /* * Under uboot, 0xffffffff is set to load register, * timer_clk equals BUSCLK/2/256. * e.g. BUSCLK equals 50M, it will roll back after 0xffffffff/timer_clk * 43980s equals 12hours */ __raw_writel(0, CFG_TIMERBASE + REG_TIMER_CONTROL); __raw_writel(~0, CFG_TIMERBASE + REG_TIMER_RELOAD); /* 32 bit, periodic */ __raw_writel(CFG_TIMER_CTRL, CFG_TIMERBASE + REG_TIMER_CONTROL); return 0; } int board_eth_init(bd_t *bis) { int rc = 0; #ifdef CONFIG_HISFV300_ETH rc = hieth_initialize(bis); #endif return rc; } #ifdef CONFIG_GENERIC_MMC int board_mmc_init(bd_t *bis) { int ret = 0; #ifdef CONFIG_HISI_SDHCI #ifndef CONFIG_HIFMC ret = hisi_sdhci_add_port(0, EMMC_BASE_REG, MMC_TYPE_MMC); if (!ret) { ret = hisi_mmc_init(0); if (ret) printf("No EMMC device found !\n"); } #else #ifdef CONFIG_AUTO_SD_UPDATE ret = hisi_sdhci_add_port(0, SDIO0_BASE_REG, MMC_TYPE_SD); if (ret) return ret; ret = hisi_mmc_init(0); if (ret) printf("No SD device found !\n"); #endif #endif #endif return ret; } #endif #ifdef CONFIG_ARMV7_NONSEC void smp_set_core_boot_addr(unsigned long addr, int corenr) { } void smp_kick_all_cpus(void) { } void smp_waitloop(unsigned previous_address) { } #endif