xref: /rk3399_rockchip-uboot/drivers/phy/phy-uclass.c (revision 6ef8929c2f7fa35e3ae40c298f042aa1dd53ae27)
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 #include <linux/list.h>
12 
13 /**
14  * struct phy_counts - Init and power-on counts of a single PHY port
15  *
16  * This structure is used to keep track of PHY initialization and power
17  * state change requests, so that we don't power off and deinitialize a
18  * PHY instance until all of its users want it done. Otherwise, multiple
19  * consumers using the same PHY port can cause problems (e.g. one might
20  * call power_off() after another's exit() and hang indefinitely).
21  *
22  * @id: The PHY ID within a PHY provider
23  * @power_on_count: Times generic_phy_power_on() was called for this ID
24  *                  without a matching generic_phy_power_off() afterwards
25  * @init_count: Times generic_phy_init() was called for this ID
26  *              without a matching generic_phy_exit() afterwards
27  * @list: Handle for a linked list of these structures corresponding to
28  *        ports of the same PHY provider
29  */
30 struct phy_counts {
31 	unsigned long id;
32 	int power_on_count;
33 	int init_count;
34 	struct list_head list;
35 };
36 
37 DECLARE_GLOBAL_DATA_PTR;
38 
phy_dev_ops(struct udevice * dev)39 static inline struct phy_ops *phy_dev_ops(struct udevice *dev)
40 {
41 	return (struct phy_ops *)dev->driver->ops;
42 }
43 
phy_get_counts(struct phy * phy)44 static struct phy_counts *phy_get_counts(struct phy *phy)
45 {
46 	struct list_head *uc_priv;
47 	struct phy_counts *counts;
48 
49 	if (!generic_phy_valid(phy))
50 		return NULL;
51 
52 	uc_priv = dev_get_uclass_priv(phy->dev);
53 	list_for_each_entry(counts, uc_priv, list)
54 		if (counts->id == phy->id)
55 			return counts;
56 
57 	return NULL;
58 }
59 
phy_alloc_counts(struct phy * phy)60 static int phy_alloc_counts(struct phy *phy)
61 {
62 	struct list_head *uc_priv;
63 	struct phy_counts *counts;
64 
65 	if (!generic_phy_valid(phy))
66 		return 0;
67 	if (phy_get_counts(phy))
68 		return 0;
69 
70 	uc_priv = dev_get_uclass_priv(phy->dev);
71 	counts = kzalloc(sizeof(*counts), GFP_KERNEL);
72 	if (!counts)
73 		return -ENOMEM;
74 
75 	counts->id = phy->id;
76 	counts->power_on_count = 0;
77 	counts->init_count = 0;
78 	list_add(&counts->list, uc_priv);
79 
80 	return 0;
81 }
82 
phy_uclass_pre_probe(struct udevice * dev)83 static int phy_uclass_pre_probe(struct udevice *dev)
84 {
85 	struct list_head *uc_priv = dev_get_uclass_priv(dev);
86 
87 	INIT_LIST_HEAD(uc_priv);
88 
89 	return 0;
90 }
91 
phy_uclass_pre_remove(struct udevice * dev)92 static int phy_uclass_pre_remove(struct udevice *dev)
93 {
94 	struct list_head *uc_priv = dev_get_uclass_priv(dev);
95 	struct phy_counts *counts, *next;
96 
97 	list_for_each_entry_safe(counts, next, uc_priv, list)
98 		kfree(counts);
99 
100 	return 0;
101 }
102 
generic_phy_xlate_offs_flags(struct phy * phy,struct ofnode_phandle_args * args)103 static int generic_phy_xlate_offs_flags(struct phy *phy,
104 					struct ofnode_phandle_args *args)
105 {
106 	debug("%s(phy=%p)\n", __func__, phy);
107 
108 	if (args->args_count > 1) {
109 		debug("Invaild args_count: %d\n", args->args_count);
110 		return -EINVAL;
111 	}
112 
113 	if (args->args_count)
114 		phy->id = args->args[0];
115 	else
116 		phy->id = 0;
117 
118 	return 0;
119 }
120 
generic_phy_get_by_index(struct udevice * dev,int index,struct phy * phy)121 int generic_phy_get_by_index(struct udevice *dev, int index,
122 			     struct phy *phy)
123 {
124 	struct ofnode_phandle_args args;
125 	struct phy_ops *ops;
126 	int ret;
127 	struct udevice *phydev;
128 
129 	debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy);
130 
131 	assert(phy);
132 	phy->dev = NULL;
133 	ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index,
134 					 &args);
135 	if (ret) {
136 		debug("%s: dev_read_phandle_with_args failed: err=%d\n",
137 		      __func__, ret);
138 		return ret;
139 	}
140 
141 	ret = uclass_get_device_by_ofnode(UCLASS_PHY, args.node, &phydev);
142 	if (ret) {
143 		debug("%s: uclass_get_device_by_ofnode failed: err=%d\n",
144 		      __func__, ret);
145 		return ret;
146 	}
147 
148 	phy->dev = phydev;
149 
150 	ops = phy_dev_ops(phydev);
151 
152 	if (ops->of_xlate)
153 		ret = ops->of_xlate(phy, &args);
154 	else
155 		ret = generic_phy_xlate_offs_flags(phy, &args);
156 	if (ret) {
157 		debug("of_xlate() failed: %d\n", ret);
158 		goto err;
159 	}
160 
161 	ret = phy_alloc_counts(phy);
162 	if (ret) {
163 		debug("phy_alloc_counts() failed: %d\n", ret);
164 		goto err;
165 	}
166 
167 	return 0;
168 
169 err:
170 	return ret;
171 }
172 
generic_phy_get_by_name(struct udevice * dev,const char * phy_name,struct phy * phy)173 int generic_phy_get_by_name(struct udevice *dev, const char *phy_name,
174 			    struct phy *phy)
175 {
176 	int index;
177 
178 	debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy);
179 
180 	index = dev_read_stringlist_search(dev, "phy-names", phy_name);
181 	if (index < 0) {
182 		debug("dev_read_stringlist_search() failed: %d\n", index);
183 		return index;
184 	}
185 
186 	return generic_phy_get_by_index(dev, index, phy);
187 }
188 
generic_phy_init(struct phy * phy)189 int generic_phy_init(struct phy *phy)
190 {
191 	struct phy_counts *counts;
192 	struct phy_ops const *ops;
193 	int ret;
194 
195 	if (!generic_phy_valid(phy))
196 		return 0;
197 	ops = phy_dev_ops(phy->dev);
198 	if (!ops->init)
199 		return 0;
200 
201 	counts = phy_get_counts(phy);
202 	if (counts->init_count > 0) {
203 		counts->init_count++;
204 		return 0;
205 	}
206 
207 	ret = ops->init(phy);
208 	if (ret)
209 		dev_err(phy->dev, "PHY: Failed to init %s: %d.\n",
210 			phy->dev->name, ret);
211 	else
212 		counts->init_count = 1;
213 
214 	return 0;
215 }
216 
generic_phy_reset(struct phy * phy)217 int generic_phy_reset(struct phy *phy)
218 {
219 	struct phy_ops const *ops;
220 
221 	if (!generic_phy_valid(phy))
222 		return 0;
223 	ops = phy_dev_ops(phy->dev);
224 
225 	return ops->reset ? ops->reset(phy) : 0;
226 }
227 
generic_phy_exit(struct phy * phy)228 int generic_phy_exit(struct phy *phy)
229 {
230 	struct phy_counts *counts;
231 	struct phy_ops const *ops;
232 	int ret;
233 
234 	if (!generic_phy_valid(phy))
235 		return 0;
236 	ops = phy_dev_ops(phy->dev);
237 	if (!ops->exit)
238 		return 0;
239 
240 	counts = phy_get_counts(phy);
241 	if (counts->init_count == 0)
242 		return 0;
243 	if (counts->init_count > 1) {
244 		counts->init_count--;
245 		return 0;
246 	}
247 
248 	ret = ops->exit(phy);
249 	if (ret)
250 		dev_err(phy->dev, "PHY: Failed to exit %s: %d.\n",
251 			phy->dev->name, ret);
252 	else
253 		counts->init_count = 0;
254 
255 	return 0;
256 }
257 
generic_phy_power_on(struct phy * phy)258 int generic_phy_power_on(struct phy *phy)
259 {
260 	struct phy_counts *counts;
261 	struct phy_ops const *ops;
262 	int ret;
263 
264 	if (!generic_phy_valid(phy))
265 		return 0;
266 	ops = phy_dev_ops(phy->dev);
267 	if (!ops->power_on)
268 		return 0;
269 
270 	counts = phy_get_counts(phy);
271 	if (counts->power_on_count > 0) {
272 		counts->power_on_count++;
273 		return 0;
274 	}
275 
276 	ret = ops->power_on(phy);
277 	if (ret)
278 		dev_err(phy->dev, "PHY: Failed to power on %s: %d.\n",
279 			phy->dev->name, ret);
280 	else
281 		counts->power_on_count = 1;
282 
283 	return 0;
284 }
285 
generic_phy_power_off(struct phy * phy)286 int generic_phy_power_off(struct phy *phy)
287 {
288 	struct phy_counts *counts;
289 	struct phy_ops const *ops;
290 	int ret;
291 
292 	if (!generic_phy_valid(phy))
293 		return 0;
294 	ops = phy_dev_ops(phy->dev);
295 	if (!ops->power_off)
296 		return 0;
297 
298 	counts = phy_get_counts(phy);
299 	if (counts->power_on_count == 0)
300 		return 0;
301 	if (counts->power_on_count > 1) {
302 		counts->power_on_count--;
303 		return 0;
304 	}
305 
306 	ret = ops->power_off(phy);
307 	if (ret)
308 		dev_err(phy->dev, "PHY: Failed to power off %s: %d.\n",
309 			phy->dev->name, ret);
310 	else
311 		counts->power_on_count = 0;
312 
313 	return 0;
314 }
315 
generic_phy_configure(struct phy * phy,union phy_configure_opts * opts)316 int generic_phy_configure(struct phy *phy, union phy_configure_opts *opts)
317 {
318 	struct phy_ops const *ops;
319 
320 	if (!generic_phy_valid(phy))
321 		return 0;
322 	ops = phy_dev_ops(phy->dev);
323 
324 	return ops->configure ? ops->configure(phy, opts) : 0;
325 }
326 
generic_phy_validate(struct phy * phy,enum phy_mode mode,int submode,union phy_configure_opts * opts)327 int generic_phy_validate(struct phy *phy, enum phy_mode mode, int submode,
328 			 union phy_configure_opts *opts)
329 {
330 	struct phy_ops const *ops;
331 
332 	if (!generic_phy_valid(phy))
333 		return 0;
334 	ops = phy_dev_ops(phy->dev);
335 
336 	return ops->validate ? ops->validate(phy, mode, submode, opts) : 0;
337 }
338 
generic_phy_set_mode_ext(struct phy * phy,enum phy_mode mode,int submode)339 int generic_phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode)
340 {
341 	struct phy_ops const *ops;
342 	int ret;
343 
344 	if (!generic_phy_valid(phy))
345 		return 0;
346 	ops = phy_dev_ops(phy->dev);
347 
348 	if (!ops->set_mode)
349 		return 0;
350 
351 	ret = ops->set_mode(phy, mode, submode);
352 	if (!ret)
353 		phy->attrs.mode = mode;
354 
355 	return ret;
356 }
357 
358 UCLASS_DRIVER(phy) = {
359 	.id		= UCLASS_PHY,
360 	.name		= "phy",
361 	.pre_probe	= phy_uclass_pre_probe,
362 	.pre_remove	= phy_uclass_pre_remove,
363 	.per_device_auto_alloc_size = sizeof(struct list_head),
364 };
365