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 "socfpga_private.h" 26 27 28 #define PLAT_FIP_BASE (0) 29 #define PLAT_FIP_MAX_SIZE (0x1000000) 30 #define PLAT_MMC_DATA_BASE (0xffe3c000) 31 #define PLAT_MMC_DATA_SIZE (0x2000) 32 #define PLAT_QSPI_DATA_BASE (0x3C00000) 33 #define PLAT_QSPI_DATA_SIZE (0x1000000) 34 #define PLAT_NAND_DATA_BASE (0x0200000) 35 #define PLAT_NAND_DATA_SIZE (0x1000000) 36 37 static const io_dev_connector_t *fip_dev_con; 38 static const io_dev_connector_t *boot_dev_con; 39 40 static io_mtd_dev_spec_t nand_dev_spec; 41 42 static uintptr_t fip_dev_handle; 43 static uintptr_t boot_dev_handle; 44 45 static const io_uuid_spec_t bl2_uuid_spec = { 46 .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, 47 }; 48 49 static const io_uuid_spec_t bl31_uuid_spec = { 50 .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 51 }; 52 53 static const io_uuid_spec_t bl33_uuid_spec = { 54 .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 55 }; 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 [GPT_IMAGE_ID] = { 104 &boot_dev_handle, 105 (uintptr_t) &gpt_block_spec, 106 check_dev 107 }, 108 }; 109 110 static int check_dev(const uintptr_t spec) 111 { 112 int result; 113 uintptr_t local_handle; 114 115 result = io_dev_init(boot_dev_handle, (uintptr_t)NULL); 116 if (result == 0) { 117 result = io_open(boot_dev_handle, spec, &local_handle); 118 if (result == 0) 119 io_close(local_handle); 120 } 121 return result; 122 } 123 124 static int check_fip(const uintptr_t spec) 125 { 126 int result; 127 uintptr_t local_image_handle; 128 129 result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 130 if (result == 0) { 131 result = io_open(fip_dev_handle, spec, &local_image_handle); 132 if (result == 0) 133 io_close(local_image_handle); 134 } 135 return result; 136 } 137 138 void socfpga_io_setup(int boot_source) 139 { 140 int result; 141 142 switch (boot_source) { 143 case BOOT_SOURCE_SDMMC: 144 register_io_dev = ®ister_io_dev_block; 145 boot_dev_spec.buffer.offset = PLAT_MMC_DATA_BASE; 146 boot_dev_spec.buffer.length = SOCFPGA_MMC_BLOCK_SIZE; 147 boot_dev_spec.ops.read = mmc_read_blocks; 148 boot_dev_spec.ops.write = mmc_write_blocks; 149 boot_dev_spec.block_size = MMC_BLOCK_SIZE; 150 break; 151 152 case BOOT_SOURCE_QSPI: 153 register_io_dev = ®ister_io_dev_memmap; 154 fip_spec.offset = PLAT_QSPI_DATA_BASE; 155 break; 156 157 #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 158 case BOOT_SOURCE_NAND: 159 register_io_dev = ®ister_io_dev_mtd; 160 nand_dev_spec.ops.init = cdns_nand_init_mtd; 161 nand_dev_spec.ops.read = cdns_nand_read; 162 nand_dev_spec.ops.write = NULL; 163 fip_spec.offset = PLAT_NAND_DATA_BASE; 164 break; 165 #endif 166 167 default: 168 ERROR("Unsupported boot source\n"); 169 panic(); 170 break; 171 } 172 173 result = (*register_io_dev)(&boot_dev_con); 174 assert(result == 0); 175 176 result = register_io_dev_fip(&fip_dev_con); 177 assert(result == 0); 178 179 if (boot_source == BOOT_SOURCE_NAND) { 180 result = io_dev_open(boot_dev_con, (uintptr_t)&nand_dev_spec, 181 &boot_dev_handle); 182 } else { 183 result = io_dev_open(boot_dev_con, (uintptr_t)&boot_dev_spec, 184 &boot_dev_handle); 185 } 186 assert(result == 0); 187 188 result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 189 assert(result == 0); 190 191 if (boot_source == BOOT_SOURCE_SDMMC) { 192 partition_init(GPT_IMAGE_ID); 193 fip_spec.offset = get_partition_entry(a2)->start; 194 } 195 196 (void)result; 197 } 198 199 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 200 uintptr_t *image_spec) 201 { 202 int result; 203 const struct plat_io_policy *policy; 204 205 assert(image_id < ARRAY_SIZE(policies)); 206 207 policy = &policies[image_id]; 208 result = policy->check(policy->image_spec); 209 assert(result == 0); 210 211 *image_spec = policy->image_spec; 212 *dev_handle = *(policy->dev_handle); 213 214 return result; 215 } 216