.. | .. |
---|
24 | 24 | #include <linux/of.h> |
---|
25 | 25 | #include <linux/of_device.h> |
---|
26 | 26 | #include <linux/of_graph.h> |
---|
| 27 | +#include <linux/of_irq.h> |
---|
27 | 28 | #include <linux/string.h> |
---|
28 | 29 | #include <linux/moduleparam.h> |
---|
29 | 30 | |
---|
30 | 31 | #include "of_private.h" |
---|
| 32 | + |
---|
| 33 | +/** |
---|
| 34 | + * of_graph_is_present() - check graph's presence |
---|
| 35 | + * @node: pointer to device_node containing graph port |
---|
| 36 | + * |
---|
| 37 | + * Return: True if @node has a port or ports (with a port) sub-node, |
---|
| 38 | + * false otherwise. |
---|
| 39 | + */ |
---|
| 40 | +bool of_graph_is_present(const struct device_node *node) |
---|
| 41 | +{ |
---|
| 42 | + struct device_node *ports, *port; |
---|
| 43 | + |
---|
| 44 | + ports = of_get_child_by_name(node, "ports"); |
---|
| 45 | + if (ports) |
---|
| 46 | + node = ports; |
---|
| 47 | + |
---|
| 48 | + port = of_get_child_by_name(node, "port"); |
---|
| 49 | + of_node_put(ports); |
---|
| 50 | + of_node_put(port); |
---|
| 51 | + |
---|
| 52 | + return !!port; |
---|
| 53 | +} |
---|
| 54 | +EXPORT_SYMBOL(of_graph_is_present); |
---|
31 | 55 | |
---|
32 | 56 | /** |
---|
33 | 57 | * of_property_count_elems_of_size - Count the number of elements in a property |
---|
.. | .. |
---|
165 | 189 | * |
---|
166 | 190 | * @np: device node from which the property value is to be read. |
---|
167 | 191 | * @propname: name of the property to be searched. |
---|
168 | | - * @out_values: pointer to return value, modified only if return value is 0. |
---|
| 192 | + * @out_values: pointer to found values. |
---|
169 | 193 | * @sz_min: minimum number of array elements to read |
---|
170 | 194 | * @sz_max: maximum number of array elements to read, if zero there is no |
---|
171 | 195 | * upper limit on the number of elements in the dts entry but only |
---|
.. | .. |
---|
213 | 237 | * |
---|
214 | 238 | * @np: device node from which the property value is to be read. |
---|
215 | 239 | * @propname: name of the property to be searched. |
---|
216 | | - * @out_values: pointer to return value, modified only if return value is 0. |
---|
| 240 | + * @out_values: pointer to found values. |
---|
217 | 241 | * @sz_min: minimum number of array elements to read |
---|
218 | 242 | * @sz_max: maximum number of array elements to read, if zero there is no |
---|
219 | 243 | * upper limit on the number of elements in the dts entry but only |
---|
.. | .. |
---|
261 | 285 | * |
---|
262 | 286 | * @np: device node from which the property value is to be read. |
---|
263 | 287 | * @propname: name of the property to be searched. |
---|
264 | | - * @out_values: pointer to return value, modified only if return value is 0. |
---|
| 288 | + * @out_values: pointer to return found values. |
---|
265 | 289 | * @sz_min: minimum number of array elements to read |
---|
266 | 290 | * @sz_max: maximum number of array elements to read, if zero there is no |
---|
267 | 291 | * upper limit on the number of elements in the dts entry but only |
---|
.. | .. |
---|
335 | 359 | * |
---|
336 | 360 | * @np: device node from which the property value is to be read. |
---|
337 | 361 | * @propname: name of the property to be searched. |
---|
338 | | - * @out_values: pointer to return value, modified only if return value is 0. |
---|
| 362 | + * @out_values: pointer to found values. |
---|
339 | 363 | * @sz_min: minimum number of array elements to read |
---|
340 | 364 | * @sz_max: maximum number of array elements to read, if zero there is no |
---|
341 | 365 | * upper limit on the number of elements in the dts entry but only |
---|
.. | .. |
---|
572 | 596 | for_each_child_of_node(parent, port) { |
---|
573 | 597 | u32 port_id = 0; |
---|
574 | 598 | |
---|
575 | | - if (of_node_cmp(port->name, "port") != 0) |
---|
| 599 | + if (!of_node_name_eq(port, "port")) |
---|
576 | 600 | continue; |
---|
577 | 601 | of_property_read_u32(port, "reg", &port_id); |
---|
578 | 602 | if (id == port_id) |
---|
.. | .. |
---|
647 | 671 | port = of_get_next_child(parent, port); |
---|
648 | 672 | if (!port) |
---|
649 | 673 | return NULL; |
---|
650 | | - } while (of_node_cmp(port->name, "port")); |
---|
| 674 | + } while (!of_node_name_eq(port, "port")); |
---|
651 | 675 | } |
---|
652 | 676 | } |
---|
653 | 677 | EXPORT_SYMBOL(of_graph_get_next_endpoint); |
---|
.. | .. |
---|
660 | 684 | * |
---|
661 | 685 | * Return: An 'endpoint' node pointer which is identified by reg and at the same |
---|
662 | 686 | * is the child of a port node identified by port_reg. reg and port_reg are |
---|
663 | | - * ignored when they are -1. |
---|
| 687 | + * ignored when they are -1. Use of_node_put() on the pointer when done. |
---|
664 | 688 | */ |
---|
665 | 689 | struct device_node *of_graph_get_endpoint_by_regs( |
---|
666 | 690 | const struct device_node *parent, int port_reg, int reg) |
---|
.. | .. |
---|
716 | 740 | /* Walk 3 levels up only if there is 'ports' node. */ |
---|
717 | 741 | for (depth = 3; depth && node; depth--) { |
---|
718 | 742 | node = of_get_next_parent(node); |
---|
719 | | - if (depth == 2 && of_node_cmp(node->name, "ports")) |
---|
| 743 | + if (depth == 2 && !of_node_name_eq(node, "ports")) |
---|
720 | 744 | break; |
---|
721 | 745 | } |
---|
722 | 746 | return node; |
---|
.. | .. |
---|
873 | 897 | of_property_count_strings(node, propname); |
---|
874 | 898 | } |
---|
875 | 899 | |
---|
| 900 | +static const char *of_fwnode_get_name(const struct fwnode_handle *fwnode) |
---|
| 901 | +{ |
---|
| 902 | + return kbasename(to_of_node(fwnode)->full_name); |
---|
| 903 | +} |
---|
| 904 | + |
---|
| 905 | +static const char *of_fwnode_get_name_prefix(const struct fwnode_handle *fwnode) |
---|
| 906 | +{ |
---|
| 907 | + /* Root needs no prefix here (its name is "/"). */ |
---|
| 908 | + if (!to_of_node(fwnode)->parent) |
---|
| 909 | + return ""; |
---|
| 910 | + |
---|
| 911 | + return "/"; |
---|
| 912 | +} |
---|
| 913 | + |
---|
876 | 914 | static struct fwnode_handle * |
---|
877 | 915 | of_fwnode_get_parent(const struct fwnode_handle *fwnode) |
---|
878 | 916 | { |
---|
.. | .. |
---|
895 | 933 | struct device_node *child; |
---|
896 | 934 | |
---|
897 | 935 | for_each_available_child_of_node(node, child) |
---|
898 | | - if (!of_node_cmp(child->name, childname)) |
---|
| 936 | + if (of_node_name_eq(child, childname)) |
---|
899 | 937 | return of_fwnode_handle(child); |
---|
900 | 938 | |
---|
901 | 939 | return NULL; |
---|
.. | .. |
---|
919 | 957 | nargs, index, &of_args); |
---|
920 | 958 | if (ret < 0) |
---|
921 | 959 | return ret; |
---|
922 | | - if (!args) |
---|
| 960 | + if (!args) { |
---|
| 961 | + of_node_put(of_args.np); |
---|
923 | 962 | return 0; |
---|
| 963 | + } |
---|
924 | 964 | |
---|
925 | 965 | args->nargs = of_args.args_count; |
---|
926 | 966 | args->fwnode = of_fwnode_handle(of_args.np); |
---|
.. | .. |
---|
957 | 997 | return NULL; |
---|
958 | 998 | |
---|
959 | 999 | /* Is this the "ports" node? If not, it's the port parent. */ |
---|
960 | | - if (of_node_cmp(np->name, "ports")) |
---|
| 1000 | + if (!of_node_name_eq(np, "ports")) |
---|
961 | 1001 | return of_fwnode_handle(np); |
---|
962 | 1002 | |
---|
963 | 1003 | return of_fwnode_handle(of_get_next_parent(np)); |
---|
.. | .. |
---|
1001 | 1041 | } |
---|
1002 | 1042 | |
---|
1003 | 1043 | /** |
---|
1004 | | - * of_link_to_phandle - Add device link to supplier from supplier phandle |
---|
1005 | | - * @dev: consumer device |
---|
1006 | | - * @sup_np: phandle to supplier device tree node |
---|
| 1044 | + * of_link_to_phandle - Add fwnode link to supplier from supplier phandle |
---|
| 1045 | + * @con_np: consumer device tree node |
---|
| 1046 | + * @sup_np: supplier device tree node |
---|
1007 | 1047 | * |
---|
1008 | 1048 | * Given a phandle to a supplier device tree node (@sup_np), this function |
---|
1009 | 1049 | * finds the device that owns the supplier device tree node and creates a |
---|
.. | .. |
---|
1013 | 1053 | * cases, it returns an error. |
---|
1014 | 1054 | * |
---|
1015 | 1055 | * Returns: |
---|
1016 | | - * - 0 if link successfully created to supplier |
---|
1017 | | - * - -EAGAIN if linking to the supplier should be reattempted |
---|
| 1056 | + * - 0 if fwnode link successfully created to supplier |
---|
1018 | 1057 | * - -EINVAL if the supplier link is invalid and should not be created |
---|
1019 | | - * - -ENODEV if there is no device that corresponds to the supplier phandle |
---|
| 1058 | + * - -ENODEV if struct device will never be create for supplier |
---|
1020 | 1059 | */ |
---|
1021 | | -static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, |
---|
1022 | | - u32 dl_flags) |
---|
| 1060 | +static int of_link_to_phandle(struct device_node *con_np, |
---|
| 1061 | + struct device_node *sup_np) |
---|
1023 | 1062 | { |
---|
1024 | 1063 | struct device *sup_dev; |
---|
1025 | | - int ret = 0; |
---|
1026 | 1064 | struct device_node *tmp_np = sup_np; |
---|
1027 | | - int is_populated; |
---|
1028 | 1065 | |
---|
1029 | 1066 | of_node_get(sup_np); |
---|
1030 | 1067 | /* |
---|
.. | .. |
---|
1046 | 1083 | } |
---|
1047 | 1084 | |
---|
1048 | 1085 | if (!sup_np) { |
---|
1049 | | - dev_dbg(dev, "Not linking to %pOFP - No device\n", tmp_np); |
---|
| 1086 | + pr_debug("Not linking %pOFP to %pOFP - No device\n", |
---|
| 1087 | + con_np, tmp_np); |
---|
1050 | 1088 | return -ENODEV; |
---|
1051 | 1089 | } |
---|
1052 | 1090 | |
---|
.. | .. |
---|
1055 | 1093 | * descendant nodes. By definition, a child node can't be a functional |
---|
1056 | 1094 | * dependency for the parent node. |
---|
1057 | 1095 | */ |
---|
1058 | | - if (of_is_ancestor_of(dev->of_node, sup_np)) { |
---|
1059 | | - dev_dbg(dev, "Not linking to %pOFP - is descendant\n", sup_np); |
---|
| 1096 | + if (of_is_ancestor_of(con_np, sup_np)) { |
---|
| 1097 | + pr_debug("Not linking %pOFP to %pOFP - is descendant\n", |
---|
| 1098 | + con_np, sup_np); |
---|
1060 | 1099 | of_node_put(sup_np); |
---|
1061 | 1100 | return -EINVAL; |
---|
1062 | 1101 | } |
---|
| 1102 | + |
---|
| 1103 | + /* |
---|
| 1104 | + * Don't create links to "early devices" that won't have struct devices |
---|
| 1105 | + * created for them. |
---|
| 1106 | + */ |
---|
1063 | 1107 | sup_dev = get_dev_from_fwnode(&sup_np->fwnode); |
---|
1064 | | - is_populated = of_node_check_flag(sup_np, OF_POPULATED); |
---|
1065 | | - of_node_put(sup_np); |
---|
1066 | | - if (!sup_dev && is_populated) { |
---|
1067 | | - /* Early device without struct device. */ |
---|
1068 | | - dev_dbg(dev, "Not linking to %pOFP - No struct device\n", |
---|
1069 | | - sup_np); |
---|
| 1108 | + if (!sup_dev && |
---|
| 1109 | + (of_node_check_flag(sup_np, OF_POPULATED) || |
---|
| 1110 | + sup_np->fwnode.flags & FWNODE_FLAG_NOT_DEVICE)) { |
---|
| 1111 | + pr_debug("Not linking %pOFP to %pOFP - No struct device\n", |
---|
| 1112 | + con_np, sup_np); |
---|
| 1113 | + of_node_put(sup_np); |
---|
1070 | 1114 | return -ENODEV; |
---|
1071 | | - } else if (!sup_dev) { |
---|
1072 | | - return -EAGAIN; |
---|
1073 | 1115 | } |
---|
1074 | | - if (!device_link_add(dev, sup_dev, dl_flags)) |
---|
1075 | | - ret = -EAGAIN; |
---|
1076 | 1116 | put_device(sup_dev); |
---|
1077 | | - return ret; |
---|
| 1117 | + |
---|
| 1118 | + fwnode_link_add(of_fwnode_handle(con_np), of_fwnode_handle(sup_np)); |
---|
| 1119 | + of_node_put(sup_np); |
---|
| 1120 | + |
---|
| 1121 | + return 0; |
---|
1078 | 1122 | } |
---|
1079 | 1123 | |
---|
1080 | 1124 | /** |
---|
.. | .. |
---|
1174 | 1218 | return parse_suffix_prop_cells(np, prop_name, index, suffix, cells); \ |
---|
1175 | 1219 | } |
---|
1176 | 1220 | |
---|
1177 | | -static struct device_node *parse_msm_bus_name(struct device_node *np, |
---|
1178 | | - const char *prop_name, int index) |
---|
1179 | | -{ |
---|
1180 | | - static struct device_node *bus_dev_np; |
---|
1181 | | - |
---|
1182 | | - if (index || strcmp(prop_name, "qcom,msm-bus,name")) |
---|
1183 | | - return NULL; |
---|
1184 | | - |
---|
1185 | | - if (!bus_dev_np) |
---|
1186 | | - bus_dev_np = of_find_compatible_node(NULL, NULL, |
---|
1187 | | - "qcom,msm-bus-device"); |
---|
1188 | | - |
---|
1189 | | - return bus_dev_np; |
---|
1190 | | -} |
---|
1191 | | - |
---|
1192 | | -/* Force ignore of any qcom properties. */ |
---|
1193 | | -static struct device_node *parse_qcom_any(struct device_node *np, |
---|
1194 | | - const char *prop_name, int index) |
---|
1195 | | -{ |
---|
1196 | | - if (index || strncmp(prop_name, "qcom,", strlen("qcom,"))) |
---|
1197 | | - return NULL; |
---|
1198 | | - |
---|
1199 | | - /* |
---|
1200 | | - * Returning np will cause this property to be matched and then |
---|
1201 | | - * ignored. |
---|
1202 | | - */ |
---|
1203 | | - return np; |
---|
1204 | | -} |
---|
1205 | | - |
---|
1206 | 1221 | /** |
---|
1207 | 1222 | * struct supplier_bindings - Property parsing functions for suppliers |
---|
1208 | 1223 | * |
---|
.. | .. |
---|
1222 | 1237 | struct supplier_bindings { |
---|
1223 | 1238 | struct device_node *(*parse_prop)(struct device_node *np, |
---|
1224 | 1239 | const char *prop_name, int index); |
---|
| 1240 | + bool optional; |
---|
1225 | 1241 | }; |
---|
1226 | 1242 | |
---|
1227 | | -DEFINE_SIMPLE_PROP(qcom_wrapper_core, "qcom,wrapper-core", NULL) |
---|
1228 | 1243 | DEFINE_SIMPLE_PROP(clocks, "clocks", "#clock-cells") |
---|
1229 | 1244 | DEFINE_SIMPLE_PROP(interconnects, "interconnects", "#interconnect-cells") |
---|
1230 | 1245 | DEFINE_SIMPLE_PROP(iommus, "iommus", "#iommu-cells") |
---|
.. | .. |
---|
1235 | 1250 | DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells") |
---|
1236 | 1251 | DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells") |
---|
1237 | 1252 | DEFINE_SIMPLE_PROP(extcon, "extcon", NULL) |
---|
| 1253 | +DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL) |
---|
1238 | 1254 | DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells") |
---|
| 1255 | +DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL) |
---|
1239 | 1256 | DEFINE_SIMPLE_PROP(pinctrl0, "pinctrl-0", NULL) |
---|
1240 | 1257 | DEFINE_SIMPLE_PROP(pinctrl1, "pinctrl-1", NULL) |
---|
1241 | 1258 | DEFINE_SIMPLE_PROP(pinctrl2, "pinctrl-2", NULL) |
---|
1242 | 1259 | DEFINE_SIMPLE_PROP(pinctrl3, "pinctrl-3", NULL) |
---|
| 1260 | +DEFINE_SIMPLE_PROP(pinctrl4, "pinctrl-4", NULL) |
---|
| 1261 | +DEFINE_SIMPLE_PROP(pinctrl5, "pinctrl-5", NULL) |
---|
| 1262 | +DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL) |
---|
| 1263 | +DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) |
---|
| 1264 | +DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) |
---|
1243 | 1265 | DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) |
---|
1244 | 1266 | DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") |
---|
1245 | | -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells") |
---|
| 1267 | + |
---|
| 1268 | +static struct device_node *parse_gpios(struct device_node *np, |
---|
| 1269 | + const char *prop_name, int index) |
---|
| 1270 | +{ |
---|
| 1271 | + if (!strcmp_suffix(prop_name, ",nr-gpios")) |
---|
| 1272 | + return NULL; |
---|
| 1273 | + |
---|
| 1274 | + return parse_suffix_prop_cells(np, prop_name, index, "-gpios", |
---|
| 1275 | + "#gpio-cells"); |
---|
| 1276 | +} |
---|
1246 | 1277 | |
---|
1247 | 1278 | static struct device_node *parse_iommu_maps(struct device_node *np, |
---|
1248 | 1279 | const char *prop_name, int index) |
---|
.. | .. |
---|
1253 | 1284 | return of_parse_phandle(np, prop_name, (index * 4) + 1); |
---|
1254 | 1285 | } |
---|
1255 | 1286 | |
---|
| 1287 | +static struct device_node *parse_gpio_compat(struct device_node *np, |
---|
| 1288 | + const char *prop_name, int index) |
---|
| 1289 | +{ |
---|
| 1290 | + struct of_phandle_args sup_args; |
---|
| 1291 | + |
---|
| 1292 | + if (strcmp(prop_name, "gpio") && strcmp(prop_name, "gpios")) |
---|
| 1293 | + return NULL; |
---|
| 1294 | + |
---|
| 1295 | + /* |
---|
| 1296 | + * Ignore node with gpio-hog property since its gpios are all provided |
---|
| 1297 | + * by its parent. |
---|
| 1298 | + */ |
---|
| 1299 | + if (of_find_property(np, "gpio-hog", NULL)) |
---|
| 1300 | + return NULL; |
---|
| 1301 | + |
---|
| 1302 | + if (of_parse_phandle_with_args(np, prop_name, "#gpio-cells", index, |
---|
| 1303 | + &sup_args)) |
---|
| 1304 | + return NULL; |
---|
| 1305 | + |
---|
| 1306 | + return sup_args.np; |
---|
| 1307 | +} |
---|
| 1308 | + |
---|
| 1309 | +static struct device_node *parse_interrupts(struct device_node *np, |
---|
| 1310 | + const char *prop_name, int index) |
---|
| 1311 | +{ |
---|
| 1312 | + struct of_phandle_args sup_args; |
---|
| 1313 | + |
---|
| 1314 | + if (!IS_ENABLED(CONFIG_OF_IRQ) || IS_ENABLED(CONFIG_PPC)) |
---|
| 1315 | + return NULL; |
---|
| 1316 | + |
---|
| 1317 | + if (strcmp(prop_name, "interrupts") && |
---|
| 1318 | + strcmp(prop_name, "interrupts-extended")) |
---|
| 1319 | + return NULL; |
---|
| 1320 | + |
---|
| 1321 | + return of_irq_parse_one(np, index, &sup_args) ? NULL : sup_args.np; |
---|
| 1322 | +} |
---|
| 1323 | + |
---|
1256 | 1324 | static const struct supplier_bindings of_supplier_bindings[] = { |
---|
1257 | | - { .parse_prop = parse_msm_bus_name, }, |
---|
1258 | | - { .parse_prop = parse_qcom_wrapper_core, }, |
---|
1259 | | - { .parse_prop = parse_qcom_any, }, |
---|
1260 | 1325 | { .parse_prop = parse_clocks, }, |
---|
1261 | 1326 | { .parse_prop = parse_interconnects, }, |
---|
1262 | | - { .parse_prop = parse_iommus, }, |
---|
1263 | | - { .parse_prop = parse_iommu_maps, }, |
---|
| 1327 | + { .parse_prop = parse_iommus, .optional = true, }, |
---|
| 1328 | + { .parse_prop = parse_iommu_maps, .optional = true, }, |
---|
1264 | 1329 | { .parse_prop = parse_mboxes, }, |
---|
1265 | 1330 | { .parse_prop = parse_io_channels, }, |
---|
1266 | 1331 | { .parse_prop = parse_interrupt_parent, }, |
---|
1267 | | - { .parse_prop = parse_dmas, }, |
---|
| 1332 | + { .parse_prop = parse_dmas, .optional = true, }, |
---|
1268 | 1333 | { .parse_prop = parse_power_domains, }, |
---|
1269 | 1334 | { .parse_prop = parse_hwlocks, }, |
---|
1270 | 1335 | { .parse_prop = parse_extcon, }, |
---|
| 1336 | + { .parse_prop = parse_nvmem_cells, }, |
---|
1271 | 1337 | { .parse_prop = parse_phys, }, |
---|
| 1338 | + { .parse_prop = parse_wakeup_parent, }, |
---|
1272 | 1339 | { .parse_prop = parse_pinctrl0, }, |
---|
1273 | 1340 | { .parse_prop = parse_pinctrl1, }, |
---|
1274 | 1341 | { .parse_prop = parse_pinctrl2, }, |
---|
1275 | 1342 | { .parse_prop = parse_pinctrl3, }, |
---|
| 1343 | + { .parse_prop = parse_pinctrl4, }, |
---|
| 1344 | + { .parse_prop = parse_pinctrl5, }, |
---|
| 1345 | + { .parse_prop = parse_pinctrl6, }, |
---|
| 1346 | + { .parse_prop = parse_pinctrl7, }, |
---|
| 1347 | + { .parse_prop = parse_pinctrl8, }, |
---|
| 1348 | + { .parse_prop = parse_gpio_compat, }, |
---|
| 1349 | + { .parse_prop = parse_interrupts, }, |
---|
1276 | 1350 | { .parse_prop = parse_regulators, }, |
---|
1277 | 1351 | { .parse_prop = parse_gpio, }, |
---|
1278 | 1352 | { .parse_prop = parse_gpios, }, |
---|
.. | .. |
---|
1290 | 1364 | * that list phandles to suppliers. If @prop_name isn't one, this function |
---|
1291 | 1365 | * doesn't do anything. |
---|
1292 | 1366 | * |
---|
1293 | | - * If @prop_name is one, this function attempts to create device links from the |
---|
1294 | | - * consumer device @dev to all the devices of the suppliers listed in |
---|
1295 | | - * @prop_name. |
---|
| 1367 | + * If @prop_name is one, this function attempts to create fwnode links from the |
---|
| 1368 | + * consumer device tree node @con_np to all the suppliers device tree nodes |
---|
| 1369 | + * listed in @prop_name. |
---|
1296 | 1370 | * |
---|
1297 | | - * Any failed attempt to create a device link will NOT result in an immediate |
---|
| 1371 | + * Any failed attempt to create a fwnode link will NOT result in an immediate |
---|
1298 | 1372 | * return. of_link_property() must create links to all the available supplier |
---|
1299 | | - * devices even when attempts to create a link to one or more suppliers fail. |
---|
| 1373 | + * device tree nodes even when attempts to create a link to one or more |
---|
| 1374 | + * suppliers fail. |
---|
1300 | 1375 | */ |
---|
1301 | | -static int of_link_property(struct device *dev, struct device_node *con_np, |
---|
1302 | | - const char *prop_name) |
---|
| 1376 | +static int of_link_property(struct device_node *con_np, const char *prop_name) |
---|
1303 | 1377 | { |
---|
1304 | 1378 | struct device_node *phandle; |
---|
1305 | 1379 | const struct supplier_bindings *s = of_supplier_bindings; |
---|
1306 | 1380 | unsigned int i = 0; |
---|
1307 | 1381 | bool matched = false; |
---|
1308 | 1382 | int ret = 0; |
---|
1309 | | - u32 dl_flags; |
---|
1310 | | - |
---|
1311 | | - if (dev->of_node == con_np) |
---|
1312 | | - dl_flags = 0; |
---|
1313 | | - else |
---|
1314 | | - dl_flags = DL_FLAG_SYNC_STATE_ONLY; |
---|
1315 | 1383 | |
---|
1316 | 1384 | /* Do not stop at first failed link, link all available suppliers. */ |
---|
1317 | 1385 | while (!matched && s->parse_prop) { |
---|
| 1386 | + if (s->optional && !fw_devlink_is_strict()) { |
---|
| 1387 | + s++; |
---|
| 1388 | + continue; |
---|
| 1389 | + } |
---|
| 1390 | + |
---|
1318 | 1391 | while ((phandle = s->parse_prop(con_np, prop_name, i))) { |
---|
1319 | 1392 | matched = true; |
---|
1320 | 1393 | i++; |
---|
1321 | | - if (of_link_to_phandle(dev, phandle, dl_flags) |
---|
1322 | | - == -EAGAIN) |
---|
1323 | | - ret = -EAGAIN; |
---|
| 1394 | + of_link_to_phandle(con_np, phandle); |
---|
1324 | 1395 | of_node_put(phandle); |
---|
1325 | 1396 | } |
---|
1326 | 1397 | s++; |
---|
.. | .. |
---|
1328 | 1399 | return ret; |
---|
1329 | 1400 | } |
---|
1330 | 1401 | |
---|
1331 | | -static int of_link_to_suppliers(struct device *dev, |
---|
1332 | | - struct device_node *con_np) |
---|
| 1402 | +static int of_fwnode_add_links(struct fwnode_handle *fwnode) |
---|
1333 | 1403 | { |
---|
1334 | | - struct device_node *child; |
---|
1335 | 1404 | struct property *p; |
---|
1336 | | - int ret = 0; |
---|
| 1405 | + struct device_node *con_np = to_of_node(fwnode); |
---|
| 1406 | + |
---|
| 1407 | + if (!con_np) |
---|
| 1408 | + return -EINVAL; |
---|
1337 | 1409 | |
---|
1338 | 1410 | for_each_property_of_node(con_np, p) |
---|
1339 | | - if (of_link_property(dev, con_np, p->name)) |
---|
1340 | | - ret = -ENODEV; |
---|
| 1411 | + of_link_property(con_np, p->name); |
---|
1341 | 1412 | |
---|
1342 | | - for_each_available_child_of_node(con_np, child) |
---|
1343 | | - if (of_link_to_suppliers(dev, child) && !ret) |
---|
1344 | | - ret = -EAGAIN; |
---|
1345 | | - |
---|
1346 | | - return ret; |
---|
1347 | | -} |
---|
1348 | | - |
---|
1349 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
1350 | | -static bool of_devlink; |
---|
1351 | | -#else |
---|
1352 | | -static bool of_devlink = true; |
---|
1353 | | -#endif |
---|
1354 | | -core_param(of_devlink, of_devlink, bool, 0); |
---|
1355 | | - |
---|
1356 | | -static int of_fwnode_add_links(const struct fwnode_handle *fwnode, |
---|
1357 | | - struct device *dev) |
---|
1358 | | -{ |
---|
1359 | | - if (!of_devlink) |
---|
1360 | | - return 0; |
---|
1361 | | - |
---|
1362 | | - if (unlikely(!is_of_node(fwnode))) |
---|
1363 | | - return 0; |
---|
1364 | | - |
---|
1365 | | - return of_link_to_suppliers(dev, to_of_node(fwnode)); |
---|
| 1413 | + return 0; |
---|
1366 | 1414 | } |
---|
1367 | 1415 | |
---|
1368 | 1416 | const struct fwnode_operations of_fwnode_ops = { |
---|
.. | .. |
---|
1373 | 1421 | .property_present = of_fwnode_property_present, |
---|
1374 | 1422 | .property_read_int_array = of_fwnode_property_read_int_array, |
---|
1375 | 1423 | .property_read_string_array = of_fwnode_property_read_string_array, |
---|
| 1424 | + .get_name = of_fwnode_get_name, |
---|
| 1425 | + .get_name_prefix = of_fwnode_get_name_prefix, |
---|
1376 | 1426 | .get_parent = of_fwnode_get_parent, |
---|
1377 | 1427 | .get_next_child_node = of_fwnode_get_next_child_node, |
---|
1378 | 1428 | .get_named_child_node = of_fwnode_get_named_child_node, |
---|