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 15dbf8423eSJoseph Chen #define SDRAM_OFFSET(offset) (CONFIG_SYS_SDRAM_BASE + (offset)) 16dbf8423eSJoseph Chen #define PARAM_DRAM_INFO_OFFSET (SZ_32M) 17dbf8423eSJoseph Chen #define PARAM_OPTEE_INFO_OFFSET (SZ_32M + SZ_2M) 18dbf8423eSJoseph Chen 19dbf8423eSJoseph Chen struct tos_param_t { 20dbf8423eSJoseph Chen u32 version; 21dbf8423eSJoseph Chen u32 checksum; 22dbf8423eSJoseph Chen struct { 23dbf8423eSJoseph Chen char name[8]; 24dbf8423eSJoseph Chen s64 phy_addr; 25dbf8423eSJoseph Chen u32 size; 26dbf8423eSJoseph Chen u32 flags; 27dbf8423eSJoseph Chen } tee_mem; 28dbf8423eSJoseph Chen struct { 29dbf8423eSJoseph Chen char name[8]; 30dbf8423eSJoseph Chen s64 phy_addr; 31dbf8423eSJoseph Chen u32 size; 32dbf8423eSJoseph Chen u32 flags; 33dbf8423eSJoseph Chen } drm_mem; 34dbf8423eSJoseph Chen s64 reserve[8]; 35dbf8423eSJoseph Chen }; 36dbf8423eSJoseph Chen 37dbf8423eSJoseph Chen static uint16_t trust_checksum(const uint8_t *buf, uint16_t len) 38dbf8423eSJoseph Chen { 39dbf8423eSJoseph Chen uint16_t i, checksum = 0; 40dbf8423eSJoseph Chen 41dbf8423eSJoseph Chen for (i = 0; i < len; i++) { 42dbf8423eSJoseph Chen if (i % 2) 43dbf8423eSJoseph Chen checksum += buf[i] << 8; 44dbf8423eSJoseph Chen else 45dbf8423eSJoseph Chen checksum += buf[i]; 46dbf8423eSJoseph Chen } 47dbf8423eSJoseph Chen checksum = ~checksum; 48dbf8423eSJoseph Chen 49dbf8423eSJoseph Chen return checksum; 50dbf8423eSJoseph Chen } 51dbf8423eSJoseph Chen 526e15146eSJoseph Chen struct memblock param_parse_atf_mem(void) 53dbf8423eSJoseph Chen { 546e15146eSJoseph Chen struct memblock mem; 55dbf8423eSJoseph Chen 566e15146eSJoseph Chen mem.base = 0; 576e15146eSJoseph Chen mem.size = 0; 58dbf8423eSJoseph Chen 59dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 60dbf8423eSJoseph Chen struct tag *t = NULL; 61dbf8423eSJoseph Chen 62dbf8423eSJoseph Chen /* 63dbf8423eSJoseph Chen * Get memory region of ATF 64dbf8423eSJoseph Chen * 65dbf8423eSJoseph Chen * 1. New way: atags info; 66dbf8423eSJoseph Chen * 2. Leagcy way: 2MB size and start from ddr 0x0 offset; 67dbf8423eSJoseph Chen */ 68dbf8423eSJoseph Chen t = atags_get_tag(ATAG_ATF_MEM); 69dbf8423eSJoseph Chen if (t && t->u.atf_mem.size) { 706e15146eSJoseph Chen mem.base = t->u.atf_mem.phy_addr; 716e15146eSJoseph Chen mem.size = t->u.atf_mem.size; 72dbf8423eSJoseph Chen /* Sanity */ 736e15146eSJoseph Chen if (mem.base + mem.size > SDRAM_OFFSET(SZ_1M)) { 74dbf8423eSJoseph Chen printf("%s: ATF reserved region is not within 0-1MB " 75dbf8423eSJoseph Chen "offset(0x%08llx-0x%08llx)!\n", 766e15146eSJoseph Chen __func__, (u64)mem.base, (u64)mem.base + mem.size); 776e15146eSJoseph Chen return mem; 78dbf8423eSJoseph Chen } 79dbf8423eSJoseph Chen } 80dbf8423eSJoseph Chen #endif 81dbf8423eSJoseph Chen 82dbf8423eSJoseph Chen /* Legacy */ 836e15146eSJoseph Chen if (!mem.size) { 84dbf8423eSJoseph Chen if (IS_ENABLED(CONFIG_ARM64) || 85dbf8423eSJoseph Chen IS_ENABLED(CONFIG_ARM64_BOOT_AARCH32)) { 866e15146eSJoseph Chen mem.base = SDRAM_OFFSET(0); 876e15146eSJoseph Chen mem.size = SZ_1M; 88dbf8423eSJoseph Chen } 89dbf8423eSJoseph Chen } 90dbf8423eSJoseph Chen 916e15146eSJoseph Chen debug("ATF: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size); 92dbf8423eSJoseph Chen 936e15146eSJoseph Chen return mem; 94dbf8423eSJoseph Chen } 95dbf8423eSJoseph Chen 966e15146eSJoseph Chen struct memblock param_parse_optee_mem(void) 97dbf8423eSJoseph Chen { 98dbf8423eSJoseph Chen struct tos_param_t *tos_parameter; 996e15146eSJoseph Chen struct memblock mem; 100dbf8423eSJoseph Chen u32 checksum; 101dbf8423eSJoseph Chen 1026e15146eSJoseph Chen mem.base = 0; 1036e15146eSJoseph Chen mem.size = 0; 104dbf8423eSJoseph Chen 105dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 106dbf8423eSJoseph Chen struct tag *t = NULL; 107dbf8423eSJoseph Chen 108dbf8423eSJoseph Chen /* 109dbf8423eSJoseph Chen * Get memory region of OP-TEE 110dbf8423eSJoseph Chen * 111dbf8423eSJoseph Chen * 1. New way: atags info; 112dbf8423eSJoseph Chen * 2. Leagcy way: info in ddr 34M offset; 113dbf8423eSJoseph Chen */ 114dbf8423eSJoseph Chen t = atags_get_tag(ATAG_TOS_MEM); 115dbf8423eSJoseph Chen if (t && (t->u.tos_mem.tee_mem.flags == 1)) { 1166e15146eSJoseph Chen mem.base = t->u.tos_mem.tee_mem.phy_addr; 1176e15146eSJoseph Chen mem.size = t->u.tos_mem.tee_mem.size; 118dbf8423eSJoseph Chen } 119dbf8423eSJoseph Chen #endif 120dbf8423eSJoseph Chen 121dbf8423eSJoseph Chen /* Legacy */ 1226e15146eSJoseph Chen if (!mem.size) { 123dbf8423eSJoseph Chen tos_parameter = 124dbf8423eSJoseph Chen (struct tos_param_t *)(SDRAM_OFFSET(PARAM_OPTEE_INFO_OFFSET)); 125dbf8423eSJoseph Chen checksum = 126dbf8423eSJoseph Chen trust_checksum((uint8_t *)(unsigned long)tos_parameter + 8, 127dbf8423eSJoseph Chen sizeof(struct tos_param_t) - 8); 128dbf8423eSJoseph Chen if ((checksum == tos_parameter->checksum) && 129dbf8423eSJoseph Chen (tos_parameter->tee_mem.flags == 1)) { 1306e15146eSJoseph Chen mem.base = tos_parameter->tee_mem.phy_addr; 1316e15146eSJoseph Chen mem.size = tos_parameter->tee_mem.size; 13207ea4f34SJoseph Chen } 13307ea4f34SJoseph Chen } 13407ea4f34SJoseph Chen 1356e15146eSJoseph Chen if (mem.size) 136dbf8423eSJoseph Chen gd->flags |= GD_FLG_BL32_ENABLED; 137dbf8423eSJoseph Chen 1386e15146eSJoseph Chen debug("TOS: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size); 139dbf8423eSJoseph Chen 1406e15146eSJoseph Chen return mem; 141dbf8423eSJoseph Chen } 142dbf8423eSJoseph Chen 1436e15146eSJoseph Chen struct memblock param_parse_common_resv_mem(void) 144dbf8423eSJoseph Chen { 1456e15146eSJoseph Chen struct memblock mem; 146dbf8423eSJoseph Chen 1476e15146eSJoseph Chen mem.base = SDRAM_OFFSET(SZ_1M); 1486e15146eSJoseph Chen mem.size = SZ_1M; 149dbf8423eSJoseph Chen 1506e15146eSJoseph Chen return mem; 151dbf8423eSJoseph Chen } 152dbf8423eSJoseph Chen 153dbf8423eSJoseph Chen int param_parse_bootdev(char **devtype, char **devnum) 154dbf8423eSJoseph Chen { 155dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 156dbf8423eSJoseph Chen struct tag *t; 157dbf8423eSJoseph Chen 158dbf8423eSJoseph Chen t = atags_get_tag(ATAG_BOOTDEV); 159dbf8423eSJoseph Chen if (t) { 160dbf8423eSJoseph Chen switch (t->u.bootdev.devtype) { 161dbf8423eSJoseph Chen case BOOT_TYPE_EMMC: 162dbf8423eSJoseph Chen *devtype = "mmc"; 163dbf8423eSJoseph Chen *devnum = "0"; 164dbf8423eSJoseph Chen break; 165dbf8423eSJoseph Chen case BOOT_TYPE_SD0: 166dbf8423eSJoseph Chen case BOOT_TYPE_SD1: 167dbf8423eSJoseph Chen *devtype = "mmc"; 168dbf8423eSJoseph Chen *devnum = "1"; 169dbf8423eSJoseph Chen break; 170dbf8423eSJoseph Chen case BOOT_TYPE_NAND: 171dbf8423eSJoseph Chen *devtype = "rknand"; 172dbf8423eSJoseph Chen *devnum = "0"; 173dbf8423eSJoseph Chen break; 174dbf8423eSJoseph Chen case BOOT_TYPE_SPI_NAND: 175dbf8423eSJoseph Chen *devtype = "spinand"; 176dbf8423eSJoseph Chen *devnum = "0"; 177dbf8423eSJoseph Chen break; 178dbf8423eSJoseph Chen case BOOT_TYPE_SPI_NOR: 179dbf8423eSJoseph Chen *devtype = "spinor"; 180dbf8423eSJoseph Chen *devnum = "1"; 181dbf8423eSJoseph Chen break; 182dbf8423eSJoseph Chen case BOOT_TYPE_RAM: 183dbf8423eSJoseph Chen *devtype = "ramdisk"; 184dbf8423eSJoseph Chen *devnum = "0"; 185dbf8423eSJoseph Chen break; 186dbf8423eSJoseph Chen default: 187dbf8423eSJoseph Chen printf("Unknown bootdev type: 0x%x\n", 188dbf8423eSJoseph Chen t->u.bootdev.devtype); 189dbf8423eSJoseph Chen return -EINVAL; 190dbf8423eSJoseph Chen } 191dbf8423eSJoseph Chen 192dbf8423eSJoseph Chen return 0; 193dbf8423eSJoseph Chen } 194dbf8423eSJoseph Chen #endif 195dbf8423eSJoseph Chen 196dbf8423eSJoseph Chen return -ENOSYS; 197dbf8423eSJoseph Chen } 198*b9bc76b4SJoseph Chen 199*b9bc76b4SJoseph Chen struct memblock *param_parse_ddr_mem(int *out_count) 200*b9bc76b4SJoseph Chen { 201*b9bc76b4SJoseph Chen struct udevice *dev; 202*b9bc76b4SJoseph Chen struct memblock *mem; 203*b9bc76b4SJoseph Chen struct ram_info ram; 204*b9bc76b4SJoseph Chen int i, ret, count; 205*b9bc76b4SJoseph Chen 206*b9bc76b4SJoseph Chen /* 207*b9bc76b4SJoseph Chen * Get memory region of DDR 208*b9bc76b4SJoseph Chen * 209*b9bc76b4SJoseph Chen * 1. New: atags info; 210*b9bc76b4SJoseph Chen * 2. Leagcy: os register; 211*b9bc76b4SJoseph Chen */ 212*b9bc76b4SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 213*b9bc76b4SJoseph Chen struct tag *t; 214*b9bc76b4SJoseph Chen 215*b9bc76b4SJoseph Chen t = atags_get_tag(ATAG_DDR_MEM); 216*b9bc76b4SJoseph Chen if (t && t->u.ddr_mem.count) { 217*b9bc76b4SJoseph Chen count = t->u.ddr_mem.count; 218*b9bc76b4SJoseph Chen mem = calloc(count, sizeof(*mem)); 219*b9bc76b4SJoseph Chen if (!mem) { 220*b9bc76b4SJoseph Chen printf("Calloc ddr memory failed\n"); 221*b9bc76b4SJoseph Chen return 0; 222*b9bc76b4SJoseph Chen } 223*b9bc76b4SJoseph Chen 224*b9bc76b4SJoseph Chen for (i = 0; i < count; i++) { 225*b9bc76b4SJoseph Chen mem[i].base = t->u.ddr_mem.bank[i]; 226*b9bc76b4SJoseph Chen mem[i].size = t->u.ddr_mem.bank[i + count]; 227*b9bc76b4SJoseph Chen } 228*b9bc76b4SJoseph Chen 229*b9bc76b4SJoseph Chen *out_count = count; 230*b9bc76b4SJoseph Chen return mem; 231*b9bc76b4SJoseph Chen } 232*b9bc76b4SJoseph Chen #endif 233*b9bc76b4SJoseph Chen 234*b9bc76b4SJoseph Chen /* Leagcy */ 235*b9bc76b4SJoseph Chen ret = uclass_get_device(UCLASS_RAM, 0, &dev); 236*b9bc76b4SJoseph Chen if (ret) { 237*b9bc76b4SJoseph Chen debug("DRAM init failed: %d\n", ret); 238*b9bc76b4SJoseph Chen return NULL; 239*b9bc76b4SJoseph Chen } 240*b9bc76b4SJoseph Chen ret = ram_get_info(dev, &ram); 241*b9bc76b4SJoseph Chen if (ret) { 242*b9bc76b4SJoseph Chen debug("Cannot get DRAM size: %d\n", ret); 243*b9bc76b4SJoseph Chen return NULL; 244*b9bc76b4SJoseph Chen } 245*b9bc76b4SJoseph Chen 246*b9bc76b4SJoseph Chen debug("SDRAM base=%lx, size=%lx\n", 247*b9bc76b4SJoseph Chen (unsigned long)ram.base, (unsigned long)ram.size); 248*b9bc76b4SJoseph Chen 249*b9bc76b4SJoseph Chen count = 1; 250*b9bc76b4SJoseph Chen mem = calloc(1, sizeof(*mem)); 251*b9bc76b4SJoseph Chen if (!mem) { 252*b9bc76b4SJoseph Chen printf("Calloc ddr memory failed\n"); 253*b9bc76b4SJoseph Chen return 0; 254*b9bc76b4SJoseph Chen } 255*b9bc76b4SJoseph Chen 256*b9bc76b4SJoseph Chen for (i = 0; i < count; i++) { 257*b9bc76b4SJoseph Chen mem[i].base = CONFIG_SYS_SDRAM_BASE; 258*b9bc76b4SJoseph Chen mem[i].size = ram.size; 259*b9bc76b4SJoseph Chen } 260*b9bc76b4SJoseph Chen 261*b9bc76b4SJoseph Chen *out_count = count; 262*b9bc76b4SJoseph Chen return mem; 263*b9bc76b4SJoseph Chen } 264