1f29d1e0cSSheetal Tigadoli /* 2f29d1e0cSSheetal Tigadoli * Copyright (c) 2016-2020, Broadcom 3f29d1e0cSSheetal Tigadoli * 4f29d1e0cSSheetal Tigadoli * SPDX-License-Identifier: BSD-3-Clause 5f29d1e0cSSheetal Tigadoli */ 6f29d1e0cSSheetal Tigadoli 7f29d1e0cSSheetal Tigadoli #include <arch_helpers.h> 8f29d1e0cSSheetal Tigadoli #include <common/bl_common.h> 9f29d1e0cSSheetal Tigadoli #include <common/debug.h> 10f29d1e0cSSheetal Tigadoli #include <drivers/arm/sp805.h> 11f29d1e0cSSheetal Tigadoli #include <drivers/delay_timer.h> 12f29d1e0cSSheetal Tigadoli #include <lib/mmio.h> 13f29d1e0cSSheetal Tigadoli 14f29d1e0cSSheetal Tigadoli #include <chimp.h> 15f29d1e0cSSheetal Tigadoli #include <chip_id.h> 16f29d1e0cSSheetal Tigadoli #include <cmn_plat_util.h> 17f29d1e0cSSheetal Tigadoli #include <dmu.h> 18bffde63dSSheetal Tigadoli #include <emmc_api.h> 19f29d1e0cSSheetal Tigadoli #include <fru.h> 20f29d1e0cSSheetal Tigadoli #ifdef USE_GPIO 21f29d1e0cSSheetal Tigadoli #include <drivers/gpio.h> 22f29d1e0cSSheetal Tigadoli #include <iproc_gpio.h> 23f29d1e0cSSheetal Tigadoli #endif 24f29d1e0cSSheetal Tigadoli #include <platform_def.h> 25f29d1e0cSSheetal Tigadoli #include <sotp.h> 26f29d1e0cSSheetal Tigadoli #include <swreg.h> 27f29d1e0cSSheetal Tigadoli #include <sr_utils.h> 28f29d1e0cSSheetal Tigadoli #ifdef USE_DDR 29f29d1e0cSSheetal Tigadoli #include <ddr_init.h> 30f29d1e0cSSheetal Tigadoli #else 31f29d1e0cSSheetal Tigadoli #include <ext_sram_init.h> 32f29d1e0cSSheetal Tigadoli #endif 33f29d1e0cSSheetal Tigadoli #if DRIVER_OCOTP_ENABLE 34f29d1e0cSSheetal Tigadoli #include <ocotp.h> 35f29d1e0cSSheetal Tigadoli #endif 36f29d1e0cSSheetal Tigadoli #include "board_info.h" 37f29d1e0cSSheetal Tigadoli 38f29d1e0cSSheetal Tigadoli #define WORD_SIZE 8 39f29d1e0cSSheetal Tigadoli #define SWREG_AVS_OTP_OFFSET (13 * WORD_SIZE) /* 13th row byte offset */ 40f29d1e0cSSheetal Tigadoli #define AON_GPIO_OTP_OFFSET (28 * WORD_SIZE) /* 28th row byte offset */ 41f29d1e0cSSheetal Tigadoli #define BYTES_TO_READ 8 42f29d1e0cSSheetal Tigadoli 43f29d1e0cSSheetal Tigadoli /* OTP voltage step definitions */ 44f29d1e0cSSheetal Tigadoli #define MVOLT_STEP_MAX 0x18 /* 1v */ 45f29d1e0cSSheetal Tigadoli #define MVOLT_PER_STEP 10 /* 0.01mv per step */ 46f29d1e0cSSheetal Tigadoli #define MVOLT_BASE 760 /* 0.76v */ 47f29d1e0cSSheetal Tigadoli 48f29d1e0cSSheetal Tigadoli #define STEP_TO_UVOLTS(step) \ 49f29d1e0cSSheetal Tigadoli ((MVOLT_BASE + (MVOLT_PER_STEP * (step))) * 1000) 50f29d1e0cSSheetal Tigadoli 51f29d1e0cSSheetal Tigadoli #define GET_BITS(first, last, data) \ 52f29d1e0cSSheetal Tigadoli ((data >> first) & ((1 << (last - first + 1)) - 1)) 53f29d1e0cSSheetal Tigadoli 54f29d1e0cSSheetal Tigadoli /* 55f29d1e0cSSheetal Tigadoli * SW-REG OTP encoding: 56f29d1e0cSSheetal Tigadoli * 57f29d1e0cSSheetal Tigadoli * SWREG_bits[11:0] = OTP 13th row 12 bits[55:44] 58f29d1e0cSSheetal Tigadoli * SWREG_bits[11:10] - Valid Bits (0x2 - valid, if not 0x2 - Invalid) 59f29d1e0cSSheetal Tigadoli * SWREG_bits[9:5] - iHost03, iHost12 60f29d1e0cSSheetal Tigadoli * SWREG_bits[4:0] - Core VDDC 61f29d1e0cSSheetal Tigadoli */ 62f29d1e0cSSheetal Tigadoli #define SWREG_OTP_BITS_START 12 /* 44th bit in MSB 32-bits */ 63f29d1e0cSSheetal Tigadoli #define SWREG_OTP_BITS_END 23 /* 55th bit in MSB 32-bits */ 64f29d1e0cSSheetal Tigadoli #define SWREG_VDDC_FIELD_START 0 65f29d1e0cSSheetal Tigadoli #define SWREG_VDDC_FIELD_END 4 66f29d1e0cSSheetal Tigadoli #define SWREG_IHOST_FIELD_START 5 67f29d1e0cSSheetal Tigadoli #define SWREG_IHOST_FIELD_END 9 68f29d1e0cSSheetal Tigadoli #define SWREG_VALID_BIT_START 10 69f29d1e0cSSheetal Tigadoli #define SWREG_VALID_BIT_END 11 70f29d1e0cSSheetal Tigadoli #define SWREG_VALID_BITS 0x2 71f29d1e0cSSheetal Tigadoli 72f29d1e0cSSheetal Tigadoli /* 73f29d1e0cSSheetal Tigadoli * Row 13 bit 56 is programmed as '1' today. It is not being used, so plan 74f29d1e0cSSheetal Tigadoli * is to flip this bit to '0' for B1 rev. Hence SW can leverage this bit 75f29d1e0cSSheetal Tigadoli * to identify Bx chip to program different sw-regulators. 76f29d1e0cSSheetal Tigadoli */ 77f29d1e0cSSheetal Tigadoli #define SPARE_BIT 24 78f29d1e0cSSheetal Tigadoli 79f29d1e0cSSheetal Tigadoli #define IS_SR_B0(data) (((data) >> SPARE_BIT) & 0x1) 80f29d1e0cSSheetal Tigadoli 81f29d1e0cSSheetal Tigadoli #if DRIVER_OCOTP_ENABLE 82f29d1e0cSSheetal Tigadoli static struct otpc_map otp_stingray_map = { 83f29d1e0cSSheetal Tigadoli .otpc_row_size = 2, 84f29d1e0cSSheetal Tigadoli .data_r_offset = {0x10, 0x5c}, 85f29d1e0cSSheetal Tigadoli .data_w_offset = {0x2c, 0x64}, 86f29d1e0cSSheetal Tigadoli .word_size = 8, 87f29d1e0cSSheetal Tigadoli .stride = 8, 88f29d1e0cSSheetal Tigadoli }; 89f29d1e0cSSheetal Tigadoli #endif 90f29d1e0cSSheetal Tigadoli 91f29d1e0cSSheetal Tigadoli void plat_bcm_bl2_early_platform_setup(void) 92f29d1e0cSSheetal Tigadoli { 93f29d1e0cSSheetal Tigadoli /* Select UART0 for AP via mux setting*/ 94f29d1e0cSSheetal Tigadoli if (PLAT_BRCM_BOOT_UART_BASE == UART0_BASE_ADDR) { 95f29d1e0cSSheetal Tigadoli mmio_write_32(UART0_SIN_MODE_SEL_CONTROL, 1); 96f29d1e0cSSheetal Tigadoli mmio_write_32(UART0_SOUT_MODE_SEL_CONTROL, 1); 97f29d1e0cSSheetal Tigadoli } 98f29d1e0cSSheetal Tigadoli } 99f29d1e0cSSheetal Tigadoli 100f29d1e0cSSheetal Tigadoli #ifdef USE_NAND 101f29d1e0cSSheetal Tigadoli static void brcm_stingray_nand_init(void) 102f29d1e0cSSheetal Tigadoli { 103f29d1e0cSSheetal Tigadoli unsigned int val; 104f29d1e0cSSheetal Tigadoli unsigned int nand_idm_reset_control = 0x68e0a800; 105f29d1e0cSSheetal Tigadoli 106f29d1e0cSSheetal Tigadoli VERBOSE(" stingray nand init start.\n"); 107f29d1e0cSSheetal Tigadoli 108f29d1e0cSSheetal Tigadoli /* Reset NAND */ 109f29d1e0cSSheetal Tigadoli VERBOSE(" - reset nand\n"); 110f29d1e0cSSheetal Tigadoli val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0)); 111f29d1e0cSSheetal Tigadoli mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val | 0x1); 112f29d1e0cSSheetal Tigadoli udelay(500); 113f29d1e0cSSheetal Tigadoli val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0)); 114f29d1e0cSSheetal Tigadoli mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val & ~0x1); 115f29d1e0cSSheetal Tigadoli udelay(500); 116f29d1e0cSSheetal Tigadoli 117f29d1e0cSSheetal Tigadoli VERBOSE(" stingray nand init done.\n"); 118f29d1e0cSSheetal Tigadoli } 119f29d1e0cSSheetal Tigadoli #endif 120f29d1e0cSSheetal Tigadoli 121f29d1e0cSSheetal Tigadoli #if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA) 122f29d1e0cSSheetal Tigadoli #define PCIE_RESCAL_CFG_0 0x40000130 123f29d1e0cSSheetal Tigadoli #define PCIE_CFG_RESCAL_RSTB_R (1 << 16) 124f29d1e0cSSheetal Tigadoli #define PCIE_CFG_RESCAL_PWRDNB_R (1 << 8) 125f29d1e0cSSheetal Tigadoli #define PCIE_RESCAL_STATUS_0 0x4000014c 126f29d1e0cSSheetal Tigadoli #define PCIE_STAT_PON_VALID_R (1 << 0) 127f29d1e0cSSheetal Tigadoli #define PCIE_RESCAL_OUTPUT_STATUS 0x40000154 128f29d1e0cSSheetal Tigadoli #define CDRU_PCIE_RESET_N_R (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R) 129f29d1e0cSSheetal Tigadoli 130f29d1e0cSSheetal Tigadoli #ifdef EMULATION_SETUP 131f29d1e0cSSheetal Tigadoli static void brcm_stingray_pcie_reset(void) 132f29d1e0cSSheetal Tigadoli { 133f29d1e0cSSheetal Tigadoli } 134f29d1e0cSSheetal Tigadoli #else 135f29d1e0cSSheetal Tigadoli static void brcm_stingray_pcie_reset(void) 136f29d1e0cSSheetal Tigadoli { 137f29d1e0cSSheetal Tigadoli unsigned int data; 138f29d1e0cSSheetal Tigadoli int try; 139f29d1e0cSSheetal Tigadoli 140f29d1e0cSSheetal Tigadoli if (bcm_chimp_is_nic_mode()) { 141f29d1e0cSSheetal Tigadoli INFO("NIC mode detected; PCIe reset/rescal not executed\n"); 142f29d1e0cSSheetal Tigadoli return; 143f29d1e0cSSheetal Tigadoli } 144f29d1e0cSSheetal Tigadoli 145f29d1e0cSSheetal Tigadoli mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R); 146f29d1e0cSSheetal Tigadoli mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R); 147f29d1e0cSSheetal Tigadoli /* Release reset */ 148f29d1e0cSSheetal Tigadoli mmio_setbits_32(PCIE_RESCAL_CFG_0, PCIE_CFG_RESCAL_RSTB_R); 149f29d1e0cSSheetal Tigadoli mdelay(1); 150f29d1e0cSSheetal Tigadoli /* Power UP */ 151f29d1e0cSSheetal Tigadoli mmio_setbits_32(PCIE_RESCAL_CFG_0, 152f29d1e0cSSheetal Tigadoli (PCIE_CFG_RESCAL_RSTB_R | PCIE_CFG_RESCAL_PWRDNB_R)); 153f29d1e0cSSheetal Tigadoli 154f29d1e0cSSheetal Tigadoli try = 1000; 155f29d1e0cSSheetal Tigadoli do { 156f29d1e0cSSheetal Tigadoli udelay(1); 157f29d1e0cSSheetal Tigadoli data = mmio_read_32(PCIE_RESCAL_STATUS_0); 158f29d1e0cSSheetal Tigadoli try--; 159f29d1e0cSSheetal Tigadoli } while ((data & PCIE_STAT_PON_VALID_R) == 0x0 && (try > 0)); 160f29d1e0cSSheetal Tigadoli 161f29d1e0cSSheetal Tigadoli if (try <= 0) 162f29d1e0cSSheetal Tigadoli ERROR("PCIE_RESCAL_STATUS_0: 0x%x\n", data); 163f29d1e0cSSheetal Tigadoli 164f29d1e0cSSheetal Tigadoli VERBOSE("PCIE_SATA_RESCAL_STATUS_0 0x%x.\n", 165f29d1e0cSSheetal Tigadoli mmio_read_32(PCIE_RESCAL_STATUS_0)); 166f29d1e0cSSheetal Tigadoli VERBOSE("PCIE_SATA_RESCAL_OUTPUT_STATUS 0x%x.\n", 167f29d1e0cSSheetal Tigadoli mmio_read_32(PCIE_RESCAL_OUTPUT_STATUS)); 168f29d1e0cSSheetal Tigadoli INFO("PCIE SATA Rescal Init done\n"); 169f29d1e0cSSheetal Tigadoli } 170f29d1e0cSSheetal Tigadoli #endif /* EMULATION_SETUP */ 171f29d1e0cSSheetal Tigadoli #endif /* USE_PAXB || USE_PAXC || USE_SATA */ 172f29d1e0cSSheetal Tigadoli 173f29d1e0cSSheetal Tigadoli #ifdef USE_PAXC 174f29d1e0cSSheetal Tigadoli void brcm_stingray_chimp_check_and_fastboot(void) 175f29d1e0cSSheetal Tigadoli { 176f29d1e0cSSheetal Tigadoli int fastboot_init_result; 177f29d1e0cSSheetal Tigadoli 178f29d1e0cSSheetal Tigadoli if (bcm_chimp_is_nic_mode()) 179f29d1e0cSSheetal Tigadoli /* Do not wait here */ 180f29d1e0cSSheetal Tigadoli return; 181f29d1e0cSSheetal Tigadoli 182f29d1e0cSSheetal Tigadoli #if WARMBOOT_DDR_S3_SUPPORT 183f29d1e0cSSheetal Tigadoli /* 184f29d1e0cSSheetal Tigadoli * Currently DDR shmoo parameters and QSPI boot source are 185f29d1e0cSSheetal Tigadoli * tied. DDR shmoo parameters are stored in QSPI, which is 186f29d1e0cSSheetal Tigadoli * used for warmboot. 187f29d1e0cSSheetal Tigadoli * Do not reset nitro for warmboot 188f29d1e0cSSheetal Tigadoli */ 189f29d1e0cSSheetal Tigadoli if (is_warmboot() && (boot_source_get() == BOOT_SOURCE_QSPI)) 190f29d1e0cSSheetal Tigadoli return; 191f29d1e0cSSheetal Tigadoli #endif /* WARMBOOT_DDR_S3_SUPPORT */ 192f29d1e0cSSheetal Tigadoli 193f29d1e0cSSheetal Tigadoli /* 194f29d1e0cSSheetal Tigadoli * Not in NIC mode, 195f29d1e0cSSheetal Tigadoli * initiate fastboot (if enabled) 196f29d1e0cSSheetal Tigadoli */ 197f29d1e0cSSheetal Tigadoli if (FASTBOOT_TYPE == CHIMP_FASTBOOT_NITRO_RESET) { 198f29d1e0cSSheetal Tigadoli 199f29d1e0cSSheetal Tigadoli VERBOSE("Bring up Nitro/ChiMP\n"); 200f29d1e0cSSheetal Tigadoli 201f29d1e0cSSheetal Tigadoli if (boot_source_get() == BOOT_SOURCE_QSPI) 202f29d1e0cSSheetal Tigadoli WARN("Nitro boots from QSPI when AP has booted from QSPI.\n"); 203f29d1e0cSSheetal Tigadoli brcm_stingray_set_qspi_mux(0); 204f29d1e0cSSheetal Tigadoli VERBOSE("Nitro controls the QSPI\n"); 205f29d1e0cSSheetal Tigadoli } 206f29d1e0cSSheetal Tigadoli 207f29d1e0cSSheetal Tigadoli fastboot_init_result = bcm_chimp_initiate_fastboot(FASTBOOT_TYPE); 208f29d1e0cSSheetal Tigadoli if (fastboot_init_result && boot_source_get() != BOOT_SOURCE_QSPI) 209f29d1e0cSSheetal Tigadoli ERROR("Nitro init error %d. Status: 0x%x; bpe_mod reg: 0x%x\n" 210f29d1e0cSSheetal Tigadoli "fastboot register: 0x%x; handshake register 0x%x\n", 211f29d1e0cSSheetal Tigadoli fastboot_init_result, 212f29d1e0cSSheetal Tigadoli bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG), 213f29d1e0cSSheetal Tigadoli bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG), 214f29d1e0cSSheetal Tigadoli bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG), 215f29d1e0cSSheetal Tigadoli bcm_chimp_read(CHIMP_REG_ECO_RESERVED)); 216f29d1e0cSSheetal Tigadoli 217f29d1e0cSSheetal Tigadoli /* 218f29d1e0cSSheetal Tigadoli * CRMU watchdog kicks is an example, which is L1 reset, 219f29d1e0cSSheetal Tigadoli * does not clear Nitro scratch pad ram. 220f29d1e0cSSheetal Tigadoli * For Nitro resets: Clear the Nitro health status memory. 221f29d1e0cSSheetal Tigadoli */ 222f29d1e0cSSheetal Tigadoli bcm_chimp_write((CHIMP_REG_CHIMP_SCPAD + CHIMP_HEALTH_STATUS_OFFSET), 223f29d1e0cSSheetal Tigadoli 0); 224f29d1e0cSSheetal Tigadoli } 225f29d1e0cSSheetal Tigadoli #endif 226f29d1e0cSSheetal Tigadoli 227f29d1e0cSSheetal Tigadoli void set_ihost_vddc_swreg(uint32_t ihost_uvolts, uint32_t vddc_uvolts) 228f29d1e0cSSheetal Tigadoli { 229f29d1e0cSSheetal Tigadoli NOTICE("ihost_uvolts: %duv, vddc_uvolts: %duv\n", 230f29d1e0cSSheetal Tigadoli ihost_uvolts, vddc_uvolts); 231f29d1e0cSSheetal Tigadoli 232f29d1e0cSSheetal Tigadoli set_swreg(VDDC_CORE, vddc_uvolts); 233f29d1e0cSSheetal Tigadoli set_swreg(IHOST03, ihost_uvolts); 234f29d1e0cSSheetal Tigadoli set_swreg(IHOST12, ihost_uvolts); 235f29d1e0cSSheetal Tigadoli } 236f29d1e0cSSheetal Tigadoli 237f29d1e0cSSheetal Tigadoli /* 238f29d1e0cSSheetal Tigadoli * Reads SWREG AVS OTP bits (13th row) with ECC enabled and get voltage 239f29d1e0cSSheetal Tigadoli * defined in OTP if valid OTP is found 240f29d1e0cSSheetal Tigadoli */ 241f29d1e0cSSheetal Tigadoli void read_avs_otp_bits(uint32_t *ihost_uvolts, uint32_t *vddc_uvolts) 242f29d1e0cSSheetal Tigadoli { 243f29d1e0cSSheetal Tigadoli uint32_t offset = SWREG_AVS_OTP_OFFSET; 244f29d1e0cSSheetal Tigadoli uint32_t ihost_step, vddc_step; 245f29d1e0cSSheetal Tigadoli uint32_t avs_bits; 246f29d1e0cSSheetal Tigadoli uint32_t buf[2]; 247f29d1e0cSSheetal Tigadoli 248f29d1e0cSSheetal Tigadoli if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1) 249f29d1e0cSSheetal Tigadoli return; 250f29d1e0cSSheetal Tigadoli 251f29d1e0cSSheetal Tigadoli VERBOSE("AVS OTP %d ROW: 0x%x.0x%x\n", 252f29d1e0cSSheetal Tigadoli offset/WORD_SIZE, buf[1], buf[0]); 253f29d1e0cSSheetal Tigadoli 254f29d1e0cSSheetal Tigadoli /* get voltage readings from AVS OTP bits */ 255f29d1e0cSSheetal Tigadoli avs_bits = GET_BITS(SWREG_OTP_BITS_START, 256f29d1e0cSSheetal Tigadoli SWREG_OTP_BITS_END, 257f29d1e0cSSheetal Tigadoli buf[1]); 258f29d1e0cSSheetal Tigadoli 259f29d1e0cSSheetal Tigadoli /* check for valid otp bits */ 260f29d1e0cSSheetal Tigadoli if (GET_BITS(SWREG_VALID_BIT_START, SWREG_VALID_BIT_END, avs_bits) != 261f29d1e0cSSheetal Tigadoli SWREG_VALID_BITS) { 262f29d1e0cSSheetal Tigadoli WARN("Invalid AVS OTP bits at %d row\n", offset/WORD_SIZE); 263f29d1e0cSSheetal Tigadoli return; 264f29d1e0cSSheetal Tigadoli } 265f29d1e0cSSheetal Tigadoli 266f29d1e0cSSheetal Tigadoli /* get ihost and vddc step value */ 267f29d1e0cSSheetal Tigadoli vddc_step = GET_BITS(SWREG_VDDC_FIELD_START, 268f29d1e0cSSheetal Tigadoli SWREG_VDDC_FIELD_END, 269f29d1e0cSSheetal Tigadoli avs_bits); 270f29d1e0cSSheetal Tigadoli 271f29d1e0cSSheetal Tigadoli ihost_step = GET_BITS(SWREG_IHOST_FIELD_START, 272f29d1e0cSSheetal Tigadoli SWREG_IHOST_FIELD_END, 273f29d1e0cSSheetal Tigadoli avs_bits); 274f29d1e0cSSheetal Tigadoli 275f29d1e0cSSheetal Tigadoli if ((ihost_step > MVOLT_STEP_MAX) || (vddc_step > MVOLT_STEP_MAX)) { 276f29d1e0cSSheetal Tigadoli WARN("OTP entry invalid\n"); 277f29d1e0cSSheetal Tigadoli return; 278f29d1e0cSSheetal Tigadoli } 279f29d1e0cSSheetal Tigadoli 280f29d1e0cSSheetal Tigadoli /* get voltage in micro-volts */ 281f29d1e0cSSheetal Tigadoli *ihost_uvolts = STEP_TO_UVOLTS(ihost_step); 282f29d1e0cSSheetal Tigadoli *vddc_uvolts = STEP_TO_UVOLTS(vddc_step); 283f29d1e0cSSheetal Tigadoli } 284f29d1e0cSSheetal Tigadoli 285f29d1e0cSSheetal Tigadoli /* 286f29d1e0cSSheetal Tigadoli * This api reads otp bits and program internal swreg's - ihos12, ihost03, 287f29d1e0cSSheetal Tigadoli * vddc_core and ddr_core based on different chip. External swreg's 288f29d1e0cSSheetal Tigadoli * programming will be done from crmu. 289f29d1e0cSSheetal Tigadoli * 290f29d1e0cSSheetal Tigadoli * For A2 chip: 291f29d1e0cSSheetal Tigadoli * Read OTP row 20, bit 50. This bit will be set for A2 chip. Once A2 chip is 292f29d1e0cSSheetal Tigadoli * found, read AVS OTP row 13, 12bits[55:44], if valid otp bits are found 293f29d1e0cSSheetal Tigadoli * then set ihost and vddc according to avs otp bits else set them to 0.94v 294f29d1e0cSSheetal Tigadoli * and 0.91v respectively. Also update the firmware after setting voltage. 295f29d1e0cSSheetal Tigadoli * 296f29d1e0cSSheetal Tigadoli * For B0 chip: 297f29d1e0cSSheetal Tigadoli * Read OTP row 13, bit 56. This bit will be set for B0 chip. Once B0 chip is 298f29d1e0cSSheetal Tigadoli * found then set ihost and vddc to 0.95v and ddr_core to 1v. No AVS OTP bits 299f29d1e0cSSheetal Tigadoli * are used get ihost/vddc voltages. 300f29d1e0cSSheetal Tigadoli * 301f29d1e0cSSheetal Tigadoli * For B1 chip: 302f29d1e0cSSheetal Tigadoli * Read AVS OTP row 13, 12bits[55:44], if valid otp bits are found then set 303f29d1e0cSSheetal Tigadoli * ihost and vddc according to avs otp bits else set them to 0.94v and 0.91v 304f29d1e0cSSheetal Tigadoli * respectively. 305f29d1e0cSSheetal Tigadoli */ 306f29d1e0cSSheetal Tigadoli void set_swreg_based_on_otp(void) 307f29d1e0cSSheetal Tigadoli { 308f29d1e0cSSheetal Tigadoli /* default voltage if no valid OTP */ 309f29d1e0cSSheetal Tigadoli uint32_t vddc_uvolts = VDDC_CORE_DEF_VOLT; 310f29d1e0cSSheetal Tigadoli uint32_t ihost_uvolts = IHOST_DEF_VOLT; 311f29d1e0cSSheetal Tigadoli uint32_t ddrc_uvolts; 312f29d1e0cSSheetal Tigadoli uint32_t offset; 313f29d1e0cSSheetal Tigadoli uint32_t buf[2]; 314f29d1e0cSSheetal Tigadoli 315f29d1e0cSSheetal Tigadoli offset = SWREG_AVS_OTP_OFFSET; 316f29d1e0cSSheetal Tigadoli if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1) 317f29d1e0cSSheetal Tigadoli return; 318f29d1e0cSSheetal Tigadoli 319f29d1e0cSSheetal Tigadoli VERBOSE("OTP %d ROW: 0x%x.0x%x\n", 320f29d1e0cSSheetal Tigadoli offset/WORD_SIZE, buf[1], buf[0]); 321f29d1e0cSSheetal Tigadoli 322f29d1e0cSSheetal Tigadoli if (IS_SR_B0(buf[1])) { 323f29d1e0cSSheetal Tigadoli /* don't read AVS OTP for B0 */ 324f29d1e0cSSheetal Tigadoli ihost_uvolts = B0_IHOST_DEF_VOLT; 325f29d1e0cSSheetal Tigadoli vddc_uvolts = B0_VDDC_CORE_DEF_VOLT; 326f29d1e0cSSheetal Tigadoli ddrc_uvolts = B0_DDR_VDDC_DEF_VOLT; 327f29d1e0cSSheetal Tigadoli } else { 328f29d1e0cSSheetal Tigadoli read_avs_otp_bits(&ihost_uvolts, &vddc_uvolts); 329f29d1e0cSSheetal Tigadoli } 330f29d1e0cSSheetal Tigadoli 331f29d1e0cSSheetal Tigadoli #if (IHOST_REG_TYPE == IHOST_REG_INTEGRATED) && \ 332f29d1e0cSSheetal Tigadoli (VDDC_REG_TYPE == VDDC_REG_INTEGRATED) 333f29d1e0cSSheetal Tigadoli /* enable IHOST12 cluster before changing voltage */ 334f29d1e0cSSheetal Tigadoli NOTICE("Switching on the Regulator idx: %u\n", 335f29d1e0cSSheetal Tigadoli SWREG_IHOST1_DIS); 336f29d1e0cSSheetal Tigadoli mmio_clrsetbits_32(CRMU_SWREG_CTRL_ADDR, 337f29d1e0cSSheetal Tigadoli BIT(SWREG_IHOST1_DIS), 338f29d1e0cSSheetal Tigadoli BIT(SWREG_IHOST1_REG_RESETB)); 339f29d1e0cSSheetal Tigadoli 340f29d1e0cSSheetal Tigadoli /* wait for regulator supply gets stable */ 341f29d1e0cSSheetal Tigadoli while (!(mmio_read_32(CRMU_SWREG_STATUS_ADDR) & 342f29d1e0cSSheetal Tigadoli (1 << SWREG_IHOST1_PMU_STABLE))) 343f29d1e0cSSheetal Tigadoli ; 344f29d1e0cSSheetal Tigadoli 345f29d1e0cSSheetal Tigadoli INFO("Regulator supply got stable\n"); 346f29d1e0cSSheetal Tigadoli 347f29d1e0cSSheetal Tigadoli #ifndef DEFAULT_SWREG_CONFIG 348f29d1e0cSSheetal Tigadoli swreg_firmware_update(); 349f29d1e0cSSheetal Tigadoli #endif 350f29d1e0cSSheetal Tigadoli 351f29d1e0cSSheetal Tigadoli set_ihost_vddc_swreg(ihost_uvolts, vddc_uvolts); 352f29d1e0cSSheetal Tigadoli #endif 353f29d1e0cSSheetal Tigadoli if (IS_SR_B0(buf[1])) { 354f29d1e0cSSheetal Tigadoli NOTICE("ddrc_uvolts: %duv\n", ddrc_uvolts); 355f29d1e0cSSheetal Tigadoli set_swreg(DDR_VDDC, ddrc_uvolts); 356f29d1e0cSSheetal Tigadoli } 357f29d1e0cSSheetal Tigadoli } 358f29d1e0cSSheetal Tigadoli 359f29d1e0cSSheetal Tigadoli #ifdef USE_DDR 360f29d1e0cSSheetal Tigadoli static struct ddr_info ddr_info; 361f29d1e0cSSheetal Tigadoli #endif 362f29d1e0cSSheetal Tigadoli #ifdef USE_FRU 363f29d1e0cSSheetal Tigadoli static struct fru_area_info fru_area[FRU_MAX_NR_AREAS]; 364f29d1e0cSSheetal Tigadoli static struct fru_board_info board_info; 365f29d1e0cSSheetal Tigadoli static struct fru_time fru_tm; 366f29d1e0cSSheetal Tigadoli static uint8_t fru_tbl[BCM_MAX_FRU_LEN]; 367f29d1e0cSSheetal Tigadoli 368f29d1e0cSSheetal Tigadoli static void board_detect_fru(void) 369f29d1e0cSSheetal Tigadoli { 370f29d1e0cSSheetal Tigadoli uint32_t i, result; 371f29d1e0cSSheetal Tigadoli int ret = -1; 372f29d1e0cSSheetal Tigadoli 373f29d1e0cSSheetal Tigadoli result = bcm_emmc_init(false); 374f29d1e0cSSheetal Tigadoli if (!result) { 375f29d1e0cSSheetal Tigadoli ERROR("eMMC init failed\n"); 376f29d1e0cSSheetal Tigadoli return; 377f29d1e0cSSheetal Tigadoli } 378f29d1e0cSSheetal Tigadoli 379f29d1e0cSSheetal Tigadoli /* go through eMMC boot partitions looking for FRU table */ 380f29d1e0cSSheetal Tigadoli for (i = EMMC_BOOT_PARTITION1; i <= EMMC_BOOT_PARTITION2; i++) { 381f29d1e0cSSheetal Tigadoli result = emmc_partition_select(i); 382f29d1e0cSSheetal Tigadoli if (!result) { 383f29d1e0cSSheetal Tigadoli ERROR("Switching to eMMC part %u failed\n", i); 384f29d1e0cSSheetal Tigadoli return; 385f29d1e0cSSheetal Tigadoli } 386f29d1e0cSSheetal Tigadoli 387f29d1e0cSSheetal Tigadoli result = emmc_read(BCM_FRU_TBL_OFFSET, (uintptr_t)fru_tbl, 388f29d1e0cSSheetal Tigadoli BCM_MAX_FRU_LEN, BCM_MAX_FRU_LEN); 389f29d1e0cSSheetal Tigadoli if (!result) { 390f29d1e0cSSheetal Tigadoli ERROR("Failed to read from eMMC part %u\n", i); 391f29d1e0cSSheetal Tigadoli return; 392f29d1e0cSSheetal Tigadoli } 393f29d1e0cSSheetal Tigadoli 394f29d1e0cSSheetal Tigadoli /* 395f29d1e0cSSheetal Tigadoli * Run sanity check and checksum to make sure valid FRU table 396f29d1e0cSSheetal Tigadoli * is detected 397f29d1e0cSSheetal Tigadoli */ 398f29d1e0cSSheetal Tigadoli ret = fru_validate(fru_tbl, fru_area); 399f29d1e0cSSheetal Tigadoli if (ret < 0) { 400f29d1e0cSSheetal Tigadoli WARN("FRU table not found in eMMC part %u\n", i); 401f29d1e0cSSheetal Tigadoli continue; 402f29d1e0cSSheetal Tigadoli } 403f29d1e0cSSheetal Tigadoli 404f29d1e0cSSheetal Tigadoli /* parse DDR information from FRU table */ 405f29d1e0cSSheetal Tigadoli ret = fru_parse_ddr(fru_tbl, &fru_area[FRU_AREA_INTERNAL], 406f29d1e0cSSheetal Tigadoli &ddr_info); 407f29d1e0cSSheetal Tigadoli if (ret < 0) { 408f29d1e0cSSheetal Tigadoli WARN("No FRU DDR info found in eMMC part %u\n", i); 409f29d1e0cSSheetal Tigadoli continue; 410f29d1e0cSSheetal Tigadoli } 411f29d1e0cSSheetal Tigadoli 412f29d1e0cSSheetal Tigadoli /* parse board information from FRU table */ 413f29d1e0cSSheetal Tigadoli ret = fru_parse_board(fru_tbl, &fru_area[FRU_AREA_BOARD_INFO], 414f29d1e0cSSheetal Tigadoli &board_info); 415f29d1e0cSSheetal Tigadoli if (ret < 0) { 416f29d1e0cSSheetal Tigadoli WARN("No FRU board info found in eMMC part %u\n", i); 417f29d1e0cSSheetal Tigadoli continue; 418f29d1e0cSSheetal Tigadoli } 419f29d1e0cSSheetal Tigadoli 420f29d1e0cSSheetal Tigadoli /* if we reach here, valid FRU table is parsed */ 421f29d1e0cSSheetal Tigadoli break; 422f29d1e0cSSheetal Tigadoli } 423f29d1e0cSSheetal Tigadoli 424f29d1e0cSSheetal Tigadoli if (ret < 0) { 425f29d1e0cSSheetal Tigadoli WARN("FRU table missing for this board\n"); 426f29d1e0cSSheetal Tigadoli return; 427f29d1e0cSSheetal Tigadoli } 428f29d1e0cSSheetal Tigadoli 429f29d1e0cSSheetal Tigadoli for (i = 0; i < BCM_MAX_NR_DDR; i++) { 430f29d1e0cSSheetal Tigadoli INFO("DDR channel index: %d\n", ddr_info.mcb[i].idx); 431f29d1e0cSSheetal Tigadoli INFO("DDR size %u GB\n", ddr_info.mcb[i].size_mb / 1024); 432f29d1e0cSSheetal Tigadoli INFO("DDR ref ID by SW (Not MCB Ref ID) 0x%x\n", 433f29d1e0cSSheetal Tigadoli ddr_info.mcb[i].ref_id); 434f29d1e0cSSheetal Tigadoli } 435f29d1e0cSSheetal Tigadoli 436f29d1e0cSSheetal Tigadoli fru_format_time(board_info.mfg_date, &fru_tm); 437f29d1e0cSSheetal Tigadoli 438f29d1e0cSSheetal Tigadoli INFO("**** FRU board information ****\n"); 439f29d1e0cSSheetal Tigadoli INFO("Language 0x%x\n", board_info.lang); 440f29d1e0cSSheetal Tigadoli INFO("Manufacturing Date %u.%02u.%02u, %02u:%02u\n", 441f29d1e0cSSheetal Tigadoli fru_tm.year, fru_tm.month, fru_tm.day, 442f29d1e0cSSheetal Tigadoli fru_tm.hour, fru_tm.min); 443f29d1e0cSSheetal Tigadoli INFO("Manufacturing Date(Raw) 0x%x\n", board_info.mfg_date); 444f29d1e0cSSheetal Tigadoli INFO("Manufacturer %s\n", board_info.manufacturer); 445f29d1e0cSSheetal Tigadoli INFO("Product Name %s\n", board_info.product_name); 446f29d1e0cSSheetal Tigadoli INFO("Serial number %s\n", board_info.serial_number); 447f29d1e0cSSheetal Tigadoli INFO("Part number %s\n", board_info.part_number); 448f29d1e0cSSheetal Tigadoli INFO("File ID %s\n", board_info.file_id); 449f29d1e0cSSheetal Tigadoli } 450f29d1e0cSSheetal Tigadoli #endif /* USE_FRU */ 451f29d1e0cSSheetal Tigadoli 452f29d1e0cSSheetal Tigadoli #ifdef USE_GPIO 453f29d1e0cSSheetal Tigadoli 454f29d1e0cSSheetal Tigadoli #define INVALID_GPIO 0xffff 455f29d1e0cSSheetal Tigadoli 456f29d1e0cSSheetal Tigadoli static const int gpio_cfg_bitmap[MAX_NR_GPIOS] = { 457f29d1e0cSSheetal Tigadoli #ifdef BRD_DETECT_GPIO_BIT0 458f29d1e0cSSheetal Tigadoli BRD_DETECT_GPIO_BIT0, 459f29d1e0cSSheetal Tigadoli #else 460f29d1e0cSSheetal Tigadoli INVALID_GPIO, 461f29d1e0cSSheetal Tigadoli #endif 462f29d1e0cSSheetal Tigadoli #ifdef BRD_DETECT_GPIO_BIT1 463f29d1e0cSSheetal Tigadoli BRD_DETECT_GPIO_BIT1, 464f29d1e0cSSheetal Tigadoli #else 465f29d1e0cSSheetal Tigadoli INVALID_GPIO, 466f29d1e0cSSheetal Tigadoli #endif 467f29d1e0cSSheetal Tigadoli #ifdef BRD_DETECT_GPIO_BIT2 468f29d1e0cSSheetal Tigadoli BRD_DETECT_GPIO_BIT2, 469f29d1e0cSSheetal Tigadoli #else 470f29d1e0cSSheetal Tigadoli INVALID_GPIO, 471f29d1e0cSSheetal Tigadoli #endif 472f29d1e0cSSheetal Tigadoli #ifdef BRD_DETECT_GPIO_BIT3 473f29d1e0cSSheetal Tigadoli BRD_DETECT_GPIO_BIT3, 474f29d1e0cSSheetal Tigadoli #else 475f29d1e0cSSheetal Tigadoli INVALID_GPIO, 476f29d1e0cSSheetal Tigadoli #endif 477f29d1e0cSSheetal Tigadoli }; 478f29d1e0cSSheetal Tigadoli 479f29d1e0cSSheetal Tigadoli static uint8_t gpio_bitmap; 480f29d1e0cSSheetal Tigadoli 481f29d1e0cSSheetal Tigadoli /* 482f29d1e0cSSheetal Tigadoli * Use an odd number to avoid potential conflict with public GPIO level 483f29d1e0cSSheetal Tigadoli * defines 484f29d1e0cSSheetal Tigadoli */ 485f29d1e0cSSheetal Tigadoli #define GPIO_STATE_FLOAT 15 486f29d1e0cSSheetal Tigadoli 487f29d1e0cSSheetal Tigadoli /* 488f29d1e0cSSheetal Tigadoli * If GPIO_SUPPORT_FLOAT_DETECTION is disabled, simply return GPIO level 489f29d1e0cSSheetal Tigadoli * 490f29d1e0cSSheetal Tigadoli * If GPIO_SUPPORT_FLOAT_DETECTION is enabled, add additional test for possible 491f29d1e0cSSheetal Tigadoli * pin floating (unconnected) scenario. This support is assuming externally 492f29d1e0cSSheetal Tigadoli * applied pull up / pull down will have a stronger pull than the internal pull 493f29d1e0cSSheetal Tigadoli * up / pull down. 494f29d1e0cSSheetal Tigadoli */ 495f29d1e0cSSheetal Tigadoli static uint8_t gpio_get_state(int gpio) 496f29d1e0cSSheetal Tigadoli { 497f29d1e0cSSheetal Tigadoli uint8_t val; 498f29d1e0cSSheetal Tigadoli 499f29d1e0cSSheetal Tigadoli /* set direction to GPIO input */ 500f29d1e0cSSheetal Tigadoli gpio_set_direction(gpio, GPIO_DIR_IN); 501f29d1e0cSSheetal Tigadoli 502f29d1e0cSSheetal Tigadoli #ifndef GPIO_SUPPORT_FLOAT_DETECTION 503f29d1e0cSSheetal Tigadoli if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH) 504f29d1e0cSSheetal Tigadoli val = GPIO_LEVEL_HIGH; 505f29d1e0cSSheetal Tigadoli else 506f29d1e0cSSheetal Tigadoli val = GPIO_LEVEL_LOW; 507f29d1e0cSSheetal Tigadoli 508f29d1e0cSSheetal Tigadoli return val; 509f29d1e0cSSheetal Tigadoli #else 510f29d1e0cSSheetal Tigadoli /* 511f29d1e0cSSheetal Tigadoli * Enable internal pull down. If GPIO level is still high, there must 512f29d1e0cSSheetal Tigadoli * be an external pull up 513f29d1e0cSSheetal Tigadoli */ 514f29d1e0cSSheetal Tigadoli gpio_set_pull(gpio, GPIO_PULL_DOWN); 515f29d1e0cSSheetal Tigadoli if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH) { 516f29d1e0cSSheetal Tigadoli val = GPIO_LEVEL_HIGH; 517f29d1e0cSSheetal Tigadoli goto exit; 518f29d1e0cSSheetal Tigadoli } 519f29d1e0cSSheetal Tigadoli 520f29d1e0cSSheetal Tigadoli /* 521f29d1e0cSSheetal Tigadoli * Enable internal pull up. If GPIO level is still low, there must 522f29d1e0cSSheetal Tigadoli * be an external pull down 523f29d1e0cSSheetal Tigadoli */ 524f29d1e0cSSheetal Tigadoli gpio_set_pull(gpio, GPIO_PULL_UP); 525f29d1e0cSSheetal Tigadoli if (gpio_get_value(gpio) == GPIO_LEVEL_LOW) { 526f29d1e0cSSheetal Tigadoli val = GPIO_LEVEL_LOW; 527f29d1e0cSSheetal Tigadoli goto exit; 528f29d1e0cSSheetal Tigadoli } 529f29d1e0cSSheetal Tigadoli 530f29d1e0cSSheetal Tigadoli /* if reached here, the pin must be not connected */ 531f29d1e0cSSheetal Tigadoli val = GPIO_STATE_FLOAT; 532f29d1e0cSSheetal Tigadoli 533f29d1e0cSSheetal Tigadoli exit: 534f29d1e0cSSheetal Tigadoli /* make sure internall pull is disabled */ 535f29d1e0cSSheetal Tigadoli if (gpio_get_pull(gpio) != GPIO_PULL_NONE) 536f29d1e0cSSheetal Tigadoli gpio_set_pull(gpio, GPIO_PULL_NONE); 537f29d1e0cSSheetal Tigadoli 538f29d1e0cSSheetal Tigadoli return val; 539f29d1e0cSSheetal Tigadoli #endif 540f29d1e0cSSheetal Tigadoli } 541f29d1e0cSSheetal Tigadoli 542f29d1e0cSSheetal Tigadoli static void board_detect_gpio(void) 543f29d1e0cSSheetal Tigadoli { 544f29d1e0cSSheetal Tigadoli unsigned int i, val; 545f29d1e0cSSheetal Tigadoli int gpio; 546f29d1e0cSSheetal Tigadoli 547f29d1e0cSSheetal Tigadoli iproc_gpio_init(IPROC_GPIO_S_BASE, IPROC_GPIO_NR, 548f29d1e0cSSheetal Tigadoli IPROC_IOPAD_MODE_BASE, HSLS_IOPAD_BASE); 549f29d1e0cSSheetal Tigadoli 550f29d1e0cSSheetal Tigadoli gpio_bitmap = 0; 551f29d1e0cSSheetal Tigadoli for (i = 0; i < MAX_NR_GPIOS; i++) { 552f29d1e0cSSheetal Tigadoli if (gpio_cfg_bitmap[i] == INVALID_GPIO) 553f29d1e0cSSheetal Tigadoli continue; 554f29d1e0cSSheetal Tigadoli 555f29d1e0cSSheetal Tigadoli /* 556f29d1e0cSSheetal Tigadoli * Construct the bitmap based on GPIO value. Floating pin 557f29d1e0cSSheetal Tigadoli * detection is a special case. As soon as a floating pin is 558f29d1e0cSSheetal Tigadoli * detected, a special value of MAX_GPIO_BITMAP_VAL is 559f29d1e0cSSheetal Tigadoli * assigned and we break out of the loop immediately 560f29d1e0cSSheetal Tigadoli */ 561f29d1e0cSSheetal Tigadoli gpio = gpio_cfg_bitmap[i]; 562f29d1e0cSSheetal Tigadoli val = gpio_get_state(gpio); 563f29d1e0cSSheetal Tigadoli if (val == GPIO_STATE_FLOAT) { 564f29d1e0cSSheetal Tigadoli gpio_bitmap = MAX_GPIO_BITMAP_VAL; 565f29d1e0cSSheetal Tigadoli break; 566f29d1e0cSSheetal Tigadoli } 567f29d1e0cSSheetal Tigadoli 568f29d1e0cSSheetal Tigadoli if (val == GPIO_LEVEL_HIGH) 569f29d1e0cSSheetal Tigadoli gpio_bitmap |= BIT(i); 570f29d1e0cSSheetal Tigadoli } 571f29d1e0cSSheetal Tigadoli 572f29d1e0cSSheetal Tigadoli memcpy(&ddr_info, &gpio_ddr_info[gpio_bitmap], sizeof(ddr_info)); 573f29d1e0cSSheetal Tigadoli INFO("Board detection GPIO bitmap = 0x%x\n", gpio_bitmap); 574f29d1e0cSSheetal Tigadoli } 575f29d1e0cSSheetal Tigadoli #endif /* USE_GPIO */ 576f29d1e0cSSheetal Tigadoli 577f29d1e0cSSheetal Tigadoli static void bcm_board_detect(void) 578f29d1e0cSSheetal Tigadoli { 579f29d1e0cSSheetal Tigadoli #ifdef DDR_LEGACY_MCB_SUPPORTED 580f29d1e0cSSheetal Tigadoli /* Loading default DDR info */ 581f29d1e0cSSheetal Tigadoli memcpy(&ddr_info, &default_ddr_info, sizeof(ddr_info)); 582f29d1e0cSSheetal Tigadoli #endif 583f29d1e0cSSheetal Tigadoli #ifdef USE_FRU 584f29d1e0cSSheetal Tigadoli board_detect_fru(); 585f29d1e0cSSheetal Tigadoli #endif 586f29d1e0cSSheetal Tigadoli #ifdef USE_GPIO 587f29d1e0cSSheetal Tigadoli board_detect_gpio(); 588f29d1e0cSSheetal Tigadoli #endif 589f29d1e0cSSheetal Tigadoli } 590f29d1e0cSSheetal Tigadoli 591f29d1e0cSSheetal Tigadoli static void dump_persistent_regs(void) 592f29d1e0cSSheetal Tigadoli { 593f29d1e0cSSheetal Tigadoli NOTICE("pr0: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG0)); 594f29d1e0cSSheetal Tigadoli NOTICE("pr1: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1)); 595f29d1e0cSSheetal Tigadoli NOTICE("pr2: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG2)); 596f29d1e0cSSheetal Tigadoli NOTICE("pr3: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG3)); 597f29d1e0cSSheetal Tigadoli NOTICE("pr4: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG4)); 598f29d1e0cSSheetal Tigadoli NOTICE("pr5: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG5)); 599f29d1e0cSSheetal Tigadoli NOTICE("pr6: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG6)); 600f29d1e0cSSheetal Tigadoli NOTICE("pr7: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG7)); 601f29d1e0cSSheetal Tigadoli NOTICE("pr8: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG8)); 602f29d1e0cSSheetal Tigadoli NOTICE("pr9: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9)); 603f29d1e0cSSheetal Tigadoli NOTICE("pr10: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG10)); 604f29d1e0cSSheetal Tigadoli NOTICE("pr11: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG11)); 605f29d1e0cSSheetal Tigadoli } 606f29d1e0cSSheetal Tigadoli 607f29d1e0cSSheetal Tigadoli void plat_bcm_bl2_plat_arch_setup(void) 608f29d1e0cSSheetal Tigadoli { 609f29d1e0cSSheetal Tigadoli if (chip_get_rev_id_major() == CHIP_REV_MAJOR_AX) { 610f29d1e0cSSheetal Tigadoli if (!(sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) & 611f29d1e0cSSheetal Tigadoli SOTP_ATF_WATCHDOG_ENABLE_MASK)) { 612f29d1e0cSSheetal Tigadoli /* 613f29d1e0cSSheetal Tigadoli * Stop sp805 watchdog timer immediately. 614f29d1e0cSSheetal Tigadoli * It might has been set up by MCU patch earlier for 615f29d1e0cSSheetal Tigadoli * eMMC workaround. 616f29d1e0cSSheetal Tigadoli * 617f29d1e0cSSheetal Tigadoli * Note the watchdog timer started in CRMU has a very 618f29d1e0cSSheetal Tigadoli * short timeout and needs to be stopped immediately. 619f29d1e0cSSheetal Tigadoli * Down below we restart it with a much longer timeout 620f29d1e0cSSheetal Tigadoli * for BL2 and BL31 621f29d1e0cSSheetal Tigadoli */ 622f29d1e0cSSheetal Tigadoli sp805_stop(ARM_SP805_TWDG_BASE); 623f29d1e0cSSheetal Tigadoli } 624f29d1e0cSSheetal Tigadoli } 625f29d1e0cSSheetal Tigadoli 626f29d1e0cSSheetal Tigadoli #if !BRCM_DISABLE_TRUSTED_WDOG 627f29d1e0cSSheetal Tigadoli /* 628f29d1e0cSSheetal Tigadoli * start secure watchdog for BL2 and BL31. 629f29d1e0cSSheetal Tigadoli * Note that UART download can take a longer time, 630f29d1e0cSSheetal Tigadoli * so do not allow watchdog for UART download, 631f29d1e0cSSheetal Tigadoli * as this boot source is not a standard modus operandi. 632f29d1e0cSSheetal Tigadoli */ 633f29d1e0cSSheetal Tigadoli if (boot_source_get() != BOOT_SOURCE_UART) 634f29d1e0cSSheetal Tigadoli sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL); 635f29d1e0cSSheetal Tigadoli #endif 636f29d1e0cSSheetal Tigadoli 637f29d1e0cSSheetal Tigadoli #ifdef BCM_ELOG 638f29d1e0cSSheetal Tigadoli /* Ensure logging is started out fresh in BL2. */ 639f29d1e0cSSheetal Tigadoli mmio_write_32(BCM_ELOG_BL2_BASE, 0); 640f29d1e0cSSheetal Tigadoli #endif 641f29d1e0cSSheetal Tigadoli /* 642f29d1e0cSSheetal Tigadoli * In BL2, since we have very limited space to store logs, we only 643f29d1e0cSSheetal Tigadoli * save logs that are >= the WARNING level. 644f29d1e0cSSheetal Tigadoli */ 645f29d1e0cSSheetal Tigadoli bcm_elog_init((void *)BCM_ELOG_BL2_BASE, BCM_ELOG_BL2_SIZE, 646f29d1e0cSSheetal Tigadoli LOG_LEVEL_WARNING); 647f29d1e0cSSheetal Tigadoli 648f29d1e0cSSheetal Tigadoli dump_persistent_regs(); 649f29d1e0cSSheetal Tigadoli 650f29d1e0cSSheetal Tigadoli /* Read CRMU mailbox 0 */ 651f29d1e0cSSheetal Tigadoli NOTICE("RESET (reported by CRMU): 0x%x\n", 652f29d1e0cSSheetal Tigadoli mmio_read_32(CRMU_READ_MAIL_BOX0)); 653f29d1e0cSSheetal Tigadoli 654f29d1e0cSSheetal Tigadoli /* 655f29d1e0cSSheetal Tigadoli * All non-boot-source PADs are in forced input-mode at 656f29d1e0cSSheetal Tigadoli * reset so clear the force on non-boot-source PADs using 657f29d1e0cSSheetal Tigadoli * CDRU register. 658f29d1e0cSSheetal Tigadoli */ 659f29d1e0cSSheetal Tigadoli mmio_clrbits_32((uintptr_t)CDRU_CHIP_IO_PAD_CONTROL, 660f29d1e0cSSheetal Tigadoli (1 << CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R)); 661f29d1e0cSSheetal Tigadoli 662f29d1e0cSSheetal Tigadoli #if DRIVER_OCOTP_ENABLE 663f29d1e0cSSheetal Tigadoli bcm_otpc_init(&otp_stingray_map); 664f29d1e0cSSheetal Tigadoli #endif 665f29d1e0cSSheetal Tigadoli 666f29d1e0cSSheetal Tigadoli set_swreg_based_on_otp(); 667f29d1e0cSSheetal Tigadoli 668f29d1e0cSSheetal Tigadoli #if IHOST_PLL_FREQ != 0 669f29d1e0cSSheetal Tigadoli bcm_set_ihost_pll_freq(0x0, IHOST_PLL_FREQ); 670f29d1e0cSSheetal Tigadoli #endif 671f29d1e0cSSheetal Tigadoli 672f29d1e0cSSheetal Tigadoli #ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE 673f29d1e0cSSheetal Tigadoli /* The erasable unit of the eMMC is the "Erase Group"; 674f29d1e0cSSheetal Tigadoli * Erase group is measured in write blocks which are the 675f29d1e0cSSheetal Tigadoli * basic writable units of the Device. 676f29d1e0cSSheetal Tigadoli * The size of the Erase Group is a Device specific parameter 677f29d1e0cSSheetal Tigadoli */ 678f29d1e0cSSheetal Tigadoli emmc_erase(EMMC_ERASE_START_BLOCK, EMMC_ERASE_BLOCK_COUNT, 679f29d1e0cSSheetal Tigadoli EMMC_ERASE_PARTITION); 680f29d1e0cSSheetal Tigadoli #endif 681f29d1e0cSSheetal Tigadoli 682f29d1e0cSSheetal Tigadoli bcm_board_detect(); 683f29d1e0cSSheetal Tigadoli #ifdef DRIVER_EMMC_ENABLE 684f29d1e0cSSheetal Tigadoli /* Initialize the card, if it is not */ 685*21767166SSheetal Tigadoli if (bcm_emmc_init(true) == 0) 686f29d1e0cSSheetal Tigadoli WARN("eMMC Card Initialization Failed!!!\n"); 687f29d1e0cSSheetal Tigadoli #endif 688f29d1e0cSSheetal Tigadoli 689f29d1e0cSSheetal Tigadoli #if BL2_TEST_I2C 690f29d1e0cSSheetal Tigadoli i2c_test(); 691f29d1e0cSSheetal Tigadoli #endif 692f29d1e0cSSheetal Tigadoli 693f29d1e0cSSheetal Tigadoli #ifdef USE_DDR 694f29d1e0cSSheetal Tigadoli ddr_initialize(&ddr_info); 695f29d1e0cSSheetal Tigadoli 696f29d1e0cSSheetal Tigadoli ddr_secure_region_config(SECURE_DDR_BASE_ADDRESS, 697f29d1e0cSSheetal Tigadoli SECURE_DDR_END_ADDRESS); 698f29d1e0cSSheetal Tigadoli #ifdef NITRO_SECURE_ACCESS 699f29d1e0cSSheetal Tigadoli ddr_secure_region_config(DDR_NITRO_SECURE_REGION_START, 700f29d1e0cSSheetal Tigadoli DDR_NITRO_SECURE_REGION_END); 701f29d1e0cSSheetal Tigadoli #endif 702f29d1e0cSSheetal Tigadoli #else 703f29d1e0cSSheetal Tigadoli ext_sram_init(); 704f29d1e0cSSheetal Tigadoli #endif 705f29d1e0cSSheetal Tigadoli 706f29d1e0cSSheetal Tigadoli #if BL2_TEST_MEM 707f29d1e0cSSheetal Tigadoli ddr_test(); 708f29d1e0cSSheetal Tigadoli #endif 709f29d1e0cSSheetal Tigadoli 710f29d1e0cSSheetal Tigadoli #ifdef USE_NAND 711f29d1e0cSSheetal Tigadoli brcm_stingray_nand_init(); 712f29d1e0cSSheetal Tigadoli #endif 713f29d1e0cSSheetal Tigadoli 714f29d1e0cSSheetal Tigadoli #if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA) 715f29d1e0cSSheetal Tigadoli brcm_stingray_pcie_reset(); 716f29d1e0cSSheetal Tigadoli #endif 717f29d1e0cSSheetal Tigadoli 718f29d1e0cSSheetal Tigadoli #ifdef USE_PAXC 719f29d1e0cSSheetal Tigadoli if (boot_source_get() != BOOT_SOURCE_QSPI) 720f29d1e0cSSheetal Tigadoli brcm_stingray_chimp_check_and_fastboot(); 721f29d1e0cSSheetal Tigadoli #endif 722f29d1e0cSSheetal Tigadoli 723f29d1e0cSSheetal Tigadoli #if ((!CLEAN_DDR || MMU_DISABLED)) 724f29d1e0cSSheetal Tigadoli /* 725f29d1e0cSSheetal Tigadoli * Now DDR has been initialized. We want to copy all the logs in SRAM 726f29d1e0cSSheetal Tigadoli * into DDR so we will have much more space to store the logs in the 727f29d1e0cSSheetal Tigadoli * next boot stage 728f29d1e0cSSheetal Tigadoli */ 729f29d1e0cSSheetal Tigadoli bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE, 730f29d1e0cSSheetal Tigadoli MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE) 731f29d1e0cSSheetal Tigadoli ); 732f29d1e0cSSheetal Tigadoli 733f29d1e0cSSheetal Tigadoli /* 734f29d1e0cSSheetal Tigadoli * We are not yet at the end of BL2, but we can stop log here so we do 735f29d1e0cSSheetal Tigadoli * not need to add 'bcm_elog_exit' to the standard BL2 code. The 736f29d1e0cSSheetal Tigadoli * benefit of capturing BL2 logs after this is very minimal in a 737f29d1e0cSSheetal Tigadoli * production system 738f29d1e0cSSheetal Tigadoli * NOTE: BL2 logging must be exited before going forward to setup 739f29d1e0cSSheetal Tigadoli * page tables 740f29d1e0cSSheetal Tigadoli */ 741f29d1e0cSSheetal Tigadoli bcm_elog_exit(); 742f29d1e0cSSheetal Tigadoli #endif 743f29d1e0cSSheetal Tigadoli } 744