| /* | |
| * common/cmd_rsvmem.c | |
| * | |
| * Copyright (C) 2015 Amlogic, Inc. All rights reserved. | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License as published by | |
| * the Free Software Foundation; either version 2 of the License, or | |
| * (at your option) any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| * more details. | |
| * | |
| */ | |
| #include <common.h> | |
| #include <command.h> | |
| #include <asm/io.h> | |
| #include <asm/arch/secure_apb.h> | |
| #ifdef CONFIG_CMD_RSVMEM | |
| //#define RSVMEM_DEBUG_ENABLE | |
| #ifdef RSVMEM_DEBUG_ENABLE | |
| #define rsvmem_dbg(fmt...) printf("[rsvmem] "fmt) | |
| #else | |
| #define rsvmem_dbg(fmt...) | |
| #endif | |
| #define rsvmem_info(fmt...) printf("[rsvmem] "fmt) | |
| #define rsvmem_err(fmt...) printf("[rsvmem] "fmt) | |
| #ifndef DTB_BIND_KERNEL | |
| #define RSVMEM_NONE -1 | |
| #define RSVMEM_RESERVED 0 | |
| #define RSVMEM_CMA 1 | |
| static int do_rsvmem_check(cmd_tbl_t *cmdtp, int flag, int argc, | |
| char *const argv[]) | |
| { | |
| unsigned int data = 0; | |
| unsigned int bl31_rsvmem_size = 0; | |
| unsigned int bl32_rsvmem_size = 0; | |
| unsigned int bl31_rsvmem_start = 0; | |
| unsigned int bl32_rsvmem_start = 0; | |
| char cmdbuf[128]; | |
| char *fdtaddr = NULL; | |
| int ret = 0; | |
| char *temp_env = NULL; | |
| int rsvmemtype = RSVMEM_NONE; | |
| rsvmem_dbg("reserved memory check!\n"); | |
| data = readl(P_AO_SEC_GP_CFG3); | |
| bl31_rsvmem_size = ((data & 0xffff0000) >> 16) << 10; | |
| bl32_rsvmem_size = (data & 0x0000ffff) << 10; | |
| bl31_rsvmem_start = readl(P_AO_SEC_GP_CFG5); | |
| bl32_rsvmem_start = readl(P_AO_SEC_GP_CFG4); | |
| fdtaddr = getenv("fdtaddr"); | |
| if (fdtaddr == NULL) { | |
| rsvmem_err("get fdtaddr NULL!\n"); | |
| return -1; | |
| } | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt addr %s;", fdtaddr); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("fdt addr error.\n"); | |
| return -2; | |
| } | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt get value env_compatible /reserved-memory/linux,secmon compatible;"); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0) { | |
| rsvmem_err("fdt get prop fail.\n"); | |
| return -2; | |
| } | |
| temp_env = getenv("env_compatible"); | |
| if (strcmp(temp_env, "shared-dma-pool") == 0) | |
| rsvmemtype = RSVMEM_CMA; | |
| else if (strcmp(temp_env, "amlogic, aml_secmon_memory") == 0) | |
| rsvmemtype = RSVMEM_RESERVED; | |
| else | |
| rsvmemtype = RSVMEM_NONE; | |
| if (rsvmemtype == RSVMEM_NONE) { | |
| rsvmem_err("env set fail.\n"); | |
| return -2; | |
| } | |
| run_command("setenv env_compatible;", 0); | |
| if ((bl31_rsvmem_size > 0) && (bl31_rsvmem_start > 0)) { | |
| if (rsvmemtype == RSVMEM_RESERVED) { | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt set /reserved-memory/linux,secmon reg <0x0 0x%x 0x0 0x%x>;", | |
| bl31_rsvmem_start, bl31_rsvmem_size); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("bl31 reserved memory set addr error.\n"); | |
| return -3; | |
| } | |
| } | |
| if (rsvmemtype == RSVMEM_CMA) { | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt set /reserved-memory/linux,secmon size <0x0 0x%x>;", | |
| ((bl31_rsvmem_size + 0x400000 - 1) / 0x400000)*0x400000); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("bl31 reserved memory set size error.\n"); | |
| return -3; | |
| } | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt set /reserved-memory/linux,secmon alloc-ranges <0x0 0x%x 0x0 0x%x>;", | |
| bl31_rsvmem_start, ((bl31_rsvmem_size + 0x400000 - 1) / 0x400000)*0x400000); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("bl31 reserved memory set alloc-ranges error.\n"); | |
| return -3; | |
| } | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt set /secmon reserve_mem_size <0x%x>;", | |
| bl31_rsvmem_size); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("bl31 reserved memory set reserve_mem_size error.\n"); | |
| return -3; | |
| } | |
| } | |
| } | |
| if ((bl32_rsvmem_size > 0) && (bl32_rsvmem_start > 0)) { | |
| if ((rsvmemtype == RSVMEM_RESERVED) | |
| || ((bl31_rsvmem_start + bl31_rsvmem_size != bl32_rsvmem_start) | |
| && (rsvmemtype == RSVMEM_CMA))) { | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt set /reserved-memory/linux,secos status okay;"); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("bl32 reserved memory set status error.\n"); | |
| return -3; | |
| } | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt set /reserved-memory/linux,secos reg <0x0 0x%x 0x0 0x%x>;", | |
| bl32_rsvmem_start, bl32_rsvmem_size); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("bl32 reserved memory set addr error.\n"); | |
| return -3; | |
| } | |
| } | |
| if ((bl31_rsvmem_start + bl31_rsvmem_size == bl32_rsvmem_start) | |
| && (rsvmemtype == RSVMEM_CMA)) { | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt set /reserved-memory/linux,secmon size <0x0 0x%x>;", | |
| ((bl31_rsvmem_size + bl32_rsvmem_size + 0x400000 - 1) / 0x400000)*0x400000); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("bl32 reserved memory set size error.\n"); | |
| return -3; | |
| } | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt set /reserved-memory/linux,secmon alloc-ranges <0x0 0x%x 0x0 0x%x>;", | |
| bl31_rsvmem_start, | |
| ((bl31_rsvmem_size + bl32_rsvmem_size + 0x400000 - 1) / 0x400000)*0x400000); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("bl32 reserved memory set alloc-ranges error.\n"); | |
| return -3; | |
| } | |
| memset(cmdbuf, 0, sizeof(cmdbuf)); | |
| sprintf(cmdbuf, "fdt set /secmon reserve_mem_size <0x%x>;", | |
| bl31_rsvmem_size + bl32_rsvmem_size); | |
| rsvmem_dbg("CMD: %s\n", cmdbuf); | |
| ret = run_command(cmdbuf, 0); | |
| if (ret != 0 ) { | |
| rsvmem_err("bl32 reserved memory set reserve_mem_size error.\n"); | |
| return -3; | |
| } | |
| } | |
| } | |
| return ret; | |
| } | |
| static int do_rsvmem_dump(cmd_tbl_t *cmdtp, int flag, int argc, | |
| char *const argv[]) | |
| { | |
| unsigned int data = 0; | |
| unsigned int bl31_rsvmem_size = 0; | |
| unsigned int bl32_rsvmem_size = 0; | |
| unsigned int bl31_rsvmem_start = 0; | |
| unsigned int bl32_rsvmem_start = 0; | |
| rsvmem_info("reserved memory:\n"); | |
| data = readl(P_AO_SEC_GP_CFG3); | |
| bl31_rsvmem_size = ((data & 0xffff0000) >> 16) << 10; | |
| bl32_rsvmem_size = (data & 0x0000ffff) << 10; | |
| bl31_rsvmem_start = readl(P_AO_SEC_GP_CFG5); | |
| bl32_rsvmem_start = readl(P_AO_SEC_GP_CFG4); | |
| rsvmem_info("bl31 reserved memory start: 0x%08x\n", bl31_rsvmem_start); | |
| rsvmem_info("bl31 reserved memory size: 0x%08x\n", bl31_rsvmem_size); | |
| rsvmem_info("bl32 reserved memory start: 0x%08x\n", bl32_rsvmem_start); | |
| rsvmem_info("bl32 reserved memory size: 0x%08x\n", bl32_rsvmem_size); | |
| return 0; | |
| } | |
| static cmd_tbl_t cmd_rsvmem_sub[] = { | |
| U_BOOT_CMD_MKENT(check, 2, 0, do_rsvmem_check, "", ""), | |
| U_BOOT_CMD_MKENT(dump, 2, 0, do_rsvmem_dump, "", ""), | |
| }; | |
| #endif | |
| static int do_rsvmem(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) | |
| { | |
| #ifdef DTB_BIND_KERNEL | |
| rsvmem_err("no check for rsvmem, should check int kernel\n"); | |
| return 0; | |
| #else | |
| cmd_tbl_t *c; | |
| /* Strip off leading 'rsvmem' command argument */ | |
| argc--; | |
| argv++; | |
| c = find_cmd_tbl(argv[0], &cmd_rsvmem_sub[0], ARRAY_SIZE(cmd_rsvmem_sub)); | |
| if (c) | |
| return c->cmd(cmdtp, flag, argc, argv); | |
| else | |
| return CMD_RET_USAGE; | |
| #endif | |
| } | |
| U_BOOT_CMD( | |
| rsvmem, 2, 0, do_rsvmem, | |
| "reserve memory", | |
| "check - check reserved memory\n" | |
| "rsvmem dump - dump reserved memory\n" | |
| ); | |
| #endif |