xref: /rk3399_ARM-atf/common/fdt_wrappers.c (revision da5f274572c063962556821914e2f64db5ae3d2d)
1e5674e1fSSoby Mathew /*
2e5674e1fSSoby Mathew  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3e5674e1fSSoby Mathew  *
4e5674e1fSSoby Mathew  * SPDX-License-Identifier: BSD-3-Clause
5e5674e1fSSoby Mathew  */
6e5674e1fSSoby Mathew 
7e5674e1fSSoby Mathew /* Helper functions to offer easier navigation of Device Tree Blob */
8e5674e1fSSoby Mathew 
9e5674e1fSSoby Mathew #include <assert.h>
10e5674e1fSSoby Mathew #include <debug.h>
11e5674e1fSSoby Mathew #include <fdt_wrappers.h>
12e5674e1fSSoby Mathew #include <libfdt.h>
13e5674e1fSSoby Mathew 
14e5674e1fSSoby Mathew /*
15e5674e1fSSoby Mathew  * Read cells from a given property of the given node. At most 2 cells of the
16e5674e1fSSoby Mathew  * property are read, and pointer is updated. Returns 0 on success, and -1 upon
17e5674e1fSSoby Mathew  * error
18e5674e1fSSoby Mathew  */
19e5674e1fSSoby Mathew int fdtw_read_cells(const void *dtb, int node, const char *prop,
20e5674e1fSSoby Mathew 		unsigned int cells, void *value)
21e5674e1fSSoby Mathew {
22e5674e1fSSoby Mathew 	const uint32_t *value_ptr;
23e5674e1fSSoby Mathew 	uint32_t hi = 0, lo;
24e5674e1fSSoby Mathew 	int value_len;
25e5674e1fSSoby Mathew 
26*da5f2745SSoby Mathew 	assert(dtb != NULL);
27*da5f2745SSoby Mathew 	assert(prop != NULL);
28*da5f2745SSoby Mathew 	assert(value != NULL);
29e5674e1fSSoby Mathew 	assert(node >= 0);
30e5674e1fSSoby Mathew 
31e5674e1fSSoby Mathew 	/* We expect either 1 or 2 cell property */
32*da5f2745SSoby Mathew 	assert(cells <= 2U);
33e5674e1fSSoby Mathew 
34e5674e1fSSoby Mathew 	/* Access property and obtain its length (in bytes) */
35*da5f2745SSoby Mathew 	value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
36e5674e1fSSoby Mathew 			&value_len);
37e5674e1fSSoby Mathew 	if (value_ptr == NULL) {
38e5674e1fSSoby Mathew 		WARN("Couldn't find property %s in dtb\n", prop);
39e5674e1fSSoby Mathew 		return -1;
40e5674e1fSSoby Mathew 	}
41e5674e1fSSoby Mathew 
42e5674e1fSSoby Mathew 
43e5674e1fSSoby Mathew 	/* Verify that property length accords with cell length */
44*da5f2745SSoby Mathew 	if (NCELLS((unsigned int)value_len) != cells) {
45e5674e1fSSoby Mathew 		WARN("Property length mismatch\n");
46e5674e1fSSoby Mathew 		return -1;
47e5674e1fSSoby Mathew 	}
48e5674e1fSSoby Mathew 
49*da5f2745SSoby Mathew 	if (cells == 2U) {
50e5674e1fSSoby Mathew 		hi = fdt32_to_cpu(*value_ptr);
51e5674e1fSSoby Mathew 		value_ptr++;
52e5674e1fSSoby Mathew 	}
53e5674e1fSSoby Mathew 
54e5674e1fSSoby Mathew 	lo = fdt32_to_cpu(*value_ptr);
55e5674e1fSSoby Mathew 
56*da5f2745SSoby Mathew 	if (cells == 2U)
57e5674e1fSSoby Mathew 		*((uint64_t *) value) = ((uint64_t) hi << 32) | lo;
58e5674e1fSSoby Mathew 	else
59e5674e1fSSoby Mathew 		*((uint32_t *) value) = lo;
60e5674e1fSSoby Mathew 
61e5674e1fSSoby Mathew 	return 0;
62e5674e1fSSoby Mathew }
63e5674e1fSSoby Mathew 
64e5674e1fSSoby Mathew /*
65e5674e1fSSoby Mathew  * Write cells in place to a given property of the given node. At most 2 cells
66e5674e1fSSoby Mathew  * of the property are written. Returns 0 on success, and -1 upon error.
67e5674e1fSSoby Mathew  */
68e5674e1fSSoby Mathew int fdtw_write_inplace_cells(void *dtb, int node, const char *prop,
69e5674e1fSSoby Mathew 		unsigned int cells, void *value)
70e5674e1fSSoby Mathew {
71e5674e1fSSoby Mathew 	int err, len;
72e5674e1fSSoby Mathew 
73*da5f2745SSoby Mathew 	assert(dtb != NULL);
74*da5f2745SSoby Mathew 	assert(prop != NULL);
75*da5f2745SSoby Mathew 	assert(value != NULL);
76e5674e1fSSoby Mathew 	assert(node >= 0);
77e5674e1fSSoby Mathew 
78e5674e1fSSoby Mathew 	/* We expect either 1 or 2 cell property */
79*da5f2745SSoby Mathew 	assert(cells <= 2U);
80e5674e1fSSoby Mathew 
81*da5f2745SSoby Mathew 	if (cells == 2U)
82e5674e1fSSoby Mathew 		*(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value);
83e5674e1fSSoby Mathew 	else
84e5674e1fSSoby Mathew 		*(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value);
85e5674e1fSSoby Mathew 
86*da5f2745SSoby Mathew 	len = (int)cells * 4;
87e5674e1fSSoby Mathew 
88e5674e1fSSoby Mathew 	/* Set property value in place */
89e5674e1fSSoby Mathew 	err = fdt_setprop_inplace(dtb, node, prop, value, len);
90e5674e1fSSoby Mathew 	if (err != 0) {
91e5674e1fSSoby Mathew 		WARN("Modify property %s failed with error %d\n", prop, err);
92e5674e1fSSoby Mathew 		return -1;
93e5674e1fSSoby Mathew 	}
94e5674e1fSSoby Mathew 
95e5674e1fSSoby Mathew 	return 0;
96e5674e1fSSoby Mathew }
97