13f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski/* 23f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * Device tree based initialization code for reserved memory. 33f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * 43f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * Copyright (c) 2013, The Linux Foundation. All Rights Reserved. 53f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. 63f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * http://www.samsung.com 73f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * Author: Marek Szyprowski <m.szyprowski@samsung.com> 83f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * Author: Josh Cartwright <joshc@codeaurora.org> 93f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * 103f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * This program is free software; you can redistribute it and/or 113f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * modify it under the terms of the GNU General Public License as 123f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * published by the Free Software Foundation; either version 2 of the 133f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * License or (at your optional) any later version of the license. 143f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski */ 153f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 163f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#include <linux/err.h> 173f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#include <linux/of.h> 183f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#include <linux/of_fdt.h> 193f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#include <linux/of_platform.h> 203f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#include <linux/mm.h> 213f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#include <linux/sizes.h> 223f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#include <linux/of_reserved_mem.h> 233f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 243f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#define MAX_RESERVED_REGIONS 16 253f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowskistatic struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; 263f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowskistatic int reserved_mem_count; 273f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 283f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#if defined(CONFIG_HAVE_MEMBLOCK) 293f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#include <linux/memblock.h> 303f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowskiint __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, 313f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, 323f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski phys_addr_t *res_base) 333f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski{ 343f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski /* 353f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * We use __memblock_alloc_base() because memblock_alloc_base() 363f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * panic()s on allocation failure. 373f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski */ 383f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski phys_addr_t base = __memblock_alloc_base(size, align, end); 393f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (!base) 403f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return -ENOMEM; 413f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 423f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski /* 433f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * Check if the allocated region fits in to start..end window 443f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski */ 453f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (base < start) { 463f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski memblock_free(base, size); 473f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return -ENOMEM; 483f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 493f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 503f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski *res_base = base; 513f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (nomap) 523f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return memblock_remove(base, size); 533f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return 0; 543f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski} 553f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#else 563f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowskiint __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, 573f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, 583f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski phys_addr_t *res_base) 593f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski{ 603f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski pr_err("Reserved memory not supported, ignoring region 0x%llx%s\n", 613f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski size, nomap ? " (nomap)" : ""); 623f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return -ENOSYS; 633f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski} 643f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski#endif 653f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 663f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski/** 673f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * res_mem_save_node() - save fdt node for second pass initialization 683f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski */ 693f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowskivoid __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, 703f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski phys_addr_t base, phys_addr_t size) 713f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski{ 723f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; 733f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 743f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) { 753f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski pr_err("Reserved memory: not enough space all defined regions.\n"); 763f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return; 773f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 783f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 793f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski rmem->fdt_node = node; 803f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski rmem->name = uname; 813f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski rmem->base = base; 823f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski rmem->size = size; 833f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 843f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski reserved_mem_count++; 853f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return; 863f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski} 873f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 883f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski/** 893f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * res_mem_alloc_size() - allocate reserved memory described by 'size', 'align' 903f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * and 'alloc-ranges' properties 913f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski */ 923f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowskistatic int __init __reserved_mem_alloc_size(unsigned long node, 933f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) 943f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski{ 953f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); 963f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski phys_addr_t start = 0, end = 0; 973f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski phys_addr_t base = 0, align = 0, size; 989d0c4dfedd96ee54fc075b16d02f82499c8cc3a6Rob Herring int len; 999d0c4dfedd96ee54fc075b16d02f82499c8cc3a6Rob Herring const __be32 *prop; 1003f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski int nomap; 1013f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski int ret; 1023f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1033f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski prop = of_get_flat_dt_prop(node, "size", &len); 1043f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (!prop) 1053f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return -EINVAL; 1063f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1073f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (len != dt_root_size_cells * sizeof(__be32)) { 1083f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski pr_err("Reserved memory: invalid size property in '%s' node.\n", 1093f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski uname); 1103f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return -EINVAL; 1113f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 1123f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski size = dt_mem_next_cell(dt_root_size_cells, &prop); 1133f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1143f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; 1153f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1163f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski prop = of_get_flat_dt_prop(node, "alignment", &len); 1173f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (prop) { 1183f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (len != dt_root_addr_cells * sizeof(__be32)) { 1193f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski pr_err("Reserved memory: invalid alignment property in '%s' node.\n", 1203f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski uname); 1213f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return -EINVAL; 1223f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 1233f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski align = dt_mem_next_cell(dt_root_addr_cells, &prop); 1243f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 1253f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1263f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski prop = of_get_flat_dt_prop(node, "alloc-ranges", &len); 1273f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (prop) { 1283f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1293f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (len % t_len != 0) { 1303f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski pr_err("Reserved memory: invalid alloc-ranges property in '%s', skipping node.\n", 1313f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski uname); 1323f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return -EINVAL; 1333f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 1343f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1353f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski base = 0; 1363f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1373f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski while (len > 0) { 1383f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski start = dt_mem_next_cell(dt_root_addr_cells, &prop); 1393f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski end = start + dt_mem_next_cell(dt_root_size_cells, 1403f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski &prop); 1413f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1423f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski ret = early_init_dt_alloc_reserved_memory_arch(size, 1433f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski align, start, end, nomap, &base); 1443f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (ret == 0) { 1453f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", 1463f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski uname, &base, 1473f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski (unsigned long)size / SZ_1M); 1483f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski break; 1493f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 1503f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski len -= t_len; 1513f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 1523f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1533f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } else { 1543f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski ret = early_init_dt_alloc_reserved_memory_arch(size, align, 1553f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 0, 0, nomap, &base); 1563f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (ret == 0) 1573f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", 1583f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski uname, &base, (unsigned long)size / SZ_1M); 1593f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 1603f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1613f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (base == 0) { 1623f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski pr_info("Reserved memory: failed to allocate memory for node '%s'\n", 1633f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski uname); 1643f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return -ENOMEM; 1653f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 1663f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1673f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski *res_base = base; 1683f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski *res_size = size; 1693f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 1703f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski return 0; 1713f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski} 1723f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 173f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowskistatic const struct of_device_id __rmem_of_table_sentinel 174f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski __used __section(__reservedmem_of_table_end); 175f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski 176f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski/** 177f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski * res_mem_init_node() - call region specific reserved memory init code 178f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski */ 179f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowskistatic int __init __reserved_mem_init_node(struct reserved_mem *rmem) 180f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski{ 181f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski extern const struct of_device_id __reservedmem_of_table[]; 182f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski const struct of_device_id *i; 183f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski 184f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { 185f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski reservedmem_of_init_fn initfn = i->data; 186f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski const char *compat = i->compatible; 187f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski 188f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) 189f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski continue; 190f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski 1919dd3107576c4bbd40e1c2c8b24d560abf9a7b991Rob Herring if (initfn(rmem) == 0) { 192f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski pr_info("Reserved memory: initialized node %s, compatible id %s\n", 193f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski rmem->name, compat); 194f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski return 0; 195f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski } 196f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski } 197f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski return -ENOENT; 198f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski} 199f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski 2003f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski/** 2013f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski * fdt_init_reserved_mem - allocate and init all saved reserved memory regions 2023f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski */ 2033f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowskivoid __init fdt_init_reserved_mem(void) 2043f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski{ 2053f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski int i; 2063f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski for (i = 0; i < reserved_mem_count; i++) { 2073f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski struct reserved_mem *rmem = &reserved_mem[i]; 2083f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski unsigned long node = rmem->fdt_node; 2099dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski int len; 2109dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski const __be32 *prop; 2113f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski int err = 0; 2123f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski 2139dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski prop = of_get_flat_dt_prop(node, "phandle", &len); 2149dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski if (!prop) 2159dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski prop = of_get_flat_dt_prop(node, "linux,phandle", &len); 2169dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski if (prop) 2179dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski rmem->phandle = of_read_number(prop, len/4); 2189dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2193f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski if (rmem->size == 0) 2203f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski err = __reserved_mem_alloc_size(node, rmem->name, 2213f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski &rmem->base, &rmem->size); 222f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski if (err == 0) 223f618c4703a14672d27bc2ca5d132a844363d6f5fMarek Szyprowski __reserved_mem_init_node(rmem); 2243f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski } 2253f0c8206644836e4f10a6b9fc47cda6a9a372f9bMarek Szyprowski} 2269dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2279dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowskistatic inline struct reserved_mem *__find_rmem(struct device_node *node) 2289dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski{ 2299dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski unsigned int i; 2309dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2319dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski if (!node->phandle) 2329dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski return NULL; 2339dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2349dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski for (i = 0; i < reserved_mem_count; i++) 2359dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski if (reserved_mem[i].phandle == node->phandle) 2369dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski return &reserved_mem[i]; 2379dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski return NULL; 2389dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski} 2399dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2409dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski/** 2419dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski * of_reserved_mem_device_init() - assign reserved memory region to given device 2429dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski * 2439dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski * This function assign memory region pointed by "memory-region" device tree 2449dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski * property to the given device. 2459dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski */ 24647f29df7db78ee4fcdb104cf36918d987ddd0278Marek Szyprowskiint of_reserved_mem_device_init(struct device *dev) 2479dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski{ 2489dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski struct reserved_mem *rmem; 2499dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski struct device_node *np; 25047f29df7db78ee4fcdb104cf36918d987ddd0278Marek Szyprowski int ret; 2519dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2529dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski np = of_parse_phandle(dev->of_node, "memory-region", 0); 2539dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski if (!np) 25447f29df7db78ee4fcdb104cf36918d987ddd0278Marek Szyprowski return -ENODEV; 2559dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2569dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski rmem = __find_rmem(np); 2579dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski of_node_put(np); 2589dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2599dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski if (!rmem || !rmem->ops || !rmem->ops->device_init) 26047f29df7db78ee4fcdb104cf36918d987ddd0278Marek Szyprowski return -EINVAL; 26147f29df7db78ee4fcdb104cf36918d987ddd0278Marek Szyprowski 26247f29df7db78ee4fcdb104cf36918d987ddd0278Marek Szyprowski ret = rmem->ops->device_init(rmem, dev); 26347f29df7db78ee4fcdb104cf36918d987ddd0278Marek Szyprowski if (ret == 0) 26447f29df7db78ee4fcdb104cf36918d987ddd0278Marek Szyprowski dev_info(dev, "assigned reserved memory node %s\n", rmem->name); 2659dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 26647f29df7db78ee4fcdb104cf36918d987ddd0278Marek Szyprowski return ret; 2679dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski} 2689dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2699dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski/** 2709dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski * of_reserved_mem_device_release() - release reserved memory device structures 2719dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski * 2729dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski * This function releases structures allocated for memory region handling for 2739dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski * the given device. 2749dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski */ 2759dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowskivoid of_reserved_mem_device_release(struct device *dev) 2769dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski{ 2779dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski struct reserved_mem *rmem; 2789dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski struct device_node *np; 2799dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2809dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski np = of_parse_phandle(dev->of_node, "memory-region", 0); 2819dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski if (!np) 2829dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski return; 2839dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2849dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski rmem = __find_rmem(np); 2859dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski of_node_put(np); 2869dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2879dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski if (!rmem || !rmem->ops || !rmem->ops->device_release) 2889dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski return; 2899dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski 2909dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski rmem->ops->device_release(rmem, dev); 2919dcfee01930e6cc1e84d28c232664f0c19a1f86cMarek Szyprowski} 292