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