kernel-brax3-ubuntu-touch/drivers/misc/mediatek/adsp/adsp_reserved_mem.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

225 lines
6.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 MediaTek Inc.
*/
#include <linux/io.h>
#if IS_ENABLED(CONFIG_OF_RESERVED_MEM)
#include <linux/of.h>
#include <linux/of_reserved_mem.h>
#endif
#if IS_ENABLED(CONFIG_MTK_EMI)
#include <soc/mediatek/emi.h>
#endif
#include "adsp_reserved_mem.h"
#include "adsp_platform.h"
#include "adsp_core.h"
#define ADSP_MEM_RESERVED_KEY "mediatek,reserve-memory-adsp_share"
#define ADSP_RESERVE_MEMORY_BLOCK(xname) \
{.phys_addr = 0x0, .virt_addr = NULL, \
.size = 0, .name = xname}
static struct adsp_reserve_mblock adsp_reserve_mem = {0};
static struct adsp_reserve_mblock adsp_reserve_mblocks[] = {
[ADSP_A_IPI_DMA_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-ipidma-a"),
[ADSP_B_IPI_DMA_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-ipidma-b"),
[ADSP_A_LOGGER_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-logger-a"),
[ADSP_B_LOGGER_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-logger-b"),
[ADSP_C2C_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-c2c"),
[ADSP_A_DEBUG_DUMP_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-dbg-dump-a"),
[ADSP_B_DEBUG_DUMP_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-dbg-dump-b"),
[ADSP_A_CORE_DUMP_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-core-dump-a"),
[ADSP_B_CORE_DUMP_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-core-dump-b"),
#if IS_ENABLED(CONFIG_MTK_USB_OFFLOAD)
[ADSP_XHCI_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-xhci"),
#endif
[ADSP_AUDIO_COMMON_MEM_ID]
= ADSP_RESERVE_MEMORY_BLOCK("adsp-rsv-audio"),
};
static struct adsp_reserve_mblock *adsp_get_reserve_mblock(
enum adsp_reserve_mem_id_t id)
{
void *va_start = adsp_reserve_mblocks[0].virt_addr;
if (id >= ADSP_NUMS_MEM_ID) {
pr_info("%s no reserve memory for %d\n", __func__, id);
return NULL;
}
if (!va_start) {
pr_info("%s va_start is NULL\n", __func__);
return NULL;
}
return &adsp_reserve_mblocks[id];
}
phys_addr_t adsp_get_reserve_mem_phys(enum adsp_reserve_mem_id_t id)
{
struct adsp_reserve_mblock *mblk = adsp_get_reserve_mblock(id);
return mblk ? mblk->phys_addr : 0;
}
EXPORT_SYMBOL(adsp_get_reserve_mem_phys);
void *adsp_get_reserve_mem_virt(enum adsp_reserve_mem_id_t id)
{
struct adsp_reserve_mblock *mblk = adsp_get_reserve_mblock(id);
return mblk ? mblk->virt_addr : NULL;
}
EXPORT_SYMBOL(adsp_get_reserve_mem_virt);
size_t adsp_get_reserve_mem_size(enum adsp_reserve_mem_id_t id)
{
struct adsp_reserve_mblock *mblk = adsp_get_reserve_mblock(id);
return mblk ? mblk->size : 0;
}
EXPORT_SYMBOL(adsp_get_reserve_mem_size);
void adsp_set_emimpu_shared_region(void)
{
pr_info("%s(), emi config not enable\n", __func__);
}
static int adsp_init_reserve_memory(struct platform_device *pdev, struct adsp_reserve_mblock *mem)
{
struct device_node *node;
struct reserved_mem *rmem;
struct device *dev = &pdev->dev;
u64 mem_info[2];
int ret;
/* Reserved memory allocated from lk */
ret = of_property_read_u64_array(dev->of_node, "shared_memory", mem_info, 2);
if (!ret) {
mem->phys_addr = (phys_addr_t)mem_info[0];
mem->size = (size_t)mem_info[1];
#ifdef MEM_DEBUG
pr_info("%s(), get \"shared_memory\" property from dts, (%llx, %zx)\n",
__func__, mem->phys_addr, mem->size);
#endif
goto RSV_IOREMAP;
}
/* Otherwise, get reserved memory from reserved node */
node = of_find_compatible_node(NULL, NULL, ADSP_MEM_RESERVED_KEY);
if (!node) {
pr_info("%s(), no node for reserved memory\n", __func__);
return -ENOMEM;
}
rmem = of_reserved_mem_lookup(node);
if (!rmem) {
pr_info("%s(), cannot lookup reserved memory\n", __func__);
return -ENOMEM;
}
if (!rmem->base || !rmem->size) {
pr_info("%s() reserve memory illegal addr:%llx, size:%llx\n",
__func__, rmem->base, rmem->size);
return -ENOMEM;
} else {
mem->phys_addr = rmem->base;
mem->size = (size_t)rmem->size;
/* set mpu of shared memory to emi */
adsp_set_emimpu_shared_region();
}
RSV_IOREMAP:
mem->virt_addr = ioremap_wc(mem->phys_addr, mem->size);
if (!mem->virt_addr) {
pr_info("%s() ioremap fail\n", __func__);
return -ENOMEM;
}
return 0;
}
int adsp_mem_device_probe(struct platform_device *pdev)
{
int ret = 0;
enum adsp_reserve_mem_id_t id;
struct adsp_reserve_mblock *mem = &adsp_reserve_mem;
size_t acc_size = 0;
u32 size = 0;
ret = adsp_init_reserve_memory(pdev, mem);
if (ret)
return ret;
for (id = 0; id < ADSP_NUMS_MEM_ID; id++) {
ret = of_property_read_u32(pdev->dev.of_node,
adsp_reserve_mblocks[id].name,
&size);
if (!ret)
adsp_reserve_mblocks[id].size = (size_t)size;
}
/* assign to each memory block */
for (id = 0; id < ADSP_NUMS_MEM_ID; id++) {
if (adsp_reserve_mblocks[id].size == 0)
continue;
adsp_reserve_mblocks[id].phys_addr = mem->phys_addr + acc_size;
adsp_reserve_mblocks[id].virt_addr = mem->virt_addr + acc_size;
acc_size += ALIGN(adsp_reserve_mblocks[id].size, RSV_BLOCK_ALIGN);
#ifdef MEM_DEBUG
pr_info("adsp_reserve_mblocks[%d] phys_addr:%llx, size:0x%zx\n",
id,
adsp_reserve_mblocks[id].phys_addr,
adsp_reserve_mblocks[id].size);
#endif
}
if (acc_size > mem->size) {
pr_info("%s(), not enough of memory use(0x%zx) > total(0x%zx)\n",
__func__, acc_size, mem->size);
return -ENOMEM;
}
return 0;
}
EXPORT_SYMBOL(adsp_mem_device_probe);
ssize_t adsp_reserve_memory_dump(char *buffer, int size)
{
int n = 0, i = 0;
struct adsp_reserve_mblock *mem = &adsp_reserve_mem;
n += scnprintf(buffer + n, size - n,
"Reserve-memory-all:0x%llx 0x%p 0x%zx\n",
mem->phys_addr, mem->virt_addr, mem->size);
for (i = 0; i < ADSP_NUMS_MEM_ID; i++) {
mem = &adsp_reserve_mblocks[i];
n += scnprintf(buffer + n, size - n,
"Reserve-memory-Block[%02d]:0x%llx 0x%p 0x%zx\n",
i, mem->phys_addr, mem->virt_addr, mem->size);
}
return n;
}
void adsp_update_mpu_memory_info(struct adsp_priv *pdata)
{
struct adsp_mpu_info_t mpu_info;
mpu_info.share_dram_addr = (u32)adsp_reserve_mem.phys_addr;
mpu_info.share_dram_size = (u32)adsp_reserve_mem.size;
pr_info("[ADSP] mpu info=(0x%x, 0x%x)\n",
mpu_info.share_dram_addr, mpu_info.share_dram_size);
adsp_copy_to_sharedmem(pdata, ADSP_SHAREDMEM_MPUINFO,
&mpu_info, sizeof(struct adsp_mpu_info_t));
}