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