1 /* 2 * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. 4 * Copyright (c) 2024, Altera Corporation. All rights reserved. 5 * 6 * SPDX-License-Identifier: BSD-3-Clause 7 */ 8 9 #include <arch_helpers.h> 10 #include <assert.h> 11 #include <common/debug.h> 12 #include <common/tbbr/tbbr_img_def.h> 13 #include <drivers/cadence/cdns_nand.h> 14 #include <drivers/cadence/cdns_sdmmc.h> 15 #include <drivers/io/io_block.h> 16 #include <drivers/io/io_driver.h> 17 #include <drivers/io/io_fip.h> 18 #include <drivers/io/io_memmap.h> 19 #include <drivers/io/io_mtd.h> 20 #include <drivers/io/io_storage.h> 21 #include <drivers/mmc.h> 22 #include <drivers/partition/partition.h> 23 #include <lib/mmio.h> 24 #include <tools_share/firmware_image_package.h> 25 26 #include "drivers/sdmmc/sdmmc.h" 27 #include "socfpga_private.h" 28 #include "socfpga_ros.h" 29 30 31 static const io_dev_connector_t *fip_dev_con; 32 static const io_dev_connector_t *boot_dev_con; 33 34 static io_mtd_dev_spec_t nand_dev_spec; 35 36 static uintptr_t fip_dev_handle; 37 static uintptr_t boot_dev_handle; 38 39 static const io_uuid_spec_t bl2_uuid_spec = { 40 .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, 41 }; 42 43 static const io_uuid_spec_t bl31_uuid_spec = { 44 .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 45 }; 46 47 static const io_uuid_spec_t bl33_uuid_spec = { 48 .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 49 }; 50 51 # if ARM_LINUX_KERNEL_AS_BL33 != 0 52 static const io_uuid_spec_t nt_fw_config_uuid_spec = { 53 .uuid = UUID_NT_FW_CONFIG, 54 }; 55 # endif 56 57 uintptr_t a2_lba_offset; 58 const char a2[] = {0xa2, 0x0}; 59 60 static const io_block_spec_t gpt_block_spec = { 61 .offset = 0, 62 .length = MMC_BLOCK_SIZE 63 }; 64 65 static int check_fip(const uintptr_t spec); 66 static int check_dev(const uintptr_t spec); 67 68 static io_block_dev_spec_t boot_dev_spec; 69 static int (*register_io_dev)(const io_dev_connector_t **); 70 71 static io_block_spec_t fip_spec = { 72 .offset = PLAT_FIP_BASE, 73 .length = PLAT_FIP_MAX_SIZE, 74 }; 75 76 struct plat_io_policy { 77 uintptr_t *dev_handle; 78 uintptr_t image_spec; 79 int (*check)(const uintptr_t spec); 80 }; 81 82 static const struct plat_io_policy policies[] = { 83 [FIP_IMAGE_ID] = { 84 &boot_dev_handle, 85 (uintptr_t)&fip_spec, 86 check_dev 87 }, 88 [BL2_IMAGE_ID] = { 89 &fip_dev_handle, 90 (uintptr_t)&bl2_uuid_spec, 91 check_fip 92 }, 93 [BL31_IMAGE_ID] = { 94 &fip_dev_handle, 95 (uintptr_t)&bl31_uuid_spec, 96 check_fip 97 }, 98 [BL33_IMAGE_ID] = { 99 &fip_dev_handle, 100 (uintptr_t) &bl33_uuid_spec, 101 check_fip 102 }, 103 # if ARM_LINUX_KERNEL_AS_BL33 != 0 104 [NT_FW_CONFIG_ID] = { 105 &fip_dev_handle, 106 (uintptr_t)&nt_fw_config_uuid_spec, 107 check_fip 108 }, 109 # endif 110 [GPT_IMAGE_ID] = { 111 &boot_dev_handle, 112 (uintptr_t) &gpt_block_spec, 113 check_dev 114 }, 115 }; 116 117 static int check_dev(const uintptr_t spec) 118 { 119 int result; 120 uintptr_t local_handle; 121 122 result = io_dev_init(boot_dev_handle, (uintptr_t)NULL); 123 if (result == 0) { 124 result = io_open(boot_dev_handle, spec, &local_handle); 125 if (result == 0) 126 io_close(local_handle); 127 } 128 return result; 129 } 130 131 static int check_fip(const uintptr_t spec) 132 { 133 int result; 134 uintptr_t local_image_handle; 135 136 result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 137 if (result == 0) { 138 result = io_open(fip_dev_handle, spec, &local_image_handle); 139 if (result == 0) 140 io_close(local_image_handle); 141 } 142 return result; 143 } 144 145 void socfpga_io_setup(int boot_source, unsigned long offset) 146 { 147 int result; 148 fip_spec.offset = offset; 149 150 switch (boot_source) { 151 case BOOT_SOURCE_SDMMC: 152 register_io_dev = ®ister_io_dev_block; 153 boot_dev_spec.buffer.offset = PLAT_MMC_DATA_BASE; 154 boot_dev_spec.buffer.length = SOCFPGA_MMC_BLOCK_SIZE; 155 boot_dev_spec.ops.read = SDMMC_READ_BLOCKS; 156 boot_dev_spec.ops.write = SDMMC_WRITE_BLOCKS; 157 boot_dev_spec.block_size = MMC_BLOCK_SIZE; 158 break; 159 160 case BOOT_SOURCE_QSPI: 161 register_io_dev = ®ister_io_dev_memmap; 162 break; 163 164 #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 165 case BOOT_SOURCE_NAND: 166 register_io_dev = ®ister_io_dev_mtd; 167 nand_dev_spec.ops.init = cdns_nand_init_mtd; 168 nand_dev_spec.ops.read = cdns_nand_read; 169 nand_dev_spec.ops.write = NULL; 170 break; 171 #endif 172 173 default: 174 ERROR("Unsupported boot source\n"); 175 panic(); 176 break; 177 } 178 179 result = (*register_io_dev)(&boot_dev_con); 180 assert(result == 0); 181 182 result = register_io_dev_fip(&fip_dev_con); 183 assert(result == 0); 184 185 if (boot_source == BOOT_SOURCE_NAND) { 186 result = io_dev_open(boot_dev_con, (uintptr_t)&nand_dev_spec, 187 &boot_dev_handle); 188 } else { 189 result = io_dev_open(boot_dev_con, (uintptr_t)&boot_dev_spec, 190 &boot_dev_handle); 191 } 192 assert(result == 0); 193 194 result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 195 assert(result == 0); 196 197 if (boot_source == BOOT_SOURCE_SDMMC) { 198 partition_init(GPT_IMAGE_ID); 199 fip_spec.offset = get_partition_entry(a2)->start; 200 } 201 202 (void)result; 203 } 204 205 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 206 uintptr_t *image_spec) 207 { 208 int result; 209 const struct plat_io_policy *policy; 210 211 assert(image_id < ARRAY_SIZE(policies)); 212 213 policy = &policies[image_id]; 214 result = policy->check(policy->image_spec); 215 assert(result == 0); 216 217 *image_spec = policy->image_spec; 218 *dev_handle = *(policy->dev_handle); 219 220 return result; 221 } 222