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

of/address: Add of_property_read_reg() helper

Add a helper, of_property_read_reg(), to read "reg" entries untranslated
address and size. This function is intended mainly for cases with an
untranslatable "reg" address (i.e. not MMIO). There's also a few
translatable cases such as address cells containing a bus chip-select
number.

Link: https://lore.kernel.org/r/20230328-dt-address-helpers-v1-5-e2456c3e77ab@kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>

+52
+23
drivers/of/address.c
··· 760 760 } 761 761 EXPORT_SYMBOL(__of_get_address); 762 762 763 + /** 764 + * of_property_read_reg - Retrieve the specified "reg" entry index without translating 765 + * @np: device tree node for which to retrieve "reg" from 766 + * @idx: "reg" entry index to read 767 + * @addr: return value for the untranslated address 768 + * @size: return value for the entry size 769 + * 770 + * Returns -EINVAL if "reg" is not found. Returns 0 on success with addr and 771 + * size values filled in. 772 + */ 773 + int of_property_read_reg(struct device_node *np, int idx, u64 *addr, u64 *size) 774 + { 775 + const __be32 *prop = of_get_address(np, idx, size, NULL); 776 + 777 + if (!prop) 778 + return -EINVAL; 779 + 780 + *addr = of_read_number(prop, of_n_addr_cells(np)); 781 + 782 + return 0; 783 + } 784 + EXPORT_SYMBOL(of_property_read_reg); 785 + 763 786 static int parser_init(struct of_pci_range_parser *parser, 764 787 struct device_node *node, const char *name) 765 788 {
+22
drivers/of/unittest.c
··· 1134 1134 of_node_put(np); 1135 1135 } 1136 1136 1137 + static void __init of_unittest_reg(void) 1138 + { 1139 + struct device_node *np; 1140 + int ret; 1141 + u64 addr, size; 1142 + 1143 + np = of_find_node_by_path("/testcase-data/address-tests/bus@80000000/device@1000"); 1144 + if (!np) { 1145 + pr_err("missing testcase data\n"); 1146 + return; 1147 + } 1148 + 1149 + ret = of_property_read_reg(np, 0, &addr, &size); 1150 + unittest(!ret, "of_property_read_reg(%pOF) returned error %d\n", 1151 + np, ret); 1152 + unittest(addr == 0x1000, "of_property_read_reg(%pOF) untranslated address (%llx) incorrect\n", 1153 + np, addr); 1154 + 1155 + of_node_put(np); 1156 + } 1157 + 1137 1158 static void __init of_unittest_parse_interrupts(void) 1138 1159 { 1139 1160 struct device_node *np; ··· 3793 3772 of_unittest_pci_dma_ranges(); 3794 3773 of_unittest_bus_ranges(); 3795 3774 of_unittest_bus_3cell_ranges(); 3775 + of_unittest_reg(); 3796 3776 of_unittest_match_node(); 3797 3777 of_unittest_platform_populate(); 3798 3778 of_unittest_overlay();
+7
include/linux/of_address.h
··· 72 72 extern const __be32 *__of_get_address(struct device_node *dev, int index, int bar_no, 73 73 u64 *size, unsigned int *flags); 74 74 75 + int of_property_read_reg(struct device_node *np, int idx, u64 *addr, u64 *size); 76 + 75 77 extern int of_pci_range_parser_init(struct of_pci_range_parser *parser, 76 78 struct device_node *node); 77 79 extern int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser, ··· 106 104 u64 *size, unsigned int *flags) 107 105 { 108 106 return NULL; 107 + } 108 + 109 + static inline int of_property_read_reg(struct device_node *np, int idx, u64 *addr, u64 *size) 110 + { 111 + return -ENOSYS; 109 112 } 110 113 111 114 static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser,