devicetree: support of 64-bit addresses from devicetree

Usage of 64-bit address constants from devicetree without a
UINT64_C wrapping macro results in the following warning and the
cut-off of the address value:

"warning: integer constant is so large that it is unsigned"

This change extends devicetree API adding few wrappers over the
address constant getters which add ULL size suffix to an
address integer literal when the appearance of 64-bit address
values is possible

Signed-off-by: Alexander Razinkov <alexander.razinkov@syntacore.com>
This commit is contained in:
Alexander Razinkov 2023-05-22 18:52:52 +03:00 committed by Kumar Gala
commit b158c52e24
4 changed files with 128 additions and 0 deletions

View file

@ -0,0 +1,15 @@
# Copyright (c) 2023 Syntacore
# SPDX-License-Identifier: Apache-2.0
description: Test 64-bit register property container
compatible: "vnd,reg-holder-64"
include: [base.yaml]
properties:
reg:
required: true
reg-names:
required: true

View file

@ -18,6 +18,10 @@
#include <devicetree_generated.h>
#if !defined(_LINKER) && !defined(_ASMLANGUAGE)
#include <stdint.h>
#endif
#include <zephyr/sys/util.h>
/**
@ -2219,6 +2223,18 @@
*/
#define DT_REG_ADDR(node_id) DT_REG_ADDR_BY_IDX(node_id, 0)
/**
* @brief 64-bit version of DT_REG_ADDR()
*
* This macro version adds the appropriate suffix for 64-bit unsigned
* integer literals.
* Note that this macro is equivalent to DT_REG_ADDR() in linker/ASM context.
*
* @param node_id node identifier
* @return node's register block address
*/
#define DT_REG_ADDR_U64(node_id) DT_U64_C(DT_REG_ADDR(node_id))
/**
* @brief Get a node's (only) register block size
*
@ -2237,6 +2253,21 @@
#define DT_REG_ADDR_BY_NAME(node_id, name) \
DT_CAT4(node_id, _REG_NAME_, name, _VAL_ADDRESS)
/**
* @brief 64-bit version of DT_REG_ADDR_BY_NAME()
*
* This macro version adds the appropriate suffix for 64-bit unsigned
* integer literals.
* Note that this macro is equivalent to DT_REG_ADDR_BY_NAME() in
* linker/ASM context.
*
* @param node_id node identifier
* @param name lowercase-and-underscores register specifier name
* @return address of the register block specified by name
*/
#define DT_REG_ADDR_BY_NAME_U64(node_id, name) \
DT_U64_C(DT_REG_ADDR_BY_NAME(node_id, name))
/**
* @brief Get a register block's size by name
* @param node_id node identifier
@ -3681,6 +3712,21 @@
#define DT_INST_REG_ADDR_BY_NAME(inst, name) \
DT_REG_ADDR_BY_NAME(DT_DRV_INST(inst), name)
/**
* @brief 64-bit version of DT_INST_REG_ADDR_BY_NAME()
*
* This macro version adds the appropriate suffix for 64-bit unsigned
* integer literals.
* Note that this macro is equivalent to DT_INST_REG_ADDR_BY_NAME() in
* linker/ASM context.
*
* @param inst instance number
* @param name lowercase-and-underscores register specifier name
* @return address of the register block with the given @p name
*/
#define DT_INST_REG_ADDR_BY_NAME_U64(inst, name) \
DT_U64_C(DT_INST_REG_ADDR_BY_NAME(inst, name))
/**
* @brief Get a `DT_DRV_COMPAT`'s register block size by name
* @param inst instance number
@ -3697,6 +3743,19 @@
*/
#define DT_INST_REG_ADDR(inst) DT_INST_REG_ADDR_BY_IDX(inst, 0)
/**
* @brief 64-bit version of DT_INST_REG_ADDR()
*
* This macro version adds the appropriate suffix for 64-bit unsigned
* integer literals.
* Note that this macro is equivalent to DT_INST_REG_ADDR() in
* linker/ASM context.
*
* @param inst instance number
* @return instance's register block address
*/
#define DT_INST_REG_ADDR_U64(inst) DT_U64_C(DT_INST_REG_ADDR(inst))
/**
* @brief Get a `DT_DRV_COMPAT`'s (only) register block size
* @param inst instance number
@ -4172,6 +4231,16 @@
#define DT_INST_NODE_HAS_PROP_AND_OR(inst, prop) \
DT_INST_NODE_HAS_PROP(inst, prop) ||
/**
* @def DT_U64_C
* @brief Macro to add ULL postfix to the devicetree address constants
*/
#if defined(_LINKER) || defined(_ASMLANGUAGE)
#define DT_U64_C(_v) (_v)
#else
#define DT_U64_C(_v) UINT64_C(_v)
#endif
/** @endcond */
/* have these last so they have access to all previously defined macros */

