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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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