aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVikas Gupta <vikas.gupta@broadcom.com>2019-07-17 11:23:38 +0530
committerJérôme Forissier <jerome@forissier.org>2019-11-07 09:28:26 +0000
commit95bec10a7d4de4bf8d7cb6c535b80ec76f2b3c94 (patch)
treeaae5db293288b9f4c46fdf6dc2b0315651b827a2
parentde5333edb926768505c5db3a2585b23a696eb74d (diff)
drivers: bnxt: add Broadcom bnxt driver
Add Broadcom bnxt driver which helps to load the firmware on bnxt device Signed-off-by: Vikas Gupta <vikas.gupta@broadcom.com> Signed-off-by: Sheetal Tigadoli <sheetal.tigadoli@broadcom.com> Reviewed-by: Sandeep Tripathy <sandeep.tripathy@broadcom.com> Acked-by: Jerome Forissier <jerome@forissier.org> Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
-rw-r--r--core/arch/arm/plat-bcm/conf.mk1
-rw-r--r--core/arch/arm/plat-bcm/crc32.c88
-rw-r--r--core/arch/arm/plat-bcm/crc32.h17
-rw-r--r--core/arch/arm/plat-bcm/main.c9
-rw-r--r--core/arch/arm/plat-bcm/platform_config.h14
-rw-r--r--core/arch/arm/plat-bcm/sub.mk1
-rw-r--r--core/drivers/bnxt/bnxt.c190
-rw-r--r--core/drivers/bnxt/bnxt_fw.c682
-rw-r--r--core/drivers/bnxt/bnxt_images.c108
-rw-r--r--core/drivers/bnxt/sub.mk3
-rw-r--r--core/drivers/sub.mk1
-rw-r--r--core/include/drivers/bcm/bnxt.h38
12 files changed, 1151 insertions, 1 deletions
diff --git a/core/arch/arm/plat-bcm/conf.mk b/core/arch/arm/plat-bcm/conf.mk
index 73d9d545..74e891b8 100644
--- a/core/arch/arm/plat-bcm/conf.mk
+++ b/core/arch/arm/plat-bcm/conf.mk
@@ -27,6 +27,7 @@ $(call force,CFG_SP805_WDT,y)
$(call force,CFG_BCM_HWRNG,y)
$(call force,CFG_BCM_SOTP,y)
$(call force,CFG_BCM_GPIO,y)
+CFG_BNXT_FW ?= y
endif
ifeq ($(DEBUG),1)
diff --git a/core/arch/arm/plat-bcm/crc32.c b/core/arch/arm/plat-bcm/crc32.c
new file mode 100644
index 00000000..c716f376
--- /dev/null
+++ b/core/arch/arm/plat-bcm/crc32.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2019 Broadcom.
+ */
+
+#include <crc32.h>
+
+static const uint32_t crc32tbl[] = { /* CRC polynomial 0xedb88320 */
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+static uint32_t ucrc32(const char ch, uint32_t crc)
+{
+ return crc32tbl[(crc ^ ch) & 0xff] ^ (crc >> 8);
+}
+
+uint32_t crc32i(uint32_t crc, const char *buf, size_t len)
+{
+ size_t l = 0;
+
+ for (l = 0; l < len; l++)
+ crc = ucrc32(buf[l], crc);
+
+ return ~crc;
+}
diff --git a/core/arch/arm/plat-bcm/crc32.h b/core/arch/arm/plat-bcm/crc32.h
new file mode 100644
index 00000000..acfb15cf
--- /dev/null
+++ b/core/arch/arm/plat-bcm/crc32.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright 2019 Broadcom.
+ */
+
+#ifndef CRC32_H
+#define CRC32_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define CRC32_INIT_VAL (~0)
+#define CRC32 crc32i
+
+uint32_t crc32i(uint32_t crc, const char *buf, size_t len);
+
+#endif /* CRC32_H */
diff --git a/core/arch/arm/plat-bcm/main.c b/core/arch/arm/plat-bcm/main.c
index 5e31f8e8..0a7d1008 100644
--- a/core/arch/arm/plat-bcm/main.c
+++ b/core/arch/arm/plat-bcm/main.c
@@ -41,6 +41,12 @@ register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE2_BASE, BCM_DEVICE2_SIZE);
#ifdef BCM_DEVICE3_BASE
register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE3_BASE, BCM_DEVICE3_SIZE);
#endif
+#ifdef BCM_DEVICE4_BASE
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE4_BASE, BCM_DEVICE4_SIZE);
+#endif
+#ifdef BCM_DEVICE5_BASE
+register_phys_mem_pgdir(MEM_AREA_IO_NSEC, BCM_DEVICE5_BASE, BCM_DEVICE5_SIZE);
+#endif
#ifdef BCM_DRAM0_NS_BASE
register_dynamic_shm(BCM_DRAM0_NS_BASE, BCM_DRAM0_NS_SIZE);
#endif
@@ -50,6 +56,9 @@ register_dynamic_shm(BCM_DRAM1_NS_BASE, BCM_DRAM1_NS_SIZE);
#ifdef BCM_DRAM2_NS_BASE
register_dynamic_shm(BCM_DRAM2_NS_BASE, BCM_DRAM2_NS_SIZE);
#endif
+#ifdef BCM_DRAM0_SEC_BASE
+register_phys_mem(MEM_AREA_RAM_SEC, BCM_DRAM0_SEC_BASE, BCM_DRAM0_SEC_SIZE);
+#endif
const struct thread_handlers *generic_boot_get_handlers(void)
{
diff --git a/core/arch/arm/plat-bcm/platform_config.h b/core/arch/arm/plat-bcm/platform_config.h
index cec39842..6e71b401 100644
--- a/core/arch/arm/plat-bcm/platform_config.h
+++ b/core/arch/arm/plat-bcm/platform_config.h
@@ -34,18 +34,30 @@
#define SOTP_BASE 0x68b50000
+#define BNXT_BASE 0x60800000
+
+#define QSPI_MEM_BASE 0x70000000
+
/* device memory ranges */
#define BCM_DEVICE0_BASE GICD_BASE
#define BCM_DEVICE0_SIZE CORE_MMU_PGDIR_SIZE
#define BCM_DEVICE1_BASE SMBUS0_BASE
#define BCM_DEVICE1_SIZE CORE_MMU_PGDIR_SIZE
+#define BCM_DEVICE4_BASE BNXT_BASE
+#define BCM_DEVICE4_SIZE 0x800000
+#define BCM_DEVICE5_BASE QSPI_MEM_BASE
+#define BCM_DEVICE5_SIZE 0x800000
/* NS DDR ranges */
#define BCM_DRAM0_NS_BASE 0x80000000
-#define BCM_DRAM0_NS_SIZE 0x0d000000
+#define BCM_DRAM0_NS_SIZE 0xae00000
#define BCM_DRAM1_NS_BASE 0x90000000
#define BCM_DRAM1_NS_SIZE 0x70000000
#define BCM_DRAM2_NS_BASE 0x880400000
#define BCM_DRAM2_NS_SIZE 0x17fbfffff
+/* Secure DDR ranges */
+#define BCM_DRAM0_SEC_BASE 0x8ae00000
+#define BCM_DRAM0_SEC_SIZE 0x2200000
+
#endif /*PLATFORM_CONFIG_H*/
diff --git a/core/arch/arm/plat-bcm/sub.mk b/core/arch/arm/plat-bcm/sub.mk
index 8ddc2fd4..bde6b231 100644
--- a/core/arch/arm/plat-bcm/sub.mk
+++ b/core/arch/arm/plat-bcm/sub.mk
@@ -1,2 +1,3 @@
global-incdirs-y += .
srcs-y += main.c
+srcs-y += crc32.c
diff --git a/core/drivers/bnxt/bnxt.c b/core/drivers/bnxt/bnxt.c
new file mode 100644
index 00000000..5bd9fd9c
--- /dev/null
+++ b/core/drivers/bnxt/bnxt.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2019 Broadcom.
+ */
+
+#include <drivers/bcm/bnxt.h>
+#include <initcall.h>
+#include <io.h>
+#include <kernel/delay.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BNXT_REG_CTRL_BASE 0x3040000
+#define BNXT_REG_ECO_RESERVED 0x3042400
+#define BNXT_FLASH_ACCESS_DONE_BIT 2
+#define NIC400_BNXT_IDM_IO_CONTROL_DIRECT 0x60e00408
+#define BNXT_INDIRECT_BASE 0x60800000
+#define BNXT_INDIRECT_ADDR_MASK 0x3fffffu
+#define BNXT_INDIRECT_BASE_MASK (~BNXT_INDIRECT_ADDR_MASK)
+#define BNXT_INDIRECT_WINDOW_SIZE (BNXT_INDIRECT_ADDR_MASK + 1)
+#define BNXT_REG_CTRL_BPE_MODE_REG 0x0
+#define BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT 2
+#define BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT 1
+#define BNXT_REG_CTRL_BPE_STAT_REG 0x4
+#define BNXT_REG_CTRL_FSTBOOT_PTR_REG 0x8
+#define BNXT_ERROR_MASK 0xf0000000
+#define BNXT_CTRL_ADDR(x) (BNXT_REG_CTRL_BASE + (x))
+#define BNXT_HANDSHAKE_TIMEOUT_MS 10000
+
+#define KONG_REG_CTRL_MODE_REG 0x03900000
+#define KONG_REG_CTRL_MODE_CPUHALT_N_BIT 0
+
+#define BNXT_STICKY_BYTE_POR 0x04030088
+#define BNXT_STICKY_BYTE_POR_MHB_BIT 4
+
+static vaddr_t bnxt_access_window_virt_addr;
+static vaddr_t bnxt_indirect_dest_addr;
+
+static void bnxt_prepare_access_window(uint32_t addr)
+{
+ addr &= BNXT_INDIRECT_BASE_MASK;
+ io_write32(bnxt_access_window_virt_addr, addr);
+}
+
+static vaddr_t bnxt_indirect_tgt_addr(uint32_t addr)
+{
+ addr &= BNXT_INDIRECT_ADDR_MASK;
+ return (vaddr_t)(bnxt_indirect_dest_addr + addr);
+}
+
+uint32_t bnxt_write32_multiple(uintptr_t dst,
+ uintptr_t src,
+ uint32_t num_entries,
+ int src_4byte_increment)
+{
+ uint32_t i = 0;
+ vaddr_t target = 0;
+
+ if (num_entries == 0)
+ return 0;
+
+ /* Only write up to the next window boundary */
+ if ((dst & BNXT_INDIRECT_BASE_MASK) !=
+ ((dst + num_entries * sizeof(uint32_t)) & BNXT_INDIRECT_BASE_MASK))
+ num_entries = (((dst + BNXT_INDIRECT_WINDOW_SIZE) &
+ BNXT_INDIRECT_BASE_MASK) -
+ dst) /
+ sizeof(uint32_t);
+
+ bnxt_prepare_access_window(dst);
+ target = bnxt_indirect_tgt_addr(dst);
+ for (i = 0; i < num_entries; i++) {
+ io_write32(target, *(uint32_t *)src);
+ target += sizeof(uint32_t);
+ if (src_4byte_increment)
+ src += sizeof(uint32_t);
+ }
+
+ return num_entries;
+}
+
+static uint32_t bnxt_read(uint32_t addr)
+{
+ bnxt_prepare_access_window(addr);
+ return io_read32(bnxt_indirect_tgt_addr(addr));
+}
+
+static uint32_t bnxt_read_ctrl(uint32_t offset)
+{
+ return bnxt_read(BNXT_CTRL_ADDR(offset));
+}
+
+static void bnxt_write(uint32_t addr, uint32_t value)
+{
+ bnxt_prepare_access_window(addr);
+ io_write32(bnxt_indirect_tgt_addr(addr), value);
+}
+
+static void bnxt_write_ctrl(uint32_t offset, uint32_t value)
+{
+ bnxt_write(BNXT_CTRL_ADDR(offset), value);
+}
+
+static int bnxt_handshake_done(void)
+{
+ uint32_t value = 0;
+
+ value = bnxt_read(BNXT_REG_ECO_RESERVED);
+ value &= BIT(BNXT_FLASH_ACCESS_DONE_BIT);
+
+ return value != 0;
+}
+
+int bnxt_wait_handshake(void)
+{
+ uint32_t timeout = BNXT_HANDSHAKE_TIMEOUT_MS;
+ uint32_t status = 0;
+
+ DMSG("Waiting for ChiMP handshake...");
+ do {
+ if (bnxt_handshake_done())
+ break;
+ /* No need to wait if ChiMP reported an error */
+ status = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_STAT_REG);
+ if (status & BNXT_ERROR_MASK) {
+ DMSG("ChiMP error 0x%x. Wait aborted", status);
+ break;
+ }
+ mdelay(1);
+ } while (--timeout);
+
+ if (!bnxt_handshake_done()) {
+ if (timeout == 0)
+ DMSG("Timeout waiting for ChiMP handshake");
+ } else {
+ DMSG("Got handshake from ChiMP!");
+ }
+ return bnxt_handshake_done();
+}
+
+void bnxt_chimp_halt(void)
+{
+ uint32_t value = 0;
+
+ value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG);
+ value |= BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT);
+ bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value);
+}
+
+void bnxt_kong_halt(void)
+{
+ uint32_t value = 0;
+
+ value = bnxt_read(KONG_REG_CTRL_MODE_REG);
+ value &= ~BIT(KONG_REG_CTRL_MODE_CPUHALT_N_BIT);
+ bnxt_write(KONG_REG_CTRL_MODE_REG, value);
+}
+
+int bnxt_fastboot(uintptr_t addr)
+{
+ uint32_t value = 0;
+
+ value = bnxt_read(BNXT_STICKY_BYTE_POR);
+ value |= BIT(BNXT_STICKY_BYTE_POR_MHB_BIT);
+ bnxt_write(BNXT_STICKY_BYTE_POR, value);
+
+ /* Set the fastboot address and type */
+ bnxt_write_ctrl(BNXT_REG_CTRL_FSTBOOT_PTR_REG, addr);
+
+ /* Set fastboot mode & take BNXT CPU1 out of reset */
+ value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG);
+ value |= BIT(BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT);
+ value &= ~BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT);
+ bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value);
+
+ return 0;
+}
+
+static TEE_Result bnxt_init(void)
+{
+ bnxt_access_window_virt_addr =
+ (vaddr_t)phys_to_virt(NIC400_BNXT_IDM_IO_CONTROL_DIRECT,
+ MEM_AREA_IO_SEC);
+ bnxt_indirect_dest_addr =
+ (vaddr_t)phys_to_virt(BNXT_INDIRECT_BASE,
+ MEM_AREA_IO_SEC);
+ return TEE_SUCCESS;
+}
+driver_init(bnxt_init);
diff --git a/core/drivers/bnxt/bnxt_fw.c b/core/drivers/bnxt/bnxt_fw.c
new file mode 100644
index 00000000..a5649f49
--- /dev/null
+++ b/core/drivers/bnxt/bnxt_fw.c
@@ -0,0 +1,682 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2019 Broadcom.
+ */
+
+#include <crc32.h>
+#include <drivers/bcm/bnxt.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * These macros are the offsets where images reside on sec mem
+ */
+#define BNXT_BUFFER_SEC_MEM 0x8ae00000
+#define BNXT_FW_SEC_MEM_SRC BNXT_BUFFER_SEC_MEM
+#define BNXT_FW_SEC_MEM_CFG (BNXT_BUFFER_SEC_MEM + 0x100000)
+#define TEMP_MEM (BNXT_BUFFER_SEC_MEM + 0x200000)
+
+#define BNXT_CRASH_SEC_MEM 0x8b000000
+#define BNXT_CRASH_LEN 0x2000000
+
+#define BNXT_CONFIG_NS3_DEST 0x03a00000
+#define BNXT_CONFIG_NS3Z_DEST 0x031a0000
+#define BNXT_BSPD_CFG_OFFSET 0x51b0
+#define BNXT_CONFIG_NS3_BSPD_DEST (BNXT_CONFIG_NS3_DEST + \
+ BNXT_BSPD_CFG_OFFSET)
+#define BNXT_CONFIG_NS3Z_BSPD_DEST (BNXT_CONFIG_NS3Z_DEST + \
+ BNXT_BSPD_CFG_OFFSET)
+#define BNXT_BSPD_CFG_SIZE 0x200
+
+#define BNXT_CRASH_DUMP_INFO_NS3_BASE 0x3a5ff00
+#define BNXT_CRASH_DUMP_INFO_NS3Z_BASE 0x31fff00
+
+#define IS_ALIGNED(addr, algn) (!((addr) & ((algn) - 1)))
+
+#define SZ_1K 0x400
+
+#define BUFFER_PADDING SZ_1K
+
+#define INC_SRC_ADDR 1
+
+#define EOF -1
+
+#define BCM_BNXT_FASTBOOT_MASK 0x3u
+#define BCM_BNXT_FASTBOOT_TYPE_1 1
+
+#define ADDR_IS_4BYTE_ALIGNED(addr) IS_ALIGNED(addr, 4)
+
+#define SECTION_IS_LOADABLE(section_ptr) \
+ ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_LOADABLE)
+#define SECTION_IS_ZIPPED(section_ptr) \
+ ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_ZIPPED)
+#define SECTION_IS_TOBE_COPIED(section_ptr) \
+ ((section_ptr)->flags_src_offset & \
+ (SECTION_FLAGS_IS_EXEC_INSTR | SECTION_FLAGS_IS_DATA))
+#define SECTION_IS_TOBE_ZEROED(section_ptr) \
+ ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_BSS)
+#define SECTION_IS_4BYTE_ALIGNED(section_ptr) \
+ ADDR_IS_4BYTE_ALIGNED((section_ptr)->dest_addr)
+
+#define SECTION_SRC_OFFSET(section_ptr) \
+ ((section_ptr)->flags_src_offset & SECTION_SRC_OFFFSET_MASK)
+
+/* -------------------------------------------------------------------------- */
+
+/* Section header for each image block */
+struct ape_section_hdr_s {
+ /* Destination address that this section is to be copied to */
+ uint32_t dest_addr;
+
+ /*
+ * bit[0:23] source offset address that this image copy from
+ * bit[24:31] flags
+ */
+ uint32_t flags_src_offset;
+#define SECTION_FLAGS_MASK 0xff000000
+ /* Session is compressed (zipped) */
+#define SECTION_FLAGS_IS_ZIPPED 0x01000000
+ /* Session contains CRC */
+#define SECTION_FLAGS_IS_CRC 0x02000000
+ /* Session contains executable code (e.g. .text) */
+#define SECTION_FLAGS_IS_EXEC_INSTR 0x04000000
+ /* Session contains initialized data (e.g. .data) */
+#define SECTION_FLAGS_IS_DATA 0x08000000
+ /* Session contains zero initialized data (e.g. .bss) */
+#define SECTION_FLAGS_IS_BSS 0x10000000
+ /* Loadable section mask */
+#define SECTION_FLAGS_IS_LOADABLE (SECTION_FLAGS_IS_EXEC_INSTR | \
+ SECTION_FLAGS_IS_DATA | \
+ SECTION_FLAGS_IS_BSS)
+#define SECTION_SRC_OFFFSET_MASK 0x00ffffff
+
+ /* Original image length, dword (4byte) length */
+ uint32_t org_data_len;
+
+ /* Compressed image length (if FlAGS_IS_ZIPPED is set) */
+ uint32_t zip_data_len;
+
+ /*
+ * checksum value for this image block, if FLAGS_IS_CRC then
+ * this is CRC checksum; otherwise it is a simple summation
+ */
+ uint32_t checksum;
+};
+
+struct version_s {
+ uint8_t version[16]; /* Null-terminated file version string */
+};
+
+struct ver_ext_offset_s {
+ uint8_t version[12]; /* Null-terminated file version string */
+ uint32_t ext_hdr_offset;
+};
+
+union version_and_offset_u {
+ struct version_s version1;
+ struct ver_ext_offset_s version2;
+};
+
+struct ape_bin_hdr_s {
+ /* APE binary header signature; expects APE_BIN_HDR_SIGNATURE */
+ uint32_t signature;
+#define APE_BIN_HDR_SIGNATURE 0x1a4d4342 /* "BCM"+0x1a */
+ /* Reserved for ChiMP's use */
+ uint8_t flags;
+ uint8_t code_type;
+ uint8_t device;
+ uint8_t media;
+ union version_and_offset_u ver;
+ uint8_t build;
+ uint8_t revision;
+ uint8_t minor_ver;
+ uint8_t major_ver;
+ uint32_t entry_address;
+ uint8_t reserved;
+ uint8_t header_dword_size;
+ uint8_t num_total_sections;
+ uint8_t num_loadable_sections;
+ uint32_t checksum;
+} __packed __aligned(1);
+
+#define APE_BIN_HDR_SIZE sizeof(struct ape_bin_hdr_s)
+#define APE_SECTION_HDR_SIZE sizeof(struct ape_section_hdr_s)
+
+/* MAX number of image sections that will be accepted */
+#define APE_IMG_MAX_SECTIONS 16
+
+#define APE_IMG_LOAD_DEBUG 0
+
+/* -------------------------------------------------------------------------- */
+
+struct ape_mem_region_s {
+ uint32_t c_base; /* ChiMP's view of address */
+ uint32_t h_base; /* Host's view of address */
+ uint32_t size; /* Size in bytes */
+};
+
+/* Memory map into various scratchpad memories */
+static struct ape_mem_region_s ape_mem_regions[] = {
+ /* CHIMP scratchpad */
+ {0x00100000, 0x03100000, 1024 * SZ_1K},
+
+ /* APE scratchpad */
+ {0x61000000, 0x03300000, 1152 * SZ_1K},
+
+ /* BONO scratchpad */
+ {0x61600000, 0x03a00000, 512 * SZ_1K},
+
+ /* KONG scratchpad */
+ {0x61400000, 0x03800000, 512 * SZ_1K},
+
+ /* Keep this last!! */
+ {0, 0, 0}
+};
+
+/* Nitro crash address configuration related macros */
+#define BNXT_CRASH_INFO_SIGNATURE 0x20524444
+#define BNXT_CRASH_INFO_VALID 0x1
+#define MAX_CRASH_ADDR_ITEM 8
+
+struct nitro_crash_addr_item {
+ uint32_t info;
+ uint32_t size;
+ uint32_t addr_hi;
+ uint32_t addr_lo;
+};
+
+struct nitro_crash_addr_info {
+ /* CRC of the struct content, starting at next field. */
+ uint32_t crc;
+ uint32_t signature;
+ uint32_t version;
+ struct nitro_crash_addr_item table[MAX_CRASH_ADDR_ITEM];
+};
+
+static inline void memcpy32_helper(uintptr_t src,
+ uintptr_t dst,
+ uint32_t entries,
+ int inc_src_addr)
+{
+ uint32_t copied_entries = 0;
+
+ while (entries) {
+ copied_entries = bnxt_write32_multiple(dst, src, entries,
+ inc_src_addr);
+
+ if (copied_entries < entries) {
+ dst += copied_entries * sizeof(uint32_t);
+ src += (inc_src_addr) ?
+ (copied_entries * sizeof(uint32_t)) : 0;
+ entries -= copied_entries;
+ } else {
+ entries = 0;
+ }
+ }
+}
+
+static uint32_t ape_host_view_addr_get(uint32_t bnxt_view_addr, uint32_t size)
+{
+ struct ape_mem_region_s *region = ape_mem_regions;
+ uint32_t addr = 0;
+
+ for (; region->size != 0; region++) {
+ if (bnxt_view_addr < region->c_base)
+ continue;
+
+ if (bnxt_view_addr >= (region->c_base + region->size))
+ continue;
+
+ if (size > (region->c_base + region->size - bnxt_view_addr)) {
+ EMSG("ERROR: 0x%x + 0x%x spans memory boundary",
+ bnxt_view_addr, size);
+ break;
+ }
+
+ addr = bnxt_view_addr - region->c_base;
+ addr += region->h_base;
+ break;
+ }
+
+ return addr;
+}
+
+static uint32_t ape_hdr_crc_calc(const struct ape_bin_hdr_s *hdr)
+{
+ uint32_t crc = 0;
+ uint32_t dummy = 0;
+
+ /* Compute the CRC up to, but not including, the checksum field */
+ crc = CRC32(CRC32_INIT_VAL,
+ (const char *)hdr,
+ (uintptr_t)(&hdr->checksum) - (uintptr_t)hdr);
+
+ /* Compute the CRC with the checksum field zeroed out */
+ crc = CRC32(~crc, (const char *)&dummy, sizeof(uint32_t));
+
+ /*
+ * Compute the remainder part of the image header, i.e., the
+ * section headers
+ */
+ crc = CRC32(~crc,
+ (const char *)((uintptr_t)hdr + APE_BIN_HDR_SIZE),
+ hdr->num_total_sections * APE_SECTION_HDR_SIZE);
+
+ return crc;
+}
+
+static int ape_bin_hdr_valid(const struct ape_bin_hdr_s *hdr)
+{
+ uint32_t checksum = 0;
+
+ if (!hdr) {
+ EMSG("ERROR: no APE image header");
+ return BNXT_FAILURE;
+ }
+
+ if (hdr->signature != APE_BIN_HDR_SIGNATURE) {
+ EMSG("ERROR: bad APE image signature");
+ return BNXT_FAILURE;
+ }
+
+ if (hdr->num_total_sections > APE_IMG_MAX_SECTIONS) {
+ EMSG("ERROR: too many sections in APE image");
+ return BNXT_FAILURE;
+ }
+
+ checksum = ape_hdr_crc_calc(hdr);
+ if (hdr->checksum != checksum) {
+ EMSG("ERROR: bad APE header checksum (exp: %x, act: %x)",
+ hdr->checksum, checksum);
+ return BNXT_FAILURE;
+ }
+
+ return BNXT_SUCCESS;
+}
+
+static int get_char(uint8_t *inbuf, size_t *inbuf_idx, size_t inbuf_size)
+{
+ int c = 0;
+
+ if (*inbuf_idx >= inbuf_size)
+ return EOF;
+
+ c = inbuf[*inbuf_idx];
+ *inbuf_idx += 1;
+
+ return c;
+}
+
+static void put_char(uint8_t *outbuf,
+ size_t *outbuf_idx,
+ size_t outbuf_size,
+ uint8_t ch)
+{
+ if (*outbuf_idx >= outbuf_size)
+ return;
+
+ outbuf[*outbuf_idx] = ch;
+ *outbuf_idx += 1;
+}
+
+static size_t ape_section_uncompress(uint8_t *inbuf,
+ size_t inbuf_size,
+ uint8_t *outbuf,
+ size_t outbuf_size)
+{
+ int i = 0, j = 0, k = 0, r = 0, c = 0;
+ uint32_t flags = 0;
+ size_t exp_size = 0, codesize = 0;
+ size_t inbuf_idx = 0, outbuf_idx = 0;
+#define CODE_8U_MASK 0xff00u /* 8 code units count mask (8 bits) */
+#define CODE_END_MASK 0x100u /* End of code units mask */
+#define CODE_IS_UNENCODED_MASK 1 /* Unencoded code unit mask */
+#define CODE_POS_MASK 0xe0u /* Encoded unit position mask and */
+#define CODE_POS_SHIFT 3 /* Bit shift */
+#define CODE_LEN_MASK 0x1fu /* Encoded unit length mask */
+#define NS 2048 /* Size of ring buffer */
+#define F 34 /* Upper limit for match_length */
+#define THRESHOLD 2 /* Encode string into position and
+ * length, if match_length is
+ * greater than this.
+ */
+ /*
+ * Ring buffer of size NS, with an extra F-1 bytes to facilitate
+ * string comparisons.
+ */
+ uint8_t text_buf[NS + F - 1];
+
+ inbuf_idx = 0;
+ outbuf_idx = 0;
+
+ for (i = 0; i < NS - F; i++)
+ text_buf[i] = ' ';
+
+ r = NS - F;
+
+ for (;;) {
+ if (((flags >>= 1) & CODE_END_MASK) == 0) {
+ c = get_char(inbuf, &inbuf_idx, inbuf_size);
+ if (c == EOF)
+ break;
+ ++exp_size;
+
+ if (exp_size > inbuf_size)
+ break;
+
+ /* Use higher byte cleverly to count to eight */
+ flags = c | CODE_8U_MASK;
+ }
+
+ if (flags & CODE_IS_UNENCODED_MASK) {
+ /* Not encoded; simply copy the unit */
+ c = get_char(inbuf, &inbuf_idx, inbuf_size);
+ if (c == EOF)
+ break;
+
+ ++exp_size;
+ if (exp_size > inbuf_size)
+ break;
+
+ put_char(outbuf, &outbuf_idx, outbuf_size, c);
+ text_buf[r++] = c;
+ r &= (NS - 1);
+ ++codesize;
+ } else {
+ /* Encoded; get the position and length & duplicate */
+ i = get_char(inbuf, &inbuf_idx, inbuf_size);
+ if (i == EOF)
+ break;
+
+ ++exp_size;
+ if (exp_size > inbuf_size)
+ break;
+
+ j = get_char(inbuf, &inbuf_idx, inbuf_size);
+ if (j == EOF)
+ break;
+
+ ++exp_size;
+ if (exp_size > inbuf_size)
+ break;
+
+ i |= ((j & CODE_POS_MASK) << CODE_POS_SHIFT);
+ j = ((j & CODE_LEN_MASK) + THRESHOLD);
+
+ for (k = 0; k <= j; k++) {
+ c = text_buf[((i + k) & (NS - 1))];
+ put_char(outbuf, &outbuf_idx, outbuf_size, c);
+ text_buf[r++] = c;
+ r &= (NS - 1);
+ ++codesize;
+ }
+ }
+ }
+
+ return codesize;
+}
+
+static int ape_section_copy(struct ape_bin_hdr_s *bin_hdr,
+ struct ape_section_hdr_s *section)
+{
+ uintptr_t src = 0;
+ uintptr_t dst = 0;
+ uint32_t checksum = 0;
+ uint32_t i = 0;
+ size_t size = 0;
+ uint8_t *section_data = NULL;
+ size_t work_buff_size = 0;
+ void *work_buff = NULL;
+ int rc = BNXT_FAILURE;
+
+ if (SECTION_IS_ZIPPED(section)) {
+ work_buff_size = section->org_data_len + BUFFER_PADDING;
+ work_buff = (void *)phys_to_virt(TEMP_MEM, MEM_AREA_RAM_SEC);
+ if (!work_buff) {
+ EMSG("ERROR: buffer allocation");
+ return BNXT_FAILURE;
+ }
+
+ section_data = (uint8_t *)((uintptr_t)bin_hdr +
+ SECTION_SRC_OFFSET(section));
+ size = ape_section_uncompress(section_data,
+ section->zip_data_len,
+ work_buff,
+ work_buff_size);
+ if (size >= work_buff_size) {
+ EMSG("ERROR: section uncompress");
+ goto ape_section_copy_exit;
+ }
+ if (size < section->org_data_len) {
+ EMSG("ERROR: decompressed data size mismatch ");
+ EMSG("(exp: %d, act: %ld)",
+ section->org_data_len, size);
+ goto ape_section_copy_exit;
+ }
+ src = (uintptr_t)work_buff;
+ } else {
+ src = (uintptr_t)bin_hdr + SECTION_SRC_OFFSET(section);
+ }
+
+ size = section->org_data_len;
+
+ if (section->flags_src_offset & SECTION_FLAGS_IS_CRC) {
+ checksum = CRC32(CRC32_INIT_VAL, (const char *)src, size);
+ } else {
+ checksum = 0;
+ for (i = 0; i < size / sizeof(uint32_t); i++)
+ checksum += ((uint32_t *)src)[i];
+ }
+ if (checksum != section->checksum) {
+ EMSG("ERROR: checksum mismatch (exp: %x, act: %x)",
+ section->checksum, checksum);
+ goto ape_section_copy_exit;
+ }
+
+ dst = ape_host_view_addr_get(section->dest_addr, size);
+ if (dst == 0) {
+ EMSG("ERROR: ChiMP-to-host address conversion of %x",
+ section->dest_addr);
+ goto ape_section_copy_exit;
+ }
+
+ /* Copy the section */
+ size = size / sizeof(uint32_t);
+ memcpy32_helper(src, dst, size, INC_SRC_ADDR);
+
+ rc = BNXT_SUCCESS;
+
+ape_section_copy_exit:
+ return rc;
+}
+
+static int ape_section_zero(struct ape_section_hdr_s *section)
+{
+ uint32_t dst = 0;
+ uint32_t size = section->org_data_len;
+ uint32_t zero = 0;
+
+ if (section->org_data_len == 0)
+ return BNXT_SUCCESS;
+
+ /* Convert ChiMP's view of the address in the image to the host view */
+ dst = ape_host_view_addr_get(section->dest_addr, size);
+ if (dst == 0) {
+ EMSG("ERROR: ChiMP-to-host address conversion of %x",
+ section->dest_addr);
+ return BNXT_FAILURE;
+ }
+
+ /*
+ * Zero the section; we simply copy zeros and do not increment the
+ * source buffer address.
+ */
+ size = size / sizeof(uint32_t);
+ memcpy32_helper((uintptr_t)&zero, dst, size, !INC_SRC_ADDR);
+
+ return BNXT_SUCCESS;
+}
+
+static int bnxt_load(vaddr_t img_buffer)
+{
+ struct ape_bin_hdr_s *bin_hdr = NULL;
+ struct ape_section_hdr_s *section = NULL;
+ int sidx = 0;
+ int rc = BNXT_SUCCESS;
+
+ bin_hdr = (struct ape_bin_hdr_s *)img_buffer;
+ section = (struct ape_section_hdr_s *)(img_buffer +
+ APE_BIN_HDR_SIZE);
+
+ if (ape_bin_hdr_valid(bin_hdr) != BNXT_SUCCESS)
+ return BNXT_FAILURE;
+
+ for (sidx = 0; sidx < bin_hdr->num_total_sections; sidx++, section++) {
+ if (!SECTION_IS_LOADABLE(section))
+ continue;
+
+ if (!ADDR_IS_4BYTE_ALIGNED(section->dest_addr)) {
+ EMSG("ERROR: unaligned section dest address 0x%x",
+ section->dest_addr);
+ rc = BNXT_FAILURE;
+ break;
+ }
+
+ if (!ADDR_IS_4BYTE_ALIGNED(SECTION_SRC_OFFSET(section))) {
+ EMSG("ERROR: unaligned section src offset (0x%x)",
+ SECTION_SRC_OFFSET(section));
+ rc = BNXT_FAILURE;
+ break;
+ }
+
+ if (section->org_data_len % sizeof(uint32_t)) {
+ EMSG("ERROR: section size (%d) not divisible by 4",
+ section->org_data_len);
+ rc = BNXT_FAILURE;
+ break;
+ }
+
+ if (SECTION_IS_TOBE_COPIED(section)) {
+ rc = ape_section_copy(bin_hdr, section);
+ if (rc != BNXT_SUCCESS)
+ break;
+ } else if (SECTION_IS_TOBE_ZEROED(section)) {
+ rc = ape_section_zero(section);
+ if (rc != BNXT_SUCCESS)
+ break;
+ }
+ }
+
+ /* Set up boot mode and take BNXT out of reset */
+ if (rc == BNXT_SUCCESS) {
+ bnxt_fastboot((bin_hdr->entry_address &
+ ~BCM_BNXT_FASTBOOT_MASK) |
+ BCM_BNXT_FASTBOOT_TYPE_1);
+ }
+
+ return rc;
+}
+
+static TEE_Result bnxt_crash_config(uintptr_t info_dst,
+ uint32_t crash_area_start,
+ uint32_t crash_len)
+{
+ struct nitro_crash_addr_item *item = NULL;
+ uintptr_t dst = 0;
+ struct nitro_crash_addr_info *info = NULL;
+ uintptr_t src = 0;
+ uint32_t crc = 0;
+ size_t size = 0;
+
+ /*
+ * First we write into local memory to calculate CRC before
+ * updating into Nitro memory
+ */
+ info = malloc(sizeof(struct nitro_crash_addr_info));
+ if (!info) {
+ EMSG("ERROR: buffer allocation");
+ return TEE_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(info, 0, sizeof(struct nitro_crash_addr_info));
+
+ info->signature = BNXT_CRASH_INFO_SIGNATURE;
+ info->version = 0x01000000 | MAX_CRASH_ADDR_ITEM;
+
+ /* As of now only one item is filled */
+ item = &info->table[0];
+ item->info = 0;
+ item->size = crash_len | BNXT_CRASH_INFO_VALID;
+ item->addr_hi = 0;
+ item->addr_lo = crash_area_start;
+
+ /* Checksum calculation */
+ crc = CRC32(CRC32_INIT_VAL,
+ (const char *)info + sizeof(uint32_t),
+ sizeof(struct nitro_crash_addr_info) - sizeof(uint32_t));
+ info->crc = crc;
+
+ /* First we write the contents and then set valid bit */
+ item->size &= ~BNXT_CRASH_INFO_VALID;
+
+ size = sizeof(struct nitro_crash_addr_info) / sizeof(uint32_t);
+ dst = info_dst;
+ src = (uintptr_t)info;
+ memcpy32_helper(src, dst, size, INC_SRC_ADDR);
+
+ /* Set the valid bit */
+ item->size |= BNXT_CRASH_INFO_VALID;
+ dst = info_dst + offsetof(struct nitro_crash_addr_info, table) +
+ offsetof(struct nitro_crash_addr_item, size);
+ bnxt_write32_multiple(dst, (uintptr_t)&item->size, 1, 1);
+
+ free(info);
+
+ return TEE_SUCCESS;
+}
+
+TEE_Result bnxt_load_fw(int chip_type)
+{
+ uint32_t size = 0;
+ uintptr_t dst = 0;
+ uintptr_t src = 0;
+ struct bnxt_images_info bnxt_src_image_info;
+
+ memset(&bnxt_src_image_info, 0, sizeof(struct bnxt_images_info));
+
+ if (get_bnxt_images_info(&bnxt_src_image_info, chip_type)
+ != BNXT_SUCCESS)
+ return TEE_ERROR_ITEM_NOT_FOUND;
+
+ bnxt_kong_halt();
+ bnxt_chimp_halt();
+
+ /* Copy the configs */
+ src = (uintptr_t)bnxt_src_image_info.bnxt_cfg_vaddr;
+ dst = (uintptr_t)BNXT_CONFIG_NS3_DEST;
+ size = bnxt_src_image_info.bnxt_cfg_len;
+ size = size / sizeof(uint32_t);
+ memcpy32_helper(src, dst, size, INC_SRC_ADDR);
+
+ /* Copy bspd config */
+ src = (uintptr_t)bnxt_src_image_info.bnxt_bspd_cfg_vaddr;
+ size = bnxt_src_image_info.bnxt_bspd_cfg_len;
+ dst = (uintptr_t)BNXT_CONFIG_NS3_BSPD_DEST;
+
+ size = size / sizeof(uint32_t);
+ memcpy32_helper(src, dst, size, INC_SRC_ADDR);
+
+ /* Fill the bnxt crash dump info */
+ bnxt_crash_config((uintptr_t)BNXT_CRASH_DUMP_INFO_NS3_BASE,
+ BNXT_CRASH_SEC_MEM,
+ BNXT_CRASH_LEN);
+
+ /* Load bnxt firmware and fastboot */
+ bnxt_load(bnxt_src_image_info.bnxt_fw_vaddr);
+
+ /* Wait for handshke */
+ bnxt_wait_handshake();
+
+ return TEE_SUCCESS;
+}
diff --git a/core/drivers/bnxt/bnxt_images.c b/core/drivers/bnxt/bnxt_images.c
new file mode 100644
index 00000000..fd7ed2c2
--- /dev/null
+++ b/core/drivers/bnxt/bnxt_images.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2019 Broadcom.
+ */
+
+#include <drivers/bcm/bnxt.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <util.h>
+
+#define BNXT_FW_NS3_IMAGE_SIG 0xFF12345A
+#define BNXT_FW_NS3Z_IMAGE_SIG 0xFF12345B
+#define BNXT_NS3_CFG_IMAGE_SIG 0xCF54321A
+#define BNXT_NS3Z_CFG_IMAGE_SIG 0xCF54321B
+
+#define BNXT_BSPD_CFG_LEN 512
+
+#define QSPI_BASE QSPI_MEM_BASE
+#define QSPI_BNXT_IMG (QSPI_BASE + 0x400000)
+#define QSPI_BSPD_ADDR (QSPI_BASE + 0x700000)
+
+#define BCM_NS3 1
+#define BCM_NS3Z 2
+
+static struct bnxt_img_header {
+ uint32_t bnxt_fw_ns3_sig;
+ uint32_t bnxt_fw_ns3_size;
+ uint32_t bnxt_fw_ns3z_sig;
+ uint32_t bnxt_fw_ns3z_size;
+ uint32_t bnxt_ns3_cfg_sig;
+ uint32_t bnxt_ns3_cfg_size;
+ uint32_t bnxt_ns3z_cfg_sig;
+ uint32_t bnxt_ns3z_cfg_size;
+} *img_header;
+
+int get_bnxt_images_info(struct bnxt_images_info *bnxt_info, int chip_type)
+{
+ uint32_t len = 0;
+ uint32_t fw_image_offset = sizeof(struct bnxt_img_header);
+ vaddr_t flash_dev_vaddr =
+ (uintptr_t)((vaddr_t)phys_to_virt(QSPI_BNXT_IMG,
+ MEM_AREA_IO_NSEC));
+
+ bnxt_info->bnxt_bspd_cfg_vaddr =
+ (uintptr_t)((vaddr_t)phys_to_virt(QSPI_BSPD_ADDR,
+ MEM_AREA_IO_NSEC));
+
+ bnxt_info->bnxt_bspd_cfg_len = BNXT_BSPD_CFG_LEN;
+
+ img_header = (struct bnxt_img_header *)flash_dev_vaddr;
+
+ if (img_header->bnxt_fw_ns3_sig != BNXT_FW_NS3_IMAGE_SIG) {
+ EMSG("Invalid Nitro bin");
+ return BNXT_FAILURE;
+ }
+
+ len = img_header->bnxt_fw_ns3_size;
+
+ if (chip_type == BCM_NS3) {
+ bnxt_info->bnxt_fw_vaddr = flash_dev_vaddr + fw_image_offset;
+ bnxt_info->bnxt_fw_len = len;
+ }
+
+ fw_image_offset += len;
+
+ if (img_header->bnxt_fw_ns3z_sig != BNXT_FW_NS3Z_IMAGE_SIG) {
+ EMSG("Invalid Nitro bin");
+ return BNXT_FAILURE;
+ }
+
+ len = img_header->bnxt_fw_ns3z_size;
+
+ if (chip_type == BCM_NS3Z) {
+ bnxt_info->bnxt_fw_vaddr = flash_dev_vaddr + fw_image_offset;
+ bnxt_info->bnxt_fw_len = len;
+ }
+
+ fw_image_offset += len;
+
+ if (img_header->bnxt_ns3_cfg_sig != BNXT_NS3_CFG_IMAGE_SIG) {
+ EMSG("Invalid Nitro config");
+ return BNXT_FAILURE;
+ }
+
+ len = img_header->bnxt_ns3_cfg_size;
+
+ if (chip_type == BCM_NS3) {
+ bnxt_info->bnxt_cfg_vaddr = flash_dev_vaddr + fw_image_offset;
+ bnxt_info->bnxt_cfg_len = len;
+ }
+
+ fw_image_offset += len;
+
+ if (img_header->bnxt_ns3z_cfg_sig != BNXT_NS3Z_CFG_IMAGE_SIG) {
+ EMSG("Invalid Nitro config");
+ return BNXT_FAILURE;
+ }
+
+ len = img_header->bnxt_ns3z_cfg_size;
+
+ if (chip_type == BCM_NS3Z) {
+ bnxt_info->bnxt_cfg_vaddr = flash_dev_vaddr + fw_image_offset;
+ bnxt_info->bnxt_cfg_len = len;
+ }
+
+ return BNXT_SUCCESS;
+}
diff --git a/core/drivers/bnxt/sub.mk b/core/drivers/bnxt/sub.mk
new file mode 100644
index 00000000..a0021a98
--- /dev/null
+++ b/core/drivers/bnxt/sub.mk
@@ -0,0 +1,3 @@
+srcs-y += bnxt.c
+srcs-y += bnxt_fw.c
+srcs-y += bnxt_images.c
diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk
index 7a4d0d36..1dabc74e 100644
--- a/core/drivers/sub.mk
+++ b/core/drivers/sub.mk
@@ -32,3 +32,4 @@ srcs-$(CFG_BCM_SOTP) += bcm_sotp.c
srcs-$(CFG_BCM_GPIO) += bcm_gpio.c
subdirs-y += crypto
+subdirs-$(CFG_BNXT_FW) += bnxt
diff --git a/core/include/drivers/bcm/bnxt.h b/core/include/drivers/bcm/bnxt.h
new file mode 100644
index 00000000..a952491d
--- /dev/null
+++ b/core/include/drivers/bcm/bnxt.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright 2019 Broadcom.
+ */
+
+#ifndef BNXT_H
+#define BNXT_H
+
+#include <compiler.h>
+#include <io.h>
+#include <mm/core_memprot.h>
+#include <util.h>
+
+#define BNXT_SUCCESS 0
+#define BNXT_FAILURE (!BNXT_SUCCESS)
+
+uint32_t bnxt_write32_multiple(uintptr_t dst,
+ uintptr_t src,
+ uint32_t num_entries,
+ int src_4byte_increment);
+void bnxt_chimp_halt(void);
+void bnxt_kong_halt(void);
+int bnxt_fastboot(uintptr_t addr);
+int bnxt_wait_handshake(void);
+TEE_Result bnxt_load_fw(int chip_type);
+
+struct bnxt_images_info {
+ vaddr_t bnxt_fw_vaddr;
+ uint32_t bnxt_fw_len;
+ vaddr_t bnxt_cfg_vaddr;
+ uint32_t bnxt_cfg_len;
+ vaddr_t bnxt_bspd_cfg_vaddr;
+ uint32_t bnxt_bspd_cfg_len;
+};
+
+int get_bnxt_images_info(struct bnxt_images_info *bnxt_info, int chip_type);
+
+#endif