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