Skip to content

Commit

Permalink
devicetree: support of 64-bit addresses from devicetree
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
amr-sc authored and galak committed Jun 25, 2023
1 parent b416a90 commit b158c52
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 0 deletions.
15 changes: 15 additions & 0 deletions dts/bindings/test/vnd,reg-holder-64.yaml
Original file line number Diff line number Diff line change
@@ -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
69 changes: 69 additions & 0 deletions include/zephyr/devicetree.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@

#include <devicetree_generated.h>

#if !defined(_LINKER) && !defined(_ASMLANGUAGE)
#include <stdint.h>
#endif

#include <zephyr/sys/util.h>

/**
Expand Down Expand Up @@ -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
*
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 */
Expand Down
12 changes: 12 additions & 0 deletions tests/lib/devicetree/api/app.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -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";
};
};
};
32 changes: 32 additions & 0 deletions tests/lib/devicetree/api/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -546,13 +547,20 @@ 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, "");

/* DT_REG_ADDR_BY_NAME */
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, "");
Expand All @@ -576,18 +584,42 @@ 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, "");

/* DT_INST_REG_ADDR_BY_NAME */
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)
Expand Down

0 comments on commit b158c52

Please sign in to comment.