xref: /rk3399_ARM-atf/plat/brcm/board/stingray/src/bl2_setup.c (revision a7e62f1d9ef6773c2c4ee186694fb2f3892f20f7)
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 
plat_bcm_bl2_early_platform_setup(void)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
brcm_stingray_nand_init(void)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
brcm_stingray_pcie_reset(void)131f29d1e0cSSheetal Tigadoli static void brcm_stingray_pcie_reset(void)
132f29d1e0cSSheetal Tigadoli {
133f29d1e0cSSheetal Tigadoli }
134f29d1e0cSSheetal Tigadoli #else
brcm_stingray_pcie_reset(void)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
brcm_stingray_chimp_check_and_fastboot(void)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 
set_ihost_vddc_swreg(uint32_t ihost_uvolts,uint32_t vddc_uvolts)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  */
read_avs_otp_bits(uint32_t * ihost_uvolts,uint32_t * vddc_uvolts)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  */
set_swreg_based_on_otp(void)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 
board_detect_fru(void)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  */
gpio_get_state(int gpio)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 
board_detect_gpio(void)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 
bcm_board_detect(void)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 
dump_persistent_regs(void)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 
plat_bcm_bl2_plat_arch_setup(void)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