// SPDX-License-Identifier: GPL-2.0+ /* * Device tree based initialization code for reserved memory. * * Copyright (c) 2013, 2015 The Linux Foundation. All Rights Reserved. * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * Author: Marek Szyprowski <[email protected]> * Author: Josh Cartwright <[email protected]> */ #define pr_fmt(fmt) … #include <linux/err.h> #include <linux/libfdt.h> #include <linux/of.h> #include <linux/of_fdt.h> #include <linux/of_platform.h> #include <linux/mm.h> #include <linux/sizes.h> #include <linux/of_reserved_mem.h> #include <linux/sort.h> #include <linux/slab.h> #include <linux/memblock.h> #include <linux/kmemleak.h> #include <linux/cma.h> #include "of_private.h" #define MAX_RESERVED_REGIONS … static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; static int reserved_mem_count; static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, phys_addr_t *res_base) { … } /* * fdt_reserved_mem_save_node() - save fdt node for second pass initialization */ static void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, phys_addr_t base, phys_addr_t size) { … } static int __init early_init_dt_reserve_memory(phys_addr_t base, phys_addr_t size, bool nomap) { … } /* * __reserved_mem_reserve_reg() - reserve all memory described in 'reg' property */ static int __init __reserved_mem_reserve_reg(unsigned long node, const char *uname) { … } /* * __reserved_mem_check_root() - check if #size-cells, #address-cells provided * in /reserved-memory matches the values supported by the current implementation, * also check if ranges property has been provided */ static int __init __reserved_mem_check_root(unsigned long node) { … } /* * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory */ int __init fdt_scan_reserved_mem(void) { … } /* * __reserved_mem_alloc_in_range() - allocate reserved memory described with * 'alloc-ranges'. Choose bottom-up/top-down depending on nearby existing * reserved regions to keep the reserved memory contiguous if possible. */ static int __init __reserved_mem_alloc_in_range(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, phys_addr_t *res_base) { … } /* * __reserved_mem_alloc_size() - allocate reserved memory described by * 'size', 'alignment' and 'alloc-ranges' properties. */ static int __init __reserved_mem_alloc_size(unsigned long node, const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) { … } static const struct of_device_id __rmem_of_table_sentinel __used __section(…); /* * __reserved_mem_init_node() - call region specific reserved memory init code */ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) { … } static int __init __rmem_cmp(const void *a, const void *b) { … } static void __init __rmem_check_for_overlap(void) { … } /** * fdt_init_reserved_mem() - allocate and init all saved reserved memory regions */ void __init fdt_init_reserved_mem(void) { … } struct rmem_assigned_device { … }; static LIST_HEAD(of_rmem_assigned_device_list); static DEFINE_MUTEX(of_rmem_assigned_device_mutex); /** * of_reserved_mem_device_init_by_idx() - assign reserved memory region to * given device * @dev: Pointer to the device to configure * @np: Pointer to the device_node with 'reserved-memory' property * @idx: Index of selected region * * This function assigns respective DMA-mapping operations based on reserved * memory region specified by 'memory-region' property in @np node to the @dev * device. When driver needs to use more than one reserved memory region, it * should allocate child devices and initialize regions by name for each of * child device. * * Returns error code or zero on success. */ int of_reserved_mem_device_init_by_idx(struct device *dev, struct device_node *np, int idx) { … } EXPORT_SYMBOL_GPL(…); /** * of_reserved_mem_device_init_by_name() - assign named reserved memory region * to given device * @dev: pointer to the device to configure * @np: pointer to the device node with 'memory-region' property * @name: name of the selected memory region * * Returns: 0 on success or a negative error-code on failure. */ int of_reserved_mem_device_init_by_name(struct device *dev, struct device_node *np, const char *name) { … } EXPORT_SYMBOL_GPL(…); /** * of_reserved_mem_device_release() - release reserved memory device structures * @dev: Pointer to the device to deconfigure * * This function releases structures allocated for memory region handling for * the given device. */ void of_reserved_mem_device_release(struct device *dev) { … } EXPORT_SYMBOL_GPL(…); /** * of_reserved_mem_lookup() - acquire reserved_mem from a device node * @np: node pointer of the desired reserved-memory region * * This function allows drivers to acquire a reference to the reserved_mem * struct based on a device node handle. * * Returns a reserved_mem reference, or NULL on error. */ struct reserved_mem *of_reserved_mem_lookup(struct device_node *np) { … } EXPORT_SYMBOL_GPL(…);