185 lines
3.9 KiB
C
Executable file
185 lines
3.9 KiB
C
Executable file
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Samsung Exynos SoC series dsp driver
|
|
*
|
|
* Copyright (c) 2019 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com/
|
|
*/
|
|
|
|
#include "dl/dsp-pm-manager.h"
|
|
#include "dl/dsp-tlsf-allocator.h"
|
|
#include "dl/dsp-lib-manager.h"
|
|
|
|
#define DL_PM_ALIGN (64)
|
|
|
|
static struct dsp_tlsf *pm_manager;
|
|
static unsigned long dsp_pm_start_addr;
|
|
static size_t dsp_pm_total_size;
|
|
static struct dsp_lib *pm_init_lib;
|
|
|
|
unsigned long dsp_pm_manager_get_pm_start_addr(void)
|
|
{
|
|
return dsp_pm_start_addr;
|
|
}
|
|
|
|
size_t dsp_pm_manager_get_pm_total_size(void)
|
|
{
|
|
return dsp_pm_total_size;
|
|
}
|
|
|
|
int dsp_pm_manager_init(unsigned long start_addr, size_t size,
|
|
unsigned int pm_offset)
|
|
{
|
|
int ret;
|
|
struct dsp_tlsf_mem *init_mem;
|
|
|
|
DL_DEBUG("PM manager init\n");
|
|
|
|
pm_manager = (struct dsp_tlsf *)dsp_dl_malloc(
|
|
sizeof(struct dsp_tlsf),
|
|
"PM manager");
|
|
pm_init_lib = (struct dsp_lib *)dsp_dl_malloc(
|
|
sizeof(struct dsp_lib),
|
|
"PM Boot lib");
|
|
|
|
dsp_pm_start_addr = start_addr;
|
|
dsp_pm_total_size = size;
|
|
|
|
ret = dsp_tlsf_init(pm_manager, start_addr, size, DL_PM_ALIGN);
|
|
if (ret == -1) {
|
|
DL_ERROR("TLSF init is failed\n");
|
|
dsp_dl_free(pm_manager);
|
|
dsp_dl_free(pm_init_lib);
|
|
return -1;
|
|
}
|
|
|
|
DL_DEBUG("PM init mem size : %u\n", pm_offset);
|
|
ret = dsp_tlsf_malloc(pm_offset, &init_mem, pm_manager);
|
|
if (ret == -1) {
|
|
DL_ERROR("[%s] CHK_ERR\n", __func__);
|
|
dsp_dl_free(pm_manager);
|
|
dsp_dl_free(pm_init_lib);
|
|
return -1;
|
|
}
|
|
|
|
pm_init_lib->name = (char *)dsp_dl_malloc(
|
|
strlen("Boot/main pm") + 1,
|
|
"Boot/main pm");
|
|
strcpy(pm_init_lib->name, "Boot/main pm");
|
|
|
|
pm_init_lib->ref_cnt = 1;
|
|
pm_init_lib->loaded = 1;
|
|
init_mem->lib = pm_init_lib;
|
|
return 0;
|
|
}
|
|
|
|
void dsp_pm_manager_free(void)
|
|
{
|
|
dsp_tlsf_delete(pm_manager);
|
|
dsp_dl_free(pm_manager);
|
|
dsp_dl_free(pm_init_lib->name);
|
|
dsp_dl_free(pm_init_lib);
|
|
}
|
|
|
|
void dsp_pm_manager_print(void)
|
|
{
|
|
DL_INFO(DL_BORDER);
|
|
DL_INFO("Program memory manager\n");
|
|
DL_INFO("Start address: %#lx, size %#zx\n",
|
|
dsp_pm_start_addr, dsp_pm_total_size);
|
|
DL_INFO("\n");
|
|
dsp_tlsf_print(pm_manager);
|
|
}
|
|
|
|
int dsp_pm_manager_alloc_libs(struct dsp_lib **libs, int libs_size,
|
|
int *pm_inv)
|
|
{
|
|
int ret, idx;
|
|
|
|
DL_DEBUG("Alloc PM\n");
|
|
|
|
*pm_inv = 0;
|
|
for (idx = 0; idx < libs_size; idx++) {
|
|
if (!libs[idx]->pm) {
|
|
size_t text_size;
|
|
|
|
DL_DEBUG("Alloc PM for library %s\n",
|
|
libs[idx]->name);
|
|
text_size = dsp_elf32_get_text_size(libs[idx]->elf);
|
|
DL_DEBUG("PM alloc libs_size : %zu\n", text_size);
|
|
|
|
ret = dsp_pm_alloc(text_size, libs[idx], pm_inv);
|
|
|
|
if (ret == -1) {
|
|
DL_ERROR("PM manager allocation failed\n");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dsp_pm_alloc(size_t size, struct dsp_lib *lib,
|
|
int *pm_inv)
|
|
{
|
|
int alloc_ret;
|
|
|
|
if (!lib) {
|
|
DL_ERROR("struct dsp_lib is null\n");
|
|
return -1;
|
|
}
|
|
|
|
DL_DEBUG("Allocate PM pm for lib %s(size : %zu)\n",
|
|
lib->name, size);
|
|
alloc_ret = dsp_tlsf_malloc(size, &lib->pm, pm_manager);
|
|
|
|
if (alloc_ret == -1) {
|
|
if (dsp_tlsf_can_be_loaded(pm_manager, size)) {
|
|
DL_INFO("PM I-cache invalidation set\n");
|
|
dsp_lib_manager_delete_no_ref();
|
|
*pm_inv = 1;
|
|
return dsp_pm_alloc(size, lib, pm_inv);
|
|
}
|
|
|
|
DL_ERROR("Can not be loaded\n");
|
|
return -1;
|
|
}
|
|
|
|
DL_DEBUG("Lib(%s) allocation success\n", lib->name);
|
|
lib->pm->lib = lib;
|
|
return 0;
|
|
}
|
|
|
|
void dsp_pm_free(struct dsp_lib *lib)
|
|
{
|
|
if (lib->pm) {
|
|
//DL_DEBUG("PM free for %s\n", lib->info->name);
|
|
dsp_tlsf_free(lib->pm, pm_manager);
|
|
lib->pm = NULL;
|
|
}
|
|
}
|
|
|
|
void dsp_pm_print(struct dsp_lib *lib)
|
|
{
|
|
unsigned int *text = (unsigned int *)lib->pm->start_addr;
|
|
unsigned long offset = ((unsigned long)text - dsp_pm_start_addr) / 4;
|
|
unsigned int idx;
|
|
|
|
for (idx = 0; idx < lib->pm->size / sizeof(unsigned int);
|
|
idx++, offset++) {
|
|
if (idx % 4 == 0) {
|
|
if (idx != 0) {
|
|
DL_BUF_STR("\n");
|
|
DL_PRINT_BUF(DEBUG);
|
|
}
|
|
DL_BUF_STR("0x%lx : ", offset);
|
|
}
|
|
|
|
DL_BUF_STR("0x");
|
|
DL_BUF_STR("%08x ", *(unsigned int *)(text + idx));
|
|
}
|
|
|
|
DL_BUF_STR("\n");
|
|
DL_PRINT_BUF(DEBUG);
|
|
}
|