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 150453d738SJoseph Chen #define SZ_4GB 0x100000000ULL 160453d738SJoseph Chen 17*7a00e4e5SJoseph Chen #ifndef CONFIG_SPL_BUILD 18dbf8423eSJoseph Chen #define SDRAM_OFFSET(offset) (CONFIG_SYS_SDRAM_BASE + (offset)) 19dbf8423eSJoseph Chen #define PARAM_DRAM_INFO_OFFSET (SZ_32M) 20dbf8423eSJoseph Chen #define PARAM_OPTEE_INFO_OFFSET (SZ_32M + SZ_2M) 21dbf8423eSJoseph Chen 22dbf8423eSJoseph Chen struct tos_param_t { 23dbf8423eSJoseph Chen u32 version; 24dbf8423eSJoseph Chen u32 checksum; 25dbf8423eSJoseph Chen struct { 26dbf8423eSJoseph Chen char name[8]; 27dbf8423eSJoseph Chen s64 phy_addr; 28dbf8423eSJoseph Chen u32 size; 29dbf8423eSJoseph Chen u32 flags; 30dbf8423eSJoseph Chen } tee_mem; 31dbf8423eSJoseph Chen struct { 32dbf8423eSJoseph Chen char name[8]; 33dbf8423eSJoseph Chen s64 phy_addr; 34dbf8423eSJoseph Chen u32 size; 35dbf8423eSJoseph Chen u32 flags; 36dbf8423eSJoseph Chen } drm_mem; 37dbf8423eSJoseph Chen s64 reserve[8]; 38dbf8423eSJoseph Chen }; 39dbf8423eSJoseph Chen 40dbf8423eSJoseph Chen static uint16_t trust_checksum(const uint8_t *buf, uint16_t len) 41dbf8423eSJoseph Chen { 42dbf8423eSJoseph Chen uint16_t i, checksum = 0; 43dbf8423eSJoseph Chen 44dbf8423eSJoseph Chen for (i = 0; i < len; i++) { 45dbf8423eSJoseph Chen if (i % 2) 46dbf8423eSJoseph Chen checksum += buf[i] << 8; 47dbf8423eSJoseph Chen else 48dbf8423eSJoseph Chen checksum += buf[i]; 49dbf8423eSJoseph Chen } 50dbf8423eSJoseph Chen checksum = ~checksum; 51dbf8423eSJoseph Chen 52dbf8423eSJoseph Chen return checksum; 53dbf8423eSJoseph Chen } 54dbf8423eSJoseph Chen 556e15146eSJoseph Chen struct memblock param_parse_atf_mem(void) 56dbf8423eSJoseph Chen { 576e15146eSJoseph Chen struct memblock mem; 58dbf8423eSJoseph Chen 596e15146eSJoseph Chen mem.base = 0; 606e15146eSJoseph Chen mem.size = 0; 61dbf8423eSJoseph Chen 62dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 63dbf8423eSJoseph Chen struct tag *t = NULL; 64dbf8423eSJoseph Chen 65dbf8423eSJoseph Chen /* 66dbf8423eSJoseph Chen * Get memory region of ATF 67dbf8423eSJoseph Chen * 68dbf8423eSJoseph Chen * 1. New way: atags info; 69dbf8423eSJoseph Chen * 2. Leagcy way: 2MB size and start from ddr 0x0 offset; 70dbf8423eSJoseph Chen */ 71dbf8423eSJoseph Chen t = atags_get_tag(ATAG_ATF_MEM); 72dbf8423eSJoseph Chen if (t && t->u.atf_mem.size) { 736e15146eSJoseph Chen mem.base = t->u.atf_mem.phy_addr; 746e15146eSJoseph Chen mem.size = t->u.atf_mem.size; 75dbf8423eSJoseph Chen /* Sanity */ 766e15146eSJoseph Chen if (mem.base + mem.size > SDRAM_OFFSET(SZ_1M)) { 77dbf8423eSJoseph Chen printf("%s: ATF reserved region is not within 0-1MB " 78dbf8423eSJoseph Chen "offset(0x%08llx-0x%08llx)!\n", 796e15146eSJoseph Chen __func__, (u64)mem.base, (u64)mem.base + mem.size); 806e15146eSJoseph Chen return mem; 81dbf8423eSJoseph Chen } 82dbf8423eSJoseph Chen } 83dbf8423eSJoseph Chen #endif 84dbf8423eSJoseph Chen 85dbf8423eSJoseph Chen /* Legacy */ 866e15146eSJoseph Chen if (!mem.size) { 87dbf8423eSJoseph Chen if (IS_ENABLED(CONFIG_ARM64) || 88dbf8423eSJoseph Chen IS_ENABLED(CONFIG_ARM64_BOOT_AARCH32)) { 896e15146eSJoseph Chen mem.base = SDRAM_OFFSET(0); 906e15146eSJoseph Chen mem.size = SZ_1M; 91dbf8423eSJoseph Chen } 92dbf8423eSJoseph Chen } 93dbf8423eSJoseph Chen 946e15146eSJoseph Chen debug("ATF: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size); 95dbf8423eSJoseph Chen 966e15146eSJoseph Chen return mem; 97dbf8423eSJoseph Chen } 98dbf8423eSJoseph Chen 996e15146eSJoseph Chen struct memblock param_parse_optee_mem(void) 100dbf8423eSJoseph Chen { 101dbf8423eSJoseph Chen struct tos_param_t *tos_parameter; 1026e15146eSJoseph Chen struct memblock mem; 103dbf8423eSJoseph Chen u32 checksum; 104dbf8423eSJoseph Chen 1056e15146eSJoseph Chen mem.base = 0; 1066e15146eSJoseph Chen mem.size = 0; 107dbf8423eSJoseph Chen 108dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 109dbf8423eSJoseph Chen struct tag *t = NULL; 110dbf8423eSJoseph Chen 111dbf8423eSJoseph Chen /* 112dbf8423eSJoseph Chen * Get memory region of OP-TEE 113dbf8423eSJoseph Chen * 114dbf8423eSJoseph Chen * 1. New way: atags info; 115dbf8423eSJoseph Chen * 2. Leagcy way: info in ddr 34M offset; 116dbf8423eSJoseph Chen */ 117dbf8423eSJoseph Chen t = atags_get_tag(ATAG_TOS_MEM); 118dbf8423eSJoseph Chen if (t && (t->u.tos_mem.tee_mem.flags == 1)) { 1196e15146eSJoseph Chen mem.base = t->u.tos_mem.tee_mem.phy_addr; 1206e15146eSJoseph Chen mem.size = t->u.tos_mem.tee_mem.size; 121dbf8423eSJoseph Chen } 122dbf8423eSJoseph Chen #endif 123dbf8423eSJoseph Chen 124dbf8423eSJoseph Chen /* Legacy */ 1256e15146eSJoseph Chen if (!mem.size) { 126dbf8423eSJoseph Chen tos_parameter = 127dbf8423eSJoseph Chen (struct tos_param_t *)(SDRAM_OFFSET(PARAM_OPTEE_INFO_OFFSET)); 128dbf8423eSJoseph Chen checksum = 129dbf8423eSJoseph Chen trust_checksum((uint8_t *)(unsigned long)tos_parameter + 8, 130dbf8423eSJoseph Chen sizeof(struct tos_param_t) - 8); 131dbf8423eSJoseph Chen if ((checksum == tos_parameter->checksum) && 132dbf8423eSJoseph Chen (tos_parameter->tee_mem.flags == 1)) { 1336e15146eSJoseph Chen mem.base = tos_parameter->tee_mem.phy_addr; 1346e15146eSJoseph Chen mem.size = tos_parameter->tee_mem.size; 13507ea4f34SJoseph Chen } 13607ea4f34SJoseph Chen } 13707ea4f34SJoseph Chen 1386e15146eSJoseph Chen if (mem.size) 139dbf8423eSJoseph Chen gd->flags |= GD_FLG_BL32_ENABLED; 140dbf8423eSJoseph Chen 1416e15146eSJoseph Chen debug("TOS: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size); 142dbf8423eSJoseph Chen 1436e15146eSJoseph Chen return mem; 144dbf8423eSJoseph Chen } 145dbf8423eSJoseph Chen 1466e15146eSJoseph Chen struct memblock param_parse_common_resv_mem(void) 147dbf8423eSJoseph Chen { 1486e15146eSJoseph Chen struct memblock mem; 149dbf8423eSJoseph Chen 150160c99aaSJoseph Chen #if defined(CONFIG_ARM64) 151160c99aaSJoseph Chen mem.base = SDRAM_OFFSET(SZ_1M); 152160c99aaSJoseph Chen mem.size = SZ_1M; 153160c99aaSJoseph Chen /* 154160c99aaSJoseph Chen * The ARMv8 platform enabling AArch32 mode should reserve memory the same 155160c99aaSJoseph Chen * as AArch64 mode(because there is no difference about ATF), only some 156160c99aaSJoseph Chen * platform has special request, they are: RK3308. 157160c99aaSJoseph Chen */ 158160c99aaSJoseph Chen #elif defined(CONFIG_ARM64_BOOT_AARCH32) && !defined(CONFIG_ROCKCHIP_RK3308) 1596e15146eSJoseph Chen mem.base = SDRAM_OFFSET(SZ_1M); 1606e15146eSJoseph Chen mem.size = SZ_1M; 1612dd104a5SJoseph Chen #else 1622dd104a5SJoseph Chen mem.size = 0; 1632dd104a5SJoseph Chen #endif 1646e15146eSJoseph Chen return mem; 165dbf8423eSJoseph Chen } 166dbf8423eSJoseph Chen 167dbf8423eSJoseph Chen int param_parse_bootdev(char **devtype, char **devnum) 168dbf8423eSJoseph Chen { 169dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 170dbf8423eSJoseph Chen struct tag *t; 171dbf8423eSJoseph Chen 172dbf8423eSJoseph Chen t = atags_get_tag(ATAG_BOOTDEV); 173dbf8423eSJoseph Chen if (t) { 174dbf8423eSJoseph Chen switch (t->u.bootdev.devtype) { 17594aee224SJason Zhu #ifdef CONFIG_DM_MMC 176dbf8423eSJoseph Chen case BOOT_TYPE_EMMC: 177dbf8423eSJoseph Chen *devtype = "mmc"; 178dbf8423eSJoseph Chen *devnum = "0"; 179dbf8423eSJoseph Chen break; 180dbf8423eSJoseph Chen case BOOT_TYPE_SD0: 181dbf8423eSJoseph Chen case BOOT_TYPE_SD1: 182dbf8423eSJoseph Chen *devtype = "mmc"; 183dbf8423eSJoseph Chen *devnum = "1"; 184c9f547d8SJason Zhu /* 185c9f547d8SJason Zhu * If preloader does not pass sdupdate value, we treat it 186c9f547d8SJason Zhu * as a unknown card and call the rkimgtest cmd to find 187c9f547d8SJason Zhu * out what it is. 188c9f547d8SJason Zhu * 189c9f547d8SJason Zhu * If preloader pass sdupdate value as an update card, 190c9f547d8SJason Zhu * we just set "sdfwupdate" to bootargs instead of 191c9f547d8SJason Zhu * calling rkimgtest cmd which consumes time. 192c9f547d8SJason Zhu */ 193c9f547d8SJason Zhu if (t->u.bootdev.sdupdate == SD_UNKNOWN_CARD) { 194c9f547d8SJason Zhu run_command("mmc dev 1", 0); 195c9f547d8SJason Zhu run_command("rkimgtest mmc 1", 0); 196c9f547d8SJason Zhu } else if (t->u.bootdev.sdupdate == SD_UPDATE_CARD) { 197c9f547d8SJason Zhu env_update("bootargs", "sdfwupdate"); 198c9f547d8SJason Zhu } 199dbf8423eSJoseph Chen break; 20094aee224SJason Zhu #endif 20144f308bdSJoseph Chen #if defined(CONFIG_RKNAND) || defined(CONFIG_RKNANDC_NAND) 202dbf8423eSJoseph Chen case BOOT_TYPE_NAND: 203dbf8423eSJoseph Chen *devtype = "rknand"; 204dbf8423eSJoseph Chen *devnum = "0"; 205dbf8423eSJoseph Chen break; 20694aee224SJason Zhu #endif 20794aee224SJason Zhu #ifdef CONFIG_RKSFC_NAND 208dbf8423eSJoseph Chen case BOOT_TYPE_SPI_NAND: 209dbf8423eSJoseph Chen *devtype = "spinand"; 210dbf8423eSJoseph Chen *devnum = "0"; 211dbf8423eSJoseph Chen break; 21294aee224SJason Zhu #endif 21394aee224SJason Zhu #ifdef CONFIG_RKSFC_NOR 214dbf8423eSJoseph Chen case BOOT_TYPE_SPI_NOR: 215dbf8423eSJoseph Chen *devtype = "spinor"; 216dbf8423eSJoseph Chen *devnum = "1"; 217dbf8423eSJoseph Chen break; 21894aee224SJason Zhu #endif 21994aee224SJason Zhu #ifdef CONFIG_DM_RAMDISK 220dbf8423eSJoseph Chen case BOOT_TYPE_RAM: 221dbf8423eSJoseph Chen *devtype = "ramdisk"; 222dbf8423eSJoseph Chen *devnum = "0"; 223dbf8423eSJoseph Chen break; 22494aee224SJason Zhu #endif 225c53a0c58SJason Zhu #ifdef CONFIG_NAND 226c53a0c58SJason Zhu case BOOT_TYPE_MTD_BLK_NAND: 227c53a0c58SJason Zhu *devtype = "mtd"; 228c53a0c58SJason Zhu *devnum = "0"; 229c53a0c58SJason Zhu break; 230c53a0c58SJason Zhu #endif 231c53a0c58SJason Zhu #ifdef CONFIG_MTD_SPI_NAND 232c53a0c58SJason Zhu case BOOT_TYPE_MTD_BLK_SPI_NAND: 233c53a0c58SJason Zhu *devtype = "mtd"; 234c53a0c58SJason Zhu *devnum = "1"; 235c53a0c58SJason Zhu break; 236c53a0c58SJason Zhu #endif 237c53a0c58SJason Zhu #ifdef CONFIG_SPI_FLASH_MTD 238c53a0c58SJason Zhu case BOOT_TYPE_MTD_BLK_SPI_NOR: 239c53a0c58SJason Zhu *devtype = "mtd"; 240c53a0c58SJason Zhu *devnum = "2"; 241c53a0c58SJason Zhu break; 242c53a0c58SJason Zhu #endif 243dbf8423eSJoseph Chen default: 244dbf8423eSJoseph Chen printf("Unknown bootdev type: 0x%x\n", 245dbf8423eSJoseph Chen t->u.bootdev.devtype); 246dbf8423eSJoseph Chen return -EINVAL; 247dbf8423eSJoseph Chen } 248dbf8423eSJoseph Chen 249dbf8423eSJoseph Chen return 0; 250dbf8423eSJoseph Chen } 251dbf8423eSJoseph Chen #endif 252dbf8423eSJoseph Chen 253dbf8423eSJoseph Chen return -ENOSYS; 254dbf8423eSJoseph Chen } 2554e92aae1SJoseph Chen #endif 256b9bc76b4SJoseph Chen 257ced10dbeSJoseph Chen static phys_size_t ddr_mem_get_usable_size(u64 base, u64 size) 258ced10dbeSJoseph Chen { 2593ceae109SJoseph Chen return (base + size >= CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE) ? 2603ceae109SJoseph Chen (CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE - base) : size; 261ced10dbeSJoseph Chen } 262ced10dbeSJoseph Chen 263b9bc76b4SJoseph Chen struct memblock *param_parse_ddr_mem(int *out_count) 264b9bc76b4SJoseph Chen { 265b9bc76b4SJoseph Chen struct udevice *dev; 266b9bc76b4SJoseph Chen struct memblock *mem; 267b9bc76b4SJoseph Chen struct ram_info ram; 268b9bc76b4SJoseph Chen int i, ret, count; 269b9bc76b4SJoseph Chen 270b9bc76b4SJoseph Chen /* 271b9bc76b4SJoseph Chen * Get memory region of DDR 272b9bc76b4SJoseph Chen * 273b9bc76b4SJoseph Chen * 1. New: atags info; 274b9bc76b4SJoseph Chen * 2. Leagcy: os register; 275b9bc76b4SJoseph Chen */ 276b9bc76b4SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 277b9bc76b4SJoseph Chen struct tag *t; 2780453d738SJoseph Chen u64 base, size; 2790453d738SJoseph Chen int n; 280b9bc76b4SJoseph Chen 281b9bc76b4SJoseph Chen t = atags_get_tag(ATAG_DDR_MEM); 282b9bc76b4SJoseph Chen if (t && t->u.ddr_mem.count) { 283b9bc76b4SJoseph Chen count = t->u.ddr_mem.count; 2840453d738SJoseph Chen mem = calloc(count + MEM_RESV_COUNT, sizeof(*mem)); 285b9bc76b4SJoseph Chen if (!mem) { 286b9bc76b4SJoseph Chen printf("Calloc ddr memory failed\n"); 287b9bc76b4SJoseph Chen return 0; 288b9bc76b4SJoseph Chen } 289b9bc76b4SJoseph Chen 2900453d738SJoseph Chen for (i = 0, n = 0; i < count; i++, n++) { 2910453d738SJoseph Chen base = t->u.ddr_mem.bank[i]; 2920453d738SJoseph Chen size = t->u.ddr_mem.bank[i + count]; 2930453d738SJoseph Chen 2940453d738SJoseph Chen /* 0~4GB */ 2950453d738SJoseph Chen if (base < SZ_4GB) { 2960453d738SJoseph Chen mem[n].base = base; 2970453d738SJoseph Chen mem[n].size = ddr_mem_get_usable_size(base, size); 2980453d738SJoseph Chen if (base + size > SZ_4GB) { 2990453d738SJoseph Chen n++; 3000453d738SJoseph Chen mem[n].base_u64 = SZ_4GB; 3010453d738SJoseph Chen mem[n].size_u64 = base + size - SZ_4GB; 3020453d738SJoseph Chen } 3030453d738SJoseph Chen } else { 3040453d738SJoseph Chen /* 4GB+ */ 3050453d738SJoseph Chen mem[n].base_u64 = base; 3060453d738SJoseph Chen mem[n].size_u64 = size; 307b9bc76b4SJoseph Chen } 308b9bc76b4SJoseph Chen 3090453d738SJoseph Chen assert(n < count + MEM_RESV_COUNT); 3100453d738SJoseph Chen } 3110453d738SJoseph Chen 3120453d738SJoseph Chen *out_count = n; 313b9bc76b4SJoseph Chen return mem; 314b9bc76b4SJoseph Chen } 315b9bc76b4SJoseph Chen #endif 316b9bc76b4SJoseph Chen 317b9bc76b4SJoseph Chen /* Leagcy */ 318b9bc76b4SJoseph Chen ret = uclass_get_device(UCLASS_RAM, 0, &dev); 319b9bc76b4SJoseph Chen if (ret) { 320b9bc76b4SJoseph Chen debug("DRAM init failed: %d\n", ret); 321b9bc76b4SJoseph Chen return NULL; 322b9bc76b4SJoseph Chen } 323b9bc76b4SJoseph Chen ret = ram_get_info(dev, &ram); 324b9bc76b4SJoseph Chen if (ret) { 325b9bc76b4SJoseph Chen debug("Cannot get DRAM size: %d\n", ret); 326b9bc76b4SJoseph Chen return NULL; 327b9bc76b4SJoseph Chen } 328b9bc76b4SJoseph Chen 329b9bc76b4SJoseph Chen debug("SDRAM base=%lx, size=%lx\n", 330b9bc76b4SJoseph Chen (unsigned long)ram.base, (unsigned long)ram.size); 331b9bc76b4SJoseph Chen 332b9bc76b4SJoseph Chen count = 1; 333b9bc76b4SJoseph Chen mem = calloc(1, sizeof(*mem)); 334b9bc76b4SJoseph Chen if (!mem) { 335b9bc76b4SJoseph Chen printf("Calloc ddr memory failed\n"); 336b9bc76b4SJoseph Chen return 0; 337b9bc76b4SJoseph Chen } 338b9bc76b4SJoseph Chen 339b9bc76b4SJoseph Chen for (i = 0; i < count; i++) { 340b9bc76b4SJoseph Chen mem[i].base = CONFIG_SYS_SDRAM_BASE; 341ced10dbeSJoseph Chen mem[i].size = ddr_mem_get_usable_size(mem[i].base, ram.size); 342b9bc76b4SJoseph Chen } 343b9bc76b4SJoseph Chen 344b9bc76b4SJoseph Chen *out_count = count; 345b9bc76b4SJoseph Chen return mem; 346b9bc76b4SJoseph Chen } 347