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 15*4e92aae1SJoseph 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 1486e15146eSJoseph Chen mem.base = SDRAM_OFFSET(SZ_1M); 1496e15146eSJoseph Chen mem.size = SZ_1M; 150dbf8423eSJoseph Chen 1516e15146eSJoseph Chen return mem; 152dbf8423eSJoseph Chen } 153dbf8423eSJoseph Chen 154dbf8423eSJoseph Chen int param_parse_bootdev(char **devtype, char **devnum) 155dbf8423eSJoseph Chen { 156dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 157dbf8423eSJoseph Chen struct tag *t; 158dbf8423eSJoseph Chen 159dbf8423eSJoseph Chen t = atags_get_tag(ATAG_BOOTDEV); 160dbf8423eSJoseph Chen if (t) { 161dbf8423eSJoseph Chen switch (t->u.bootdev.devtype) { 162dbf8423eSJoseph Chen case BOOT_TYPE_EMMC: 163dbf8423eSJoseph Chen *devtype = "mmc"; 164dbf8423eSJoseph Chen *devnum = "0"; 165dbf8423eSJoseph Chen break; 166dbf8423eSJoseph Chen case BOOT_TYPE_SD0: 167dbf8423eSJoseph Chen case BOOT_TYPE_SD1: 168dbf8423eSJoseph Chen *devtype = "mmc"; 169dbf8423eSJoseph Chen *devnum = "1"; 170dbf8423eSJoseph Chen break; 171dbf8423eSJoseph Chen case BOOT_TYPE_NAND: 172dbf8423eSJoseph Chen *devtype = "rknand"; 173dbf8423eSJoseph Chen *devnum = "0"; 174dbf8423eSJoseph Chen break; 175dbf8423eSJoseph Chen case BOOT_TYPE_SPI_NAND: 176dbf8423eSJoseph Chen *devtype = "spinand"; 177dbf8423eSJoseph Chen *devnum = "0"; 178dbf8423eSJoseph Chen break; 179dbf8423eSJoseph Chen case BOOT_TYPE_SPI_NOR: 180dbf8423eSJoseph Chen *devtype = "spinor"; 181dbf8423eSJoseph Chen *devnum = "1"; 182dbf8423eSJoseph Chen break; 183dbf8423eSJoseph Chen case BOOT_TYPE_RAM: 184dbf8423eSJoseph Chen *devtype = "ramdisk"; 185dbf8423eSJoseph Chen *devnum = "0"; 186dbf8423eSJoseph Chen break; 187dbf8423eSJoseph Chen default: 188dbf8423eSJoseph Chen printf("Unknown bootdev type: 0x%x\n", 189dbf8423eSJoseph Chen t->u.bootdev.devtype); 190dbf8423eSJoseph Chen return -EINVAL; 191dbf8423eSJoseph Chen } 192dbf8423eSJoseph Chen 193dbf8423eSJoseph Chen return 0; 194dbf8423eSJoseph Chen } 195dbf8423eSJoseph Chen #endif 196dbf8423eSJoseph Chen 197dbf8423eSJoseph Chen return -ENOSYS; 198dbf8423eSJoseph Chen } 199*4e92aae1SJoseph Chen #endif 200b9bc76b4SJoseph Chen 201b9bc76b4SJoseph Chen struct memblock *param_parse_ddr_mem(int *out_count) 202b9bc76b4SJoseph Chen { 203b9bc76b4SJoseph Chen struct udevice *dev; 204b9bc76b4SJoseph Chen struct memblock *mem; 205b9bc76b4SJoseph Chen struct ram_info ram; 206b9bc76b4SJoseph Chen int i, ret, count; 207b9bc76b4SJoseph Chen 208b9bc76b4SJoseph Chen /* 209b9bc76b4SJoseph Chen * Get memory region of DDR 210b9bc76b4SJoseph Chen * 211b9bc76b4SJoseph Chen * 1. New: atags info; 212b9bc76b4SJoseph Chen * 2. Leagcy: os register; 213b9bc76b4SJoseph Chen */ 214b9bc76b4SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 215b9bc76b4SJoseph Chen struct tag *t; 216b9bc76b4SJoseph Chen 217b9bc76b4SJoseph Chen t = atags_get_tag(ATAG_DDR_MEM); 218b9bc76b4SJoseph Chen if (t && t->u.ddr_mem.count) { 219b9bc76b4SJoseph Chen count = t->u.ddr_mem.count; 220b9bc76b4SJoseph Chen mem = calloc(count, sizeof(*mem)); 221b9bc76b4SJoseph Chen if (!mem) { 222b9bc76b4SJoseph Chen printf("Calloc ddr memory failed\n"); 223b9bc76b4SJoseph Chen return 0; 224b9bc76b4SJoseph Chen } 225b9bc76b4SJoseph Chen 226b9bc76b4SJoseph Chen for (i = 0; i < count; i++) { 227b9bc76b4SJoseph Chen mem[i].base = t->u.ddr_mem.bank[i]; 228b9bc76b4SJoseph Chen mem[i].size = t->u.ddr_mem.bank[i + count]; 229b9bc76b4SJoseph Chen } 230b9bc76b4SJoseph Chen 231b9bc76b4SJoseph Chen *out_count = count; 232b9bc76b4SJoseph Chen return mem; 233b9bc76b4SJoseph Chen } 234b9bc76b4SJoseph Chen #endif 235b9bc76b4SJoseph Chen 236b9bc76b4SJoseph Chen /* Leagcy */ 237b9bc76b4SJoseph Chen ret = uclass_get_device(UCLASS_RAM, 0, &dev); 238b9bc76b4SJoseph Chen if (ret) { 239b9bc76b4SJoseph Chen debug("DRAM init failed: %d\n", ret); 240b9bc76b4SJoseph Chen return NULL; 241b9bc76b4SJoseph Chen } 242b9bc76b4SJoseph Chen ret = ram_get_info(dev, &ram); 243b9bc76b4SJoseph Chen if (ret) { 244b9bc76b4SJoseph Chen debug("Cannot get DRAM size: %d\n", ret); 245b9bc76b4SJoseph Chen return NULL; 246b9bc76b4SJoseph Chen } 247b9bc76b4SJoseph Chen 248b9bc76b4SJoseph Chen debug("SDRAM base=%lx, size=%lx\n", 249b9bc76b4SJoseph Chen (unsigned long)ram.base, (unsigned long)ram.size); 250b9bc76b4SJoseph Chen 251b9bc76b4SJoseph Chen count = 1; 252b9bc76b4SJoseph Chen mem = calloc(1, sizeof(*mem)); 253b9bc76b4SJoseph Chen if (!mem) { 254b9bc76b4SJoseph Chen printf("Calloc ddr memory failed\n"); 255b9bc76b4SJoseph Chen return 0; 256b9bc76b4SJoseph Chen } 257b9bc76b4SJoseph Chen 258b9bc76b4SJoseph Chen for (i = 0; i < count; i++) { 259b9bc76b4SJoseph Chen mem[i].base = CONFIG_SYS_SDRAM_BASE; 260b9bc76b4SJoseph Chen mem[i].size = ram.size; 261b9bc76b4SJoseph Chen } 262b9bc76b4SJoseph Chen 263b9bc76b4SJoseph Chen *out_count = count; 264b9bc76b4SJoseph Chen return mem; 265b9bc76b4SJoseph Chen } 266