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

of: reserved_mem: Add functions to parse "memory-region"

Drivers with "memory-region" properties currently have to do their own
parsing of "memory-region" properties. The result is all the drivers
have similar patterns of a call to parse "memory-region" and then get
the region's address and size. As this is a standard property, it should
have common functions for drivers to use. Add new functions to count the
number of regions and retrieve the region's address as a resource.

Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Acked-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
Link: https://lore.kernel.org/r/20250423-dt-memory-region-v2-v2-1-2fbd6ebd3c88@kernel.org
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>

+106
+80
drivers/of/of_reserved_mem.c
··· 12 12 #define pr_fmt(fmt) "OF: reserved mem: " fmt 13 13 14 14 #include <linux/err.h> 15 + #include <linux/ioport.h> 15 16 #include <linux/libfdt.h> 16 17 #include <linux/of.h> 17 18 #include <linux/of_fdt.h> ··· 741 740 return NULL; 742 741 } 743 742 EXPORT_SYMBOL_GPL(of_reserved_mem_lookup); 743 + 744 + /** 745 + * of_reserved_mem_region_to_resource() - Get a reserved memory region as a resource 746 + * @np: node containing 'memory-region' property 747 + * @idx: index of 'memory-region' property to lookup 748 + * @res: Pointer to a struct resource to fill in with reserved region 749 + * 750 + * This function allows drivers to lookup a node's 'memory-region' property 751 + * entries by index and return a struct resource for the entry. 752 + * 753 + * Returns 0 on success with @res filled in. Returns -ENODEV if 'memory-region' 754 + * is missing or unavailable, -EINVAL for any other error. 755 + */ 756 + int of_reserved_mem_region_to_resource(const struct device_node *np, 757 + unsigned int idx, struct resource *res) 758 + { 759 + struct reserved_mem *rmem; 760 + 761 + if (!np) 762 + return -EINVAL; 763 + 764 + struct device_node __free(device_node) *target = of_parse_phandle(np, "memory-region", idx); 765 + if (!target || !of_device_is_available(target)) 766 + return -ENODEV; 767 + 768 + rmem = of_reserved_mem_lookup(target); 769 + if (!rmem) 770 + return -EINVAL; 771 + 772 + resource_set_range(res, rmem->base, rmem->size); 773 + res->name = rmem->name; 774 + return 0; 775 + } 776 + EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource); 777 + 778 + /** 779 + * of_reserved_mem_region_to_resource_byname() - Get a reserved memory region as a resource 780 + * @np: node containing 'memory-region' property 781 + * @name: name of 'memory-region' property entry to lookup 782 + * @res: Pointer to a struct resource to fill in with reserved region 783 + * 784 + * This function allows drivers to lookup a node's 'memory-region' property 785 + * entries by name and return a struct resource for the entry. 786 + * 787 + * Returns 0 on success with @res filled in, or a negative error-code on 788 + * failure. 789 + */ 790 + int of_reserved_mem_region_to_resource_byname(const struct device_node *np, 791 + const char *name, 792 + struct resource *res) 793 + { 794 + int idx; 795 + 796 + if (!name) 797 + return -EINVAL; 798 + 799 + idx = of_property_match_string(np, "memory-region-names", name); 800 + if (idx < 0) 801 + return idx; 802 + 803 + return of_reserved_mem_region_to_resource(np, idx, res); 804 + } 805 + EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource_byname); 806 + 807 + /** 808 + * of_reserved_mem_region_count() - Return the number of 'memory-region' entries 809 + * @np: node containing 'memory-region' property 810 + * 811 + * This function allows drivers to retrieve the number of entries for a node's 812 + * 'memory-region' property. 813 + * 814 + * Returns the number of entries on success, or negative error code on a 815 + * malformed property. 816 + */ 817 + int of_reserved_mem_region_count(const struct device_node *np) 818 + { 819 + return of_count_phandle_with_args(np, "memory-region", NULL); 820 + } 821 + EXPORT_SYMBOL_GPL(of_reserved_mem_region_count);
+26
include/linux/of_reserved_mem.h
··· 7 7 8 8 struct of_phandle_args; 9 9 struct reserved_mem_ops; 10 + struct resource; 10 11 11 12 struct reserved_mem { 12 13 const char *name; ··· 40 39 void of_reserved_mem_device_release(struct device *dev); 41 40 42 41 struct reserved_mem *of_reserved_mem_lookup(struct device_node *np); 42 + int of_reserved_mem_region_to_resource(const struct device_node *np, 43 + unsigned int idx, struct resource *res); 44 + int of_reserved_mem_region_to_resource_byname(const struct device_node *np, 45 + const char *name, struct resource *res); 46 + int of_reserved_mem_region_count(const struct device_node *np); 47 + 43 48 #else 44 49 45 50 #define RESERVEDMEM_OF_DECLARE(name, compat, init) \ ··· 69 62 static inline struct reserved_mem *of_reserved_mem_lookup(struct device_node *np) 70 63 { 71 64 return NULL; 65 + } 66 + 67 + static inline int of_reserved_mem_region_to_resource(const struct device_node *np, 68 + unsigned int idx, 69 + struct resource *res) 70 + { 71 + return -ENOSYS; 72 + } 73 + 74 + static inline int of_reserved_mem_region_to_resource_byname(const struct device_node *np, 75 + const char *name, 76 + struct resource *res) 77 + { 78 + return -ENOSYS; 79 + } 80 + 81 + static inline int of_reserved_mem_region_count(const struct device_node *np) 82 + { 83 + return 0; 72 84 } 73 85 #endif 74 86