| // 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_NS3_CFG_IMAGE_SIG 0xCF54321A |
| |
| #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 |
| |
| static void set_bnxt_images_info(struct bnxt_images_info *bnxt_info, |
| int chip_type, vaddr_t src, vaddr_t dst); |
| |
| static struct bnxt_img_header { |
| uint32_t bnxt_fw_ns3_sig; |
| uint32_t bnxt_fw_ns3_size; |
| uint32_t bnxt_ns3_cfg_sig; |
| uint32_t bnxt_ns3_cfg_size; |
| } *img_header; |
| |
| static int verify_header(vaddr_t mem) |
| { |
| img_header = (struct bnxt_img_header *)mem; |
| |
| if (img_header->bnxt_fw_ns3_sig == BNXT_FW_NS3_IMAGE_SIG && |
| img_header->bnxt_ns3_cfg_sig == BNXT_NS3_CFG_IMAGE_SIG) |
| return BNXT_SUCCESS; |
| return BNXT_FAILURE; |
| } |
| |
| static void set_bnxt_images_info(struct bnxt_images_info *bnxt_info, |
| int chip_type, vaddr_t src, vaddr_t dst) |
| { |
| uint32_t len = 0; |
| struct bnxt_img_header *dst_header = NULL; |
| uint32_t fw_image_offset = sizeof(struct bnxt_img_header); |
| |
| img_header = (struct bnxt_img_header *)src; |
| if (dst) { |
| dst_header = (struct bnxt_img_header *)dst; |
| memcpy(dst_header, img_header, sizeof(*img_header)); |
| dst += sizeof(*img_header); |
| |
| if (chip_type != BCM_NS3) { |
| dst_header->bnxt_fw_ns3_size = 0; |
| dst_header->bnxt_ns3_cfg_size = 0; |
| } |
| } |
| |
| if (chip_type == BCM_NS3) { |
| len = img_header->bnxt_fw_ns3_size; |
| bnxt_info->bnxt_fw_vaddr = src + fw_image_offset; |
| bnxt_info->bnxt_fw_len = len; |
| if (dst) { |
| memcpy((void *)dst, (void *)(src + fw_image_offset), |
| len); |
| dst += len; |
| } |
| |
| fw_image_offset += len; |
| |
| len = img_header->bnxt_ns3_cfg_size; |
| bnxt_info->bnxt_cfg_vaddr = src + fw_image_offset; |
| bnxt_info->bnxt_cfg_len = len; |
| if (dst) { |
| memcpy((void *)dst, (void *)(src + fw_image_offset), |
| len); |
| } |
| } |
| } |
| |
| int get_bnxt_images_info(struct bnxt_images_info *bnxt_info, int chip_type, |
| vaddr_t ddr_dest) |
| { |
| vaddr_t flash_dev_vaddr = 0; |
| |
| bnxt_info->bnxt_bspd_cfg_len = BNXT_BSPD_CFG_LEN; |
| |
| /* First verify if images are on sec mem */ |
| if (verify_header(ddr_dest + BNXT_IMG_SECMEM_OFFSET) == BNXT_SUCCESS) { |
| DMSG("Images found on sec memory"); |
| |
| bnxt_info->bnxt_bspd_cfg_vaddr = ddr_dest; |
| |
| set_bnxt_images_info(bnxt_info, chip_type, |
| ddr_dest + BNXT_IMG_SECMEM_OFFSET, 0); |
| } else { |
| flash_dev_vaddr = (vaddr_t)phys_to_virt(QSPI_BNXT_IMG, |
| MEM_AREA_IO_NSEC); |
| |
| if (verify_header(flash_dev_vaddr) != BNXT_SUCCESS) { |
| EMSG("failed to load fw images"); |
| return BNXT_FAILURE; |
| } |
| |
| DMSG("Images loading from flash memory"); |
| bnxt_info->bnxt_bspd_cfg_vaddr = |
| (vaddr_t)phys_to_virt(QSPI_BSPD_ADDR, |
| MEM_AREA_IO_NSEC); |
| memcpy((void *)ddr_dest, (void *)bnxt_info->bnxt_bspd_cfg_vaddr, |
| BNXT_BSPD_CFG_LEN); |
| |
| set_bnxt_images_info(bnxt_info, chip_type, flash_dev_vaddr, |
| ddr_dest + BNXT_IMG_SECMEM_OFFSET); |
| } |
| |
| return BNXT_SUCCESS; |
| } |