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