Add a new API to look up a memory region's index using its DeviceTree node name. This allows callers to identify specific regions within the internal regions array. Includes unit tests for successful lookups and error handling for non-existent names. Signed-off-by: Firas Sammoura <fsammoura@google.com>
81 lines
2.0 KiB
C
81 lines
2.0 KiB
C
/*
|
|
* Copyright (c) 2023 Carlo Caione, <ccaione@baylibre.com>
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/mem_mgmt/mem_attr.h>
|
|
|
|
#include <string.h>
|
|
|
|
#define _BUILD_MEM_ATTR_REGION(node_id) \
|
|
{ \
|
|
.dt_name = DT_NODE_FULL_NAME(node_id), \
|
|
.dt_addr = DT_REG_ADDR(node_id), \
|
|
.dt_size = DT_REG_SIZE(node_id), \
|
|
.dt_attr = DT_PROP(node_id, zephyr_memory_attr), \
|
|
},
|
|
|
|
static const struct mem_attr_region_t mem_attr_region[] = {
|
|
DT_MEMORY_ATTR_FOREACH_STATUS_OKAY_NODE(_BUILD_MEM_ATTR_REGION)
|
|
};
|
|
|
|
size_t mem_attr_get_regions(const struct mem_attr_region_t **region)
|
|
{
|
|
*region = mem_attr_region;
|
|
|
|
return ARRAY_SIZE(mem_attr_region);
|
|
}
|
|
|
|
int mem_attr_check_buf(void *v_addr, size_t size, uint32_t attr)
|
|
{
|
|
uintptr_t addr = (uintptr_t) v_addr;
|
|
|
|
/*
|
|
* If MMU is enabled the address of the buffer is a virtual address
|
|
* while the addresses in the DT are physical addresses. Given that we
|
|
* have no way of knowing whether a mapping exists, we simply bail out.
|
|
*/
|
|
if (IS_ENABLED(CONFIG_MMU)) {
|
|
return -ENOSYS;
|
|
}
|
|
|
|
if (size == 0) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
for (size_t idx = 0; idx < ARRAY_SIZE(mem_attr_region); idx++) {
|
|
const struct mem_attr_region_t *region = &mem_attr_region[idx];
|
|
size_t region_end = region->dt_addr + region->dt_size;
|
|
|
|
/* Check if the buffer is in the region */
|
|
if ((addr >= region->dt_addr) && (addr < region_end)) {
|
|
/* Check if the buffer is entirely contained in the region */
|
|
if ((addr + size) <= region_end) {
|
|
/* check if the attribute is correct */
|
|
return (region->dt_attr & attr) == attr ? 0 : -EINVAL;
|
|
}
|
|
return -ENOSPC;
|
|
}
|
|
}
|
|
return -ENOBUFS;
|
|
}
|
|
|
|
int mem_attr_get_region_index_by_name(const char *target_name)
|
|
{
|
|
const struct mem_attr_region_t *regions;
|
|
size_t num_regions;
|
|
|
|
num_regions = mem_attr_get_regions(®ions);
|
|
|
|
for (int i = 0; i < num_regions; ++i) {
|
|
if (regions[i].dt_name != NULL &&
|
|
strcmp(regions[i].dt_name, target_name) == 0) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -ENOENT;
|
|
}
|