xref: /openbmc/u-boot/drivers/phy/phy-uclass.c (revision 699e831e)
1 /*
2  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
3  * Written by Jean-Jacques Hiblot  <jjhiblot@ti.com>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <generic-phy.h>
11 
12 static inline struct phy_ops *phy_dev_ops(struct udevice *dev)
13 {
14 	return (struct phy_ops *)dev->driver->ops;
15 }
16 
17 static int generic_phy_xlate_offs_flags(struct phy *phy,
18 					struct ofnode_phandle_args *args)
19 {
20 	debug("%s(phy=%p)\n", __func__, phy);
21 
22 	if (args->args_count > 1) {
23 		debug("Invaild args_count: %d\n", args->args_count);
24 		return -EINVAL;
25 	}
26 
27 	if (args->args_count)
28 		phy->id = args->args[0];
29 	else
30 		phy->id = 0;
31 
32 	return 0;
33 }
34 
35 int generic_phy_get_by_index(struct udevice *dev, int index,
36 			     struct phy *phy)
37 {
38 	struct ofnode_phandle_args args;
39 	struct phy_ops *ops;
40 	int ret;
41 	struct udevice *phydev;
42 
43 	debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy);
44 
45 	assert(phy);
46 	phy->dev = NULL;
47 	ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index,
48 					 &args);
49 	if (ret) {
50 		debug("%s: dev_read_phandle_with_args failed: err=%d\n",
51 		      __func__, ret);
52 		return ret;
53 	}
54 
55 	ret = uclass_get_device_by_ofnode(UCLASS_PHY, args.node, &phydev);
56 	if (ret) {
57 		debug("%s: uclass_get_device_by_ofnode failed: err=%d\n",
58 		      __func__, ret);
59 		return ret;
60 	}
61 
62 	phy->dev = phydev;
63 
64 	ops = phy_dev_ops(phydev);
65 
66 	if (ops->of_xlate)
67 		ret = ops->of_xlate(phy, &args);
68 	else
69 		ret = generic_phy_xlate_offs_flags(phy, &args);
70 	if (ret) {
71 		debug("of_xlate() failed: %d\n", ret);
72 		goto err;
73 	}
74 
75 	return 0;
76 
77 err:
78 	return ret;
79 }
80 
81 int generic_phy_get_by_name(struct udevice *dev, const char *phy_name,
82 			    struct phy *phy)
83 {
84 	int index;
85 
86 	debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy);
87 
88 	index = dev_read_stringlist_search(dev, "phy-names", phy_name);
89 	if (index < 0) {
90 		debug("dev_read_stringlist_search() failed: %d\n", index);
91 		return index;
92 	}
93 
94 	return generic_phy_get_by_index(dev, index, phy);
95 }
96 
97 int generic_phy_init(struct phy *phy)
98 {
99 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
100 
101 	return ops->init ? ops->init(phy) : 0;
102 }
103 
104 int generic_phy_reset(struct phy *phy)
105 {
106 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
107 
108 	return ops->reset ? ops->reset(phy) : 0;
109 }
110 
111 int generic_phy_exit(struct phy *phy)
112 {
113 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
114 
115 	return ops->exit ? ops->exit(phy) : 0;
116 }
117 
118 int generic_phy_power_on(struct phy *phy)
119 {
120 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
121 
122 	return ops->power_on ? ops->power_on(phy) : 0;
123 }
124 
125 int generic_phy_power_off(struct phy *phy)
126 {
127 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
128 
129 	return ops->power_off ? ops->power_off(phy) : 0;
130 }
131 
132 UCLASS_DRIVER(phy) = {
133 	.id		= UCLASS_PHY,
134 	.name		= "phy",
135 };
136