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 #include "drivers/sdmmc/sdmmc.h" 26 #include "socfpga_private.h" 27 #include "socfpga_ros.h" 28 29 30 #define PLAT_FIP_BASE (0) 31 # if ARM_LINUX_KERNEL_AS_BL33 32 #define PLAT_FIP_MAX_SIZE (0x8000000) 33 #define PLAT_MMC_DATA_BASE (0x10000000) 34 #define PLAT_MMC_DATA_SIZE (0x100000) 35 # else 36 #define PLAT_FIP_MAX_SIZE (0x1000000) 37 #define PLAT_MMC_DATA_BASE (0xffe3c000) 38 #define PLAT_MMC_DATA_SIZE (0x2000) 39 # endif 40 41 static const io_dev_connector_t *fip_dev_con; 42 static const io_dev_connector_t *boot_dev_con; 43 44 static io_mtd_dev_spec_t nand_dev_spec; 45 46 static uintptr_t fip_dev_handle; 47 static uintptr_t boot_dev_handle; 48 49 static const io_uuid_spec_t bl2_uuid_spec = { 50 .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, 51 }; 52 53 static const io_uuid_spec_t bl31_uuid_spec = { 54 .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 55 }; 56 57 static const io_uuid_spec_t bl33_uuid_spec = { 58 .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 59 }; 60 61 # if ARM_LINUX_KERNEL_AS_BL33 != 0 62 static const io_uuid_spec_t nt_fw_config_uuid_spec = { 63 .uuid = UUID_NT_FW_CONFIG, 64 }; 65 # endif 66 67 uintptr_t a2_lba_offset; 68 const char a2[] = {0xa2, 0x0}; 69 70 static const io_block_spec_t gpt_block_spec = { 71 .offset = 0, 72 .length = MMC_BLOCK_SIZE 73 }; 74 75 static int check_fip(const uintptr_t spec); 76 static int check_dev(const uintptr_t spec); 77 78 static io_block_dev_spec_t boot_dev_spec; 79 static int (*register_io_dev)(const io_dev_connector_t **); 80 81 static io_block_spec_t fip_spec = { 82 .offset = PLAT_FIP_BASE, 83 .length = PLAT_FIP_MAX_SIZE, 84 }; 85 86 struct plat_io_policy { 87 uintptr_t *dev_handle; 88 uintptr_t image_spec; 89 int (*check)(const uintptr_t spec); 90 }; 91 92 static const struct plat_io_policy policies[] = { 93 [FIP_IMAGE_ID] = { 94 &boot_dev_handle, 95 (uintptr_t)&fip_spec, 96 check_dev 97 }, 98 [BL2_IMAGE_ID] = { 99 &fip_dev_handle, 100 (uintptr_t)&bl2_uuid_spec, 101 check_fip 102 }, 103 [BL31_IMAGE_ID] = { 104 &fip_dev_handle, 105 (uintptr_t)&bl31_uuid_spec, 106 check_fip 107 }, 108 [BL33_IMAGE_ID] = { 109 &fip_dev_handle, 110 (uintptr_t) &bl33_uuid_spec, 111 check_fip 112 }, 113 # if ARM_LINUX_KERNEL_AS_BL33 != 0 114 [NT_FW_CONFIG_ID] = { 115 &fip_dev_handle, 116 (uintptr_t)&nt_fw_config_uuid_spec, 117 check_fip 118 }, 119 # endif 120 [GPT_IMAGE_ID] = { 121 &boot_dev_handle, 122 (uintptr_t) &gpt_block_spec, 123 check_dev 124 }, 125 }; 126 127 static int check_dev(const uintptr_t spec) 128 { 129 int result; 130 uintptr_t local_handle; 131 132 result = io_dev_init(boot_dev_handle, (uintptr_t)NULL); 133 if (result == 0) { 134 result = io_open(boot_dev_handle, spec, &local_handle); 135 if (result == 0) 136 io_close(local_handle); 137 } 138 return result; 139 } 140 141 static int check_fip(const uintptr_t spec) 142 { 143 int result; 144 uintptr_t local_image_handle; 145 146 result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 147 if (result == 0) { 148 result = io_open(fip_dev_handle, spec, &local_image_handle); 149 if (result == 0) 150 io_close(local_image_handle); 151 } 152 return result; 153 } 154 155 void socfpga_io_setup(int boot_source, unsigned long offset) 156 { 157 int result; 158 fip_spec.offset = offset; 159 160 switch (boot_source) { 161 case BOOT_SOURCE_SDMMC: 162 register_io_dev = ®ister_io_dev_block; 163 boot_dev_spec.buffer.offset = PLAT_MMC_DATA_BASE; 164 boot_dev_spec.buffer.length = SOCFPGA_MMC_BLOCK_SIZE; 165 boot_dev_spec.ops.read = SDMMC_READ_BLOCKS; 166 boot_dev_spec.ops.write = SDMMC_WRITE_BLOCKS; 167 boot_dev_spec.block_size = MMC_BLOCK_SIZE; 168 break; 169 170 case BOOT_SOURCE_QSPI: 171 register_io_dev = ®ister_io_dev_memmap; 172 break; 173 174 #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 175 case BOOT_SOURCE_NAND: 176 register_io_dev = ®ister_io_dev_mtd; 177 nand_dev_spec.ops.init = cdns_nand_init_mtd; 178 nand_dev_spec.ops.read = cdns_nand_read; 179 nand_dev_spec.ops.write = NULL; 180 break; 181 #endif 182 183 default: 184 ERROR("Unsupported boot source\n"); 185 panic(); 186 break; 187 } 188 189 result = (*register_io_dev)(&boot_dev_con); 190 assert(result == 0); 191 192 result = register_io_dev_fip(&fip_dev_con); 193 assert(result == 0); 194 195 if (boot_source == BOOT_SOURCE_NAND) { 196 result = io_dev_open(boot_dev_con, (uintptr_t)&nand_dev_spec, 197 &boot_dev_handle); 198 } else { 199 result = io_dev_open(boot_dev_con, (uintptr_t)&boot_dev_spec, 200 &boot_dev_handle); 201 } 202 assert(result == 0); 203 204 result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 205 assert(result == 0); 206 207 if (boot_source == BOOT_SOURCE_SDMMC) { 208 partition_init(GPT_IMAGE_ID); 209 fip_spec.offset = get_partition_entry(a2)->start; 210 } 211 212 (void)result; 213 } 214 215 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 216 uintptr_t *image_spec) 217 { 218 int result; 219 const struct plat_io_policy *policy; 220 221 assert(image_id < ARRAY_SIZE(policies)); 222 223 policy = &policies[image_id]; 224 result = policy->check(policy->image_spec); 225 assert(result == 0); 226 227 *image_spec = policy->image_spec; 228 *dev_handle = *(policy->dev_handle); 229 230 return result; 231 } 232