blob: 66ca30e11b35a59e4d02fc47dbe751d5f1f9ed0f [file] [log] [blame] [edit]
/*
* 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