aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy/phy-core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 17:57:16 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 17:57:16 -0500
commite7cf773d431a63a2417902696fcc9e0ebdc83bbe (patch)
tree86dbdceb7d91226507a3af0d57e03b0ca664b22e /drivers/phy/phy-core.c
parent7a02d089695a1217992434f03a78aa32bad85b5c (diff)
parent81e1dadfb5b2d47aa513ad60b1c9cf0ea17b6514 (diff)
Merge tag 'usb-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH: "Here's the big set of USB and PHY patches for 3.19-rc1. The normal churn in the USB gadget area is in here, as well as xhci and other individual USB driver updates. The PHY tree is also in here, as there were dependancies on the USB tree. All of these have been in linux-next" * tag 'usb-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (351 commits) arm: omap3: twl: remove usb phy init data usbip: fix error handling in stub_probe() usb: gadget: udc: missing curly braces USB: mos7720: delete some unneeded code wusb: replace memset by memzero_explicit usbip: remove unneeded structure usb: xhci: fix comment for PORT_DEV_REMOVE xhci: don't use the same variable for stopped and halted rings current TD xhci: clear extra bits from slot context when setting max exit latency xhci: cleanup finish_td function USB: adutux: NULL dereferences on disconnect usb: chipidea: fix platform_no_drv_owner.cocci warnings usb: chipidea: Fixed a few typos in comments Documentation: bindings: add doc for the USB2 ChipIdea USB driver usb: chipidea: add a usb2 driver for ci13xxx usb: chipidea: fix phy handling usb: chipidea: remove duplicate dev_set_drvdata for host_start usb: chipidea: parameter 'mode' isn't needed for hw_device_reset usb: chipidea: add controller reset API usb: chipidea: remove flag CI_HDRC_REQUIRE_TRANSCEIVER ...
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);