/* * Copyright (c) 2016-2020, Broadcom * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_GPIO #include #include #endif #include #include #include #include #ifdef USE_DDR #include #else #include #endif #if DRIVER_OCOTP_ENABLE #include #endif #include "board_info.h" #define WORD_SIZE 8 #define SWREG_AVS_OTP_OFFSET (13 * WORD_SIZE) /* 13th row byte offset */ #define AON_GPIO_OTP_OFFSET (28 * WORD_SIZE) /* 28th row byte offset */ #define BYTES_TO_READ 8 /* OTP voltage step definitions */ #define MVOLT_STEP_MAX 0x18 /* 1v */ #define MVOLT_PER_STEP 10 /* 0.01mv per step */ #define MVOLT_BASE 760 /* 0.76v */ #define STEP_TO_UVOLTS(step) \ ((MVOLT_BASE + (MVOLT_PER_STEP * (step))) * 1000) #define GET_BITS(first, last, data) \ ((data >> first) & ((1 << (last - first + 1)) - 1)) /* * SW-REG OTP encoding: * * SWREG_bits[11:0] = OTP 13th row 12 bits[55:44] * SWREG_bits[11:10] - Valid Bits (0x2 - valid, if not 0x2 - Invalid) * SWREG_bits[9:5] - iHost03, iHost12 * SWREG_bits[4:0] - Core VDDC */ #define SWREG_OTP_BITS_START 12 /* 44th bit in MSB 32-bits */ #define SWREG_OTP_BITS_END 23 /* 55th bit in MSB 32-bits */ #define SWREG_VDDC_FIELD_START 0 #define SWREG_VDDC_FIELD_END 4 #define SWREG_IHOST_FIELD_START 5 #define SWREG_IHOST_FIELD_END 9 #define SWREG_VALID_BIT_START 10 #define SWREG_VALID_BIT_END 11 #define SWREG_VALID_BITS 0x2 /* * Row 13 bit 56 is programmed as '1' today. It is not being used, so plan * is to flip this bit to '0' for B1 rev. Hence SW can leverage this bit * to identify Bx chip to program different sw-regulators. */ #define SPARE_BIT 24 #define IS_SR_B0(data) (((data) >> SPARE_BIT) & 0x1) #if DRIVER_OCOTP_ENABLE static struct otpc_map otp_stingray_map = { .otpc_row_size = 2, .data_r_offset = {0x10, 0x5c}, .data_w_offset = {0x2c, 0x64}, .word_size = 8, .stride = 8, }; #endif void plat_bcm_bl2_early_platform_setup(void) { /* Select UART0 for AP via mux setting*/ if (PLAT_BRCM_BOOT_UART_BASE == UART0_BASE_ADDR) { mmio_write_32(UART0_SIN_MODE_SEL_CONTROL, 1); mmio_write_32(UART0_SOUT_MODE_SEL_CONTROL, 1); } } #ifdef USE_NAND static void brcm_stingray_nand_init(void) { unsigned int val; unsigned int nand_idm_reset_control = 0x68e0a800; VERBOSE(" stingray nand init start.\n"); /* Reset NAND */ VERBOSE(" - reset nand\n"); val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0)); mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val | 0x1); udelay(500); val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0)); mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val & ~0x1); udelay(500); VERBOSE(" stingray nand init done.\n"); } #endif #if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA) #define PCIE_RESCAL_CFG_0 0x40000130 #define PCIE_CFG_RESCAL_RSTB_R (1 << 16) #define PCIE_CFG_RESCAL_PWRDNB_R (1 << 8) #define PCIE_RESCAL_STATUS_0 0x4000014c #define PCIE_STAT_PON_VALID_R (1 << 0) #define PCIE_RESCAL_OUTPUT_STATUS 0x40000154 #define CDRU_PCIE_RESET_N_R (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R) #ifdef EMULATION_SETUP static void brcm_stingray_pcie_reset(void) { } #else static void brcm_stingray_pcie_reset(void) { unsigned int data; int try; if (bcm_chimp_is_nic_mode()) { INFO("NIC mode detected; PCIe reset/rescal not executed\n"); return; } mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R); mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R); /* Release reset */ mmio_setbits_32(PCIE_RESCAL_CFG_0, PCIE_CFG_RESCAL_RSTB_R); mdelay(1); /* Power UP */ mmio_setbits_32(PCIE_RESCAL_CFG_0, (PCIE_CFG_RESCAL_RSTB_R | PCIE_CFG_RESCAL_PWRDNB_R)); try = 1000; do { udelay(1); data = mmio_read_32(PCIE_RESCAL_STATUS_0); try--; } while ((data & PCIE_STAT_PON_VALID_R) == 0x0 && (try > 0)); if (try <= 0) ERROR("PCIE_RESCAL_STATUS_0: 0x%x\n", data); VERBOSE("PCIE_SATA_RESCAL_STATUS_0 0x%x.\n", mmio_read_32(PCIE_RESCAL_STATUS_0)); VERBOSE("PCIE_SATA_RESCAL_OUTPUT_STATUS 0x%x.\n", mmio_read_32(PCIE_RESCAL_OUTPUT_STATUS)); INFO("PCIE SATA Rescal Init done\n"); } #endif /* EMULATION_SETUP */ #endif /* USE_PAXB || USE_PAXC || USE_SATA */ #ifdef USE_PAXC void brcm_stingray_chimp_check_and_fastboot(void) { int fastboot_init_result; if (bcm_chimp_is_nic_mode()) /* Do not wait here */ return; #if WARMBOOT_DDR_S3_SUPPORT /* * Currently DDR shmoo parameters and QSPI boot source are * tied. DDR shmoo parameters are stored in QSPI, which is * used for warmboot. * Do not reset nitro for warmboot */ if (is_warmboot() && (boot_source_get() == BOOT_SOURCE_QSPI)) return; #endif /* WARMBOOT_DDR_S3_SUPPORT */ /* * Not in NIC mode, * initiate fastboot (if enabled) */ if (FASTBOOT_TYPE == CHIMP_FASTBOOT_NITRO_RESET) { VERBOSE("Bring up Nitro/ChiMP\n"); if (boot_source_get() == BOOT_SOURCE_QSPI) WARN("Nitro boots from QSPI when AP has booted from QSPI.\n"); brcm_stingray_set_qspi_mux(0); VERBOSE("Nitro controls the QSPI\n"); } fastboot_init_result = bcm_chimp_initiate_fastboot(FASTBOOT_TYPE); if (fastboot_init_result && boot_source_get() != BOOT_SOURCE_QSPI) ERROR("Nitro init error %d. Status: 0x%x; bpe_mod reg: 0x%x\n" "fastboot register: 0x%x; handshake register 0x%x\n", fastboot_init_result, bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG), bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG), bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG), bcm_chimp_read(CHIMP_REG_ECO_RESERVED)); /* * CRMU watchdog kicks is an example, which is L1 reset, * does not clear Nitro scratch pad ram. * For Nitro resets: Clear the Nitro health status memory. */ bcm_chimp_write((CHIMP_REG_CHIMP_SCPAD + CHIMP_HEALTH_STATUS_OFFSET), 0); } #endif void set_ihost_vddc_swreg(uint32_t ihost_uvolts, uint32_t vddc_uvolts) { NOTICE("ihost_uvolts: %duv, vddc_uvolts: %duv\n", ihost_uvolts, vddc_uvolts); set_swreg(VDDC_CORE, vddc_uvolts); set_swreg(IHOST03, ihost_uvolts); set_swreg(IHOST12, ihost_uvolts); } /* * Reads SWREG AVS OTP bits (13th row) with ECC enabled and get voltage * defined in OTP if valid OTP is found */ void read_avs_otp_bits(uint32_t *ihost_uvolts, uint32_t *vddc_uvolts) { uint32_t offset = SWREG_AVS_OTP_OFFSET; uint32_t ihost_step, vddc_step; uint32_t avs_bits; uint32_t buf[2]; if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1) return; VERBOSE("AVS OTP %d ROW: 0x%x.0x%x\n", offset/WORD_SIZE, buf[1], buf[0]); /* get voltage readings from AVS OTP bits */ avs_bits = GET_BITS(SWREG_OTP_BITS_START, SWREG_OTP_BITS_END, buf[1]); /* check for valid otp bits */ if (GET_BITS(SWREG_VALID_BIT_START, SWREG_VALID_BIT_END, avs_bits) != SWREG_VALID_BITS) { WARN("Invalid AVS OTP bits at %d row\n", offset/WORD_SIZE); return; } /* get ihost and vddc step value */ vddc_step = GET_BITS(SWREG_VDDC_FIELD_START, SWREG_VDDC_FIELD_END, avs_bits); ihost_step = GET_BITS(SWREG_IHOST_FIELD_START, SWREG_IHOST_FIELD_END, avs_bits); if ((ihost_step > MVOLT_STEP_MAX) || (vddc_step > MVOLT_STEP_MAX)) { WARN("OTP entry invalid\n"); return; } /* get voltage in micro-volts */ *ihost_uvolts = STEP_TO_UVOLTS(ihost_step); *vddc_uvolts = STEP_TO_UVOLTS(vddc_step); } /* * This api reads otp bits and program internal swreg's - ihos12, ihost03, * vddc_core and ddr_core based on different chip. External swreg's * programming will be done from crmu. * * For A2 chip: * Read OTP row 20, bit 50. This bit will be set for A2 chip. Once A2 chip is * found, read AVS OTP row 13, 12bits[55:44], if valid otp bits are found * then set ihost and vddc according to avs otp bits else set them to 0.94v * and 0.91v respectively. Also update the firmware after setting voltage. * * For B0 chip: * Read OTP row 13, bit 56. This bit will be set for B0 chip. Once B0 chip is * found then set ihost and vddc to 0.95v and ddr_core to 1v. No AVS OTP bits * are used get ihost/vddc voltages. * * For B1 chip: * Read AVS OTP row 13, 12bits[55:44], if valid otp bits are found then set * ihost and vddc according to avs otp bits else set them to 0.94v and 0.91v * respectively. */ void set_swreg_based_on_otp(void) { /* default voltage if no valid OTP */ uint32_t vddc_uvolts = VDDC_CORE_DEF_VOLT; uint32_t ihost_uvolts = IHOST_DEF_VOLT; uint32_t ddrc_uvolts; uint32_t offset; uint32_t buf[2]; offset = SWREG_AVS_OTP_OFFSET; if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1) return; VERBOSE("OTP %d ROW: 0x%x.0x%x\n", offset/WORD_SIZE, buf[1], buf[0]); if (IS_SR_B0(buf[1])) { /* don't read AVS OTP for B0 */ ihost_uvolts = B0_IHOST_DEF_VOLT; vddc_uvolts = B0_VDDC_CORE_DEF_VOLT; ddrc_uvolts = B0_DDR_VDDC_DEF_VOLT; } else { read_avs_otp_bits(&ihost_uvolts, &vddc_uvolts); } #if (IHOST_REG_TYPE == IHOST_REG_INTEGRATED) && \ (VDDC_REG_TYPE == VDDC_REG_INTEGRATED) /* enable IHOST12 cluster before changing voltage */ NOTICE("Switching on the Regulator idx: %u\n", SWREG_IHOST1_DIS); mmio_clrsetbits_32(CRMU_SWREG_CTRL_ADDR, BIT(SWREG_IHOST1_DIS), BIT(SWREG_IHOST1_REG_RESETB)); /* wait for regulator supply gets stable */ while (!(mmio_read_32(CRMU_SWREG_STATUS_ADDR) & (1 << SWREG_IHOST1_PMU_STABLE))) ; INFO("Regulator supply got stable\n"); #ifndef DEFAULT_SWREG_CONFIG swreg_firmware_update(); #endif set_ihost_vddc_swreg(ihost_uvolts, vddc_uvolts); #endif if (IS_SR_B0(buf[1])) { NOTICE("ddrc_uvolts: %duv\n", ddrc_uvolts); set_swreg(DDR_VDDC, ddrc_uvolts); } } #ifdef USE_DDR static struct ddr_info ddr_info; #endif #ifdef USE_FRU static struct fru_area_info fru_area[FRU_MAX_NR_AREAS]; static struct fru_board_info board_info; static struct fru_time fru_tm; static uint8_t fru_tbl[BCM_MAX_FRU_LEN]; static void board_detect_fru(void) { uint32_t i, result; int ret = -1; result = bcm_emmc_init(false); if (!result) { ERROR("eMMC init failed\n"); return; } /* go through eMMC boot partitions looking for FRU table */ for (i = EMMC_BOOT_PARTITION1; i <= EMMC_BOOT_PARTITION2; i++) { result = emmc_partition_select(i); if (!result) { ERROR("Switching to eMMC part %u failed\n", i); return; } result = emmc_read(BCM_FRU_TBL_OFFSET, (uintptr_t)fru_tbl, BCM_MAX_FRU_LEN, BCM_MAX_FRU_LEN); if (!result) { ERROR("Failed to read from eMMC part %u\n", i); return; } /* * Run sanity check and checksum to make sure valid FRU table * is detected */ ret = fru_validate(fru_tbl, fru_area); if (ret < 0) { WARN("FRU table not found in eMMC part %u\n", i); continue; } /* parse DDR information from FRU table */ ret = fru_parse_ddr(fru_tbl, &fru_area[FRU_AREA_INTERNAL], &ddr_info); if (ret < 0) { WARN("No FRU DDR info found in eMMC part %u\n", i); continue; } /* parse board information from FRU table */ ret = fru_parse_board(fru_tbl, &fru_area[FRU_AREA_BOARD_INFO], &board_info); if (ret < 0) { WARN("No FRU board info found in eMMC part %u\n", i); continue; } /* if we reach here, valid FRU table is parsed */ break; } if (ret < 0) { WARN("FRU table missing for this board\n"); return; } for (i = 0; i < BCM_MAX_NR_DDR; i++) { INFO("DDR channel index: %d\n", ddr_info.mcb[i].idx); INFO("DDR size %u GB\n", ddr_info.mcb[i].size_mb / 1024); INFO("DDR ref ID by SW (Not MCB Ref ID) 0x%x\n", ddr_info.mcb[i].ref_id); } fru_format_time(board_info.mfg_date, &fru_tm); INFO("**** FRU board information ****\n"); INFO("Language 0x%x\n", board_info.lang); INFO("Manufacturing Date %u.%02u.%02u, %02u:%02u\n", fru_tm.year, fru_tm.month, fru_tm.day, fru_tm.hour, fru_tm.min); INFO("Manufacturing Date(Raw) 0x%x\n", board_info.mfg_date); INFO("Manufacturer %s\n", board_info.manufacturer); INFO("Product Name %s\n", board_info.product_name); INFO("Serial number %s\n", board_info.serial_number); INFO("Part number %s\n", board_info.part_number); INFO("File ID %s\n", board_info.file_id); } #endif /* USE_FRU */ #ifdef USE_GPIO #define INVALID_GPIO 0xffff static const int gpio_cfg_bitmap[MAX_NR_GPIOS] = { #ifdef BRD_DETECT_GPIO_BIT0 BRD_DETECT_GPIO_BIT0, #else INVALID_GPIO, #endif #ifdef BRD_DETECT_GPIO_BIT1 BRD_DETECT_GPIO_BIT1, #else INVALID_GPIO, #endif #ifdef BRD_DETECT_GPIO_BIT2 BRD_DETECT_GPIO_BIT2, #else INVALID_GPIO, #endif #ifdef BRD_DETECT_GPIO_BIT3 BRD_DETECT_GPIO_BIT3, #else INVALID_GPIO, #endif }; static uint8_t gpio_bitmap; /* * Use an odd number to avoid potential conflict with public GPIO level * defines */ #define GPIO_STATE_FLOAT 15 /* * If GPIO_SUPPORT_FLOAT_DETECTION is disabled, simply return GPIO level * * If GPIO_SUPPORT_FLOAT_DETECTION is enabled, add additional test for possible * pin floating (unconnected) scenario. This support is assuming externally * applied pull up / pull down will have a stronger pull than the internal pull * up / pull down. */ static uint8_t gpio_get_state(int gpio) { uint8_t val; /* set direction to GPIO input */ gpio_set_direction(gpio, GPIO_DIR_IN); #ifndef GPIO_SUPPORT_FLOAT_DETECTION if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH) val = GPIO_LEVEL_HIGH; else val = GPIO_LEVEL_LOW; return val; #else /* * Enable internal pull down. If GPIO level is still high, there must * be an external pull up */ gpio_set_pull(gpio, GPIO_PULL_DOWN); if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH) { val = GPIO_LEVEL_HIGH; goto exit; } /* * Enable internal pull up. If GPIO level is still low, there must * be an external pull down */ gpio_set_pull(gpio, GPIO_PULL_UP); if (gpio_get_value(gpio) == GPIO_LEVEL_LOW) { val = GPIO_LEVEL_LOW; goto exit; } /* if reached here, the pin must be not connected */ val = GPIO_STATE_FLOAT; exit: /* make sure internall pull is disabled */ if (gpio_get_pull(gpio) != GPIO_PULL_NONE) gpio_set_pull(gpio, GPIO_PULL_NONE); return val; #endif } static void board_detect_gpio(void) { unsigned int i, val; int gpio; iproc_gpio_init(IPROC_GPIO_S_BASE, IPROC_GPIO_NR, IPROC_IOPAD_MODE_BASE, HSLS_IOPAD_BASE); gpio_bitmap = 0; for (i = 0; i < MAX_NR_GPIOS; i++) { if (gpio_cfg_bitmap[i] == INVALID_GPIO) continue; /* * Construct the bitmap based on GPIO value. Floating pin * detection is a special case. As soon as a floating pin is * detected, a special value of MAX_GPIO_BITMAP_VAL is * assigned and we break out of the loop immediately */ gpio = gpio_cfg_bitmap[i]; val = gpio_get_state(gpio); if (val == GPIO_STATE_FLOAT) { gpio_bitmap = MAX_GPIO_BITMAP_VAL; break; } if (val == GPIO_LEVEL_HIGH) gpio_bitmap |= BIT(i); } memcpy(&ddr_info, &gpio_ddr_info[gpio_bitmap], sizeof(ddr_info)); INFO("Board detection GPIO bitmap = 0x%x\n", gpio_bitmap); } #endif /* USE_GPIO */ static void bcm_board_detect(void) { #ifdef DDR_LEGACY_MCB_SUPPORTED /* Loading default DDR info */ memcpy(&ddr_info, &default_ddr_info, sizeof(ddr_info)); #endif #ifdef USE_FRU board_detect_fru(); #endif #ifdef USE_GPIO board_detect_gpio(); #endif } static void dump_persistent_regs(void) { NOTICE("pr0: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG0)); NOTICE("pr1: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1)); NOTICE("pr2: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG2)); NOTICE("pr3: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG3)); NOTICE("pr4: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG4)); NOTICE("pr5: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG5)); NOTICE("pr6: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG6)); NOTICE("pr7: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG7)); NOTICE("pr8: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG8)); NOTICE("pr9: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9)); NOTICE("pr10: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG10)); NOTICE("pr11: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG11)); } void plat_bcm_bl2_plat_arch_setup(void) { if (chip_get_rev_id_major() == CHIP_REV_MAJOR_AX) { if (!(sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) & SOTP_ATF_WATCHDOG_ENABLE_MASK)) { /* * Stop sp805 watchdog timer immediately. * It might has been set up by MCU patch earlier for * eMMC workaround. * * Note the watchdog timer started in CRMU has a very * short timeout and needs to be stopped immediately. * Down below we restart it with a much longer timeout * for BL2 and BL31 */ sp805_stop(ARM_SP805_TWDG_BASE); } } #if !BRCM_DISABLE_TRUSTED_WDOG /* * start secure watchdog for BL2 and BL31. * Note that UART download can take a longer time, * so do not allow watchdog for UART download, * as this boot source is not a standard modus operandi. */ if (boot_source_get() != BOOT_SOURCE_UART) sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); #endif #ifdef BCM_ELOG /* Ensure logging is started out fresh in BL2. */ mmio_write_32(BCM_ELOG_BL2_BASE, 0); #endif /* * In BL2, since we have very limited space to store logs, we only * save logs that are >= the WARNING level. */ bcm_elog_init((void *)BCM_ELOG_BL2_BASE, BCM_ELOG_BL2_SIZE, LOG_LEVEL_WARNING); dump_persistent_regs(); /* Read CRMU mailbox 0 */ NOTICE("RESET (reported by CRMU): 0x%x\n", mmio_read_32(CRMU_READ_MAIL_BOX0)); /* * All non-boot-source PADs are in forced input-mode at * reset so clear the force on non-boot-source PADs using * CDRU register. */ mmio_clrbits_32((uintptr_t)CDRU_CHIP_IO_PAD_CONTROL, (1 << CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R)); #if DRIVER_OCOTP_ENABLE bcm_otpc_init(&otp_stingray_map); #endif set_swreg_based_on_otp(); #if IHOST_PLL_FREQ != 0 bcm_set_ihost_pll_freq(0x0, IHOST_PLL_FREQ); #endif #ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE /* The erasable unit of the eMMC is the "Erase Group"; * Erase group is measured in write blocks which are the * basic writable units of the Device. * The size of the Erase Group is a Device specific parameter */ emmc_erase(EMMC_ERASE_START_BLOCK, EMMC_ERASE_BLOCK_COUNT, EMMC_ERASE_PARTITION); #endif bcm_board_detect(); #ifdef DRIVER_EMMC_ENABLE /* Initialize the card, if it is not */ if (bcm_emmc_init(true) == 0) WARN("eMMC Card Initialization Failed!!!\n"); #endif #if BL2_TEST_I2C i2c_test(); #endif #ifdef USE_DDR ddr_initialize(&ddr_info); ddr_secure_region_config(SECURE_DDR_BASE_ADDRESS, SECURE_DDR_END_ADDRESS); #ifdef NITRO_SECURE_ACCESS ddr_secure_region_config(DDR_NITRO_SECURE_REGION_START, DDR_NITRO_SECURE_REGION_END); #endif #else ext_sram_init(); #endif #if BL2_TEST_MEM ddr_test(); #endif #ifdef USE_NAND brcm_stingray_nand_init(); #endif #if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA) brcm_stingray_pcie_reset(); #endif #ifdef USE_PAXC if (boot_source_get() != BOOT_SOURCE_QSPI) brcm_stingray_chimp_check_and_fastboot(); #endif #if ((!CLEAN_DDR || MMU_DISABLED)) /* * Now DDR has been initialized. We want to copy all the logs in SRAM * into DDR so we will have much more space to store the logs in the * next boot stage */ bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE, MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE) ); /* * We are not yet at the end of BL2, but we can stop log here so we do * not need to add 'bcm_elog_exit' to the standard BL2 code. The * benefit of capturing BL2 logs after this is very minimal in a * production system * NOTE: BL2 logging must be exited before going forward to setup * page tables */ bcm_elog_exit(); #endif }