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 135e0a7341SSimon Glass int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry) 14b7e0d73bSSimon Glass { 15b7e0d73bSSimon Glass const char *prop; 16b7e0d73bSSimon Glass u32 reg[2]; 17b7e0d73bSSimon Glass 18b7e0d73bSSimon Glass if (ofnode_read_u32_array(node, "reg", reg, 2)) { 195e0a7341SSimon Glass debug("Node '%s' has bad/missing 'reg' property\n", 205e0a7341SSimon Glass ofnode_get_name(node)); 215e0a7341SSimon Glass return -log_ret(ENOENT); 22b7e0d73bSSimon Glass } 23b7e0d73bSSimon Glass entry->offset = reg[0]; 24b7e0d73bSSimon Glass entry->length = reg[1]; 25b7e0d73bSSimon Glass entry->used = ofnode_read_s32_default(node, "used", entry->length); 26b7e0d73bSSimon Glass prop = ofnode_read_string(node, "compress"); 27b7e0d73bSSimon Glass entry->compress_algo = prop && !strcmp(prop, "lzo") ? 28b7e0d73bSSimon Glass FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE; 29b7e0d73bSSimon Glass prop = ofnode_read_string(node, "hash"); 30b7e0d73bSSimon Glass if (prop) 31b7e0d73bSSimon Glass entry->hash_size = strlen(prop); 32b7e0d73bSSimon Glass entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE; 33b7e0d73bSSimon Glass entry->hash = (uint8_t *)prop; 34b7e0d73bSSimon Glass 35b7e0d73bSSimon Glass return 0; 36b7e0d73bSSimon Glass } 37*964cadc4SSimon Glass 38*964cadc4SSimon Glass int ofnode_decode_region(ofnode node, const char *prop_name, fdt_addr_t *basep, 39*964cadc4SSimon Glass fdt_size_t *sizep) 40*964cadc4SSimon Glass { 41*964cadc4SSimon Glass const fdt_addr_t *cell; 42*964cadc4SSimon Glass int len; 43*964cadc4SSimon Glass 44*964cadc4SSimon Glass debug("%s: %s: %s\n", __func__, ofnode_get_name(node), prop_name); 45*964cadc4SSimon Glass cell = ofnode_get_property(node, prop_name, &len); 46*964cadc4SSimon Glass if (!cell || (len < sizeof(fdt_addr_t) * 2)) { 47*964cadc4SSimon Glass debug("cell=%p, len=%d\n", cell, len); 48*964cadc4SSimon Glass return -1; 49*964cadc4SSimon Glass } 50*964cadc4SSimon Glass 51*964cadc4SSimon Glass *basep = fdt_addr_to_cpu(*cell); 52*964cadc4SSimon Glass *sizep = fdt_size_to_cpu(cell[1]); 53*964cadc4SSimon Glass debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep, 54*964cadc4SSimon Glass (ulong)*sizep); 55*964cadc4SSimon Glass 56*964cadc4SSimon Glass return 0; 57*964cadc4SSimon Glass } 58*964cadc4SSimon Glass 59*964cadc4SSimon Glass int ofnode_decode_memory_region(ofnode config_node, const char *mem_type, 60*964cadc4SSimon Glass const char *suffix, fdt_addr_t *basep, 61*964cadc4SSimon Glass fdt_size_t *sizep) 62*964cadc4SSimon Glass { 63*964cadc4SSimon Glass char prop_name[50]; 64*964cadc4SSimon Glass const char *mem; 65*964cadc4SSimon Glass fdt_size_t size, offset_size; 66*964cadc4SSimon Glass fdt_addr_t base, offset; 67*964cadc4SSimon Glass ofnode node; 68*964cadc4SSimon Glass 69*964cadc4SSimon Glass if (!ofnode_valid(config_node)) { 70*964cadc4SSimon Glass config_node = ofnode_path("/config"); 71*964cadc4SSimon Glass if (!ofnode_valid(config_node)) { 72*964cadc4SSimon Glass debug("%s: Cannot find /config node\n", __func__); 73*964cadc4SSimon Glass return -ENOENT; 74*964cadc4SSimon Glass } 75*964cadc4SSimon Glass } 76*964cadc4SSimon Glass if (!suffix) 77*964cadc4SSimon Glass suffix = ""; 78*964cadc4SSimon Glass 79*964cadc4SSimon Glass snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type, 80*964cadc4SSimon Glass suffix); 81*964cadc4SSimon Glass mem = ofnode_read_string(config_node, prop_name); 82*964cadc4SSimon Glass if (!mem) { 83*964cadc4SSimon Glass debug("%s: No memory type for '%s', using /memory\n", __func__, 84*964cadc4SSimon Glass prop_name); 85*964cadc4SSimon Glass mem = "/memory"; 86*964cadc4SSimon Glass } 87*964cadc4SSimon Glass 88*964cadc4SSimon Glass node = ofnode_path(mem); 89*964cadc4SSimon Glass if (!ofnode_valid(node)) { 90*964cadc4SSimon Glass debug("%s: Failed to find node '%s'\n", __func__, mem); 91*964cadc4SSimon Glass return -ENOENT; 92*964cadc4SSimon Glass } 93*964cadc4SSimon Glass 94*964cadc4SSimon Glass /* 95*964cadc4SSimon Glass * Not strictly correct - the memory may have multiple banks. We just 96*964cadc4SSimon Glass * use the first 97*964cadc4SSimon Glass */ 98*964cadc4SSimon Glass if (ofnode_decode_region(node, "reg", &base, &size)) { 99*964cadc4SSimon Glass debug("%s: Failed to decode memory region %s\n", __func__, 100*964cadc4SSimon Glass mem); 101*964cadc4SSimon Glass return -EINVAL; 102*964cadc4SSimon Glass } 103*964cadc4SSimon Glass 104*964cadc4SSimon Glass snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type, 105*964cadc4SSimon Glass suffix); 106*964cadc4SSimon Glass if (ofnode_decode_region(config_node, prop_name, &offset, 107*964cadc4SSimon Glass &offset_size)) { 108*964cadc4SSimon Glass debug("%s: Failed to decode memory region '%s'\n", __func__, 109*964cadc4SSimon Glass prop_name); 110*964cadc4SSimon Glass return -EINVAL; 111*964cadc4SSimon Glass } 112*964cadc4SSimon Glass 113*964cadc4SSimon Glass *basep = base + offset; 114*964cadc4SSimon Glass *sizep = offset_size; 115*964cadc4SSimon Glass 116*964cadc4SSimon Glass return 0; 117*964cadc4SSimon Glass } 118