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