aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy/phy-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/phy/phy-core.c')
-rw-r--r--drivers/phy/phy-core.c115
1 files changed, 74 insertions, 41 deletions
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index ff5eec5af817..a12d35338313 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -26,6 +26,7 @@
26static struct class *phy_class; 26static struct class *phy_class;
27static DEFINE_MUTEX(phy_provider_mutex); 27static DEFINE_MUTEX(phy_provider_mutex);
28static LIST_HEAD(phy_provider_list); 28static LIST_HEAD(phy_provider_list);
29static LIST_HEAD(phys);
29static DEFINE_IDA(phy_ida); 30static DEFINE_IDA(phy_ida);
30 31
31static void devm_phy_release(struct device *dev, void *res) 32static void devm_phy_release(struct device *dev, void *res)
@@ -54,34 +55,79 @@ static int devm_phy_match(struct device *dev, void *res, void *match_data)
54 return res == match_data; 55 return res == match_data;
55} 56}
56 57
57static struct phy *phy_lookup(struct device *device, const char *port) 58/**
59 * phy_create_lookup() - allocate and register PHY/device association
60 * @phy: the phy of the association
61 * @con_id: connection ID string on device
62 * @dev_id: the device of the association
63 *
64 * Creates and registers phy_lookup entry.
65 */
66int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id)
58{ 67{
59 unsigned int count; 68 struct phy_lookup *pl;
60 struct phy *phy;
61 struct device *dev;
62 struct phy_consumer *consumers;
63 struct class_dev_iter iter;
64 69
65 class_dev_iter_init(&iter, phy_class, NULL, NULL); 70 if (!phy || !dev_id || !con_id)
66 while ((dev = class_dev_iter_next(&iter))) { 71 return -EINVAL;
67 phy = to_phy(dev);
68 72
69 if (!phy->init_data) 73 pl = kzalloc(sizeof(*pl), GFP_KERNEL);
70 continue; 74 if (!pl)
71 count = phy->init_data->num_consumers; 75 return -ENOMEM;
72 consumers = phy->init_data->consumers; 76
73 while (count--) { 77 pl->dev_id = dev_id;
74 if (!strcmp(consumers->dev_name, dev_name(device)) && 78 pl->con_id = con_id;
75 !strcmp(consumers->port, port)) { 79 pl->phy = phy;
76 class_dev_iter_exit(&iter); 80
77 return phy; 81 mutex_lock(&phy_provider_mutex);
78 } 82 list_add_tail(&pl->node, &phys);
79 consumers++; 83 mutex_unlock(&phy_provider_mutex);
84
85 return 0;
86}
87EXPORT_SYMBOL_GPL(phy_create_lookup);
88
89/**
90 * phy_remove_lookup() - find and remove PHY/device association
91 * @phy: the phy of the association
92 * @con_id: connection ID string on device
93 * @dev_id: the device of the association
94 *
95 * Finds and unregisters phy_lookup entry that was created with
96 * phy_create_lookup().
97 */
98void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id)
99{
100 struct phy_lookup *pl;
101
102 if (!phy || !dev_id || !con_id)
103 return;
104
105 mutex_lock(&phy_provider_mutex);
106 list_for_each_entry(pl, &phys, node)
107 if (pl->phy == phy && !strcmp(pl->dev_id, dev_id) &&
108 !strcmp(pl->con_id, con_id)) {
109 list_del(&pl->node);
110 kfree(pl);
111 break;
80 } 112 }
81 } 113 mutex_unlock(&phy_provider_mutex);
114}
115EXPORT_SYMBOL_GPL(phy_remove_lookup);
82 116
83 class_dev_iter_exit(&iter); 117static struct phy *phy_find(struct device *dev, const char *con_id)
84 return ERR_PTR(-ENODEV); 118{
119 const char *dev_id = dev_name(dev);
120 struct phy_lookup *p, *pl = NULL;
121
122 mutex_lock(&phy_provider_mutex);
123 list_for_each_entry(p, &phys, node)
124 if (!strcmp(p->dev_id, dev_id) && !strcmp(p->con_id, con_id)) {
125 pl = p;
126 break;
127 }
128 mutex_unlock(&phy_provider_mutex);
129
130 return pl ? pl->phy : ERR_PTR(-ENODEV);
85} 131}
86 132
87static struct phy_provider *of_phy_provider_lookup(struct device_node *node) 133static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
@@ -414,21 +460,13 @@ struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
414{ 460{
415 struct phy *phy; 461 struct phy *phy;
416 struct class_dev_iter iter; 462 struct class_dev_iter iter;
417 struct device_node *node = dev->of_node;
418 struct device_node *child;
419 463
420 class_dev_iter_init(&iter, phy_class, NULL, NULL); 464 class_dev_iter_init(&iter, phy_class, NULL, NULL);
421 while ((dev = class_dev_iter_next(&iter))) { 465 while ((dev = class_dev_iter_next(&iter))) {
422 phy = to_phy(dev); 466 phy = to_phy(dev);
423 if (node != phy->dev.of_node) { 467 if (args->np != phy->dev.of_node)
424 for_each_child_of_node(node, child) {
425 if (child == phy->dev.of_node)
426 goto phy_found;
427 }
428 continue; 468 continue;
429 }
430 469
431phy_found:
432 class_dev_iter_exit(&iter); 470 class_dev_iter_exit(&iter);
433 return phy; 471 return phy;
434 } 472 }
@@ -463,7 +501,7 @@ struct phy *phy_get(struct device *dev, const char *string)
463 string); 501 string);
464 phy = _of_phy_get(dev->of_node, index); 502 phy = _of_phy_get(dev->of_node, index);
465 } else { 503 } else {
466 phy = phy_lookup(dev, string); 504 phy = phy_find(dev, string);
467 } 505 }
468 if (IS_ERR(phy)) 506 if (IS_ERR(phy))
469 return phy; 507 return phy;
@@ -588,13 +626,11 @@ EXPORT_SYMBOL_GPL(devm_of_phy_get);
588 * @dev: device that is creating the new phy 626 * @dev: device that is creating the new phy
589 * @node: device node of the phy 627 * @node: device node of the phy
590 * @ops: function pointers for performing phy operations 628 * @ops: function pointers for performing phy operations
591 * @init_data: contains the list of PHY consumers or NULL
592 * 629 *
593 * Called to create a phy using phy framework. 630 * Called to create a phy using phy framework.
594 */ 631 */
595struct phy *phy_create(struct device *dev, struct device_node *node, 632struct phy *phy_create(struct device *dev, struct device_node *node,
596 const struct phy_ops *ops, 633 const struct phy_ops *ops)
597 struct phy_init_data *init_data)
598{ 634{
599 int ret; 635 int ret;
600 int id; 636 int id;
@@ -632,7 +668,6 @@ struct phy *phy_create(struct device *dev, struct device_node *node,
632 phy->dev.of_node = node ?: dev->of_node; 668 phy->dev.of_node = node ?: dev->of_node;
633 phy->id = id; 669 phy->id = id;
634 phy->ops = ops; 670 phy->ops = ops;
635 phy->init_data = init_data;
636 671
637 ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id); 672 ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
638 if (ret) 673 if (ret)
@@ -667,7 +702,6 @@ EXPORT_SYMBOL_GPL(phy_create);
667 * @dev: device that is creating the new phy 702 * @dev: device that is creating the new phy
668 * @node: device node of the phy 703 * @node: device node of the phy
669 * @ops: function pointers for performing phy operations 704 * @ops: function pointers for performing phy operations
670 * @init_data: contains the list of PHY consumers or NULL
671 * 705 *
672 * Creates a new PHY device adding it to the PHY class. 706 * Creates a new PHY device adding it to the PHY class.
673 * While at that, it also associates the device with the phy using devres. 707 * While at that, it also associates the device with the phy using devres.
@@ -675,8 +709,7 @@ EXPORT_SYMBOL_GPL(phy_create);
675 * then, devres data is freed. 709 * then, devres data is freed.
676 */ 710 */
677struct phy *devm_phy_create(struct device *dev, struct device_node *node, 711struct phy *devm_phy_create(struct device *dev, struct device_node *node,
678 const struct phy_ops *ops, 712 const struct phy_ops *ops)
679 struct phy_init_data *init_data)
680{ 713{
681 struct phy **ptr, *phy; 714 struct phy **ptr, *phy;
682 715
@@ -684,7 +717,7 @@ struct phy *devm_phy_create(struct device *dev, struct device_node *node,
684 if (!ptr) 717 if (!ptr)
685 return ERR_PTR(-ENOMEM); 718 return ERR_PTR(-ENOMEM);
686 719
687 phy = phy_create(dev, node, ops, init_data); 720 phy = phy_create(dev, node, ops);
688 if (!IS_ERR(phy)) { 721 if (!IS_ERR(phy)) {
689 *ptr = phy; 722 *ptr = phy;
690 devres_add(dev, ptr); 723 devres_add(dev, ptr);