1dbf8423eSJoseph Chen // SPDX-License-Identifier: GPL-2.0 2dbf8423eSJoseph Chen /* 3dbf8423eSJoseph Chen * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 4dbf8423eSJoseph Chen */ 5dbf8423eSJoseph Chen 6dbf8423eSJoseph Chen #include <common.h> 76e15146eSJoseph Chen #include <dm.h> 86e15146eSJoseph Chen #include <ram.h> 9dbf8423eSJoseph Chen #include <asm/io.h> 10dbf8423eSJoseph Chen #include <asm/arch/rk_atags.h> 11dbf8423eSJoseph Chen #include <asm/arch/param.h> 12dbf8423eSJoseph Chen 13dbf8423eSJoseph Chen DECLARE_GLOBAL_DATA_PTR; 14dbf8423eSJoseph Chen 154e92aae1SJoseph Chen #if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) 16dbf8423eSJoseph Chen #define SDRAM_OFFSET(offset) (CONFIG_SYS_SDRAM_BASE + (offset)) 17dbf8423eSJoseph Chen #define PARAM_DRAM_INFO_OFFSET (SZ_32M) 18dbf8423eSJoseph Chen #define PARAM_OPTEE_INFO_OFFSET (SZ_32M + SZ_2M) 19dbf8423eSJoseph Chen 20dbf8423eSJoseph Chen struct tos_param_t { 21dbf8423eSJoseph Chen u32 version; 22dbf8423eSJoseph Chen u32 checksum; 23dbf8423eSJoseph Chen struct { 24dbf8423eSJoseph Chen char name[8]; 25dbf8423eSJoseph Chen s64 phy_addr; 26dbf8423eSJoseph Chen u32 size; 27dbf8423eSJoseph Chen u32 flags; 28dbf8423eSJoseph Chen } tee_mem; 29dbf8423eSJoseph Chen struct { 30dbf8423eSJoseph Chen char name[8]; 31dbf8423eSJoseph Chen s64 phy_addr; 32dbf8423eSJoseph Chen u32 size; 33dbf8423eSJoseph Chen u32 flags; 34dbf8423eSJoseph Chen } drm_mem; 35dbf8423eSJoseph Chen s64 reserve[8]; 36dbf8423eSJoseph Chen }; 37dbf8423eSJoseph Chen 38dbf8423eSJoseph Chen static uint16_t trust_checksum(const uint8_t *buf, uint16_t len) 39dbf8423eSJoseph Chen { 40dbf8423eSJoseph Chen uint16_t i, checksum = 0; 41dbf8423eSJoseph Chen 42dbf8423eSJoseph Chen for (i = 0; i < len; i++) { 43dbf8423eSJoseph Chen if (i % 2) 44dbf8423eSJoseph Chen checksum += buf[i] << 8; 45dbf8423eSJoseph Chen else 46dbf8423eSJoseph Chen checksum += buf[i]; 47dbf8423eSJoseph Chen } 48dbf8423eSJoseph Chen checksum = ~checksum; 49dbf8423eSJoseph Chen 50dbf8423eSJoseph Chen return checksum; 51dbf8423eSJoseph Chen } 52dbf8423eSJoseph Chen 536e15146eSJoseph Chen struct memblock param_parse_atf_mem(void) 54dbf8423eSJoseph Chen { 556e15146eSJoseph Chen struct memblock mem; 56dbf8423eSJoseph Chen 576e15146eSJoseph Chen mem.base = 0; 586e15146eSJoseph Chen mem.size = 0; 59dbf8423eSJoseph Chen 60dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 61dbf8423eSJoseph Chen struct tag *t = NULL; 62dbf8423eSJoseph Chen 63dbf8423eSJoseph Chen /* 64dbf8423eSJoseph Chen * Get memory region of ATF 65dbf8423eSJoseph Chen * 66dbf8423eSJoseph Chen * 1. New way: atags info; 67dbf8423eSJoseph Chen * 2. Leagcy way: 2MB size and start from ddr 0x0 offset; 68dbf8423eSJoseph Chen */ 69dbf8423eSJoseph Chen t = atags_get_tag(ATAG_ATF_MEM); 70dbf8423eSJoseph Chen if (t && t->u.atf_mem.size) { 716e15146eSJoseph Chen mem.base = t->u.atf_mem.phy_addr; 726e15146eSJoseph Chen mem.size = t->u.atf_mem.size; 73dbf8423eSJoseph Chen /* Sanity */ 746e15146eSJoseph Chen if (mem.base + mem.size > SDRAM_OFFSET(SZ_1M)) { 75dbf8423eSJoseph Chen printf("%s: ATF reserved region is not within 0-1MB " 76dbf8423eSJoseph Chen "offset(0x%08llx-0x%08llx)!\n", 776e15146eSJoseph Chen __func__, (u64)mem.base, (u64)mem.base + mem.size); 786e15146eSJoseph Chen return mem; 79dbf8423eSJoseph Chen } 80dbf8423eSJoseph Chen } 81dbf8423eSJoseph Chen #endif 82dbf8423eSJoseph Chen 83dbf8423eSJoseph Chen /* Legacy */ 846e15146eSJoseph Chen if (!mem.size) { 85dbf8423eSJoseph Chen if (IS_ENABLED(CONFIG_ARM64) || 86dbf8423eSJoseph Chen IS_ENABLED(CONFIG_ARM64_BOOT_AARCH32)) { 876e15146eSJoseph Chen mem.base = SDRAM_OFFSET(0); 886e15146eSJoseph Chen mem.size = SZ_1M; 89dbf8423eSJoseph Chen } 90dbf8423eSJoseph Chen } 91dbf8423eSJoseph Chen 926e15146eSJoseph Chen debug("ATF: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size); 93dbf8423eSJoseph Chen 946e15146eSJoseph Chen return mem; 95dbf8423eSJoseph Chen } 96dbf8423eSJoseph Chen 976e15146eSJoseph Chen struct memblock param_parse_optee_mem(void) 98dbf8423eSJoseph Chen { 99dbf8423eSJoseph Chen struct tos_param_t *tos_parameter; 1006e15146eSJoseph Chen struct memblock mem; 101dbf8423eSJoseph Chen u32 checksum; 102dbf8423eSJoseph Chen 1036e15146eSJoseph Chen mem.base = 0; 1046e15146eSJoseph Chen mem.size = 0; 105dbf8423eSJoseph Chen 106dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 107dbf8423eSJoseph Chen struct tag *t = NULL; 108dbf8423eSJoseph Chen 109dbf8423eSJoseph Chen /* 110dbf8423eSJoseph Chen * Get memory region of OP-TEE 111dbf8423eSJoseph Chen * 112dbf8423eSJoseph Chen * 1. New way: atags info; 113dbf8423eSJoseph Chen * 2. Leagcy way: info in ddr 34M offset; 114dbf8423eSJoseph Chen */ 115dbf8423eSJoseph Chen t = atags_get_tag(ATAG_TOS_MEM); 116dbf8423eSJoseph Chen if (t && (t->u.tos_mem.tee_mem.flags == 1)) { 1176e15146eSJoseph Chen mem.base = t->u.tos_mem.tee_mem.phy_addr; 1186e15146eSJoseph Chen mem.size = t->u.tos_mem.tee_mem.size; 119dbf8423eSJoseph Chen } 120dbf8423eSJoseph Chen #endif 121dbf8423eSJoseph Chen 122dbf8423eSJoseph Chen /* Legacy */ 1236e15146eSJoseph Chen if (!mem.size) { 124dbf8423eSJoseph Chen tos_parameter = 125dbf8423eSJoseph Chen (struct tos_param_t *)(SDRAM_OFFSET(PARAM_OPTEE_INFO_OFFSET)); 126dbf8423eSJoseph Chen checksum = 127dbf8423eSJoseph Chen trust_checksum((uint8_t *)(unsigned long)tos_parameter + 8, 128dbf8423eSJoseph Chen sizeof(struct tos_param_t) - 8); 129dbf8423eSJoseph Chen if ((checksum == tos_parameter->checksum) && 130dbf8423eSJoseph Chen (tos_parameter->tee_mem.flags == 1)) { 1316e15146eSJoseph Chen mem.base = tos_parameter->tee_mem.phy_addr; 1326e15146eSJoseph Chen mem.size = tos_parameter->tee_mem.size; 13307ea4f34SJoseph Chen } 13407ea4f34SJoseph Chen } 13507ea4f34SJoseph Chen 1366e15146eSJoseph Chen if (mem.size) 137dbf8423eSJoseph Chen gd->flags |= GD_FLG_BL32_ENABLED; 138dbf8423eSJoseph Chen 1396e15146eSJoseph Chen debug("TOS: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size); 140dbf8423eSJoseph Chen 1416e15146eSJoseph Chen return mem; 142dbf8423eSJoseph Chen } 143dbf8423eSJoseph Chen 1446e15146eSJoseph Chen struct memblock param_parse_common_resv_mem(void) 145dbf8423eSJoseph Chen { 1466e15146eSJoseph Chen struct memblock mem; 147dbf8423eSJoseph Chen 148160c99aaSJoseph Chen #if defined(CONFIG_ARM64) 149160c99aaSJoseph Chen mem.base = SDRAM_OFFSET(SZ_1M); 150160c99aaSJoseph Chen mem.size = SZ_1M; 151160c99aaSJoseph Chen /* 152160c99aaSJoseph Chen * The ARMv8 platform enabling AArch32 mode should reserve memory the same 153160c99aaSJoseph Chen * as AArch64 mode(because there is no difference about ATF), only some 154160c99aaSJoseph Chen * platform has special request, they are: RK3308. 155160c99aaSJoseph Chen */ 156160c99aaSJoseph Chen #elif defined(CONFIG_ARM64_BOOT_AARCH32) && !defined(CONFIG_ROCKCHIP_RK3308) 1576e15146eSJoseph Chen mem.base = SDRAM_OFFSET(SZ_1M); 1586e15146eSJoseph Chen mem.size = SZ_1M; 1592dd104a5SJoseph Chen #else 1602dd104a5SJoseph Chen mem.size = 0; 1612dd104a5SJoseph Chen #endif 1626e15146eSJoseph Chen return mem; 163dbf8423eSJoseph Chen } 164dbf8423eSJoseph Chen 165dbf8423eSJoseph Chen int param_parse_bootdev(char **devtype, char **devnum) 166dbf8423eSJoseph Chen { 167dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 168dbf8423eSJoseph Chen struct tag *t; 169dbf8423eSJoseph Chen 170dbf8423eSJoseph Chen t = atags_get_tag(ATAG_BOOTDEV); 171dbf8423eSJoseph Chen if (t) { 172dbf8423eSJoseph Chen switch (t->u.bootdev.devtype) { 17394aee224SJason Zhu #ifdef CONFIG_DM_MMC 174dbf8423eSJoseph Chen case BOOT_TYPE_EMMC: 175dbf8423eSJoseph Chen *devtype = "mmc"; 176dbf8423eSJoseph Chen *devnum = "0"; 177dbf8423eSJoseph Chen break; 178dbf8423eSJoseph Chen case BOOT_TYPE_SD0: 179dbf8423eSJoseph Chen case BOOT_TYPE_SD1: 180dbf8423eSJoseph Chen *devtype = "mmc"; 181dbf8423eSJoseph Chen *devnum = "1"; 182c9f547d8SJason Zhu /* 183c9f547d8SJason Zhu * If preloader does not pass sdupdate value, we treat it 184c9f547d8SJason Zhu * as a unknown card and call the rkimgtest cmd to find 185c9f547d8SJason Zhu * out what it is. 186c9f547d8SJason Zhu * 187c9f547d8SJason Zhu * If preloader pass sdupdate value as an update card, 188c9f547d8SJason Zhu * we just set "sdfwupdate" to bootargs instead of 189c9f547d8SJason Zhu * calling rkimgtest cmd which consumes time. 190c9f547d8SJason Zhu */ 191c9f547d8SJason Zhu if (t->u.bootdev.sdupdate == SD_UNKNOWN_CARD) { 192c9f547d8SJason Zhu run_command("mmc dev 1", 0); 193c9f547d8SJason Zhu run_command("rkimgtest mmc 1", 0); 194c9f547d8SJason Zhu } else if (t->u.bootdev.sdupdate == SD_UPDATE_CARD) { 195c9f547d8SJason Zhu env_update("bootargs", "sdfwupdate"); 196c9f547d8SJason Zhu } 197dbf8423eSJoseph Chen break; 19894aee224SJason Zhu #endif 19944f308bdSJoseph Chen #if defined(CONFIG_RKNAND) || defined(CONFIG_RKNANDC_NAND) 200dbf8423eSJoseph Chen case BOOT_TYPE_NAND: 201dbf8423eSJoseph Chen *devtype = "rknand"; 202dbf8423eSJoseph Chen *devnum = "0"; 203dbf8423eSJoseph Chen break; 20494aee224SJason Zhu #endif 20594aee224SJason Zhu #ifdef CONFIG_RKSFC_NAND 206dbf8423eSJoseph Chen case BOOT_TYPE_SPI_NAND: 207dbf8423eSJoseph Chen *devtype = "spinand"; 208dbf8423eSJoseph Chen *devnum = "0"; 209dbf8423eSJoseph Chen break; 21094aee224SJason Zhu #endif 21194aee224SJason Zhu #ifdef CONFIG_RKSFC_NOR 212dbf8423eSJoseph Chen case BOOT_TYPE_SPI_NOR: 213dbf8423eSJoseph Chen *devtype = "spinor"; 214dbf8423eSJoseph Chen *devnum = "1"; 215dbf8423eSJoseph Chen break; 21694aee224SJason Zhu #endif 21794aee224SJason Zhu #ifdef CONFIG_DM_RAMDISK 218dbf8423eSJoseph Chen case BOOT_TYPE_RAM: 219dbf8423eSJoseph Chen *devtype = "ramdisk"; 220dbf8423eSJoseph Chen *devnum = "0"; 221dbf8423eSJoseph Chen break; 22294aee224SJason Zhu #endif 223dbf8423eSJoseph Chen default: 224dbf8423eSJoseph Chen printf("Unknown bootdev type: 0x%x\n", 225dbf8423eSJoseph Chen t->u.bootdev.devtype); 226dbf8423eSJoseph Chen return -EINVAL; 227dbf8423eSJoseph Chen } 228dbf8423eSJoseph Chen 229dbf8423eSJoseph Chen return 0; 230dbf8423eSJoseph Chen } 231dbf8423eSJoseph Chen #endif 232dbf8423eSJoseph Chen 233dbf8423eSJoseph Chen return -ENOSYS; 234dbf8423eSJoseph Chen } 2354e92aae1SJoseph Chen #endif 236b9bc76b4SJoseph Chen 237*ced10dbeSJoseph Chen static phys_size_t ddr_mem_get_usable_size(u64 base, u64 size) 238*ced10dbeSJoseph Chen { 239*ced10dbeSJoseph Chen return (base + size >= SDRAM_MAX_SIZE) ? (SDRAM_MAX_SIZE - base) : size; 240*ced10dbeSJoseph Chen } 241*ced10dbeSJoseph Chen 242b9bc76b4SJoseph Chen struct memblock *param_parse_ddr_mem(int *out_count) 243b9bc76b4SJoseph Chen { 244b9bc76b4SJoseph Chen struct udevice *dev; 245b9bc76b4SJoseph Chen struct memblock *mem; 246b9bc76b4SJoseph Chen struct ram_info ram; 247b9bc76b4SJoseph Chen int i, ret, count; 248b9bc76b4SJoseph Chen 249b9bc76b4SJoseph Chen /* 250b9bc76b4SJoseph Chen * Get memory region of DDR 251b9bc76b4SJoseph Chen * 252b9bc76b4SJoseph Chen * 1. New: atags info; 253b9bc76b4SJoseph Chen * 2. Leagcy: os register; 254b9bc76b4SJoseph Chen */ 255b9bc76b4SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 256b9bc76b4SJoseph Chen struct tag *t; 257b9bc76b4SJoseph Chen 258b9bc76b4SJoseph Chen t = atags_get_tag(ATAG_DDR_MEM); 259b9bc76b4SJoseph Chen if (t && t->u.ddr_mem.count) { 260b9bc76b4SJoseph Chen count = t->u.ddr_mem.count; 261b9bc76b4SJoseph Chen mem = calloc(count, sizeof(*mem)); 262b9bc76b4SJoseph Chen if (!mem) { 263b9bc76b4SJoseph Chen printf("Calloc ddr memory failed\n"); 264b9bc76b4SJoseph Chen return 0; 265b9bc76b4SJoseph Chen } 266b9bc76b4SJoseph Chen 267b9bc76b4SJoseph Chen for (i = 0; i < count; i++) { 268b9bc76b4SJoseph Chen mem[i].base = t->u.ddr_mem.bank[i]; 269*ced10dbeSJoseph Chen mem[i].size = 270*ced10dbeSJoseph Chen ddr_mem_get_usable_size(t->u.ddr_mem.bank[i], 271*ced10dbeSJoseph Chen t->u.ddr_mem.bank[i + count]); 272b9bc76b4SJoseph Chen } 273b9bc76b4SJoseph Chen 274b9bc76b4SJoseph Chen *out_count = count; 275b9bc76b4SJoseph Chen return mem; 276b9bc76b4SJoseph Chen } 277b9bc76b4SJoseph Chen #endif 278b9bc76b4SJoseph Chen 279b9bc76b4SJoseph Chen /* Leagcy */ 280b9bc76b4SJoseph Chen ret = uclass_get_device(UCLASS_RAM, 0, &dev); 281b9bc76b4SJoseph Chen if (ret) { 282b9bc76b4SJoseph Chen debug("DRAM init failed: %d\n", ret); 283b9bc76b4SJoseph Chen return NULL; 284b9bc76b4SJoseph Chen } 285b9bc76b4SJoseph Chen ret = ram_get_info(dev, &ram); 286b9bc76b4SJoseph Chen if (ret) { 287b9bc76b4SJoseph Chen debug("Cannot get DRAM size: %d\n", ret); 288b9bc76b4SJoseph Chen return NULL; 289b9bc76b4SJoseph Chen } 290b9bc76b4SJoseph Chen 291b9bc76b4SJoseph Chen debug("SDRAM base=%lx, size=%lx\n", 292b9bc76b4SJoseph Chen (unsigned long)ram.base, (unsigned long)ram.size); 293b9bc76b4SJoseph Chen 294b9bc76b4SJoseph Chen count = 1; 295b9bc76b4SJoseph Chen mem = calloc(1, sizeof(*mem)); 296b9bc76b4SJoseph Chen if (!mem) { 297b9bc76b4SJoseph Chen printf("Calloc ddr memory failed\n"); 298b9bc76b4SJoseph Chen return 0; 299b9bc76b4SJoseph Chen } 300b9bc76b4SJoseph Chen 301b9bc76b4SJoseph Chen for (i = 0; i < count; i++) { 302b9bc76b4SJoseph Chen mem[i].base = CONFIG_SYS_SDRAM_BASE; 303*ced10dbeSJoseph Chen mem[i].size = ddr_mem_get_usable_size(mem[i].base, ram.size); 304b9bc76b4SJoseph Chen } 305b9bc76b4SJoseph Chen 306b9bc76b4SJoseph Chen *out_count = count; 307b9bc76b4SJoseph Chen return mem; 308b9bc76b4SJoseph Chen } 309