diff --git a/dts/bindings/reserved-memory/reserved-memory.yaml b/dts/bindings/reserved-memory/reserved-memory.yaml new file mode 100644 index 00000000000..5b2d26aa0f3 --- /dev/null +++ b/dts/bindings/reserved-memory/reserved-memory.yaml @@ -0,0 +1,23 @@ +description: | + Reserved memory - Each child of the reserved-memory node specifies one or + more regions of reserved memory. Regions in the /reserved-memory node may be + referenced by other device nodes by adding a memory-region property to the + device node. + +compatible: "reserved-memory" + +include: + - name: base.yaml + property-allowlist: ['#address-cells', '#size-cells'] + +child-binding: + description: Regions + properties: + label: + type: string + required: false + description: Human readable string describing the device (used as device_get_binding() argument) + reg: + type: array + description: register space + required: true diff --git a/include/devicetree/memory.h b/include/devicetree/memory.h new file mode 100644 index 00000000000..a6c173e652e --- /dev/null +++ b/include/devicetree/memory.h @@ -0,0 +1,139 @@ +/** + * @file + * @brief reserved-memory Devicetree macro public API header file. + */ + +/* + * Copyright (c) 2021 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DEVICETREE_MEMORY_H_ +#define ZEPHYR_INCLUDE_DEVICETREE_MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup devicetree-reserved Devicetree reserved-memory API + * @ingroup devicetree + * @{ + */ + +/** + * @brief Get the pointer to the reserved-memory region + * + * Example devicetree fragment: + * + * reserved: reserved-memory { + * compatible = "reserved-memory"; + * ... + * n: node { + * reg = <0x42000000 0x1000>; + * }; + * }; + * + * Example usage: + * + * DT_RESERVED_MEM_GET_PTR(DT_NODELABEL(n)) // (uint8_t *) 0x42000000 + * + * @param node_id node identifier + * @return pointer to the beginning of the reserved-memory region + */ +#define DT_RESERVED_MEM_GET_PTR(node_id) _DT_RESERVED_START(node_id) + +/** + * @brief Get the size of the reserved-memory region + * + * Example devicetree fragment: + * + * reserved: reserved-memory { + * compatible = "reserved-memory"; + * ... + * n: node { + * reg = <0x42000000 0x1000>; + * }; + * }; + * + * Example usage: + * + * DT_RESERVED_MEM_GET_SIZE(DT_NODELABEL(n)) // 0x1000 + * + * @param node_id node identifier + * @return the size of the reserved-memory region + */ +#define DT_RESERVED_MEM_GET_SIZE(node_id) DT_REG_SIZE(node_id) + +/** + * @brief Get the pointer to the reserved-memory region from a memory-reserved + * phandle + * + * Example devicetree fragment: + * + * reserved: reserved-memory { + * compatible = "reserved-memory"; + * ... + * res0: res { + * reg = <0x42000000 0x1000>; + * label = "res0"; + * }; + * }; + * + * n: node { + * memory-region = <&res0>; + * }; + * + * Example usage: + * + * DT_RESERVED_MEM_GET_PTR_BY_PHANDLE(DT_NODELABEL(n), memory_region) // (uint8_t *) 0x42000000 + * + * @param node_id node identifier + * @param ph phandle to reserved-memory region + * + * @return pointer to the beginning of the reserved-memory region + */ +#define DT_RESERVED_MEM_GET_PTR_BY_PHANDLE(node_id, ph) \ + DT_RESERVED_MEM_GET_PTR(DT_PHANDLE(node_id, ph)) + +/** + * @brief Get the size of the reserved-memory region from a memory-reserved + * phandle + * + * Example devicetree fragment: + * + * reserved: reserved-memory { + * compatible = "reserved-memory"; + * ... + * res0: res { + * reg = <0x42000000 0x1000>; + * label = "res0"; + * }; + * }; + * + * n: node { + * memory-region = <&res0>; + * }; + * + * Example usage: + * + * DT_RESERVED_MEM_GET_SIZE_BY_PHANDLE(DT_NODELABEL(n), memory_region) // (uint8_t *) 0x42000000 + * + * @param node_id node identifier + * @param ph phandle to reserved-memory region + * + * @return size of the reserved-memory region + */ +#define DT_RESERVED_MEM_GET_SIZE_BY_PHANDLE(node_id, ph) \ + DT_RESERVED_MEM_GET_SIZE(DT_PHANDLE(node_id, ph)) + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DEVICETREE_MEMORY_H_ */ diff --git a/include/linker/devicetree_reserved.h b/include/linker/devicetree_reserved.h new file mode 100644 index 00000000000..92797602be2 --- /dev/null +++ b/include/linker/devicetree_reserved.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + * + * Generate memory regions and sections from reserved-memory nodes. + */ + +#include + +/* Reserved memory node */ +#define _NODE_RESERVED DT_INST(0, reserved_memory) + +/* Unquoted region label */ +#define _DT_LABEL_TOKEN(res) DT_STRING_TOKEN(res, label) + +/* _start and _end section symbols */ +#define _DT_RESERVED_PREFIX(res) UTIL_CAT(__, _DT_LABEL_TOKEN(res)) +#define _DT_RESERVED_START(res) UTIL_CAT(_DT_RESERVED_PREFIX(res), _start) +#define _DT_RESERVED_END(res) UTIL_CAT(_DT_RESERVED_PREFIX(res), _end) + +/* Declare a reserved memory region */ +#define _RESERVED_REGION_DECLARE(res) DT_STRING_TOKEN(res, label) (rw) : \ + ORIGIN = DT_REG_ADDR(res), \ + LENGTH = DT_REG_SIZE(res) + +/* Declare a reserved memory section */ +#define _RESERVED_SECTION_DECLARE(res) SECTION_DATA_PROLOGUE(_DT_LABEL_TOKEN(res), ,) \ + { \ + _DT_RESERVED_START(res) = .; \ + KEEP(*(._DT_LABEL_TOKEN(res))) \ + KEEP(*(._DT_LABEL_TOKEN(res).*)) \ + _DT_RESERVED_END(res) = \ + _DT_RESERVED_START(res) + DT_REG_SIZE(res); \ + } GROUP_LINK_IN(_DT_LABEL_TOKEN(res)) + +/* Declare reserved memory linker symbols */ +#define _RESERVED_SYMBOL_DECLARE(res) extern char _DT_RESERVED_START(res)[]; \ + extern char _DT_RESERVED_END(res)[]; + +/* Apply a macro to a reserved memory region */ +#define _RESERVED_REGION_APPLY(f) \ + COND_CODE_1(IS_ENABLED(UTIL_CAT(_NODE_RESERVED, _EXISTS)), \ + (DT_FOREACH_CHILD(_NODE_RESERVED, f)), ()) + +/** + * @brief Generate region definitions for all the reserved memory regions + */ +#define DT_RESERVED_MEM_REGIONS() _RESERVED_REGION_APPLY(_RESERVED_REGION_DECLARE) + +/** + * @brief Generate section definitions for all the reserved memory regions + */ +#define DT_RESERVED_MEM_SECTIONS() _RESERVED_REGION_APPLY(_RESERVED_SECTION_DECLARE) + +/** + * @brief Generate linker script symbols for all the reserved memory regions + */ +#define DT_RESERVED_MEM_SYMBOLS() _RESERVED_REGION_APPLY(_RESERVED_SYMBOL_DECLARE) diff --git a/include/linker/linker-defs.h b/include/linker/linker-defs.h index 3ae8f27c5df..4d2dee50d5f 100644 --- a/include/linker/linker-defs.h +++ b/include/linker/linker-defs.h @@ -33,6 +33,7 @@ #ifdef ZTEST_UNITTEST #define DT_NODE_HAS_STATUS(node, status) 0 #else +#include #include #endif @@ -213,6 +214,10 @@ extern char _image_rodata_size[]; extern char _vector_start[]; extern char _vector_end[]; +#if DT_NODE_HAS_STATUS(_NODE_RESERVED, okay) +DT_RESERVED_MEM_SYMBOLS() +#endif + #ifdef CONFIG_SW_VECTOR_RELAY extern char __vector_relay_table[]; #endif