123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- /*
- * Copyright (c) 2016 - 2020, Broadcom
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <string.h>
- #include <drivers/delay_timer.h>
- #include <chimp.h>
- #include <chimp_nv_defs.h>
- #define CHIMP_DEFAULT_STARTUP_ADDR 0xb4300000
- /* ChiMP's view of APE scratchpad memory for fastboot */
- #define CHIMP_FASTBOOT_ADDR 0x61000000
- #define CHIMP_PREPARE_ACCESS_WINDOW(addr) \
- (\
- mmio_write_32(\
- NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT, \
- addr & 0xffc00000)\
- )
- #define CHIMP_INDIRECT_TGT_ADDR(addr) \
- (CHIMP_INDIRECT_BASE + (addr & CHIMP_INDIRECT_ADDR_MASK))
- #define CHIMP_CTRL_ADDR(x) (CHIMP_REG_CTRL_BASE + x)
- /* For non-PAXC builds */
- #ifndef CHIMP_FB1_ENTRY
- #define CHIMP_FB1_ENTRY 0
- #endif
- #define CHIMP_DBG VERBOSE
- void bcm_chimp_write(uintptr_t addr, uint32_t value)
- {
- CHIMP_PREPARE_ACCESS_WINDOW(addr);
- mmio_write_32(CHIMP_INDIRECT_TGT_ADDR(addr), value);
- }
- uint32_t bcm_chimp_read(uintptr_t addr)
- {
- CHIMP_PREPARE_ACCESS_WINDOW(addr);
- return mmio_read_32(CHIMP_INDIRECT_TGT_ADDR(addr));
- }
- void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits)
- {
- CHIMP_PREPARE_ACCESS_WINDOW(addr);
- mmio_clrbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits);
- }
- void bcm_chimp_setbits(uintptr_t addr, uint32_t bits)
- {
- CHIMP_PREPARE_ACCESS_WINDOW(addr);
- mmio_setbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits);
- }
- int bcm_chimp_is_nic_mode(void)
- {
- uint32_t val;
- /* Check if ChiMP straps are set */
- val = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW);
- val &= CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK;
- return val == CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK;
- }
- void bcm_chimp_fru_prog_done(bool is_done)
- {
- uint32_t val;
- val = is_done ? (1 << CHIMP_FRU_PROG_DONE_BIT) : 0;
- bcm_chimp_setbits(CHIMP_REG_ECO_RESERVED, val);
- }
- int bcm_chimp_handshake_done(void)
- {
- uint32_t value;
- value = bcm_chimp_read(CHIMP_REG_ECO_RESERVED);
- value &= (1 << CHIMP_FLASH_ACCESS_DONE_BIT);
- return value != 0;
- }
- int bcm_chimp_wait_handshake(void)
- {
- uint32_t timeout = CHIMP_HANDSHAKE_TIMEOUT_MS;
- uint32_t status;
- INFO("Waiting for ChiMP handshake...\n");
- do {
- if (bcm_chimp_handshake_done())
- break;
- /* No need to wait if ChiMP reported an error */
- status = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG);
- if (status & CHIMP_ERROR_MASK) {
- ERROR("ChiMP error 0x%x. Wait aborted\n", status);
- break;
- }
- mdelay(1);
- } while (--timeout);
- if (!bcm_chimp_handshake_done()) {
- if (timeout == 0) {
- WARN("Timeout waiting for ChiMP handshake\n");
- }
- } else {
- INFO("Got handshake from ChiMP!\n");
- }
- return bcm_chimp_handshake_done();
- }
- uint32_t bcm_chimp_read_ctrl(uint32_t offset)
- {
- return bcm_chimp_read(CHIMP_CTRL_ADDR(offset));
- }
- static int bcm_chimp_nitro_reset(void)
- {
- uint32_t timeout;
- /* Perform tasks done by M0 in NIC mode */
- CHIMP_DBG("Taking Nitro out of reset\n");
- mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
- /* MHB_RESET_N */
- (1 << CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R) |
- /* PCI_RESET_N */
- (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R) |
- /* PM_RESET_N */
- (1 << CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R) |
- /* NIC_RESET_N */
- (1 << CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R)
- );
- /* Wait until Nitro is out of reset */
- timeout = NIC_RESET_RELEASE_TIMEOUT_US;
- do {
- uint32_t value;
- value = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG);
- if ((value & CHIMP_BPE_MODE_ID_MASK) ==
- CHIMP_BPE_MODE_ID_PATTERN)
- break;
- udelay(1);
- } while (--timeout);
- if (timeout == 0) {
- ERROR("NIC reset release timed out\n");
- return -1;
- }
- return 0;
- }
- static void bcm_nitro_secure_mode_enable(void)
- {
- mmio_setbits_32(CDRU_NITRO_CONTROL,
- (1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R) |
- (1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R));
- mmio_write_32(NITRO_TZPC_TZPCDECPROT0clr,
- /* NITRO_TZPC */
- 1 << NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R);
- }
- static int bcm_chimp_reset_and_initial_setup(void)
- {
- int err;
- uint32_t handshake_reg;
- err = bcm_chimp_nitro_reset();
- if (err)
- return err;
- /* Enable Nitro secure mode */
- bcm_nitro_secure_mode_enable();
- /* Force ChiMP back into reset */
- bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
- 1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R);
- handshake_reg = (1 << SR_IN_SMARTNIC_MODE_BIT);
- /* Get OTP secure Chimp boot status */
- if (mmio_read_32(CRMU_OTP_STATUS) & (1 << CRMU_OTP_STATUS_BIT))
- handshake_reg |= (1 << SR_CHIMP_SECURE_BOOT_BIT);
- bcm_chimp_write(CHIMP_REG_ECO_RESERVED, handshake_reg);
- CHIMP_DBG("ChiMP reset and initial handshake parameters set\n");
- return 0;
- }
- static void bcm_nitro_chimp_release_reset(void)
- {
- bcm_chimp_clrbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
- 1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R);
- CHIMP_DBG("Nitro Reset Released\n");
- }
- static void bcm_chimp_set_fastboot(int mode)
- {
- uint32_t fb_entry;
- /* 1. Enable fastboot */
- bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
- (1 << CHIMP_FAST_BOOT_MODE_BIT));
- fb_entry = CHIMP_FASTBOOT_ADDR | mode;
- if (mode == CHIMP_FASTBOOT_JUMP_IN_PLACE)
- fb_entry = CHIMP_FB1_ENTRY;
- /* 2. Write startup address and mode */
- INFO("Setting fastboot type %d entry to 0x%x\n", mode, fb_entry);
- bcm_chimp_write(
- CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
- fb_entry);
- }
- #ifndef CHIMPFW_USE_SIDELOAD
- static void bcm_chimp_load_fw_from_spi(uintptr_t spi_addr, size_t size)
- {
- uintptr_t ape_scpad;
- uintptr_t dest;
- size_t bytes_left;
- ape_scpad = CHIMP_REG_CHIMP_APE_SCPAD;
- dest = CHIMP_INDIRECT_TGT_ADDR(CHIMP_REG_CHIMP_APE_SCPAD);
- bytes_left = size;
- while (bytes_left) {
- uint32_t delta;
- delta = bytes_left > CHIMP_WINDOW_SIZE ?
- bytes_left - CHIMP_WINDOW_SIZE : bytes_left;
- CHIMP_PREPARE_ACCESS_WINDOW(ape_scpad);
- INFO("Transferring %d byte(s) from 0x%lx to 0x%lx\n",
- delta, spi_addr, dest);
- /*
- * This single memcpy call takes significant amount of time
- * on Palladium. Be patient
- */
- memcpy((void *)dest, (void *)spi_addr, delta);
- bytes_left -= delta;
- INFO("Transferred %d byte(s) from 0x%lx to 0x%lx (%lu%%)\n",
- delta, spi_addr, dest,
- ((size - bytes_left) * 100)/size);
- spi_addr += delta;
- dest += delta;
- ape_scpad += delta;
- }
- }
- static int bcm_chimp_find_fw_in_spi(uintptr_t *addr, size_t *size)
- {
- int i;
- bnxnvm_master_block_header_t *master_block_hdr;
- bnxnvm_directory_block_header_t *dir_block_hdr;
- bnxnvm_directory_entry_t *dir_entry;
- int found;
- found = 0;
- /* Read the master block */
- master_block_hdr =
- (bnxnvm_master_block_header_t *)(uintptr_t)QSPI_BASE_ADDR;
- if (master_block_hdr->sig != BNXNVM_MASTER_BLOCK_SIG) {
- WARN("Invalid masterblock 0x%x (expected 0x%x)\n",
- master_block_hdr->sig,
- BNXNVM_MASTER_BLOCK_SIG);
- return -NV_NOT_NVRAM;
- }
- if ((master_block_hdr->block_size > NV_MAX_BLOCK_SIZE) ||
- (master_block_hdr->directory_offset >=
- master_block_hdr->nvram_size)) {
- WARN("Invalid masterblock block size 0x%x or directory offset 0x%x\n",
- master_block_hdr->block_size,
- master_block_hdr->directory_offset);
- return -NV_BAD_MB;
- }
- /* Skip to the Directory block start */
- dir_block_hdr =
- (bnxnvm_directory_block_header_t *)
- ((uintptr_t)QSPI_BASE_ADDR +
- master_block_hdr->directory_offset);
- if (dir_block_hdr->sig != BNXNVM_DIRECTORY_BLOCK_SIG) {
- WARN("Invalid directory header 0x%x (expected 0x%x)\n",
- dir_block_hdr->sig,
- BNXNVM_DIRECTORY_BLOCK_SIG);
- return -NV_BAD_DIR_HEADER;
- }
- /* Locate the firmware */
- for (i = 0; i < dir_block_hdr->entries; i++) {
- *addr = ((uintptr_t)dir_block_hdr + dir_block_hdr->length +
- i * dir_block_hdr->entry_length);
- dir_entry = (bnxnvm_directory_entry_t *)(*addr);
- if ((dir_entry->type == BNX_DIR_TYPE_BOOTCODE) ||
- (dir_entry->type == BNX_DIR_TYPE_BOOTCODE_2)) {
- found = 1;
- break;
- }
- }
- if (!found)
- return -NV_FW_NOT_FOUND;
- *addr = QSPI_BASE_ADDR + dir_entry->item_location;
- *size = dir_entry->data_length;
- INFO("Found chimp firmware at 0x%lx, size %lu byte(s)\n",
- *addr, *size);
- return NV_OK;
- }
- #endif
- int bcm_chimp_initiate_fastboot(int fastboot_type)
- {
- int err;
- if ((fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) &&
- (fastboot_type <= CHIMP_FASTBOOT_JUMP_DECOMPRESS)) {
- CHIMP_DBG("Initiating ChiMP fastboot type %d\n", fastboot_type);
- }
- /*
- * If we are here, M0 did not setup Nitro because NIC mode
- * strap was not present
- */
- err = bcm_chimp_reset_and_initial_setup();
- if (err)
- return err;
- if (fastboot_type > CHIMP_FASTBOOT_JUMP_DECOMPRESS) {
- WARN("ChiMP setup deferred\n");
- return -1;
- }
- if (fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) {
- if ((fastboot_type == CHIMP_FASTBOOT_JUMP_IN_PLACE) &&
- (CHIMP_FB1_ENTRY == 0)) {
- ERROR("Missing ESAL entry point for fastboot type 1.\n"
- "Fastboot failed\n");
- return -1;
- }
- /*
- * TODO: We need to think of the way to load the ChiMP fw.
- * This could be SPI, NAND, etc.
- * For now we temporarily stick to the SPI load unless
- * CHIMPFW_USE_SIDELOAD is defined. Note that for the SPI NVRAM
- * image we need to parse directory and get the image.
- * When we load image from other media there is no need to
- * parse because fw image can be directly placed into the APE's
- * scratchpad.
- * For sideload method we simply reset the ChiMP, set bpe_reg
- * to do fastboot with the type we define, and release from
- * reset so that ROM loader would initiate fastboot immediately
- */
- #ifndef CHIMPFW_USE_SIDELOAD
- {
- uintptr_t spi_addr;
- size_t size;
- err = bcm_chimp_find_fw_in_spi(&spi_addr, &size);
- if (!err) {
- INFO("Loading ChiMP firmware, addr 0x%lx, size %lu byte(s)\n",
- spi_addr, size);
- bcm_chimp_load_fw_from_spi(spi_addr, size);
- } else {
- ERROR("Error %d ChiMP firmware not in NVRAM directory!\n",
- err);
- }
- }
- #else
- INFO("Skip ChiMP QSPI fastboot type %d due to sideload requested\n",
- fastboot_type);
- #endif
- if (!err) {
- INFO("Instruct ChiMP to fastboot\n");
- bcm_chimp_set_fastboot(fastboot_type);
- INFO("Fastboot mode set\n");
- }
- }
- bcm_nitro_chimp_release_reset();
- return err;
- }
|