Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'devicetree/next-reserved-mem' into devicetree/next

+577
+133
Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
··· 1 + *** Reserved memory regions *** 2 + 3 + Reserved memory is specified as a node under the /reserved-memory node. 4 + The operating system shall exclude reserved memory from normal usage 5 + one can create child nodes describing particular reserved (excluded from 6 + normal use) memory regions. Such memory regions are usually designed for 7 + the special usage by various device drivers. 8 + 9 + Parameters for each memory region can be encoded into the device tree 10 + with the following nodes: 11 + 12 + /reserved-memory node 13 + --------------------- 14 + #address-cells, #size-cells (required) - standard definition 15 + - Should use the same values as the root node 16 + ranges (required) - standard definition 17 + - Should be empty 18 + 19 + /reserved-memory/ child nodes 20 + ----------------------------- 21 + Each child of the reserved-memory node specifies one or more regions of 22 + reserved memory. Each child node may either use a 'reg' property to 23 + specify a specific range of reserved memory, or a 'size' property with 24 + optional constraints to request a dynamically allocated block of memory. 25 + 26 + Following the generic-names recommended practice, node names should 27 + reflect the purpose of the node (ie. "framebuffer" or "dma-pool"). Unit 28 + address (@<address>) should be appended to the name if the node is a 29 + static allocation. 30 + 31 + Properties: 32 + Requires either a) or b) below. 33 + a) static allocation 34 + reg (required) - standard definition 35 + b) dynamic allocation 36 + size (required) - length based on parent's #size-cells 37 + - Size in bytes of memory to reserve. 38 + alignment (optional) - length based on parent's #size-cells 39 + - Address boundary for alignment of allocation. 40 + alloc-ranges (optional) - prop-encoded-array (address, length pairs). 41 + - Specifies regions of memory that are 42 + acceptable to allocate from. 43 + 44 + If both reg and size are present, then the reg property takes precedence 45 + and size is ignored. 46 + 47 + Additional properties: 48 + compatible (optional) - standard definition 49 + - may contain the following strings: 50 + - shared-dma-pool: This indicates a region of memory meant to be 51 + used as a shared pool of DMA buffers for a set of devices. It can 52 + be used by an operating system to instanciate the necessary pool 53 + management subsystem if necessary. 54 + - vendor specific string in the form <vendor>,[<device>-]<usage> 55 + no-map (optional) - empty property 56 + - Indicates the operating system must not create a virtual mapping 57 + of the region as part of its standard mapping of system memory, 58 + nor permit speculative access to it under any circumstances other 59 + than under the control of the device driver using the region. 60 + reusable (optional) - empty property 61 + - The operating system can use the memory in this region with the 62 + limitation that the device driver(s) owning the region need to be 63 + able to reclaim it back. Typically that means that the operating 64 + system can use that region to store volatile or cached data that 65 + can be otherwise regenerated or migrated elsewhere. 66 + 67 + Linux implementation note: 68 + - If a "linux,cma-default" property is present, then Linux will use the 69 + region for the default pool of the contiguous memory allocator. 70 + 71 + Device node references to reserved memory 72 + ----------------------------------------- 73 + Regions in the /reserved-memory node may be referenced by other device 74 + nodes by adding a memory-region property to the device node. 75 + 76 + memory-region (optional) - phandle, specifier pairs to children of /reserved-memory 77 + 78 + Example 79 + ------- 80 + This example defines 3 contiguous regions are defined for Linux kernel: 81 + one default of all device drivers (named linux,cma@72000000 and 64MiB in size), 82 + one dedicated to the framebuffer device (named framebuffer@78000000, 8MiB), and 83 + one for multimedia processing (named multimedia-memory@77000000, 64MiB). 84 + 85 + / { 86 + #address-cells = <1>; 87 + #size-cells = <1>; 88 + 89 + memory { 90 + reg = <0x40000000 0x40000000>; 91 + }; 92 + 93 + reserved-memory { 94 + #address-cells = <1>; 95 + #size-cells = <1>; 96 + ranges; 97 + 98 + /* global autoconfigured region for contiguous allocations */ 99 + linux,cma { 100 + compatible = "shared-dma-pool"; 101 + reusable; 102 + size = <0x4000000>; 103 + alignment = <0x2000>; 104 + linux,cma-default; 105 + }; 106 + 107 + display_reserved: framebuffer@78000000 { 108 + reg = <0x78000000 0x800000>; 109 + }; 110 + 111 + multimedia_reserved: multimedia@77000000 { 112 + compatible = "acme,multimedia-memory"; 113 + reg = <0x77000000 0x4000000>; 114 + }; 115 + }; 116 + 117 + /* ... */ 118 + 119 + fb0: video@12300000 { 120 + memory-region = <&display_reserved>; 121 + /* ... */ 122 + }; 123 + 124 + scaler: scaler@12500000 { 125 + memory-region = <&multimedia_reserved>; 126 + /* ... */ 127 + }; 128 + 129 + codec: codec@12600000 { 130 + memory-region = <&multimedia_reserved>; 131 + /* ... */ 132 + }; 133 + };
+1
arch/arm/Kconfig
··· 1918 1918 select IRQ_DOMAIN 1919 1919 select OF 1920 1920 select OF_EARLY_FLATTREE 1921 + select OF_RESERVED_MEM 1921 1922 help 1922 1923 Include support for flattened device tree machine descriptions. 1923 1924
+2
arch/arm/mm/init.c
··· 323 323 if (mdesc->reserve) 324 324 mdesc->reserve(); 325 325 326 + early_init_fdt_scan_reserved_mem(); 327 + 326 328 /* 327 329 * reserve memory for DMA contigouos allocations, 328 330 * must come from DMA area inside low memory
+1
arch/arm64/Kconfig
··· 43 43 select NO_BOOTMEM 44 44 select OF 45 45 select OF_EARLY_FLATTREE 46 + select OF_RESERVED_MEM 46 47 select PERF_USE_VMALLOC 47 48 select POWER_RESET 48 49 select POWER_SUPPLY
+1
arch/arm64/mm/init.c
··· 160 160 memblock_reserve(base, size); 161 161 } 162 162 163 + early_init_fdt_scan_reserved_mem(); 163 164 dma_contiguous_reserve(0); 164 165 165 166 memblock_allow_resize();
+1
arch/powerpc/Kconfig
··· 90 90 select BINFMT_ELF 91 91 select OF 92 92 select OF_EARLY_FLATTREE 93 + select OF_RESERVED_MEM 93 94 select HAVE_FTRACE_MCOUNT_RECORD 94 95 select HAVE_DYNAMIC_FTRACE 95 96 select HAVE_FUNCTION_TRACER
+3
arch/powerpc/kernel/prom.c
··· 33 33 #include <linux/irq.h> 34 34 #include <linux/memblock.h> 35 35 #include <linux/of.h> 36 + #include <linux/of_fdt.h> 36 37 37 38 #include <asm/prom.h> 38 39 #include <asm/rtas.h> ··· 589 588 memblock_reserve(base, size); 590 589 } 591 590 } 591 + 592 + early_init_fdt_scan_reserved_mem(); 592 593 } 593 594 594 595 static void __init early_reserve_mem(void)
+6
drivers/of/Kconfig
··· 71 71 depends on MTD 72 72 def_bool y 73 73 74 + config OF_RESERVED_MEM 75 + depends on OF_EARLY_FLATTREE 76 + bool 77 + help 78 + Helpers to allow for reservation of memory regions 79 + 74 80 endmenu # OF
+1
drivers/of/Makefile
··· 9 9 obj-$(CONFIG_OF_PCI) += of_pci.o 10 10 obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o 11 11 obj-$(CONFIG_OF_MTD) += of_mtd.o 12 + obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
+143
drivers/of/fdt.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/of.h> 17 17 #include <linux/of_fdt.h> 18 + #include <linux/of_reserved_mem.h> 19 + #include <linux/sizes.h> 18 20 #include <linux/string.h> 19 21 #include <linux/errno.h> 20 22 #include <linux/slab.h> ··· 442 440 #ifdef CONFIG_OF_EARLY_FLATTREE 443 441 444 442 /** 443 + * res_mem_reserve_reg() - reserve all memory described in 'reg' property 444 + */ 445 + static int __init __reserved_mem_reserve_reg(unsigned long node, 446 + const char *uname) 447 + { 448 + int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); 449 + phys_addr_t base, size; 450 + unsigned long len; 451 + __be32 *prop; 452 + int nomap, first = 1; 453 + 454 + prop = of_get_flat_dt_prop(node, "reg", &len); 455 + if (!prop) 456 + return -ENOENT; 457 + 458 + if (len && len % t_len != 0) { 459 + pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n", 460 + uname); 461 + return -EINVAL; 462 + } 463 + 464 + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; 465 + 466 + while (len >= t_len) { 467 + base = dt_mem_next_cell(dt_root_addr_cells, &prop); 468 + size = dt_mem_next_cell(dt_root_size_cells, &prop); 469 + 470 + if (base && size && 471 + early_init_dt_reserve_memory_arch(base, size, nomap) == 0) 472 + pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", 473 + uname, &base, (unsigned long)size / SZ_1M); 474 + else 475 + pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n", 476 + uname, &base, (unsigned long)size / SZ_1M); 477 + 478 + len -= t_len; 479 + if (first) { 480 + fdt_reserved_mem_save_node(node, uname, base, size); 481 + first = 0; 482 + } 483 + } 484 + return 0; 485 + } 486 + 487 + /** 488 + * __reserved_mem_check_root() - check if #size-cells, #address-cells provided 489 + * in /reserved-memory matches the values supported by the current implementation, 490 + * also check if ranges property has been provided 491 + */ 492 + static int __reserved_mem_check_root(unsigned long node) 493 + { 494 + __be32 *prop; 495 + 496 + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); 497 + if (!prop || be32_to_cpup(prop) != dt_root_size_cells) 498 + return -EINVAL; 499 + 500 + prop = of_get_flat_dt_prop(node, "#address-cells", NULL); 501 + if (!prop || be32_to_cpup(prop) != dt_root_addr_cells) 502 + return -EINVAL; 503 + 504 + prop = of_get_flat_dt_prop(node, "ranges", NULL); 505 + if (!prop) 506 + return -EINVAL; 507 + return 0; 508 + } 509 + 510 + /** 511 + * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory 512 + */ 513 + static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, 514 + int depth, void *data) 515 + { 516 + static int found; 517 + const char *status; 518 + int err; 519 + 520 + if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { 521 + if (__reserved_mem_check_root(node) != 0) { 522 + pr_err("Reserved memory: unsupported node format, ignoring\n"); 523 + /* break scan */ 524 + return 1; 525 + } 526 + found = 1; 527 + /* scan next node */ 528 + return 0; 529 + } else if (!found) { 530 + /* scan next node */ 531 + return 0; 532 + } else if (found && depth < 2) { 533 + /* scanning of /reserved-memory has been finished */ 534 + return 1; 535 + } 536 + 537 + status = of_get_flat_dt_prop(node, "status", NULL); 538 + if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) 539 + return 0; 540 + 541 + err = __reserved_mem_reserve_reg(node, uname); 542 + if (err == -ENOENT && of_get_flat_dt_prop(node, "size", NULL)) 543 + fdt_reserved_mem_save_node(node, uname, 0, 0); 544 + 545 + /* scan next node */ 546 + return 0; 547 + } 548 + 549 + /** 550 + * early_init_fdt_scan_reserved_mem() - create reserved memory regions 551 + * 552 + * This function grabs memory from early allocator for device exclusive use 553 + * defined in device tree structures. It should be called by arch specific code 554 + * once the early allocator (i.e. memblock) has been fully activated. 555 + */ 556 + void __init early_init_fdt_scan_reserved_mem(void) 557 + { 558 + if (!initial_boot_params) 559 + return; 560 + 561 + of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); 562 + fdt_init_reserved_mem(); 563 + } 564 + 565 + /** 445 566 * of_scan_flat_dt - scan flattened tree blob and call callback on each. 446 567 * @it: callback function 447 568 * @data: context data pointer ··· 981 856 memblock_add(base, size); 982 857 } 983 858 859 + int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, 860 + phys_addr_t size, bool nomap) 861 + { 862 + if (memblock_is_region_reserved(base, size)) 863 + return -EBUSY; 864 + if (nomap) 865 + return memblock_remove(base, size); 866 + return memblock_reserve(base, size); 867 + } 868 + 984 869 /* 985 870 * called from unflatten_device_tree() to bootstrap devicetree itself 986 871 * Architectures can override this definition if memblock isn't used ··· 998 863 void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align) 999 864 { 1000 865 return __va(memblock_alloc(size, align)); 866 + } 867 + #else 868 + int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, 869 + phys_addr_t size, bool nomap) 870 + { 871 + pr_err("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n", 872 + base, size, nomap ? " (nomap)" : ""); 873 + return -ENOSYS; 1001 874 } 1002 875 #endif 1003 876
+217
drivers/of/of_reserved_mem.c
··· 1 + /* 2 + * Device tree based initialization code for reserved memory. 3 + * 4 + * Copyright (c) 2013, The Linux Foundation. All Rights Reserved. 5 + * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. 6 + * http://www.samsung.com 7 + * Author: Marek Szyprowski <m.szyprowski@samsung.com> 8 + * Author: Josh Cartwright <joshc@codeaurora.org> 9 + * 10 + * This program is free software; you can redistribute it and/or 11 + * modify it under the terms of the GNU General Public License as 12 + * published by the Free Software Foundation; either version 2 of the 13 + * License or (at your optional) any later version of the license. 14 + */ 15 + 16 + #include <linux/err.h> 17 + #include <linux/of.h> 18 + #include <linux/of_fdt.h> 19 + #include <linux/of_platform.h> 20 + #include <linux/mm.h> 21 + #include <linux/sizes.h> 22 + #include <linux/of_reserved_mem.h> 23 + 24 + #define MAX_RESERVED_REGIONS 16 25 + static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; 26 + static int reserved_mem_count; 27 + 28 + #if defined(CONFIG_HAVE_MEMBLOCK) 29 + #include <linux/memblock.h> 30 + int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, 31 + phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, 32 + phys_addr_t *res_base) 33 + { 34 + /* 35 + * We use __memblock_alloc_base() because memblock_alloc_base() 36 + * panic()s on allocation failure. 37 + */ 38 + phys_addr_t base = __memblock_alloc_base(size, align, end); 39 + if (!base) 40 + return -ENOMEM; 41 + 42 + /* 43 + * Check if the allocated region fits in to start..end window 44 + */ 45 + if (base < start) { 46 + memblock_free(base, size); 47 + return -ENOMEM; 48 + } 49 + 50 + *res_base = base; 51 + if (nomap) 52 + return memblock_remove(base, size); 53 + return 0; 54 + } 55 + #else 56 + int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, 57 + phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, 58 + phys_addr_t *res_base) 59 + { 60 + pr_err("Reserved memory not supported, ignoring region 0x%llx%s\n", 61 + size, nomap ? " (nomap)" : ""); 62 + return -ENOSYS; 63 + } 64 + #endif 65 + 66 + /** 67 + * res_mem_save_node() - save fdt node for second pass initialization 68 + */ 69 + void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, 70 + phys_addr_t base, phys_addr_t size) 71 + { 72 + struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; 73 + 74 + if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) { 75 + pr_err("Reserved memory: not enough space all defined regions.\n"); 76 + return; 77 + } 78 + 79 + rmem->fdt_node = node; 80 + rmem->name = uname; 81 + rmem->base = base; 82 + rmem->size = size; 83 + 84 + reserved_mem_count++; 85 + return; 86 + } 87 + 88 + /** 89 + * res_mem_alloc_size() - allocate reserved memory described by 'size', 'align' 90 + * and 'alloc-ranges' properties 91 + */ 92 + static int __init __reserved_mem_alloc_size(unsigned long node, 93 + const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) 94 + { 95 + int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); 96 + phys_addr_t start = 0, end = 0; 97 + phys_addr_t base = 0, align = 0, size; 98 + unsigned long len; 99 + __be32 *prop; 100 + int nomap; 101 + int ret; 102 + 103 + prop = of_get_flat_dt_prop(node, "size", &len); 104 + if (!prop) 105 + return -EINVAL; 106 + 107 + if (len != dt_root_size_cells * sizeof(__be32)) { 108 + pr_err("Reserved memory: invalid size property in '%s' node.\n", 109 + uname); 110 + return -EINVAL; 111 + } 112 + size = dt_mem_next_cell(dt_root_size_cells, &prop); 113 + 114 + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; 115 + 116 + prop = of_get_flat_dt_prop(node, "alignment", &len); 117 + if (prop) { 118 + if (len != dt_root_addr_cells * sizeof(__be32)) { 119 + pr_err("Reserved memory: invalid alignment property in '%s' node.\n", 120 + uname); 121 + return -EINVAL; 122 + } 123 + align = dt_mem_next_cell(dt_root_addr_cells, &prop); 124 + } 125 + 126 + prop = of_get_flat_dt_prop(node, "alloc-ranges", &len); 127 + if (prop) { 128 + 129 + if (len % t_len != 0) { 130 + pr_err("Reserved memory: invalid alloc-ranges property in '%s', skipping node.\n", 131 + uname); 132 + return -EINVAL; 133 + } 134 + 135 + base = 0; 136 + 137 + while (len > 0) { 138 + start = dt_mem_next_cell(dt_root_addr_cells, &prop); 139 + end = start + dt_mem_next_cell(dt_root_size_cells, 140 + &prop); 141 + 142 + ret = early_init_dt_alloc_reserved_memory_arch(size, 143 + align, start, end, nomap, &base); 144 + if (ret == 0) { 145 + pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", 146 + uname, &base, 147 + (unsigned long)size / SZ_1M); 148 + break; 149 + } 150 + len -= t_len; 151 + } 152 + 153 + } else { 154 + ret = early_init_dt_alloc_reserved_memory_arch(size, align, 155 + 0, 0, nomap, &base); 156 + if (ret == 0) 157 + pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", 158 + uname, &base, (unsigned long)size / SZ_1M); 159 + } 160 + 161 + if (base == 0) { 162 + pr_info("Reserved memory: failed to allocate memory for node '%s'\n", 163 + uname); 164 + return -ENOMEM; 165 + } 166 + 167 + *res_base = base; 168 + *res_size = size; 169 + 170 + return 0; 171 + } 172 + 173 + static const struct of_device_id __rmem_of_table_sentinel 174 + __used __section(__reservedmem_of_table_end); 175 + 176 + /** 177 + * res_mem_init_node() - call region specific reserved memory init code 178 + */ 179 + static int __init __reserved_mem_init_node(struct reserved_mem *rmem) 180 + { 181 + extern const struct of_device_id __reservedmem_of_table[]; 182 + const struct of_device_id *i; 183 + 184 + for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { 185 + reservedmem_of_init_fn initfn = i->data; 186 + const char *compat = i->compatible; 187 + 188 + if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) 189 + continue; 190 + 191 + if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) { 192 + pr_info("Reserved memory: initialized node %s, compatible id %s\n", 193 + rmem->name, compat); 194 + return 0; 195 + } 196 + } 197 + return -ENOENT; 198 + } 199 + 200 + /** 201 + * fdt_init_reserved_mem - allocate and init all saved reserved memory regions 202 + */ 203 + void __init fdt_init_reserved_mem(void) 204 + { 205 + int i; 206 + for (i = 0; i < reserved_mem_count; i++) { 207 + struct reserved_mem *rmem = &reserved_mem[i]; 208 + unsigned long node = rmem->fdt_node; 209 + int err = 0; 210 + 211 + if (rmem->size == 0) 212 + err = __reserved_mem_alloc_size(node, rmem->name, 213 + &rmem->base, &rmem->size); 214 + if (err == 0) 215 + __reserved_mem_init_node(rmem); 216 + } 217 + }
+11
include/asm-generic/vmlinux.lds.h
··· 167 167 #define CLK_OF_TABLES() 168 168 #endif 169 169 170 + #ifdef CONFIG_OF_RESERVED_MEM 171 + #define RESERVEDMEM_OF_TABLES() \ 172 + . = ALIGN(8); \ 173 + VMLINUX_SYMBOL(__reservedmem_of_table) = .; \ 174 + *(__reservedmem_of_table) \ 175 + *(__reservedmem_of_table_end) 176 + #else 177 + #define RESERVEDMEM_OF_TABLES() 178 + #endif 179 + 170 180 #define KERNEL_DTB() \ 171 181 STRUCT_ALIGN(); \ 172 182 VMLINUX_SYMBOL(__dtb_start) = .; \ ··· 500 490 TRACE_SYSCALLS() \ 501 491 MEM_DISCARD(init.rodata) \ 502 492 CLK_OF_TABLES() \ 493 + RESERVEDMEM_OF_TABLES() \ 503 494 CLKSRC_OF_TABLES() \ 504 495 KERNEL_DTB() \ 505 496 IRQCHIP_OF_MATCH_TABLE()
+4
include/linux/of_fdt.h
··· 98 98 int depth, void *data); 99 99 extern int early_init_dt_scan_memory(unsigned long node, const char *uname, 100 100 int depth, void *data); 101 + extern void early_init_fdt_scan_reserved_mem(void); 101 102 extern void early_init_dt_add_memory_arch(u64 base, u64 size); 103 + extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, 104 + bool no_map); 102 105 extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); 103 106 extern u64 dt_mem_next_cell(int s, __be32 **cellp); 104 107 ··· 121 118 extern void early_init_devtree(void *); 122 119 extern void early_get_first_memblock_info(void *, phys_addr_t *); 123 120 #else /* CONFIG_OF_FLATTREE */ 121 + static inline void early_init_fdt_scan_reserved_mem(void) {} 124 122 static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } 125 123 static inline void unflatten_device_tree(void) {} 126 124 static inline void unflatten_and_copy_device_tree(void) {}
+53
include/linux/of_reserved_mem.h
··· 1 + #ifndef __OF_RESERVED_MEM_H 2 + #define __OF_RESERVED_MEM_H 3 + 4 + struct device; 5 + struct of_phandle_args; 6 + struct reserved_mem_ops; 7 + 8 + struct reserved_mem { 9 + const char *name; 10 + unsigned long fdt_node; 11 + const struct reserved_mem_ops *ops; 12 + phys_addr_t base; 13 + phys_addr_t size; 14 + void *priv; 15 + }; 16 + 17 + struct reserved_mem_ops { 18 + void (*device_init)(struct reserved_mem *rmem, 19 + struct device *dev); 20 + void (*device_release)(struct reserved_mem *rmem, 21 + struct device *dev); 22 + }; 23 + 24 + typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem, 25 + unsigned long node, const char *uname); 26 + 27 + #ifdef CONFIG_OF_RESERVED_MEM 28 + void fdt_init_reserved_mem(void); 29 + void fdt_reserved_mem_save_node(unsigned long node, const char *uname, 30 + phys_addr_t base, phys_addr_t size); 31 + 32 + #define RESERVEDMEM_OF_DECLARE(name, compat, init) \ 33 + static const struct of_device_id __reservedmem_of_table_##name \ 34 + __used __section(__reservedmem_of_table) \ 35 + = { .compatible = compat, \ 36 + .data = (init == (reservedmem_of_init_fn)NULL) ? \ 37 + init : init } 38 + 39 + #else 40 + static inline void fdt_init_reserved_mem(void) { } 41 + static inline void fdt_reserved_mem_save_node(unsigned long node, 42 + const char *uname, phys_addr_t base, phys_addr_t size) { } 43 + 44 + #define RESERVEDMEM_OF_DECLARE(name, compat, init) \ 45 + static const struct of_device_id __reservedmem_of_table_##name \ 46 + __attribute__((unused)) \ 47 + = { .compatible = compat, \ 48 + .data = (init == (reservedmem_of_init_fn)NULL) ? \ 49 + init : init } 50 + 51 + #endif 52 + 53 + #endif /* __OF_RESERVED_MEM_H */