1*2f2abcf4SHaojian Zhuang /* 2*2f2abcf4SHaojian Zhuang * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*2f2abcf4SHaojian Zhuang * 4*2f2abcf4SHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause 5*2f2abcf4SHaojian Zhuang */ 6*2f2abcf4SHaojian Zhuang 7*2f2abcf4SHaojian Zhuang #include <arch_helpers.h> 8*2f2abcf4SHaojian Zhuang #include <assert.h> 9*2f2abcf4SHaojian Zhuang #include <debug.h> 10*2f2abcf4SHaojian Zhuang #include <errno.h> 11*2f2abcf4SHaojian Zhuang #include <firmware_image_package.h> 12*2f2abcf4SHaojian Zhuang #include <io_block.h> 13*2f2abcf4SHaojian Zhuang #include <io_driver.h> 14*2f2abcf4SHaojian Zhuang #include <io_fip.h> 15*2f2abcf4SHaojian Zhuang #include <io_memmap.h> 16*2f2abcf4SHaojian Zhuang #include <io_storage.h> 17*2f2abcf4SHaojian Zhuang #include <mmio.h> 18*2f2abcf4SHaojian Zhuang #include <platform_def.h> 19*2f2abcf4SHaojian Zhuang #include <semihosting.h> /* For FOPEN_MODE_... */ 20*2f2abcf4SHaojian Zhuang #include <string.h> 21*2f2abcf4SHaojian Zhuang #include <ufs.h> 22*2f2abcf4SHaojian Zhuang 23*2f2abcf4SHaojian Zhuang struct plat_io_policy { 24*2f2abcf4SHaojian Zhuang uintptr_t *dev_handle; 25*2f2abcf4SHaojian Zhuang uintptr_t image_spec; 26*2f2abcf4SHaojian Zhuang int (*check)(const uintptr_t spec); 27*2f2abcf4SHaojian Zhuang }; 28*2f2abcf4SHaojian Zhuang 29*2f2abcf4SHaojian Zhuang static const io_dev_connector_t *ufs_dev_con, *fip_dev_con; 30*2f2abcf4SHaojian Zhuang static uintptr_t ufs_dev_handle, fip_dev_handle; 31*2f2abcf4SHaojian Zhuang 32*2f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec); 33*2f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec); 34*2f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size); 35*2f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size); 36*2f2abcf4SHaojian Zhuang 37*2f2abcf4SHaojian Zhuang static const io_block_spec_t ufs_fip_spec = { 38*2f2abcf4SHaojian Zhuang .offset = HIKEY960_FIP_BASE, 39*2f2abcf4SHaojian Zhuang .length = HIKEY960_FIP_MAX_SIZE, 40*2f2abcf4SHaojian Zhuang }; 41*2f2abcf4SHaojian Zhuang 42*2f2abcf4SHaojian Zhuang static const io_block_spec_t ufs_data_spec = { 43*2f2abcf4SHaojian Zhuang .offset = 0, 44*2f2abcf4SHaojian Zhuang .length = 256 << 20, 45*2f2abcf4SHaojian Zhuang }; 46*2f2abcf4SHaojian Zhuang 47*2f2abcf4SHaojian Zhuang static const io_block_dev_spec_t ufs_dev_spec = { 48*2f2abcf4SHaojian Zhuang /* It's used as temp buffer in block driver. */ 49*2f2abcf4SHaojian Zhuang .buffer = { 50*2f2abcf4SHaojian Zhuang .offset = HIKEY960_UFS_DATA_BASE, 51*2f2abcf4SHaojian Zhuang .length = HIKEY960_UFS_DATA_SIZE, 52*2f2abcf4SHaojian Zhuang }, 53*2f2abcf4SHaojian Zhuang .ops = { 54*2f2abcf4SHaojian Zhuang .read = ufs_read_lun3_blks, 55*2f2abcf4SHaojian Zhuang .write = ufs_write_lun3_blks, 56*2f2abcf4SHaojian Zhuang }, 57*2f2abcf4SHaojian Zhuang .block_size = UFS_BLOCK_SIZE, 58*2f2abcf4SHaojian Zhuang }; 59*2f2abcf4SHaojian Zhuang 60*2f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl2_uuid_spec = { 61*2f2abcf4SHaojian Zhuang .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, 62*2f2abcf4SHaojian Zhuang }; 63*2f2abcf4SHaojian Zhuang 64*2f2abcf4SHaojian Zhuang static const io_uuid_spec_t scp_bl2_uuid_spec = { 65*2f2abcf4SHaojian Zhuang .uuid = UUID_SCP_FIRMWARE_SCP_BL2, 66*2f2abcf4SHaojian Zhuang }; 67*2f2abcf4SHaojian Zhuang 68*2f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl31_uuid_spec = { 69*2f2abcf4SHaojian Zhuang .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, 70*2f2abcf4SHaojian Zhuang }; 71*2f2abcf4SHaojian Zhuang 72*2f2abcf4SHaojian Zhuang static const io_uuid_spec_t bl33_uuid_spec = { 73*2f2abcf4SHaojian Zhuang .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, 74*2f2abcf4SHaojian Zhuang }; 75*2f2abcf4SHaojian Zhuang 76*2f2abcf4SHaojian Zhuang static const struct plat_io_policy policies[] = { 77*2f2abcf4SHaojian Zhuang [FIP_IMAGE_ID] = { 78*2f2abcf4SHaojian Zhuang &ufs_dev_handle, 79*2f2abcf4SHaojian Zhuang (uintptr_t)&ufs_fip_spec, 80*2f2abcf4SHaojian Zhuang check_ufs 81*2f2abcf4SHaojian Zhuang }, 82*2f2abcf4SHaojian Zhuang [BL2_IMAGE_ID] = { 83*2f2abcf4SHaojian Zhuang &fip_dev_handle, 84*2f2abcf4SHaojian Zhuang (uintptr_t)&bl2_uuid_spec, 85*2f2abcf4SHaojian Zhuang check_fip 86*2f2abcf4SHaojian Zhuang }, 87*2f2abcf4SHaojian Zhuang [SCP_BL2_IMAGE_ID] = { 88*2f2abcf4SHaojian Zhuang &fip_dev_handle, 89*2f2abcf4SHaojian Zhuang (uintptr_t)&scp_bl2_uuid_spec, 90*2f2abcf4SHaojian Zhuang check_fip 91*2f2abcf4SHaojian Zhuang }, 92*2f2abcf4SHaojian Zhuang [BL31_IMAGE_ID] = { 93*2f2abcf4SHaojian Zhuang &fip_dev_handle, 94*2f2abcf4SHaojian Zhuang (uintptr_t)&bl31_uuid_spec, 95*2f2abcf4SHaojian Zhuang check_fip 96*2f2abcf4SHaojian Zhuang }, 97*2f2abcf4SHaojian Zhuang [BL33_IMAGE_ID] = { 98*2f2abcf4SHaojian Zhuang &fip_dev_handle, 99*2f2abcf4SHaojian Zhuang (uintptr_t)&bl33_uuid_spec, 100*2f2abcf4SHaojian Zhuang check_fip 101*2f2abcf4SHaojian Zhuang }, 102*2f2abcf4SHaojian Zhuang [BL2U_IMAGE_ID] = { 103*2f2abcf4SHaojian Zhuang &ufs_dev_handle, 104*2f2abcf4SHaojian Zhuang (uintptr_t)&ufs_data_spec, 105*2f2abcf4SHaojian Zhuang check_ufs 106*2f2abcf4SHaojian Zhuang } 107*2f2abcf4SHaojian Zhuang }; 108*2f2abcf4SHaojian Zhuang 109*2f2abcf4SHaojian Zhuang static int check_ufs(const uintptr_t spec) 110*2f2abcf4SHaojian Zhuang { 111*2f2abcf4SHaojian Zhuang int result; 112*2f2abcf4SHaojian Zhuang uintptr_t local_handle; 113*2f2abcf4SHaojian Zhuang 114*2f2abcf4SHaojian Zhuang result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); 115*2f2abcf4SHaojian Zhuang if (result == 0) { 116*2f2abcf4SHaojian Zhuang result = io_open(ufs_dev_handle, spec, &local_handle); 117*2f2abcf4SHaojian Zhuang if (result == 0) 118*2f2abcf4SHaojian Zhuang io_close(local_handle); 119*2f2abcf4SHaojian Zhuang } 120*2f2abcf4SHaojian Zhuang return result; 121*2f2abcf4SHaojian Zhuang } 122*2f2abcf4SHaojian Zhuang 123*2f2abcf4SHaojian Zhuang static int check_fip(const uintptr_t spec) 124*2f2abcf4SHaojian Zhuang { 125*2f2abcf4SHaojian Zhuang int result; 126*2f2abcf4SHaojian Zhuang uintptr_t local_image_handle; 127*2f2abcf4SHaojian Zhuang 128*2f2abcf4SHaojian Zhuang /* See if a Firmware Image Package is available */ 129*2f2abcf4SHaojian Zhuang result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 130*2f2abcf4SHaojian Zhuang if (result == 0) { 131*2f2abcf4SHaojian Zhuang result = io_open(fip_dev_handle, spec, &local_image_handle); 132*2f2abcf4SHaojian Zhuang if (result == 0) { 133*2f2abcf4SHaojian Zhuang VERBOSE("Using FIP\n"); 134*2f2abcf4SHaojian Zhuang io_close(local_image_handle); 135*2f2abcf4SHaojian Zhuang } 136*2f2abcf4SHaojian Zhuang } 137*2f2abcf4SHaojian Zhuang return result; 138*2f2abcf4SHaojian Zhuang } 139*2f2abcf4SHaojian Zhuang 140*2f2abcf4SHaojian Zhuang void hikey960_io_setup(void) 141*2f2abcf4SHaojian Zhuang { 142*2f2abcf4SHaojian Zhuang int result; 143*2f2abcf4SHaojian Zhuang 144*2f2abcf4SHaojian Zhuang result = register_io_dev_block(&ufs_dev_con); 145*2f2abcf4SHaojian Zhuang assert(result == 0); 146*2f2abcf4SHaojian Zhuang 147*2f2abcf4SHaojian Zhuang result = register_io_dev_fip(&fip_dev_con); 148*2f2abcf4SHaojian Zhuang assert(result == 0); 149*2f2abcf4SHaojian Zhuang 150*2f2abcf4SHaojian Zhuang result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec, 151*2f2abcf4SHaojian Zhuang &ufs_dev_handle); 152*2f2abcf4SHaojian Zhuang assert(result == 0); 153*2f2abcf4SHaojian Zhuang 154*2f2abcf4SHaojian Zhuang result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle); 155*2f2abcf4SHaojian Zhuang assert(result == 0); 156*2f2abcf4SHaojian Zhuang 157*2f2abcf4SHaojian Zhuang /* Ignore improbable errors in release builds */ 158*2f2abcf4SHaojian Zhuang (void)result; 159*2f2abcf4SHaojian Zhuang } 160*2f2abcf4SHaojian Zhuang 161*2f2abcf4SHaojian Zhuang /* Return an IO device handle and specification which can be used to access 162*2f2abcf4SHaojian Zhuang * an image. Use this to enforce platform load policy 163*2f2abcf4SHaojian Zhuang */ 164*2f2abcf4SHaojian Zhuang int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 165*2f2abcf4SHaojian Zhuang uintptr_t *image_spec) 166*2f2abcf4SHaojian Zhuang { 167*2f2abcf4SHaojian Zhuang int result; 168*2f2abcf4SHaojian Zhuang const struct plat_io_policy *policy; 169*2f2abcf4SHaojian Zhuang 170*2f2abcf4SHaojian Zhuang assert(image_id < ARRAY_SIZE(policies)); 171*2f2abcf4SHaojian Zhuang 172*2f2abcf4SHaojian Zhuang policy = &policies[image_id]; 173*2f2abcf4SHaojian Zhuang result = policy->check(policy->image_spec); 174*2f2abcf4SHaojian Zhuang assert(result == 0); 175*2f2abcf4SHaojian Zhuang 176*2f2abcf4SHaojian Zhuang *image_spec = policy->image_spec; 177*2f2abcf4SHaojian Zhuang *dev_handle = *(policy->dev_handle); 178*2f2abcf4SHaojian Zhuang 179*2f2abcf4SHaojian Zhuang return result; 180*2f2abcf4SHaojian Zhuang } 181*2f2abcf4SHaojian Zhuang 182*2f2abcf4SHaojian Zhuang size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size) 183*2f2abcf4SHaojian Zhuang { 184*2f2abcf4SHaojian Zhuang return ufs_read_blocks(3, lba, buf, size); 185*2f2abcf4SHaojian Zhuang } 186*2f2abcf4SHaojian Zhuang 187*2f2abcf4SHaojian Zhuang size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size) 188*2f2abcf4SHaojian Zhuang { 189*2f2abcf4SHaojian Zhuang return ufs_write_blocks(3, lba, buf, size); 190*2f2abcf4SHaojian Zhuang } 191