1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (c) 2016 - 2020, Broadcom
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park
7*54fd6939SJiyong Park #include <string.h>
8*54fd6939SJiyong Park
9*54fd6939SJiyong Park #include <drivers/delay_timer.h>
10*54fd6939SJiyong Park
11*54fd6939SJiyong Park #include <chimp.h>
12*54fd6939SJiyong Park #include <chimp_nv_defs.h>
13*54fd6939SJiyong Park
14*54fd6939SJiyong Park #define CHIMP_DEFAULT_STARTUP_ADDR 0xb4300000
15*54fd6939SJiyong Park
16*54fd6939SJiyong Park /* ChiMP's view of APE scratchpad memory for fastboot */
17*54fd6939SJiyong Park #define CHIMP_FASTBOOT_ADDR 0x61000000
18*54fd6939SJiyong Park
19*54fd6939SJiyong Park #define CHIMP_PREPARE_ACCESS_WINDOW(addr) \
20*54fd6939SJiyong Park (\
21*54fd6939SJiyong Park mmio_write_32(\
22*54fd6939SJiyong Park NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT, \
23*54fd6939SJiyong Park addr & 0xffc00000)\
24*54fd6939SJiyong Park )
25*54fd6939SJiyong Park #define CHIMP_INDIRECT_TGT_ADDR(addr) \
26*54fd6939SJiyong Park (CHIMP_INDIRECT_BASE + (addr & CHIMP_INDIRECT_ADDR_MASK))
27*54fd6939SJiyong Park
28*54fd6939SJiyong Park #define CHIMP_CTRL_ADDR(x) (CHIMP_REG_CTRL_BASE + x)
29*54fd6939SJiyong Park
30*54fd6939SJiyong Park /* For non-PAXC builds */
31*54fd6939SJiyong Park #ifndef CHIMP_FB1_ENTRY
32*54fd6939SJiyong Park #define CHIMP_FB1_ENTRY 0
33*54fd6939SJiyong Park #endif
34*54fd6939SJiyong Park
35*54fd6939SJiyong Park #define CHIMP_DBG VERBOSE
36*54fd6939SJiyong Park
bcm_chimp_write(uintptr_t addr,uint32_t value)37*54fd6939SJiyong Park void bcm_chimp_write(uintptr_t addr, uint32_t value)
38*54fd6939SJiyong Park {
39*54fd6939SJiyong Park CHIMP_PREPARE_ACCESS_WINDOW(addr);
40*54fd6939SJiyong Park mmio_write_32(CHIMP_INDIRECT_TGT_ADDR(addr), value);
41*54fd6939SJiyong Park }
42*54fd6939SJiyong Park
bcm_chimp_read(uintptr_t addr)43*54fd6939SJiyong Park uint32_t bcm_chimp_read(uintptr_t addr)
44*54fd6939SJiyong Park {
45*54fd6939SJiyong Park CHIMP_PREPARE_ACCESS_WINDOW(addr);
46*54fd6939SJiyong Park return mmio_read_32(CHIMP_INDIRECT_TGT_ADDR(addr));
47*54fd6939SJiyong Park }
48*54fd6939SJiyong Park
bcm_chimp_clrbits(uintptr_t addr,uint32_t bits)49*54fd6939SJiyong Park void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits)
50*54fd6939SJiyong Park {
51*54fd6939SJiyong Park CHIMP_PREPARE_ACCESS_WINDOW(addr);
52*54fd6939SJiyong Park mmio_clrbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits);
53*54fd6939SJiyong Park }
54*54fd6939SJiyong Park
bcm_chimp_setbits(uintptr_t addr,uint32_t bits)55*54fd6939SJiyong Park void bcm_chimp_setbits(uintptr_t addr, uint32_t bits)
56*54fd6939SJiyong Park {
57*54fd6939SJiyong Park CHIMP_PREPARE_ACCESS_WINDOW(addr);
58*54fd6939SJiyong Park mmio_setbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits);
59*54fd6939SJiyong Park }
60*54fd6939SJiyong Park
bcm_chimp_is_nic_mode(void)61*54fd6939SJiyong Park int bcm_chimp_is_nic_mode(void)
62*54fd6939SJiyong Park {
63*54fd6939SJiyong Park uint32_t val;
64*54fd6939SJiyong Park
65*54fd6939SJiyong Park /* Check if ChiMP straps are set */
66*54fd6939SJiyong Park val = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW);
67*54fd6939SJiyong Park val &= CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK;
68*54fd6939SJiyong Park
69*54fd6939SJiyong Park return val == CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK;
70*54fd6939SJiyong Park }
71*54fd6939SJiyong Park
bcm_chimp_fru_prog_done(bool is_done)72*54fd6939SJiyong Park void bcm_chimp_fru_prog_done(bool is_done)
73*54fd6939SJiyong Park {
74*54fd6939SJiyong Park uint32_t val;
75*54fd6939SJiyong Park
76*54fd6939SJiyong Park val = is_done ? (1 << CHIMP_FRU_PROG_DONE_BIT) : 0;
77*54fd6939SJiyong Park bcm_chimp_setbits(CHIMP_REG_ECO_RESERVED, val);
78*54fd6939SJiyong Park }
79*54fd6939SJiyong Park
bcm_chimp_handshake_done(void)80*54fd6939SJiyong Park int bcm_chimp_handshake_done(void)
81*54fd6939SJiyong Park {
82*54fd6939SJiyong Park uint32_t value;
83*54fd6939SJiyong Park
84*54fd6939SJiyong Park value = bcm_chimp_read(CHIMP_REG_ECO_RESERVED);
85*54fd6939SJiyong Park value &= (1 << CHIMP_FLASH_ACCESS_DONE_BIT);
86*54fd6939SJiyong Park
87*54fd6939SJiyong Park return value != 0;
88*54fd6939SJiyong Park }
89*54fd6939SJiyong Park
bcm_chimp_wait_handshake(void)90*54fd6939SJiyong Park int bcm_chimp_wait_handshake(void)
91*54fd6939SJiyong Park {
92*54fd6939SJiyong Park uint32_t timeout = CHIMP_HANDSHAKE_TIMEOUT_MS;
93*54fd6939SJiyong Park uint32_t status;
94*54fd6939SJiyong Park
95*54fd6939SJiyong Park INFO("Waiting for ChiMP handshake...\n");
96*54fd6939SJiyong Park do {
97*54fd6939SJiyong Park if (bcm_chimp_handshake_done())
98*54fd6939SJiyong Park break;
99*54fd6939SJiyong Park /* No need to wait if ChiMP reported an error */
100*54fd6939SJiyong Park status = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG);
101*54fd6939SJiyong Park if (status & CHIMP_ERROR_MASK) {
102*54fd6939SJiyong Park ERROR("ChiMP error 0x%x. Wait aborted\n", status);
103*54fd6939SJiyong Park break;
104*54fd6939SJiyong Park }
105*54fd6939SJiyong Park mdelay(1);
106*54fd6939SJiyong Park } while (--timeout);
107*54fd6939SJiyong Park
108*54fd6939SJiyong Park if (!bcm_chimp_handshake_done()) {
109*54fd6939SJiyong Park if (timeout == 0) {
110*54fd6939SJiyong Park WARN("Timeout waiting for ChiMP handshake\n");
111*54fd6939SJiyong Park }
112*54fd6939SJiyong Park } else {
113*54fd6939SJiyong Park INFO("Got handshake from ChiMP!\n");
114*54fd6939SJiyong Park }
115*54fd6939SJiyong Park
116*54fd6939SJiyong Park return bcm_chimp_handshake_done();
117*54fd6939SJiyong Park }
118*54fd6939SJiyong Park
bcm_chimp_read_ctrl(uint32_t offset)119*54fd6939SJiyong Park uint32_t bcm_chimp_read_ctrl(uint32_t offset)
120*54fd6939SJiyong Park {
121*54fd6939SJiyong Park return bcm_chimp_read(CHIMP_CTRL_ADDR(offset));
122*54fd6939SJiyong Park }
123*54fd6939SJiyong Park
bcm_chimp_nitro_reset(void)124*54fd6939SJiyong Park static int bcm_chimp_nitro_reset(void)
125*54fd6939SJiyong Park {
126*54fd6939SJiyong Park uint32_t timeout;
127*54fd6939SJiyong Park
128*54fd6939SJiyong Park /* Perform tasks done by M0 in NIC mode */
129*54fd6939SJiyong Park CHIMP_DBG("Taking Nitro out of reset\n");
130*54fd6939SJiyong Park mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
131*54fd6939SJiyong Park /* MHB_RESET_N */
132*54fd6939SJiyong Park (1 << CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R) |
133*54fd6939SJiyong Park /* PCI_RESET_N */
134*54fd6939SJiyong Park (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R) |
135*54fd6939SJiyong Park /* PM_RESET_N */
136*54fd6939SJiyong Park (1 << CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R) |
137*54fd6939SJiyong Park /* NIC_RESET_N */
138*54fd6939SJiyong Park (1 << CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R)
139*54fd6939SJiyong Park );
140*54fd6939SJiyong Park
141*54fd6939SJiyong Park /* Wait until Nitro is out of reset */
142*54fd6939SJiyong Park timeout = NIC_RESET_RELEASE_TIMEOUT_US;
143*54fd6939SJiyong Park do {
144*54fd6939SJiyong Park uint32_t value;
145*54fd6939SJiyong Park
146*54fd6939SJiyong Park value = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG);
147*54fd6939SJiyong Park if ((value & CHIMP_BPE_MODE_ID_MASK) ==
148*54fd6939SJiyong Park CHIMP_BPE_MODE_ID_PATTERN)
149*54fd6939SJiyong Park break;
150*54fd6939SJiyong Park udelay(1);
151*54fd6939SJiyong Park } while (--timeout);
152*54fd6939SJiyong Park
153*54fd6939SJiyong Park if (timeout == 0) {
154*54fd6939SJiyong Park ERROR("NIC reset release timed out\n");
155*54fd6939SJiyong Park return -1;
156*54fd6939SJiyong Park }
157*54fd6939SJiyong Park
158*54fd6939SJiyong Park return 0;
159*54fd6939SJiyong Park }
160*54fd6939SJiyong Park
bcm_nitro_secure_mode_enable(void)161*54fd6939SJiyong Park static void bcm_nitro_secure_mode_enable(void)
162*54fd6939SJiyong Park {
163*54fd6939SJiyong Park mmio_setbits_32(CDRU_NITRO_CONTROL,
164*54fd6939SJiyong Park (1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R) |
165*54fd6939SJiyong Park (1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R));
166*54fd6939SJiyong Park mmio_write_32(NITRO_TZPC_TZPCDECPROT0clr,
167*54fd6939SJiyong Park /* NITRO_TZPC */
168*54fd6939SJiyong Park 1 << NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R);
169*54fd6939SJiyong Park }
170*54fd6939SJiyong Park
bcm_chimp_reset_and_initial_setup(void)171*54fd6939SJiyong Park static int bcm_chimp_reset_and_initial_setup(void)
172*54fd6939SJiyong Park {
173*54fd6939SJiyong Park
174*54fd6939SJiyong Park int err;
175*54fd6939SJiyong Park uint32_t handshake_reg;
176*54fd6939SJiyong Park
177*54fd6939SJiyong Park err = bcm_chimp_nitro_reset();
178*54fd6939SJiyong Park if (err)
179*54fd6939SJiyong Park return err;
180*54fd6939SJiyong Park
181*54fd6939SJiyong Park /* Enable Nitro secure mode */
182*54fd6939SJiyong Park bcm_nitro_secure_mode_enable();
183*54fd6939SJiyong Park
184*54fd6939SJiyong Park /* Force ChiMP back into reset */
185*54fd6939SJiyong Park bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
186*54fd6939SJiyong Park 1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R);
187*54fd6939SJiyong Park
188*54fd6939SJiyong Park handshake_reg = (1 << SR_IN_SMARTNIC_MODE_BIT);
189*54fd6939SJiyong Park
190*54fd6939SJiyong Park /* Get OTP secure Chimp boot status */
191*54fd6939SJiyong Park if (mmio_read_32(CRMU_OTP_STATUS) & (1 << CRMU_OTP_STATUS_BIT))
192*54fd6939SJiyong Park handshake_reg |= (1 << SR_CHIMP_SECURE_BOOT_BIT);
193*54fd6939SJiyong Park
194*54fd6939SJiyong Park bcm_chimp_write(CHIMP_REG_ECO_RESERVED, handshake_reg);
195*54fd6939SJiyong Park
196*54fd6939SJiyong Park CHIMP_DBG("ChiMP reset and initial handshake parameters set\n");
197*54fd6939SJiyong Park
198*54fd6939SJiyong Park return 0;
199*54fd6939SJiyong Park }
200*54fd6939SJiyong Park
bcm_nitro_chimp_release_reset(void)201*54fd6939SJiyong Park static void bcm_nitro_chimp_release_reset(void)
202*54fd6939SJiyong Park {
203*54fd6939SJiyong Park bcm_chimp_clrbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
204*54fd6939SJiyong Park 1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R);
205*54fd6939SJiyong Park
206*54fd6939SJiyong Park CHIMP_DBG("Nitro Reset Released\n");
207*54fd6939SJiyong Park }
208*54fd6939SJiyong Park
bcm_chimp_set_fastboot(int mode)209*54fd6939SJiyong Park static void bcm_chimp_set_fastboot(int mode)
210*54fd6939SJiyong Park {
211*54fd6939SJiyong Park uint32_t fb_entry;
212*54fd6939SJiyong Park
213*54fd6939SJiyong Park /* 1. Enable fastboot */
214*54fd6939SJiyong Park bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
215*54fd6939SJiyong Park (1 << CHIMP_FAST_BOOT_MODE_BIT));
216*54fd6939SJiyong Park fb_entry = CHIMP_FASTBOOT_ADDR | mode;
217*54fd6939SJiyong Park if (mode == CHIMP_FASTBOOT_JUMP_IN_PLACE)
218*54fd6939SJiyong Park fb_entry = CHIMP_FB1_ENTRY;
219*54fd6939SJiyong Park /* 2. Write startup address and mode */
220*54fd6939SJiyong Park INFO("Setting fastboot type %d entry to 0x%x\n", mode, fb_entry);
221*54fd6939SJiyong Park bcm_chimp_write(
222*54fd6939SJiyong Park CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
223*54fd6939SJiyong Park fb_entry);
224*54fd6939SJiyong Park }
225*54fd6939SJiyong Park
226*54fd6939SJiyong Park #ifndef CHIMPFW_USE_SIDELOAD
bcm_chimp_load_fw_from_spi(uintptr_t spi_addr,size_t size)227*54fd6939SJiyong Park static void bcm_chimp_load_fw_from_spi(uintptr_t spi_addr, size_t size)
228*54fd6939SJiyong Park {
229*54fd6939SJiyong Park uintptr_t ape_scpad;
230*54fd6939SJiyong Park uintptr_t dest;
231*54fd6939SJiyong Park size_t bytes_left;
232*54fd6939SJiyong Park
233*54fd6939SJiyong Park ape_scpad = CHIMP_REG_CHIMP_APE_SCPAD;
234*54fd6939SJiyong Park dest = CHIMP_INDIRECT_TGT_ADDR(CHIMP_REG_CHIMP_APE_SCPAD);
235*54fd6939SJiyong Park bytes_left = size;
236*54fd6939SJiyong Park
237*54fd6939SJiyong Park while (bytes_left) {
238*54fd6939SJiyong Park uint32_t delta;
239*54fd6939SJiyong Park
240*54fd6939SJiyong Park delta = bytes_left > CHIMP_WINDOW_SIZE ?
241*54fd6939SJiyong Park bytes_left - CHIMP_WINDOW_SIZE : bytes_left;
242*54fd6939SJiyong Park CHIMP_PREPARE_ACCESS_WINDOW(ape_scpad);
243*54fd6939SJiyong Park INFO("Transferring %d byte(s) from 0x%lx to 0x%lx\n",
244*54fd6939SJiyong Park delta, spi_addr, dest);
245*54fd6939SJiyong Park /*
246*54fd6939SJiyong Park * This single memcpy call takes significant amount of time
247*54fd6939SJiyong Park * on Palladium. Be patient
248*54fd6939SJiyong Park */
249*54fd6939SJiyong Park memcpy((void *)dest, (void *)spi_addr, delta);
250*54fd6939SJiyong Park bytes_left -= delta;
251*54fd6939SJiyong Park INFO("Transferred %d byte(s) from 0x%lx to 0x%lx (%lu%%)\n",
252*54fd6939SJiyong Park delta, spi_addr, dest,
253*54fd6939SJiyong Park ((size - bytes_left) * 100)/size);
254*54fd6939SJiyong Park spi_addr += delta;
255*54fd6939SJiyong Park dest += delta;
256*54fd6939SJiyong Park ape_scpad += delta;
257*54fd6939SJiyong Park }
258*54fd6939SJiyong Park }
259*54fd6939SJiyong Park
bcm_chimp_find_fw_in_spi(uintptr_t * addr,size_t * size)260*54fd6939SJiyong Park static int bcm_chimp_find_fw_in_spi(uintptr_t *addr, size_t *size)
261*54fd6939SJiyong Park {
262*54fd6939SJiyong Park int i;
263*54fd6939SJiyong Park bnxnvm_master_block_header_t *master_block_hdr;
264*54fd6939SJiyong Park bnxnvm_directory_block_header_t *dir_block_hdr;
265*54fd6939SJiyong Park bnxnvm_directory_entry_t *dir_entry;
266*54fd6939SJiyong Park int found;
267*54fd6939SJiyong Park
268*54fd6939SJiyong Park found = 0;
269*54fd6939SJiyong Park
270*54fd6939SJiyong Park /* Read the master block */
271*54fd6939SJiyong Park master_block_hdr =
272*54fd6939SJiyong Park (bnxnvm_master_block_header_t *)(uintptr_t)QSPI_BASE_ADDR;
273*54fd6939SJiyong Park if (master_block_hdr->sig != BNXNVM_MASTER_BLOCK_SIG) {
274*54fd6939SJiyong Park WARN("Invalid masterblock 0x%x (expected 0x%x)\n",
275*54fd6939SJiyong Park master_block_hdr->sig,
276*54fd6939SJiyong Park BNXNVM_MASTER_BLOCK_SIG);
277*54fd6939SJiyong Park return -NV_NOT_NVRAM;
278*54fd6939SJiyong Park }
279*54fd6939SJiyong Park if ((master_block_hdr->block_size > NV_MAX_BLOCK_SIZE) ||
280*54fd6939SJiyong Park (master_block_hdr->directory_offset >=
281*54fd6939SJiyong Park master_block_hdr->nvram_size)) {
282*54fd6939SJiyong Park WARN("Invalid masterblock block size 0x%x or directory offset 0x%x\n",
283*54fd6939SJiyong Park master_block_hdr->block_size,
284*54fd6939SJiyong Park master_block_hdr->directory_offset);
285*54fd6939SJiyong Park return -NV_BAD_MB;
286*54fd6939SJiyong Park }
287*54fd6939SJiyong Park
288*54fd6939SJiyong Park /* Skip to the Directory block start */
289*54fd6939SJiyong Park dir_block_hdr =
290*54fd6939SJiyong Park (bnxnvm_directory_block_header_t *)
291*54fd6939SJiyong Park ((uintptr_t)QSPI_BASE_ADDR +
292*54fd6939SJiyong Park master_block_hdr->directory_offset);
293*54fd6939SJiyong Park if (dir_block_hdr->sig != BNXNVM_DIRECTORY_BLOCK_SIG) {
294*54fd6939SJiyong Park WARN("Invalid directory header 0x%x (expected 0x%x)\n",
295*54fd6939SJiyong Park dir_block_hdr->sig,
296*54fd6939SJiyong Park BNXNVM_DIRECTORY_BLOCK_SIG);
297*54fd6939SJiyong Park return -NV_BAD_DIR_HEADER;
298*54fd6939SJiyong Park }
299*54fd6939SJiyong Park
300*54fd6939SJiyong Park /* Locate the firmware */
301*54fd6939SJiyong Park for (i = 0; i < dir_block_hdr->entries; i++) {
302*54fd6939SJiyong Park *addr = ((uintptr_t)dir_block_hdr + dir_block_hdr->length +
303*54fd6939SJiyong Park i * dir_block_hdr->entry_length);
304*54fd6939SJiyong Park dir_entry = (bnxnvm_directory_entry_t *)(*addr);
305*54fd6939SJiyong Park if ((dir_entry->type == BNX_DIR_TYPE_BOOTCODE) ||
306*54fd6939SJiyong Park (dir_entry->type == BNX_DIR_TYPE_BOOTCODE_2)) {
307*54fd6939SJiyong Park found = 1;
308*54fd6939SJiyong Park break;
309*54fd6939SJiyong Park }
310*54fd6939SJiyong Park }
311*54fd6939SJiyong Park
312*54fd6939SJiyong Park if (!found)
313*54fd6939SJiyong Park return -NV_FW_NOT_FOUND;
314*54fd6939SJiyong Park
315*54fd6939SJiyong Park *addr = QSPI_BASE_ADDR + dir_entry->item_location;
316*54fd6939SJiyong Park *size = dir_entry->data_length;
317*54fd6939SJiyong Park
318*54fd6939SJiyong Park INFO("Found chimp firmware at 0x%lx, size %lu byte(s)\n",
319*54fd6939SJiyong Park *addr, *size);
320*54fd6939SJiyong Park
321*54fd6939SJiyong Park return NV_OK;
322*54fd6939SJiyong Park }
323*54fd6939SJiyong Park #endif
324*54fd6939SJiyong Park
bcm_chimp_initiate_fastboot(int fastboot_type)325*54fd6939SJiyong Park int bcm_chimp_initiate_fastboot(int fastboot_type)
326*54fd6939SJiyong Park {
327*54fd6939SJiyong Park int err;
328*54fd6939SJiyong Park
329*54fd6939SJiyong Park if ((fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) &&
330*54fd6939SJiyong Park (fastboot_type <= CHIMP_FASTBOOT_JUMP_DECOMPRESS)) {
331*54fd6939SJiyong Park CHIMP_DBG("Initiating ChiMP fastboot type %d\n", fastboot_type);
332*54fd6939SJiyong Park }
333*54fd6939SJiyong Park
334*54fd6939SJiyong Park /*
335*54fd6939SJiyong Park * If we are here, M0 did not setup Nitro because NIC mode
336*54fd6939SJiyong Park * strap was not present
337*54fd6939SJiyong Park */
338*54fd6939SJiyong Park err = bcm_chimp_reset_and_initial_setup();
339*54fd6939SJiyong Park if (err)
340*54fd6939SJiyong Park return err;
341*54fd6939SJiyong Park
342*54fd6939SJiyong Park if (fastboot_type > CHIMP_FASTBOOT_JUMP_DECOMPRESS) {
343*54fd6939SJiyong Park WARN("ChiMP setup deferred\n");
344*54fd6939SJiyong Park return -1;
345*54fd6939SJiyong Park }
346*54fd6939SJiyong Park
347*54fd6939SJiyong Park if (fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) {
348*54fd6939SJiyong Park
349*54fd6939SJiyong Park if ((fastboot_type == CHIMP_FASTBOOT_JUMP_IN_PLACE) &&
350*54fd6939SJiyong Park (CHIMP_FB1_ENTRY == 0)) {
351*54fd6939SJiyong Park ERROR("Missing ESAL entry point for fastboot type 1.\n"
352*54fd6939SJiyong Park "Fastboot failed\n");
353*54fd6939SJiyong Park return -1;
354*54fd6939SJiyong Park }
355*54fd6939SJiyong Park
356*54fd6939SJiyong Park /*
357*54fd6939SJiyong Park * TODO: We need to think of the way to load the ChiMP fw.
358*54fd6939SJiyong Park * This could be SPI, NAND, etc.
359*54fd6939SJiyong Park * For now we temporarily stick to the SPI load unless
360*54fd6939SJiyong Park * CHIMPFW_USE_SIDELOAD is defined. Note that for the SPI NVRAM
361*54fd6939SJiyong Park * image we need to parse directory and get the image.
362*54fd6939SJiyong Park * When we load image from other media there is no need to
363*54fd6939SJiyong Park * parse because fw image can be directly placed into the APE's
364*54fd6939SJiyong Park * scratchpad.
365*54fd6939SJiyong Park * For sideload method we simply reset the ChiMP, set bpe_reg
366*54fd6939SJiyong Park * to do fastboot with the type we define, and release from
367*54fd6939SJiyong Park * reset so that ROM loader would initiate fastboot immediately
368*54fd6939SJiyong Park */
369*54fd6939SJiyong Park #ifndef CHIMPFW_USE_SIDELOAD
370*54fd6939SJiyong Park {
371*54fd6939SJiyong Park uintptr_t spi_addr;
372*54fd6939SJiyong Park size_t size;
373*54fd6939SJiyong Park
374*54fd6939SJiyong Park err = bcm_chimp_find_fw_in_spi(&spi_addr, &size);
375*54fd6939SJiyong Park if (!err) {
376*54fd6939SJiyong Park INFO("Loading ChiMP firmware, addr 0x%lx, size %lu byte(s)\n",
377*54fd6939SJiyong Park spi_addr, size);
378*54fd6939SJiyong Park bcm_chimp_load_fw_from_spi(spi_addr, size);
379*54fd6939SJiyong Park } else {
380*54fd6939SJiyong Park ERROR("Error %d ChiMP firmware not in NVRAM directory!\n",
381*54fd6939SJiyong Park err);
382*54fd6939SJiyong Park }
383*54fd6939SJiyong Park }
384*54fd6939SJiyong Park #else
385*54fd6939SJiyong Park INFO("Skip ChiMP QSPI fastboot type %d due to sideload requested\n",
386*54fd6939SJiyong Park fastboot_type);
387*54fd6939SJiyong Park #endif
388*54fd6939SJiyong Park if (!err) {
389*54fd6939SJiyong Park INFO("Instruct ChiMP to fastboot\n");
390*54fd6939SJiyong Park bcm_chimp_set_fastboot(fastboot_type);
391*54fd6939SJiyong Park INFO("Fastboot mode set\n");
392*54fd6939SJiyong Park }
393*54fd6939SJiyong Park }
394*54fd6939SJiyong Park
395*54fd6939SJiyong Park bcm_nitro_chimp_release_reset();
396*54fd6939SJiyong Park
397*54fd6939SJiyong Park return err;
398*54fd6939SJiyong Park }
399