xref: /openbmc/u-boot/drivers/core/of_extra.c (revision cf033e04)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2b7e0d73bSSimon Glass /*
3b7e0d73bSSimon Glass  * Copyright (c) 2017 Google, Inc
4b7e0d73bSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
5b7e0d73bSSimon Glass  */
6b7e0d73bSSimon Glass 
7b7e0d73bSSimon Glass #include <common.h>
8b08c8c48SMasahiro Yamada #include <linux/libfdt.h>
9b7e0d73bSSimon Glass #include <dm/of_access.h>
10b7e0d73bSSimon Glass #include <dm/of_extra.h>
11b7e0d73bSSimon Glass #include <dm/ofnode.h>
12b7e0d73bSSimon Glass 
ofnode_read_fmap_entry(ofnode node,struct fmap_entry * entry)135e0a7341SSimon Glass int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry)
14b7e0d73bSSimon Glass {
15b7e0d73bSSimon Glass 	const char *prop;
16b7e0d73bSSimon Glass 
17*e6c5c94aSSimon Glass 	if (ofnode_read_u32(node, "image-pos", &entry->offset)) {
18*e6c5c94aSSimon Glass 		debug("Node '%s' has bad/missing 'image-pos' property\n",
195e0a7341SSimon Glass 		      ofnode_get_name(node));
20*e6c5c94aSSimon Glass 		return log_ret(-ENOENT);
21b7e0d73bSSimon Glass 	}
22*e6c5c94aSSimon Glass 	if (ofnode_read_u32(node, "size", &entry->length)) {
23*e6c5c94aSSimon Glass 		debug("Node '%s' has bad/missing 'size' property\n",
24*e6c5c94aSSimon Glass 		      ofnode_get_name(node));
25*e6c5c94aSSimon Glass 		return log_ret(-ENOENT);
26*e6c5c94aSSimon Glass 	}
27b7e0d73bSSimon Glass 	entry->used = ofnode_read_s32_default(node, "used", entry->length);
28b7e0d73bSSimon Glass 	prop = ofnode_read_string(node, "compress");
29*e6c5c94aSSimon Glass 	if (prop) {
30*e6c5c94aSSimon Glass 		if (!strcmp(prop, "lz4"))
31*e6c5c94aSSimon Glass 			entry->compress_algo = FMAP_COMPRESS_LZ4;
32*e6c5c94aSSimon Glass 		else
33*e6c5c94aSSimon Glass 			return log_msg_ret("Unknown compression algo",
34*e6c5c94aSSimon Glass 					   -EINVAL);
35*e6c5c94aSSimon Glass 	} else {
36*e6c5c94aSSimon Glass 		entry->compress_algo = FMAP_COMPRESS_NONE;
37*e6c5c94aSSimon Glass 	}
38*e6c5c94aSSimon Glass 	entry->unc_length = ofnode_read_s32_default(node, "uncomp-size",
39*e6c5c94aSSimon Glass 						    entry->length);
40b7e0d73bSSimon Glass 	prop = ofnode_read_string(node, "hash");
41b7e0d73bSSimon Glass 	if (prop)
42b7e0d73bSSimon Glass 		entry->hash_size = strlen(prop);
43b7e0d73bSSimon Glass 	entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE;
44b7e0d73bSSimon Glass 	entry->hash = (uint8_t *)prop;
45b7e0d73bSSimon Glass 
46b7e0d73bSSimon Glass 	return 0;
47b7e0d73bSSimon Glass }
48964cadc4SSimon Glass 
ofnode_decode_region(ofnode node,const char * prop_name,fdt_addr_t * basep,fdt_size_t * sizep)49964cadc4SSimon Glass int ofnode_decode_region(ofnode node, const char *prop_name, fdt_addr_t *basep,
50964cadc4SSimon Glass 			 fdt_size_t *sizep)
51964cadc4SSimon Glass {
52964cadc4SSimon Glass 	const fdt_addr_t *cell;
53964cadc4SSimon Glass 	int len;
54964cadc4SSimon Glass 
55964cadc4SSimon Glass 	debug("%s: %s: %s\n", __func__, ofnode_get_name(node), prop_name);
56964cadc4SSimon Glass 	cell = ofnode_get_property(node, prop_name, &len);
57964cadc4SSimon Glass 	if (!cell || (len < sizeof(fdt_addr_t) * 2)) {
58964cadc4SSimon Glass 		debug("cell=%p, len=%d\n", cell, len);
59964cadc4SSimon Glass 		return -1;
60964cadc4SSimon Glass 	}
61964cadc4SSimon Glass 
62964cadc4SSimon Glass 	*basep = fdt_addr_to_cpu(*cell);
63964cadc4SSimon Glass 	*sizep = fdt_size_to_cpu(cell[1]);
64964cadc4SSimon Glass 	debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep,
65964cadc4SSimon Glass 	      (ulong)*sizep);
66964cadc4SSimon Glass 
67964cadc4SSimon Glass 	return 0;
68964cadc4SSimon Glass }
69964cadc4SSimon Glass 
ofnode_decode_memory_region(ofnode config_node,const char * mem_type,const char * suffix,fdt_addr_t * basep,fdt_size_t * sizep)70964cadc4SSimon Glass int ofnode_decode_memory_region(ofnode config_node, const char *mem_type,
71964cadc4SSimon Glass 				const char *suffix, fdt_addr_t *basep,
72964cadc4SSimon Glass 				fdt_size_t *sizep)
73964cadc4SSimon Glass {
74964cadc4SSimon Glass 	char prop_name[50];
75964cadc4SSimon Glass 	const char *mem;
76964cadc4SSimon Glass 	fdt_size_t size, offset_size;
77964cadc4SSimon Glass 	fdt_addr_t base, offset;
78964cadc4SSimon Glass 	ofnode node;
79964cadc4SSimon Glass 
80964cadc4SSimon Glass 	if (!ofnode_valid(config_node)) {
81964cadc4SSimon Glass 		config_node = ofnode_path("/config");
82964cadc4SSimon Glass 		if (!ofnode_valid(config_node)) {
83964cadc4SSimon Glass 			debug("%s: Cannot find /config node\n", __func__);
84964cadc4SSimon Glass 			return -ENOENT;
85964cadc4SSimon Glass 		}
86964cadc4SSimon Glass 	}
87964cadc4SSimon Glass 	if (!suffix)
88964cadc4SSimon Glass 		suffix = "";
89964cadc4SSimon Glass 
90964cadc4SSimon Glass 	snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type,
91964cadc4SSimon Glass 		 suffix);
92964cadc4SSimon Glass 	mem = ofnode_read_string(config_node, prop_name);
93964cadc4SSimon Glass 	if (!mem) {
94964cadc4SSimon Glass 		debug("%s: No memory type for '%s', using /memory\n", __func__,
95964cadc4SSimon Glass 		      prop_name);
96964cadc4SSimon Glass 		mem = "/memory";
97964cadc4SSimon Glass 	}
98964cadc4SSimon Glass 
99964cadc4SSimon Glass 	node = ofnode_path(mem);
100964cadc4SSimon Glass 	if (!ofnode_valid(node)) {
101964cadc4SSimon Glass 		debug("%s: Failed to find node '%s'\n", __func__, mem);
102964cadc4SSimon Glass 		return -ENOENT;
103964cadc4SSimon Glass 	}
104964cadc4SSimon Glass 
105964cadc4SSimon Glass 	/*
106964cadc4SSimon Glass 	 * Not strictly correct - the memory may have multiple banks. We just
107964cadc4SSimon Glass 	 * use the first
108964cadc4SSimon Glass 	 */
109964cadc4SSimon Glass 	if (ofnode_decode_region(node, "reg", &base, &size)) {
110964cadc4SSimon Glass 		debug("%s: Failed to decode memory region %s\n", __func__,
111964cadc4SSimon Glass 		      mem);
112964cadc4SSimon Glass 		return -EINVAL;
113964cadc4SSimon Glass 	}
114964cadc4SSimon Glass 
115964cadc4SSimon Glass 	snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type,
116964cadc4SSimon Glass 		 suffix);
117964cadc4SSimon Glass 	if (ofnode_decode_region(config_node, prop_name, &offset,
118964cadc4SSimon Glass 				 &offset_size)) {
119964cadc4SSimon Glass 		debug("%s: Failed to decode memory region '%s'\n", __func__,
120964cadc4SSimon Glass 		      prop_name);
121964cadc4SSimon Glass 		return -EINVAL;
122964cadc4SSimon Glass 	}
123964cadc4SSimon Glass 
124964cadc4SSimon Glass 	*basep = base + offset;
125964cadc4SSimon Glass 	*sizep = offset_size;
126964cadc4SSimon Glass 
127964cadc4SSimon Glass 	return 0;
128964cadc4SSimon Glass }
129