forked from barebox/barebox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfdt.c
105 lines (85 loc) · 2.29 KB
/
fdt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// SPDX-License-Identifier: GPL-2.0
#include <linux/libfdt.h>
#include <pbl.h>
#include <linux/printk.h>
void fdt_find_mem(const void *fdt, unsigned long *membase, unsigned long *memsize)
{
const __be32 *nap, *nsp, *reg;
uint32_t na, ns;
uint64_t memsize64, membase64;
int node, size, i;
/* Make sure FDT blob is sane */
if (fdt_check_header(fdt) != 0) {
pr_err("Invalid device tree blob\n");
goto err;
}
/* Find the #address-cells and #size-cells properties */
node = fdt_path_offset(fdt, "/");
if (node < 0) {
pr_err("Cannot find root node\n");
goto err;
}
nap = fdt_getprop(fdt, node, "#address-cells", &size);
if (!nap || (size != 4)) {
pr_err("Cannot find #address-cells property");
goto err;
}
na = fdt32_to_cpu(*nap);
nsp = fdt_getprop(fdt, node, "#size-cells", &size);
if (!nsp || (size != 4)) {
pr_err("Cannot find #size-cells property");
goto err;
}
ns = fdt32_to_cpu(*nap);
/* Find the memory range */
node = fdt_node_offset_by_prop_value(fdt, -1, "device_type",
"memory", sizeof("memory"));
if (node < 0) {
pr_err("Cannot find memory node\n");
goto err;
}
reg = fdt_getprop(fdt, node, "reg", &size);
if (size < (na + ns) * sizeof(u32)) {
pr_err("cannot get memory range\n");
goto err;
}
membase64 = 0;
for (i = 0; i < na; i++)
membase64 = (membase64 << 32) | fdt32_to_cpu(*reg++);
/* get the memsize and truncate it to under 4G on 32 bit machines */
memsize64 = 0;
for (i = 0; i < ns; i++)
memsize64 = (memsize64 << 32) | fdt32_to_cpu(*reg++);
*membase = membase64;
*memsize = memsize64;
return;
err:
pr_err("No memory, cannot continue\n");
while (1);
}
const void *fdt_device_get_match_data(const void *fdt, const char *nodepath,
const struct fdt_device_id ids[])
{
int node, length;
const char *list, *end;
const struct fdt_device_id *id;
node = fdt_path_offset(fdt, nodepath);
if (node < 0)
return NULL;
list = fdt_getprop(fdt, node, "compatible", &length);
if (!list)
return NULL;
end = list + length;
while (list < end) {
length = strnlen(list, end - list) + 1;
/* Abort if the last string isn't properly NUL-terminated. */
if (list + length > end)
return NULL;
for (id = ids; id->compatible; id++) {
if (!strcasecmp(list, id->compatible))
return id->data;
}
list += length;
}
return NULL;
}