Merge git://git.denx.de/u-boot-usb
[platform/kernel/u-boot.git] / drivers / phy / phy-uclass.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
4  * Written by Jean-Jacques Hiblot  <jjhiblot@ti.com>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <dm/devres.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_node(ofnode node, int index, struct phy *phy)
36 {
37         struct ofnode_phandle_args args;
38         struct phy_ops *ops;
39         struct udevice *phydev;
40         int i, ret;
41
42         debug("%s(node=%s, index=%d, phy=%p)\n",
43               __func__, ofnode_get_name(node), index, phy);
44
45         assert(phy);
46         phy->dev = NULL;
47         ret = ofnode_parse_phandle_with_args(node, "phys", "#phy-cells", 0,
48                                              index, &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
60                 /* Check if args.node's parent is a PHY provider */
61                 ret = uclass_get_device_by_ofnode(UCLASS_PHY,
62                                                   ofnode_get_parent(args.node),
63                                                   &phydev);
64                 if (ret)
65                         return ret;
66
67                 /* insert phy idx at first position into args array */
68                 for (i = args.args_count; i >= 1 ; i--)
69                         args.args[i] = args.args[i - 1];
70
71                 args.args_count++;
72                 args.args[0] = ofnode_read_u32_default(args.node, "reg", -1);
73         }
74
75         phy->dev = phydev;
76
77         ops = phy_dev_ops(phydev);
78
79         if (ops->of_xlate)
80                 ret = ops->of_xlate(phy, &args);
81         else
82                 ret = generic_phy_xlate_offs_flags(phy, &args);
83         if (ret) {
84                 debug("of_xlate() failed: %d\n", ret);
85                 goto err;
86         }
87
88         return 0;
89
90 err:
91         return ret;
92 }
93
94 int generic_phy_get_by_index(struct udevice *dev, int index,
95                              struct phy *phy)
96 {
97         return generic_phy_get_by_node(dev_ofnode(dev), index, phy);
98 }
99
100 int generic_phy_get_by_name(struct udevice *dev, const char *phy_name,
101                             struct phy *phy)
102 {
103         int index;
104
105         debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy);
106
107         index = dev_read_stringlist_search(dev, "phy-names", phy_name);
108         if (index < 0) {
109                 debug("dev_read_stringlist_search() failed: %d\n", index);
110                 return index;
111         }
112
113         return generic_phy_get_by_index(dev, index, phy);
114 }
115
116 int generic_phy_init(struct phy *phy)
117 {
118         struct phy_ops const *ops;
119
120         if (!phy)
121                 return 0;
122         ops = phy_dev_ops(phy->dev);
123
124         return ops->init ? ops->init(phy) : 0;
125 }
126
127 int generic_phy_reset(struct phy *phy)
128 {
129         struct phy_ops const *ops;
130
131         if (!phy)
132                 return 0;
133         ops = phy_dev_ops(phy->dev);
134
135         return ops->reset ? ops->reset(phy) : 0;
136 }
137
138 int generic_phy_exit(struct phy *phy)
139 {
140         struct phy_ops const *ops;
141
142         if (!phy)
143                 return 0;
144         ops = phy_dev_ops(phy->dev);
145
146         return ops->exit ? ops->exit(phy) : 0;
147 }
148
149 int generic_phy_power_on(struct phy *phy)
150 {
151         struct phy_ops const *ops;
152
153         if (!phy)
154                 return 0;
155         ops = phy_dev_ops(phy->dev);
156
157         return ops->power_on ? ops->power_on(phy) : 0;
158 }
159
160 int generic_phy_power_off(struct phy *phy)
161 {
162         struct phy_ops const *ops;
163
164         if (!phy)
165                 return 0;
166         ops = phy_dev_ops(phy->dev);
167
168         return ops->power_off ? ops->power_off(phy) : 0;
169 }
170
171 int generic_phy_get_bulk(struct udevice *dev, struct phy_bulk *bulk)
172 {
173         int i, ret, count;
174
175         bulk->count = 0;
176
177         /* Return if no phy declared */
178         if (!dev_read_prop(dev, "phys", NULL))
179                 return 0;
180
181         count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
182         if (count < 1)
183                 return count;
184
185         bulk->phys = devm_kcalloc(dev, count, sizeof(struct phy), GFP_KERNEL);
186         if (!bulk->phys)
187                 return -ENOMEM;
188
189         for (i = 0; i < count; i++) {
190                 ret = generic_phy_get_by_index(dev, i, &bulk->phys[i]);
191                 if (ret) {
192                         pr_err("Failed to get PHY%d for %s\n", i, dev->name);
193                         return ret;
194                 }
195                 bulk->count++;
196         }
197
198         return 0;
199 }
200
201 int generic_phy_init_bulk(struct phy_bulk *bulk)
202 {
203         struct phy *phys = bulk->phys;
204         int i, ret;
205
206         for (i = 0; i < bulk->count; i++) {
207                 ret = generic_phy_init(&phys[i]);
208                 if (ret) {
209                         pr_err("Can't init PHY%d\n", i);
210                         goto phys_init_err;
211                 }
212         }
213
214         return 0;
215
216 phys_init_err:
217         for (; i > 0; i--)
218                 generic_phy_exit(&phys[i - 1]);
219
220         return ret;
221 }
222
223 int generic_phy_exit_bulk(struct phy_bulk *bulk)
224 {
225         struct phy *phys = bulk->phys;
226         int i, ret = 0;
227
228         for (i = 0; i < bulk->count; i++)
229                 ret |= generic_phy_exit(&phys[i]);
230
231         return ret;
232 }
233
234 int generic_phy_power_on_bulk(struct phy_bulk *bulk)
235 {
236         struct phy *phys = bulk->phys;
237         int i, ret;
238
239         for (i = 0; i < bulk->count; i++) {
240                 ret = generic_phy_power_on(&phys[i]);
241                 if (ret) {
242                         pr_err("Can't power on PHY%d\n", i);
243                         goto phys_poweron_err;
244                 }
245         }
246
247         return 0;
248
249 phys_poweron_err:
250         for (; i > 0; i--)
251                 generic_phy_power_off(&phys[i - 1]);
252
253         return ret;
254 }
255
256 int generic_phy_power_off_bulk(struct phy_bulk *bulk)
257 {
258         struct phy *phys = bulk->phys;
259         int i, ret = 0;
260
261         for (i = 0; i < bulk->count; i++)
262                 ret |= generic_phy_power_off(&phys[i]);
263
264         return ret;
265 }
266
267 UCLASS_DRIVER(phy) = {
268         .id             = UCLASS_PHY,
269         .name           = "phy",
270 };