View file

@ -621,4 +621,16 @@
val = "XA XPLUS XB", "XC XPLUS XD", "XA XMINUS XB", "XC XMINUS XD";
};
};
test_64 {
#address-cells = < 2 >;
#size-cells = < 0 >;
test_reg_64: reg-holder-64@ffffffff11223344 {
compatible = "vnd,reg-holder-64";
reg = < 0xffffffff 0x11223344>;
status = "okay";
reg-names = "test_name";
};
};
};

View file

@ -39,6 +39,7 @@
#define TEST_VENDOR DT_NODELABEL(test_vendor)
#define TEST_MODEL DT_NODELABEL(test_vendor)
#define TEST_ENUM_0 DT_NODELABEL(test_enum_0)
#define TEST_64BIT DT_NODELABEL(test_reg_64)
#define TEST_I2C DT_NODELABEL(test_i2c)
#define TEST_I2C_DEV DT_PATH(test, i2c_11112222, test_i2c_dev_10)
@ -546,6 +547,9 @@ ZTEST(devicetree_api, test_reg)
/* DT_REG_ADDR */
zassert_equal(DT_REG_ADDR(TEST_ABCD1234), 0xabcd1234, "");
/* DT_REG_ADDR_U64 */
zassert_equal(DT_REG_ADDR_U64(TEST_ABCD1234), 0xabcd1234, "");
/* DT_REG_SIZE */
zassert_equal(DT_REG_SIZE(TEST_ABCD1234), 0x500, "");
@ -553,6 +557,10 @@ ZTEST(devicetree_api, test_reg)
zassert_equal(DT_REG_ADDR_BY_NAME(TEST_ABCD1234, one), 0xabcd1234, "");
zassert_equal(DT_REG_ADDR_BY_NAME(TEST_ABCD1234, two), 0x98765432, "");
/* DT_REG_ADDR_BY_NAME_U64 */
zassert_equal(DT_REG_ADDR_BY_NAME_U64(TEST_ABCD1234, one), 0xabcd1234, "");
zassert_equal(DT_REG_ADDR_BY_NAME_U64(TEST_ABCD1234, two), 0x98765432, "");
/* DT_REG_SIZE_BY_NAME */
zassert_equal(DT_REG_SIZE_BY_NAME(TEST_ABCD1234, one), 0x500, "");
zassert_equal(DT_REG_SIZE_BY_NAME(TEST_ABCD1234, two), 0xff, "");
@ -576,6 +584,9 @@ ZTEST(devicetree_api, test_reg)
/* DT_INST_REG_ADDR */
zassert_equal(DT_INST_REG_ADDR(0), 0x9999aaaa, "");
/* DT_INST_REG_ADDR_U64 */
zassert_equal(DT_INST_REG_ADDR_U64(0), 0x9999aaaa, "");
/* DT_INST_REG_SIZE */
zassert_equal(DT_INST_REG_SIZE(0), 0x1000, "");
@ -583,11 +594,32 @@ ZTEST(devicetree_api, test_reg)
zassert_equal(DT_INST_REG_ADDR_BY_NAME(0, first), 0x9999aaaa, "");
zassert_equal(DT_INST_REG_ADDR_BY_NAME(0, second), 0xbbbbcccc, "");
/* DT_INST_REG_ADDR_BY_NAME_U64 */
zassert_equal(DT_INST_REG_ADDR_BY_NAME_U64(0, first), 0x9999aaaa, "");
zassert_equal(DT_INST_REG_ADDR_BY_NAME_U64(0, second), 0xbbbbcccc, "");
/* DT_INST_REG_SIZE_BY_NAME */
zassert_equal(DT_INST_REG_SIZE_BY_NAME(0, first), 0x1000, "");
zassert_equal(DT_INST_REG_SIZE_BY_NAME(0, second), 0x3f, "");
}
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT vnd_reg_holder_64
ZTEST(devicetree_api, test_reg_64)
{
/* DT_REG_ADDR_U64 */
zassert_equal(DT_REG_ADDR_U64(TEST_64BIT), 0xffffffff11223344, "");
/* DT_REG_ADDR_BY_NAME_U64 */
zassert_equal(DT_REG_ADDR_BY_NAME_U64(TEST_64BIT, test_name), 0xffffffff11223344, "");
/* DT_INST_REG_ADDR_U64 */
zassert_equal(DT_INST_REG_ADDR_U64(0), 0xffffffff11223344, "");
/* DT_INST_REG_ADDR_BY_NAME_U64 */
zassert_equal(DT_INST_REG_ADDR_BY_NAME_U64(0, test_name), 0xffffffff11223344, "");
}
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT vnd_interrupt_holder
ZTEST(devicetree_api, test_irq)