blob: 1a726a8aaaba151b8a7b4ba682a2425fddd6ce86 [file] [log] [blame]
Soby Mathewb9fccca2017-11-06 13:56:40 +00001/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/* Helper functions to offer easier navigation of Device Tree Blob */
8
9#include <assert.h>
10#include <debug.h>
11#include <fdt_wrappers.h>
12#include <libfdt.h>
13
14/*
15 * Read cells from a given property of the given node. At most 2 cells of the
16 * property are read, and pointer is updated. Returns 0 on success, and -1 upon
17 * error
18 */
19int fdtw_read_cells(const void *dtb, int node, const char *prop,
20 unsigned int cells, void *value)
21{
22 const uint32_t *value_ptr;
23 uint32_t hi = 0, lo;
24 int value_len;
25
Soby Mathewcc364842018-02-21 01:16:39 +000026 assert(dtb != NULL);
27 assert(prop != NULL);
28 assert(value != NULL);
Soby Mathewb9fccca2017-11-06 13:56:40 +000029 assert(node >= 0);
30
31 /* We expect either 1 or 2 cell property */
Soby Mathewcc364842018-02-21 01:16:39 +000032 assert(cells <= 2U);
Soby Mathewb9fccca2017-11-06 13:56:40 +000033
34 /* Access property and obtain its length (in bytes) */
Soby Mathewcc364842018-02-21 01:16:39 +000035 value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
Soby Mathewb9fccca2017-11-06 13:56:40 +000036 &value_len);
37 if (value_ptr == NULL) {
38 WARN("Couldn't find property %s in dtb\n", prop);
39 return -1;
40 }
41
42
43 /* Verify that property length accords with cell length */
Soby Mathewcc364842018-02-21 01:16:39 +000044 if (NCELLS((unsigned int)value_len) != cells) {
Soby Mathewb9fccca2017-11-06 13:56:40 +000045 WARN("Property length mismatch\n");
46 return -1;
47 }
48
Soby Mathewcc364842018-02-21 01:16:39 +000049 if (cells == 2U) {
Soby Mathewb9fccca2017-11-06 13:56:40 +000050 hi = fdt32_to_cpu(*value_ptr);
51 value_ptr++;
52 }
53
54 lo = fdt32_to_cpu(*value_ptr);
55
Soby Mathewcc364842018-02-21 01:16:39 +000056 if (cells == 2U)
Soby Mathewb9fccca2017-11-06 13:56:40 +000057 *((uint64_t *) value) = ((uint64_t) hi << 32) | lo;
58 else
59 *((uint32_t *) value) = lo;
60
61 return 0;
62}
63
64/*
65 * Write cells in place to a given property of the given node. At most 2 cells
66 * of the property are written. Returns 0 on success, and -1 upon error.
67 */
68int fdtw_write_inplace_cells(void *dtb, int node, const char *prop,
69 unsigned int cells, void *value)
70{
71 int err, len;
72
Soby Mathewcc364842018-02-21 01:16:39 +000073 assert(dtb != NULL);
74 assert(prop != NULL);
75 assert(value != NULL);
Soby Mathewb9fccca2017-11-06 13:56:40 +000076 assert(node >= 0);
77
78 /* We expect either 1 or 2 cell property */
Soby Mathewcc364842018-02-21 01:16:39 +000079 assert(cells <= 2U);
Soby Mathewb9fccca2017-11-06 13:56:40 +000080
Soby Mathewcc364842018-02-21 01:16:39 +000081 if (cells == 2U)
Soby Mathewb9fccca2017-11-06 13:56:40 +000082 *(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value);
83 else
84 *(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value);
85
Soby Mathewcc364842018-02-21 01:16:39 +000086 len = (int)cells * 4;
Soby Mathewb9fccca2017-11-06 13:56:40 +000087
88 /* Set property value in place */
89 err = fdt_setprop_inplace(dtb, node, prop, value, len);
90 if (err != 0) {
91 WARN("Modify property %s failed with error %d\n", prop, err);
92 return -1;
93 }
94
95 return 0;
96}