0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/acpi.h>
0011 #include <linux/export.h>
0012 #include <linux/kernel.h>
0013 #include <linux/of.h>
0014 #include <linux/of_address.h>
0015 #include <linux/of_graph.h>
0016 #include <linux/of_irq.h>
0017 #include <linux/property.h>
0018 #include <linux/phy.h>
0019
0020 struct fwnode_handle *dev_fwnode(struct device *dev)
0021 {
0022 return IS_ENABLED(CONFIG_OF) && dev->of_node ?
0023 of_fwnode_handle(dev->of_node) : dev->fwnode;
0024 }
0025 EXPORT_SYMBOL_GPL(dev_fwnode);
0026
0027
0028
0029
0030
0031
0032
0033
0034 bool device_property_present(struct device *dev, const char *propname)
0035 {
0036 return fwnode_property_present(dev_fwnode(dev), propname);
0037 }
0038 EXPORT_SYMBOL_GPL(device_property_present);
0039
0040
0041
0042
0043
0044
0045 bool fwnode_property_present(const struct fwnode_handle *fwnode,
0046 const char *propname)
0047 {
0048 bool ret;
0049
0050 if (IS_ERR_OR_NULL(fwnode))
0051 return false;
0052
0053 ret = fwnode_call_bool_op(fwnode, property_present, propname);
0054 if (ret)
0055 return ret;
0056
0057 return fwnode_call_bool_op(fwnode->secondary, property_present, propname);
0058 }
0059 EXPORT_SYMBOL_GPL(fwnode_property_present);
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 int device_property_read_u8_array(struct device *dev, const char *propname,
0083 u8 *val, size_t nval)
0084 {
0085 return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval);
0086 }
0087 EXPORT_SYMBOL_GPL(device_property_read_u8_array);
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 int device_property_read_u16_array(struct device *dev, const char *propname,
0111 u16 *val, size_t nval)
0112 {
0113 return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval);
0114 }
0115 EXPORT_SYMBOL_GPL(device_property_read_u16_array);
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138 int device_property_read_u32_array(struct device *dev, const char *propname,
0139 u32 *val, size_t nval)
0140 {
0141 return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval);
0142 }
0143 EXPORT_SYMBOL_GPL(device_property_read_u32_array);
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 int device_property_read_u64_array(struct device *dev, const char *propname,
0167 u64 *val, size_t nval)
0168 {
0169 return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval);
0170 }
0171 EXPORT_SYMBOL_GPL(device_property_read_u64_array);
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194 int device_property_read_string_array(struct device *dev, const char *propname,
0195 const char **val, size_t nval)
0196 {
0197 return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval);
0198 }
0199 EXPORT_SYMBOL_GPL(device_property_read_string_array);
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 int device_property_read_string(struct device *dev, const char *propname,
0217 const char **val)
0218 {
0219 return fwnode_property_read_string(dev_fwnode(dev), propname, val);
0220 }
0221 EXPORT_SYMBOL_GPL(device_property_read_string);
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238 int device_property_match_string(struct device *dev, const char *propname,
0239 const char *string)
0240 {
0241 return fwnode_property_match_string(dev_fwnode(dev), propname, string);
0242 }
0243 EXPORT_SYMBOL_GPL(device_property_match_string);
0244
0245 static int fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
0246 const char *propname,
0247 unsigned int elem_size, void *val,
0248 size_t nval)
0249 {
0250 int ret;
0251
0252 if (IS_ERR_OR_NULL(fwnode))
0253 return -EINVAL;
0254
0255 ret = fwnode_call_int_op(fwnode, property_read_int_array, propname,
0256 elem_size, val, nval);
0257 if (ret != -EINVAL)
0258 return ret;
0259
0260 return fwnode_call_int_op(fwnode->secondary, property_read_int_array, propname,
0261 elem_size, val, nval);
0262 }
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 int fwnode_property_read_u8_array(const struct fwnode_handle *fwnode,
0286 const char *propname, u8 *val, size_t nval)
0287 {
0288 return fwnode_property_read_int_array(fwnode, propname, sizeof(u8),
0289 val, nval);
0290 }
0291 EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314 int fwnode_property_read_u16_array(const struct fwnode_handle *fwnode,
0315 const char *propname, u16 *val, size_t nval)
0316 {
0317 return fwnode_property_read_int_array(fwnode, propname, sizeof(u16),
0318 val, nval);
0319 }
0320 EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343 int fwnode_property_read_u32_array(const struct fwnode_handle *fwnode,
0344 const char *propname, u32 *val, size_t nval)
0345 {
0346 return fwnode_property_read_int_array(fwnode, propname, sizeof(u32),
0347 val, nval);
0348 }
0349 EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372 int fwnode_property_read_u64_array(const struct fwnode_handle *fwnode,
0373 const char *propname, u64 *val, size_t nval)
0374 {
0375 return fwnode_property_read_int_array(fwnode, propname, sizeof(u64),
0376 val, nval);
0377 }
0378 EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401 int fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
0402 const char *propname, const char **val,
0403 size_t nval)
0404 {
0405 int ret;
0406
0407 if (IS_ERR_OR_NULL(fwnode))
0408 return -EINVAL;
0409
0410 ret = fwnode_call_int_op(fwnode, property_read_string_array, propname,
0411 val, nval);
0412 if (ret != -EINVAL)
0413 return ret;
0414
0415 return fwnode_call_int_op(fwnode->secondary, property_read_string_array, propname,
0416 val, nval);
0417 }
0418 EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435 int fwnode_property_read_string(const struct fwnode_handle *fwnode,
0436 const char *propname, const char **val)
0437 {
0438 int ret = fwnode_property_read_string_array(fwnode, propname, val, 1);
0439
0440 return ret < 0 ? ret : 0;
0441 }
0442 EXPORT_SYMBOL_GPL(fwnode_property_read_string);
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459 int fwnode_property_match_string(const struct fwnode_handle *fwnode,
0460 const char *propname, const char *string)
0461 {
0462 const char **values;
0463 int nval, ret;
0464
0465 nval = fwnode_property_read_string_array(fwnode, propname, NULL, 0);
0466 if (nval < 0)
0467 return nval;
0468
0469 if (nval == 0)
0470 return -ENODATA;
0471
0472 values = kcalloc(nval, sizeof(*values), GFP_KERNEL);
0473 if (!values)
0474 return -ENOMEM;
0475
0476 ret = fwnode_property_read_string_array(fwnode, propname, values, nval);
0477 if (ret < 0)
0478 goto out;
0479
0480 ret = match_string(values, nval, string);
0481 if (ret < 0)
0482 ret = -ENODATA;
0483 out:
0484 kfree(values);
0485 return ret;
0486 }
0487 EXPORT_SYMBOL_GPL(fwnode_property_match_string);
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511 int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode,
0512 const char *prop, const char *nargs_prop,
0513 unsigned int nargs, unsigned int index,
0514 struct fwnode_reference_args *args)
0515 {
0516 int ret;
0517
0518 if (IS_ERR_OR_NULL(fwnode))
0519 return -ENOENT;
0520
0521 ret = fwnode_call_int_op(fwnode, get_reference_args, prop, nargs_prop,
0522 nargs, index, args);
0523 if (ret == 0)
0524 return ret;
0525
0526 if (IS_ERR_OR_NULL(fwnode->secondary))
0527 return ret;
0528
0529 return fwnode_call_int_op(fwnode->secondary, get_reference_args, prop, nargs_prop,
0530 nargs, index, args);
0531 }
0532 EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args);
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545 struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode,
0546 const char *name,
0547 unsigned int index)
0548 {
0549 struct fwnode_reference_args args;
0550 int ret;
0551
0552 ret = fwnode_property_get_reference_args(fwnode, name, NULL, 0, index,
0553 &args);
0554 return ret ? ERR_PTR(ret) : args.fwnode;
0555 }
0556 EXPORT_SYMBOL_GPL(fwnode_find_reference);
0557
0558
0559
0560
0561
0562
0563
0564 const char *fwnode_get_name(const struct fwnode_handle *fwnode)
0565 {
0566 return fwnode_call_ptr_op(fwnode, get_name);
0567 }
0568 EXPORT_SYMBOL_GPL(fwnode_get_name);
0569
0570
0571
0572
0573
0574
0575
0576
0577 const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
0578 {
0579 return fwnode_call_ptr_op(fwnode, get_name_prefix);
0580 }
0581
0582
0583
0584
0585
0586
0587
0588
0589 struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode)
0590 {
0591 return fwnode_call_ptr_op(fwnode, get_parent);
0592 }
0593 EXPORT_SYMBOL_GPL(fwnode_get_parent);
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606 struct fwnode_handle *fwnode_get_next_parent(struct fwnode_handle *fwnode)
0607 {
0608 struct fwnode_handle *parent = fwnode_get_parent(fwnode);
0609
0610 fwnode_handle_put(fwnode);
0611
0612 return parent;
0613 }
0614 EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627 struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode)
0628 {
0629 struct fwnode_handle *parent;
0630 struct device *dev;
0631
0632 fwnode_for_each_parent_node(fwnode, parent) {
0633 dev = get_dev_from_fwnode(parent);
0634 if (dev) {
0635 fwnode_handle_put(parent);
0636 return dev;
0637 }
0638 }
0639 return NULL;
0640 }
0641
0642
0643
0644
0645
0646
0647
0648 unsigned int fwnode_count_parents(const struct fwnode_handle *fwnode)
0649 {
0650 struct fwnode_handle *parent;
0651 unsigned int count = 0;
0652
0653 fwnode_for_each_parent_node(fwnode, parent)
0654 count++;
0655
0656 return count;
0657 }
0658 EXPORT_SYMBOL_GPL(fwnode_count_parents);
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672 struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode,
0673 unsigned int depth)
0674 {
0675 struct fwnode_handle *parent;
0676
0677 if (depth == 0)
0678 return fwnode_handle_get(fwnode);
0679
0680 fwnode_for_each_parent_node(fwnode, parent) {
0681 if (--depth == 0)
0682 return parent;
0683 }
0684 return NULL;
0685 }
0686 EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697 bool fwnode_is_ancestor_of(struct fwnode_handle *ancestor, struct fwnode_handle *child)
0698 {
0699 struct fwnode_handle *parent;
0700
0701 if (IS_ERR_OR_NULL(ancestor))
0702 return false;
0703
0704 if (child == ancestor)
0705 return true;
0706
0707 fwnode_for_each_parent_node(child, parent) {
0708 if (parent == ancestor) {
0709 fwnode_handle_put(parent);
0710 return true;
0711 }
0712 }
0713 return false;
0714 }
0715
0716
0717
0718
0719
0720
0721 struct fwnode_handle *
0722 fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
0723 struct fwnode_handle *child)
0724 {
0725 return fwnode_call_ptr_op(fwnode, get_next_child_node, child);
0726 }
0727 EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
0728
0729
0730
0731
0732
0733
0734
0735 struct fwnode_handle *
0736 fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode,
0737 struct fwnode_handle *child)
0738 {
0739 struct fwnode_handle *next_child = child;
0740
0741 if (IS_ERR_OR_NULL(fwnode))
0742 return NULL;
0743
0744 do {
0745 next_child = fwnode_get_next_child_node(fwnode, next_child);
0746 if (!next_child)
0747 return NULL;
0748 } while (!fwnode_device_is_available(next_child));
0749
0750 return next_child;
0751 }
0752 EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
0753
0754
0755
0756
0757
0758
0759 struct fwnode_handle *device_get_next_child_node(struct device *dev,
0760 struct fwnode_handle *child)
0761 {
0762 const struct fwnode_handle *fwnode = dev_fwnode(dev);
0763 struct fwnode_handle *next;
0764
0765 if (IS_ERR_OR_NULL(fwnode))
0766 return NULL;
0767
0768
0769 next = fwnode_get_next_child_node(fwnode, child);
0770 if (next)
0771 return next;
0772
0773
0774 return fwnode_get_next_child_node(fwnode->secondary, child);
0775 }
0776 EXPORT_SYMBOL_GPL(device_get_next_child_node);
0777
0778
0779
0780
0781
0782
0783 struct fwnode_handle *
0784 fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
0785 const char *childname)
0786 {
0787 return fwnode_call_ptr_op(fwnode, get_named_child_node, childname);
0788 }
0789 EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);
0790
0791
0792
0793
0794
0795
0796 struct fwnode_handle *device_get_named_child_node(struct device *dev,
0797 const char *childname)
0798 {
0799 return fwnode_get_named_child_node(dev_fwnode(dev), childname);
0800 }
0801 EXPORT_SYMBOL_GPL(device_get_named_child_node);
0802
0803
0804
0805
0806
0807
0808
0809 struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode)
0810 {
0811 if (!fwnode_has_op(fwnode, get))
0812 return fwnode;
0813
0814 return fwnode_call_ptr_op(fwnode, get);
0815 }
0816 EXPORT_SYMBOL_GPL(fwnode_handle_get);
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826 void fwnode_handle_put(struct fwnode_handle *fwnode)
0827 {
0828 fwnode_call_void_op(fwnode, put);
0829 }
0830 EXPORT_SYMBOL_GPL(fwnode_handle_put);
0831
0832
0833
0834
0835
0836
0837
0838
0839 bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
0840 {
0841 if (IS_ERR_OR_NULL(fwnode))
0842 return false;
0843
0844 if (!fwnode_has_op(fwnode, device_is_available))
0845 return true;
0846
0847 return fwnode_call_bool_op(fwnode, device_is_available);
0848 }
0849 EXPORT_SYMBOL_GPL(fwnode_device_is_available);
0850
0851
0852
0853
0854
0855 unsigned int device_get_child_node_count(struct device *dev)
0856 {
0857 struct fwnode_handle *child;
0858 unsigned int count = 0;
0859
0860 device_for_each_child_node(dev, child)
0861 count++;
0862
0863 return count;
0864 }
0865 EXPORT_SYMBOL_GPL(device_get_child_node_count);
0866
0867 bool device_dma_supported(struct device *dev)
0868 {
0869 return fwnode_call_bool_op(dev_fwnode(dev), device_dma_supported);
0870 }
0871 EXPORT_SYMBOL_GPL(device_dma_supported);
0872
0873 enum dev_dma_attr device_get_dma_attr(struct device *dev)
0874 {
0875 if (!fwnode_has_op(dev_fwnode(dev), device_get_dma_attr))
0876 return DEV_DMA_NOT_SUPPORTED;
0877
0878 return fwnode_call_int_op(dev_fwnode(dev), device_get_dma_attr);
0879 }
0880 EXPORT_SYMBOL_GPL(device_get_dma_attr);
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890 int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
0891 {
0892 const char *pm;
0893 int err, i;
0894
0895 err = fwnode_property_read_string(fwnode, "phy-mode", &pm);
0896 if (err < 0)
0897 err = fwnode_property_read_string(fwnode,
0898 "phy-connection-type", &pm);
0899 if (err < 0)
0900 return err;
0901
0902 for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
0903 if (!strcasecmp(pm, phy_modes(i)))
0904 return i;
0905
0906 return -ENODEV;
0907 }
0908 EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918 int device_get_phy_mode(struct device *dev)
0919 {
0920 return fwnode_get_phy_mode(dev_fwnode(dev));
0921 }
0922 EXPORT_SYMBOL_GPL(device_get_phy_mode);
0923
0924
0925
0926
0927
0928
0929
0930
0931 void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index)
0932 {
0933 return fwnode_call_ptr_op(fwnode, iomap, index);
0934 }
0935 EXPORT_SYMBOL(fwnode_iomap);
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945 int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index)
0946 {
0947 return fwnode_call_int_op(fwnode, irq_get, index);
0948 }
0949 EXPORT_SYMBOL(fwnode_irq_get);
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965 int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name)
0966 {
0967 int index;
0968
0969 if (!name)
0970 return -EINVAL;
0971
0972 index = fwnode_property_match_string(fwnode, "interrupt-names", name);
0973 if (index < 0)
0974 return index;
0975
0976 return fwnode_irq_get(fwnode, index);
0977 }
0978 EXPORT_SYMBOL(fwnode_irq_get_byname);
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988 struct fwnode_handle *
0989 fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
0990 struct fwnode_handle *prev)
0991 {
0992 const struct fwnode_handle *parent;
0993 struct fwnode_handle *ep;
0994
0995
0996
0997
0998
0999
1000 if (prev)
1001 parent = fwnode_graph_get_port_parent(prev);
1002 else
1003 parent = fwnode;
1004 if (IS_ERR_OR_NULL(parent))
1005 return NULL;
1006
1007 ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev);
1008 if (ep)
1009 return ep;
1010
1011 return fwnode_graph_get_next_endpoint(parent->secondary, NULL);
1012 }
1013 EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
1014
1015
1016
1017
1018
1019
1020
1021 struct fwnode_handle *
1022 fwnode_graph_get_port_parent(const struct fwnode_handle *endpoint)
1023 {
1024 struct fwnode_handle *port, *parent;
1025
1026 port = fwnode_get_parent(endpoint);
1027 parent = fwnode_call_ptr_op(port, graph_get_port_parent);
1028
1029 fwnode_handle_put(port);
1030
1031 return parent;
1032 }
1033 EXPORT_SYMBOL_GPL(fwnode_graph_get_port_parent);
1034
1035
1036
1037
1038
1039
1040
1041 struct fwnode_handle *
1042 fwnode_graph_get_remote_port_parent(const struct fwnode_handle *fwnode)
1043 {
1044 struct fwnode_handle *endpoint, *parent;
1045
1046 endpoint = fwnode_graph_get_remote_endpoint(fwnode);
1047 parent = fwnode_graph_get_port_parent(endpoint);
1048
1049 fwnode_handle_put(endpoint);
1050
1051 return parent;
1052 }
1053 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
1054
1055
1056
1057
1058
1059
1060
1061 struct fwnode_handle *
1062 fwnode_graph_get_remote_port(const struct fwnode_handle *fwnode)
1063 {
1064 return fwnode_get_next_parent(fwnode_graph_get_remote_endpoint(fwnode));
1065 }
1066 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
1067
1068
1069
1070
1071
1072
1073
1074 struct fwnode_handle *
1075 fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
1076 {
1077 return fwnode_call_ptr_op(fwnode, graph_get_remote_endpoint);
1078 }
1079 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
1080
1081 static bool fwnode_graph_remote_available(struct fwnode_handle *ep)
1082 {
1083 struct fwnode_handle *dev_node;
1084 bool available;
1085
1086 dev_node = fwnode_graph_get_remote_port_parent(ep);
1087 available = fwnode_device_is_available(dev_node);
1088 fwnode_handle_put(dev_node);
1089
1090 return available;
1091 }
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113 struct fwnode_handle *
1114 fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
1115 u32 port, u32 endpoint, unsigned long flags)
1116 {
1117 struct fwnode_handle *ep, *best_ep = NULL;
1118 unsigned int best_ep_id = 0;
1119 bool endpoint_next = flags & FWNODE_GRAPH_ENDPOINT_NEXT;
1120 bool enabled_only = !(flags & FWNODE_GRAPH_DEVICE_DISABLED);
1121
1122 fwnode_graph_for_each_endpoint(fwnode, ep) {
1123 struct fwnode_endpoint fwnode_ep = { 0 };
1124 int ret;
1125
1126 if (enabled_only && !fwnode_graph_remote_available(ep))
1127 continue;
1128
1129 ret = fwnode_graph_parse_endpoint(ep, &fwnode_ep);
1130 if (ret < 0)
1131 continue;
1132
1133 if (fwnode_ep.port != port)
1134 continue;
1135
1136 if (fwnode_ep.id == endpoint)
1137 return ep;
1138
1139 if (!endpoint_next)
1140 continue;
1141
1142
1143
1144
1145
1146
1147 if (fwnode_ep.id < endpoint ||
1148 (best_ep && best_ep_id < fwnode_ep.id))
1149 continue;
1150
1151 fwnode_handle_put(best_ep);
1152 best_ep = fwnode_handle_get(ep);
1153 best_ep_id = fwnode_ep.id;
1154 }
1155
1156 return best_ep;
1157 }
1158 EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169 unsigned int fwnode_graph_get_endpoint_count(struct fwnode_handle *fwnode,
1170 unsigned long flags)
1171 {
1172 struct fwnode_handle *ep;
1173 unsigned int count = 0;
1174
1175 fwnode_graph_for_each_endpoint(fwnode, ep) {
1176 if (flags & FWNODE_GRAPH_DEVICE_DISABLED ||
1177 fwnode_graph_remote_available(ep))
1178 count++;
1179 }
1180
1181 return count;
1182 }
1183 EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_count);
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194 int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
1195 struct fwnode_endpoint *endpoint)
1196 {
1197 memset(endpoint, 0, sizeof(*endpoint));
1198
1199 return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
1200 }
1201 EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
1202
1203 const void *device_get_match_data(struct device *dev)
1204 {
1205 return fwnode_call_ptr_op(dev_fwnode(dev), device_get_match_data, dev);
1206 }
1207 EXPORT_SYMBOL_GPL(device_get_match_data);
1208
1209 static unsigned int fwnode_graph_devcon_matches(struct fwnode_handle *fwnode,
1210 const char *con_id, void *data,
1211 devcon_match_fn_t match,
1212 void **matches,
1213 unsigned int matches_len)
1214 {
1215 struct fwnode_handle *node;
1216 struct fwnode_handle *ep;
1217 unsigned int count = 0;
1218 void *ret;
1219
1220 fwnode_graph_for_each_endpoint(fwnode, ep) {
1221 if (matches && count >= matches_len) {
1222 fwnode_handle_put(ep);
1223 break;
1224 }
1225
1226 node = fwnode_graph_get_remote_port_parent(ep);
1227 if (!fwnode_device_is_available(node)) {
1228 fwnode_handle_put(node);
1229 continue;
1230 }
1231
1232 ret = match(node, con_id, data);
1233 fwnode_handle_put(node);
1234 if (ret) {
1235 if (matches)
1236 matches[count] = ret;
1237 count++;
1238 }
1239 }
1240 return count;
1241 }
1242
1243 static unsigned int fwnode_devcon_matches(struct fwnode_handle *fwnode,
1244 const char *con_id, void *data,
1245 devcon_match_fn_t match,
1246 void **matches,
1247 unsigned int matches_len)
1248 {
1249 struct fwnode_handle *node;
1250 unsigned int count = 0;
1251 unsigned int i;
1252 void *ret;
1253
1254 for (i = 0; ; i++) {
1255 if (matches && count >= matches_len)
1256 break;
1257
1258 node = fwnode_find_reference(fwnode, con_id, i);
1259 if (IS_ERR(node))
1260 break;
1261
1262 ret = match(node, NULL, data);
1263 fwnode_handle_put(node);
1264 if (ret) {
1265 if (matches)
1266 matches[count] = ret;
1267 count++;
1268 }
1269 }
1270
1271 return count;
1272 }
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285 void *fwnode_connection_find_match(struct fwnode_handle *fwnode,
1286 const char *con_id, void *data,
1287 devcon_match_fn_t match)
1288 {
1289 unsigned int count;
1290 void *ret;
1291
1292 if (!fwnode || !match)
1293 return NULL;
1294
1295 count = fwnode_graph_devcon_matches(fwnode, con_id, data, match, &ret, 1);
1296 if (count)
1297 return ret;
1298
1299 count = fwnode_devcon_matches(fwnode, con_id, data, match, &ret, 1);
1300 return count ? ret : NULL;
1301 }
1302 EXPORT_SYMBOL_GPL(fwnode_connection_find_match);
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322 int fwnode_connection_find_matches(struct fwnode_handle *fwnode,
1323 const char *con_id, void *data,
1324 devcon_match_fn_t match,
1325 void **matches, unsigned int matches_len)
1326 {
1327 unsigned int count_graph;
1328 unsigned int count_ref;
1329
1330 if (!fwnode || !match)
1331 return -EINVAL;
1332
1333 count_graph = fwnode_graph_devcon_matches(fwnode, con_id, data, match,
1334 matches, matches_len);
1335
1336 if (matches) {
1337 matches += count_graph;
1338 matches_len -= count_graph;
1339 }
1340
1341 count_ref = fwnode_devcon_matches(fwnode, con_id, data, match,
1342 matches, matches_len);
1343
1344 return count_graph + count_ref;
1345 }
1346 EXPORT_SYMBOL_GPL(fwnode_connection_find_matches);