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