You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
9.4 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2012-2019. All rights reserved.
* Description: decoder
* Author: Hisilicon
* Create: 2012-04-22
*/
#include "dmcu_mem.h"
#include "dmcu_hal.h"
#include "dmcu_adapt.h"
#include "drv_mbx.h"
#include "los_dynshm.h"
#include "los_memory.h"
static dmcu_mem_ctx g_ctx;
static td_void *g_dmcu_mem_pool = NULL;
static td_u32 dmcu_vam_flush_tlb(td_u32 flush_cache)
{
return dmcu_iommu_flush_tlb(flush_cache);
}
static td_u32 dmcu_vam_bulk_alloc(DynShmBulkMem *mem)
{
td_u32 ret = TD_SUCCESS;
if (mem == NULL || mem->name == NULL || mem->size == 0) {
soc_log_err("mem is NULL!\n");
return TD_FAILURE;
}
dmcu_mem_record report = { 0 };
report.length = mem->size;
report.type = mem->type;
if (memcpy_s(report.mem_name, DMCU_MEM_NAME_MAX_LEN, mem->name, strlen(mem->name) + 1) != EOK) {
soc_log_err("mem_name memcpy fail\n");
return TD_FAILURE;
}
ret = dmcu_client_send_process(DMCU_CMD_VAM_ALLOC, (td_void *)&report, sizeof(dmcu_mem_record));
mem->phyAddr = report.phy_addr;
mem->dmaBuf = report.dma_buf;
return ret;
}
static td_u32 dmcu_vam_bulk_free(DynShmBulkMem *mem)
{
td_u32 ret = TD_SUCCESS;
if (mem == NULL || mem->size == 0 || mem->phyAddr == 0 || mem->dmaBuf == 0) {
soc_log_err("mem is NULL!\n");
return TD_FAILURE;
}
dmcu_mem_record report = { 0 };
report.type = mem->type;
report.phy_addr = mem->phyAddr;
report.length = mem->size;
report.dma_buf = mem->dmaBuf;
ret = dmcu_client_send_process(DMCU_CMD_VAM_FREE, (td_void *)&report, sizeof(dmcu_mem_record));
return ret;
}
td_s32 dmcu_pool_mem_init(UADDR phy_addr, td_u32 size, dmcu_mem_type type, UADDR *vir_addr)
{
td_u32 ret;
td_u32 pool_vir_addr;
if ((g_dmcu_mem_pool != NULL) || (vir_addr == NULL)) {
soc_log_err("Invalid parameter\n");
return TD_FAILURE;
}
ret = LOS_DynShmMap(phy_addr, size, type, &pool_vir_addr);
if (ret != TD_SUCCESS) {
soc_log_err("LOS_DynShmMap fail\n");
return TD_FAILURE;
}
ret = LOS_MemInit((td_void *)(UINTPTR)pool_vir_addr, size);
if (ret != TD_SUCCESS) {
soc_log_err("LOS_MemInit fail, ret:%#x\n", ret);
ret = LOS_DynShmUnmap(pool_vir_addr, size);
if (ret != TD_SUCCESS) {
soc_log_err("LOS_DynShmUnmap fail\n");
return TD_FAILURE;
}
return TD_FAILURE;
}
*vir_addr = pool_vir_addr;
g_dmcu_mem_pool = (td_void *)(UINTPTR)pool_vir_addr;
return TD_SUCCESS;
}
td_void *dmcu_pool_mem_malloc(td_u32 size)
{
if (g_dmcu_mem_pool == NULL) {
soc_log_err("g_dmcu_mem_pool not null\n");
return NULL;
}
return LOS_MemAlloc(g_dmcu_mem_pool, size);
}
td_s32 dmcu_pool_mem_free(td_void *addr)
{
td_u32 ret;
if (g_dmcu_mem_pool == NULL) {
soc_log_err("g_dmcu_mem_pool is null\n");
return TD_FAILURE;
}
ret = LOS_MemFree(g_dmcu_mem_pool, addr);
if (ret != TD_SUCCESS) {
soc_log_err("LOS_MemFree fail\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 dmcu_pool_mem_deinit(UADDR vir_addr, td_u32 size)
{
td_u32 ret;
if (g_dmcu_mem_pool == NULL) {
soc_log_err("g_dmcu_mem_pool is null\n");
return TD_FAILURE;
}
ret = LOS_MemDeInit((void *)(uintptr_t)vir_addr);
if (ret != TD_SUCCESS) {
soc_log_err("LOS_MemDeInit fail, ret:%#x\n", ret);
}
ret = LOS_DynShmUnmap(vir_addr, size);
if (ret != TD_SUCCESS) {
soc_log_err("LOS_DynShmUnmap fail\n");
return TD_FAILURE;
}
g_dmcu_mem_pool = NULL;
return TD_SUCCESS;
}
static dmcu_mem_ctx *dmcu_mem_get_ctx(td_void)
{
return &g_ctx;
}
static td_void dmcu_mem_init_page(td_void)
{
td_u32 page_size;
dmcu_mem_ctx *ctx = TD_NULL;
ctx = dmcu_mem_get_ctx();
page_size = PAGE_SIZE_4K;
if (page_size >= PAGE_SIZE_MAX) {
soc_log_err("err %d\n", page_size);
}
ctx->page_size = 0x1000 << (page_size << 1);
return;
}
static td_s32 dmcu_mem_get_no_cache_scale(td_void)
{
return DMCU_ADDR_LEN_NC_SCALE;
}
static td_void dmcu_mem_set_iommu_pt_addr(dmcu_iommu_pt_addr *pt_addr)
{
dmcu_mem_ctx *ctx = TD_NULL;
ctx = dmcu_mem_get_ctx();
pt_addr->pt_no_sec_addr = ctx->dmcu_pt[MEM_PT_NS].base_addr;
pt_addr->pt_no_sec_err_rd_addr = ctx->dmcu_pt[MEM_PT_NS].err_read_addr;
pt_addr->pt_no_sec_err_wt_addr = ctx->dmcu_pt[MEM_PT_NS].err_write_addr;
return;
}
static td_void dmcu_mem_debug_info(DynShmConfig *cfg)
{
int i = 0;
printf("[dmcu]: arm pt addr:0x%x, dmcu pt addr:0x%x, pageSize:0x%x\n", cfg->outerPageTable.nonsec.baseAddr,
cfg->innerPageTable.nonsec.baseAddr, cfg->pageSize);
for (i = 0; i < cfg->regionCnt; i++) {
printf("[dmcu]: num:%d, regionStart:0x%x, regionSize:0x%x, type:0x%x\n", i, cfg->regions[i].startAddr,
cfg->regions[i].size, cfg->regions[i].type);
}
return;
}
td_s32 dmcu_mem_vam_init(void)
{
dmcu_mem_ctx *ctx = TD_NULL;
ctx = dmcu_mem_get_ctx();
td_s32 no_cache_scale = dmcu_mem_get_no_cache_scale();
td_u32 total_size = ctx->iommu_total_size;
td_u32 no_cache_addr = ctx->iommu_base_vir_addr;
td_u32 no_cache_size = (td_u32)((td_u64)total_size * (td_u64)no_cache_scale / DMCU_SCALE_NUM);
no_cache_size = dmcu_align_dn(no_cache_size, ctx->page_size);
td_u32 cache_addr = no_cache_addr + no_cache_size;
td_u32 cache_size = total_size - no_cache_size;
cache_size = dmcu_align_dn(cache_size, ctx->page_size);
DynShmConfig cfg = {
.outerPageTable.nonsec.baseAddr = ctx->arm_pt[MEM_PT_NS].base_addr,
.outerPageTable.nonsec.tableSize = DMCU_NS_PT_SIZE,
.innerPageTable.nonsec.baseAddr = ctx->dmcu_pt[MEM_PT_NS].base_addr,
.innerPageTable.nonsec.tableSize = DMCU_NS_PT_SIZE,
.pageSize = ctx->page_size,
.flushTlbHandler = dmcu_vam_flush_tlb,
.bulkAllocHandler = dmcu_vam_bulk_alloc,
.bulkFreeHandler = dmcu_vam_bulk_free,
.regionCnt = 2,
.regions = {
{.startAddr = no_cache_addr, .size = no_cache_size, .type = DMCU_IOMMU_NOSEC_NOCACHE},
{.startAddr = cache_addr, .size = cache_size, .type = DMCU_IOMMU_NOSEC_CACHE},
}
};
dmcu_iommu_pt_addr pt_addr = { 0 };
dmcu_mem_set_iommu_pt_addr(&pt_addr);
dmcu_iommu_init(&pt_addr);
dmcu_mem_debug_info(&cfg);
return LOS_DynShmInit(&cfg);
}
static td_void dmcu_mem_calc_vir_base_addr(td_void)
{
dmcu_mem_ctx *ctx = TD_NULL;
ctx = dmcu_mem_get_ctx();
ctx->iommu_base_vir_addr =
dmcu_max(ctx->mmz_info.base_addr + ctx->mmz_info.mmz_size, DMCU_RESERVED_START_ADDR + DMCU_RESERVED_START_SIZE);
ctx->iommu_base_vir_addr = dmcu_max(ctx->iommu_base_vir_addr, ctx->arm_pt[MEM_PT_NS].base_addr + MEM_PT_SIZE_MAX);
ctx->iommu_total_size = DMCU_IOMMU_MAX_ADDR - (ctx->iommu_base_vir_addr);
soc_log_info("dmcu vir base_addr = 0x%llx size = 0x%x\n", ctx->iommu_base_vir_addr, ctx->iommu_total_size);
return;
}
static td_void dmcu_mem_fill_pt_addr(td_void)
{
dmcu_mem_ctx *ctx;
ctx = dmcu_mem_get_ctx();
ctx->dmcu_pt[MEM_PT_NS].base_addr = DMCU_NS_PT_BASEADDR;
ctx->dmcu_pt[MEM_PT_NS].err_read_addr = DMCU_NS_PT_ERRADDR_RD;
ctx->dmcu_pt[MEM_PT_NS].err_write_addr = DMCU_NS_PT_ERRADDR_WR;
ctx->dmcu_pt[MEM_PT_S].base_addr = DMCU_PT_BASEADDR_S;
ctx->dmcu_pt[MEM_PT_S].err_read_addr = DMCU_PT_ERRADDR_RD_S;
ctx->dmcu_pt[MEM_PT_S].err_write_addr = DMCU_PT_ERRADDR_WR_S;
return;
}
static td_s32 dmcu_mem_init_pre(td_void)
{
td_s32 ret = TD_SUCCESS;
dmcu_mem_init_data mem_init_data = { 0 };
mem_init_data.flag = 0x5a5a;
ret = dmcu_client_send_process(DMCU_CMD_MEM_INIT, (td_void *)&mem_init_data, sizeof(dmcu_mem_init_data));
if (ret != TD_SUCCESS) {
soc_log_err("send DMCU_CMD_MEM_INIT Messages failed\n");
return ret;
}
dmcu_mem_ctx *ctx = TD_NULL;
ctx = dmcu_mem_get_ctx();
ctx->arm_pt[MEM_PT_S].base_addr = mem_init_data.pt_sec_addr;
ctx->arm_pt[MEM_PT_NS].base_addr = mem_init_data.pt_nosec_addr;
ctx->mmz_info.base_addr = mem_init_data.pt_mmz_addr;
ctx->mmz_info.mmz_size = mem_init_data.pt_mmz_size;
return TD_SUCCESS;
}
td_s32 dmcu_mem_init(td_void)
{
td_s32 ret = TD_SUCCESS;
ret = dmcu_mem_init_pre();
if (ret != TD_SUCCESS) {
soc_log_err("dmcu_mem_init_pre failed, ret: %d\n", ret);
return TD_FAILURE;
}
dmcu_mem_calc_vir_base_addr();
dmcu_mem_fill_pt_addr();
dmcu_mem_init_page();
ret = dmcu_mem_vam_init();
if (ret != TD_SUCCESS) {
soc_log_err("dmcu_mem_vam_init failed, ret: %d\n", ret);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_void dmcu_mem_resume(td_void)
{
dmcu_mem_ctx *ctx = TD_NULL;
ctx = dmcu_mem_get_ctx();
const dmcu_iommu_pt_addr pt_addr = {
.pt_no_sec_addr = ctx->dmcu_pt[MEM_PT_NS].base_addr,
.pt_no_sec_err_rd_addr = ctx->dmcu_pt[MEM_PT_NS].err_read_addr,
.pt_no_sec_err_wt_addr = ctx->dmcu_pt[MEM_PT_NS].err_write_addr,
};
dmcu_iommu_deinit();
dmcu_iommu_init(&pt_addr);
return;
}