1 /* 2 * Copyright 2021 NXP 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 8 #include <assert.h> 9 #include <string.h> 10 11 #include <common/debug.h> 12 #include <dcfg.h> 13 #include <drivers/delay_timer.h> 14 #include <fuse_prov.h> 15 #include <io_block.h> 16 #include <io_driver.h> 17 #include <io_fip.h> 18 #include <io_memmap.h> 19 #include <io_storage.h> 20 #include <lib/utils.h> 21 #include <nxp_gpio.h> 22 #include <sfp.h> 23 #include <sfp_error_codes.h> 24 #include <tools_share/firmware_image_package.h> 25 26 #include "fuse_io.h" 27 #include <load_img.h> 28 #include <plat/common/platform.h> 29 #include "plat_common.h" 30 #include "platform_def.h" 31 32 extern uintptr_t backend_dev_handle; 33 34 static uint32_t fuse_fip; 35 36 static uintptr_t fuse_fip_dev_handle; 37 38 static io_block_spec_t fuse_fip_block_spec = { 39 .offset = PLAT_FUSE_FIP_OFFSET, 40 .length = PLAT_FUSE_FIP_MAX_SIZE 41 }; 42 43 static const io_uuid_spec_t fuse_prov_uuid_spec = { 44 .uuid = UUID_FUSE_PROV, 45 }; 46 47 static const io_uuid_spec_t fuse_up_uuid_spec = { 48 .uuid = UUID_FUSE_UP, 49 }; 50 51 static int open_fuse_fip(const uintptr_t spec); 52 53 struct plat_io_policy { 54 uintptr_t *dev_handle; 55 uintptr_t image_spec; 56 int (*check)(const uintptr_t spec); 57 }; 58 59 /* By default, ARM platforms load images from the FIP */ 60 static const struct plat_io_policy fuse_policies[] = { 61 [FUSE_FIP_IMAGE_ID - FUSE_FIP_IMAGE_ID] = { 62 &backend_dev_handle, 63 (uintptr_t)&fuse_fip_block_spec, 64 NULL 65 }, 66 [FUSE_PROV_IMAGE_ID - FUSE_FIP_IMAGE_ID] = { 67 &fuse_fip_dev_handle, 68 (uintptr_t)&fuse_prov_uuid_spec, 69 open_fuse_fip 70 }, 71 [FUSE_UP_IMAGE_ID - FUSE_FIP_IMAGE_ID] = { 72 &fuse_fip_dev_handle, 73 (uintptr_t)&fuse_up_uuid_spec, 74 open_fuse_fip 75 } 76 }; 77 78 static int open_fuse_fip(const uintptr_t spec) 79 { 80 int result; 81 uintptr_t local_image_handle; 82 83 /* See if a Firmware Image Package is available */ 84 result = io_dev_init(fuse_fip_dev_handle, (uintptr_t)FUSE_FIP_IMAGE_ID); 85 if (result == 0) { 86 result = io_open(fuse_fip_dev_handle, 87 spec, 88 &local_image_handle); 89 if (result == 0) { 90 VERBOSE("Using FIP\n"); 91 io_close(local_image_handle); 92 } 93 } 94 return result; 95 } 96 97 /* The image can be one of the DDR PHY images, which can be sleected via DDR 98 * policies 99 */ 100 int plat_get_fuse_image_source(unsigned int image_id, 101 uintptr_t *dev_handle, 102 uintptr_t *image_spec, 103 int (*check)(const uintptr_t spec)) 104 { 105 int result; 106 const struct plat_io_policy *policy; 107 108 assert(image_id < (FUSE_FIP_IMAGE_ID + ARRAY_SIZE(fuse_policies))); 109 110 policy = &fuse_policies[image_id - FUSE_FIP_IMAGE_ID]; 111 112 if (image_id == FUSE_FIP_IMAGE_ID) { 113 result = check(policy->image_spec); 114 } else { 115 result = policy->check(policy->image_spec); 116 } 117 118 if (result == 0) { 119 *image_spec = policy->image_spec; 120 *dev_handle = *(policy->dev_handle); 121 } 122 return result; 123 } 124 125 int fuse_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev) 126 { 127 int io_result; 128 size_t fuse_fip_offset = PLAT_FUSE_FIP_OFFSET; 129 130 /* Open connections to fuse fip and cache the handles */ 131 io_result = io_dev_open(fip_dev_con, (uintptr_t)&fuse_fip, 132 &fuse_fip_dev_handle); 133 134 assert(io_result == 0); 135 136 switch (boot_dev) { 137 #if QSPI_BOOT 138 case BOOT_DEVICE_QSPI: 139 fuse_fip_offset += NXP_QSPI_FLASH_ADDR; 140 break; 141 #endif 142 #if NOR_BOOT 143 case BOOT_DEVICE_IFC_NOR: 144 fuse_fip_offset += NXP_NOR_FLASH_ADDR; 145 break; 146 #endif 147 #if FLEXSPI_NOR_BOOT 148 case BOOT_DEVICE_FLEXSPI_NOR: 149 fuse_fip_offset += NXP_FLEXSPI_FLASH_ADDR; 150 break; 151 #endif 152 default: 153 break; 154 } 155 156 fuse_fip_block_spec.offset = fuse_fip_offset; 157 158 return io_result; 159 } 160 161 int fip_fuse_provisioning(uintptr_t image_buf, uint32_t size) 162 { 163 uint32_t bit_num; 164 uint32_t *gpio_base_addr = NULL; 165 struct fuse_hdr_t *fuse_hdr = NULL; 166 uint8_t barker[] = {0x68U, 0x39U, 0x27U, 0x81U}; 167 int ret = -1; 168 169 if (sfp_check_oem_wp() == 0) { 170 ret = load_img(FUSE_PROV_IMAGE_ID, &image_buf, &size); 171 if (ret != 0) { 172 ERROR("Failed to load FUSE PRIV image\n"); 173 assert(ret == 0); 174 } 175 fuse_hdr = (struct fuse_hdr_t *)image_buf; 176 177 /* Check barker code */ 178 if (memcmp(fuse_hdr->barker, barker, sizeof(barker)) != 0) { 179 ERROR("FUSE Barker code mismatch.\n"); 180 error_handler(ERROR_FUSE_BARKER); 181 return 1; 182 } 183 184 /* Check if GPIO pin to be set for POVDD */ 185 if (((fuse_hdr->flags >> FLAG_POVDD_SHIFT) & 0x1) != 0) { 186 gpio_base_addr = 187 select_gpio_n_bitnum(fuse_hdr->povdd_gpio, 188 &bit_num); 189 /* 190 * Add delay so that Efuse gets the power 191 * when GPIO is enabled. 192 */ 193 ret = set_gpio_bit(gpio_base_addr, bit_num); 194 mdelay(EFUSE_POWERUP_DELAY_mSec); 195 } else { 196 ret = (board_enable_povdd() == true) ? 0 : PLAT_ERROR_ENABLE_POVDD; 197 } 198 if (ret != 0) { 199 ERROR("Error enabling board POVDD: %d\n", ret); 200 ERROR("Only SFP mirror register will be set.\n"); 201 } 202 203 provision_fuses(image_buf, ret == 0); 204 205 /* Check if GPIO pin to be reset for POVDD */ 206 if (((fuse_hdr->flags >> FLAG_POVDD_SHIFT) & 0x1) != 0) { 207 if (gpio_base_addr == NULL) { 208 gpio_base_addr = 209 select_gpio_n_bitnum( 210 fuse_hdr->povdd_gpio, 211 &bit_num); 212 } 213 ret = clr_gpio_bit(gpio_base_addr, bit_num); 214 } else { 215 ret = board_disable_povdd() ? 0 : PLAT_ERROR_DISABLE_POVDD; 216 } 217 218 if (ret != 0) { 219 ERROR("Error disabling board POVDD: %d\n", ret); 220 } 221 } 222 return 0; 223 } 224