172e5016fSJean-Jacques Hiblot /*
272e5016fSJean-Jacques Hiblot * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
372e5016fSJean-Jacques Hiblot * Written by Jean-Jacques Hiblot <jjhiblot@ti.com>
472e5016fSJean-Jacques Hiblot *
572e5016fSJean-Jacques Hiblot * SPDX-License-Identifier: GPL-2.0+
672e5016fSJean-Jacques Hiblot */
772e5016fSJean-Jacques Hiblot
872e5016fSJean-Jacques Hiblot #include <common.h>
972e5016fSJean-Jacques Hiblot #include <dm.h>
1072e5016fSJean-Jacques Hiblot #include <generic-phy.h>
11*6ef8929cSAlper Nebi Yasak #include <linux/list.h>
12*6ef8929cSAlper Nebi Yasak
13*6ef8929cSAlper Nebi Yasak /**
14*6ef8929cSAlper Nebi Yasak * struct phy_counts - Init and power-on counts of a single PHY port
15*6ef8929cSAlper Nebi Yasak *
16*6ef8929cSAlper Nebi Yasak * This structure is used to keep track of PHY initialization and power
17*6ef8929cSAlper Nebi Yasak * state change requests, so that we don't power off and deinitialize a
18*6ef8929cSAlper Nebi Yasak * PHY instance until all of its users want it done. Otherwise, multiple
19*6ef8929cSAlper Nebi Yasak * consumers using the same PHY port can cause problems (e.g. one might
20*6ef8929cSAlper Nebi Yasak * call power_off() after another's exit() and hang indefinitely).
21*6ef8929cSAlper Nebi Yasak *
22*6ef8929cSAlper Nebi Yasak * @id: The PHY ID within a PHY provider
23*6ef8929cSAlper Nebi Yasak * @power_on_count: Times generic_phy_power_on() was called for this ID
24*6ef8929cSAlper Nebi Yasak * without a matching generic_phy_power_off() afterwards
25*6ef8929cSAlper Nebi Yasak * @init_count: Times generic_phy_init() was called for this ID
26*6ef8929cSAlper Nebi Yasak * without a matching generic_phy_exit() afterwards
27*6ef8929cSAlper Nebi Yasak * @list: Handle for a linked list of these structures corresponding to
28*6ef8929cSAlper Nebi Yasak * ports of the same PHY provider
29*6ef8929cSAlper Nebi Yasak */
30*6ef8929cSAlper Nebi Yasak struct phy_counts {
31*6ef8929cSAlper Nebi Yasak unsigned long id;
32*6ef8929cSAlper Nebi Yasak int power_on_count;
33*6ef8929cSAlper Nebi Yasak int init_count;
34*6ef8929cSAlper Nebi Yasak struct list_head list;
35*6ef8929cSAlper Nebi Yasak };
3672e5016fSJean-Jacques Hiblot
3772e5016fSJean-Jacques Hiblot DECLARE_GLOBAL_DATA_PTR;
3872e5016fSJean-Jacques Hiblot
phy_dev_ops(struct udevice * dev)3972e5016fSJean-Jacques Hiblot static inline struct phy_ops *phy_dev_ops(struct udevice *dev)
4072e5016fSJean-Jacques Hiblot {
4172e5016fSJean-Jacques Hiblot return (struct phy_ops *)dev->driver->ops;
4272e5016fSJean-Jacques Hiblot }
4372e5016fSJean-Jacques Hiblot
phy_get_counts(struct phy * phy)44*6ef8929cSAlper Nebi Yasak static struct phy_counts *phy_get_counts(struct phy *phy)
45*6ef8929cSAlper Nebi Yasak {
46*6ef8929cSAlper Nebi Yasak struct list_head *uc_priv;
47*6ef8929cSAlper Nebi Yasak struct phy_counts *counts;
48*6ef8929cSAlper Nebi Yasak
49*6ef8929cSAlper Nebi Yasak if (!generic_phy_valid(phy))
50*6ef8929cSAlper Nebi Yasak return NULL;
51*6ef8929cSAlper Nebi Yasak
52*6ef8929cSAlper Nebi Yasak uc_priv = dev_get_uclass_priv(phy->dev);
53*6ef8929cSAlper Nebi Yasak list_for_each_entry(counts, uc_priv, list)
54*6ef8929cSAlper Nebi Yasak if (counts->id == phy->id)
55*6ef8929cSAlper Nebi Yasak return counts;
56*6ef8929cSAlper Nebi Yasak
57*6ef8929cSAlper Nebi Yasak return NULL;
58*6ef8929cSAlper Nebi Yasak }
59*6ef8929cSAlper Nebi Yasak
phy_alloc_counts(struct phy * phy)60*6ef8929cSAlper Nebi Yasak static int phy_alloc_counts(struct phy *phy)
61*6ef8929cSAlper Nebi Yasak {
62*6ef8929cSAlper Nebi Yasak struct list_head *uc_priv;
63*6ef8929cSAlper Nebi Yasak struct phy_counts *counts;
64*6ef8929cSAlper Nebi Yasak
65*6ef8929cSAlper Nebi Yasak if (!generic_phy_valid(phy))
66*6ef8929cSAlper Nebi Yasak return 0;
67*6ef8929cSAlper Nebi Yasak if (phy_get_counts(phy))
68*6ef8929cSAlper Nebi Yasak return 0;
69*6ef8929cSAlper Nebi Yasak
70*6ef8929cSAlper Nebi Yasak uc_priv = dev_get_uclass_priv(phy->dev);
71*6ef8929cSAlper Nebi Yasak counts = kzalloc(sizeof(*counts), GFP_KERNEL);
72*6ef8929cSAlper Nebi Yasak if (!counts)
73*6ef8929cSAlper Nebi Yasak return -ENOMEM;
74*6ef8929cSAlper Nebi Yasak
75*6ef8929cSAlper Nebi Yasak counts->id = phy->id;
76*6ef8929cSAlper Nebi Yasak counts->power_on_count = 0;
77*6ef8929cSAlper Nebi Yasak counts->init_count = 0;
78*6ef8929cSAlper Nebi Yasak list_add(&counts->list, uc_priv);
79*6ef8929cSAlper Nebi Yasak
80*6ef8929cSAlper Nebi Yasak return 0;
81*6ef8929cSAlper Nebi Yasak }
82*6ef8929cSAlper Nebi Yasak
phy_uclass_pre_probe(struct udevice * dev)83*6ef8929cSAlper Nebi Yasak static int phy_uclass_pre_probe(struct udevice *dev)
84*6ef8929cSAlper Nebi Yasak {
85*6ef8929cSAlper Nebi Yasak struct list_head *uc_priv = dev_get_uclass_priv(dev);
86*6ef8929cSAlper Nebi Yasak
87*6ef8929cSAlper Nebi Yasak INIT_LIST_HEAD(uc_priv);
88*6ef8929cSAlper Nebi Yasak
89*6ef8929cSAlper Nebi Yasak return 0;
90*6ef8929cSAlper Nebi Yasak }
91*6ef8929cSAlper Nebi Yasak
phy_uclass_pre_remove(struct udevice * dev)92*6ef8929cSAlper Nebi Yasak static int phy_uclass_pre_remove(struct udevice *dev)
93*6ef8929cSAlper Nebi Yasak {
94*6ef8929cSAlper Nebi Yasak struct list_head *uc_priv = dev_get_uclass_priv(dev);
95*6ef8929cSAlper Nebi Yasak struct phy_counts *counts, *next;
96*6ef8929cSAlper Nebi Yasak
97*6ef8929cSAlper Nebi Yasak list_for_each_entry_safe(counts, next, uc_priv, list)
98*6ef8929cSAlper Nebi Yasak kfree(counts);
99*6ef8929cSAlper Nebi Yasak
100*6ef8929cSAlper Nebi Yasak return 0;
101*6ef8929cSAlper Nebi Yasak }
102*6ef8929cSAlper Nebi Yasak
generic_phy_xlate_offs_flags(struct phy * phy,struct ofnode_phandle_args * args)10372e5016fSJean-Jacques Hiblot static int generic_phy_xlate_offs_flags(struct phy *phy,
10423558bb6SSimon Glass struct ofnode_phandle_args *args)
10572e5016fSJean-Jacques Hiblot {
10672e5016fSJean-Jacques Hiblot debug("%s(phy=%p)\n", __func__, phy);
10772e5016fSJean-Jacques Hiblot
10872e5016fSJean-Jacques Hiblot if (args->args_count > 1) {
10972e5016fSJean-Jacques Hiblot debug("Invaild args_count: %d\n", args->args_count);
11072e5016fSJean-Jacques Hiblot return -EINVAL;
11172e5016fSJean-Jacques Hiblot }
11272e5016fSJean-Jacques Hiblot
11372e5016fSJean-Jacques Hiblot if (args->args_count)
11472e5016fSJean-Jacques Hiblot phy->id = args->args[0];
11572e5016fSJean-Jacques Hiblot else
11672e5016fSJean-Jacques Hiblot phy->id = 0;
11772e5016fSJean-Jacques Hiblot
11872e5016fSJean-Jacques Hiblot return 0;
11972e5016fSJean-Jacques Hiblot }
12072e5016fSJean-Jacques Hiblot
generic_phy_get_by_index(struct udevice * dev,int index,struct phy * phy)12172e5016fSJean-Jacques Hiblot int generic_phy_get_by_index(struct udevice *dev, int index,
12272e5016fSJean-Jacques Hiblot struct phy *phy)
12372e5016fSJean-Jacques Hiblot {
12423558bb6SSimon Glass struct ofnode_phandle_args args;
12572e5016fSJean-Jacques Hiblot struct phy_ops *ops;
12672e5016fSJean-Jacques Hiblot int ret;
12772e5016fSJean-Jacques Hiblot struct udevice *phydev;
12872e5016fSJean-Jacques Hiblot
12972e5016fSJean-Jacques Hiblot debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy);
13072e5016fSJean-Jacques Hiblot
13172e5016fSJean-Jacques Hiblot assert(phy);
132b9688df3SPatrice Chotard phy->dev = NULL;
13323558bb6SSimon Glass ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index,
13472e5016fSJean-Jacques Hiblot &args);
13572e5016fSJean-Jacques Hiblot if (ret) {
13623558bb6SSimon Glass debug("%s: dev_read_phandle_with_args failed: err=%d\n",
13772e5016fSJean-Jacques Hiblot __func__, ret);
13872e5016fSJean-Jacques Hiblot return ret;
13972e5016fSJean-Jacques Hiblot }
14072e5016fSJean-Jacques Hiblot
14123558bb6SSimon Glass ret = uclass_get_device_by_ofnode(UCLASS_PHY, args.node, &phydev);
14272e5016fSJean-Jacques Hiblot if (ret) {
14323558bb6SSimon Glass debug("%s: uclass_get_device_by_ofnode failed: err=%d\n",
14472e5016fSJean-Jacques Hiblot __func__, ret);
14572e5016fSJean-Jacques Hiblot return ret;
14672e5016fSJean-Jacques Hiblot }
14772e5016fSJean-Jacques Hiblot
14872e5016fSJean-Jacques Hiblot phy->dev = phydev;
14972e5016fSJean-Jacques Hiblot
15072e5016fSJean-Jacques Hiblot ops = phy_dev_ops(phydev);
15172e5016fSJean-Jacques Hiblot
15272e5016fSJean-Jacques Hiblot if (ops->of_xlate)
15372e5016fSJean-Jacques Hiblot ret = ops->of_xlate(phy, &args);
15472e5016fSJean-Jacques Hiblot else
15572e5016fSJean-Jacques Hiblot ret = generic_phy_xlate_offs_flags(phy, &args);
15672e5016fSJean-Jacques Hiblot if (ret) {
15772e5016fSJean-Jacques Hiblot debug("of_xlate() failed: %d\n", ret);
15872e5016fSJean-Jacques Hiblot goto err;
15972e5016fSJean-Jacques Hiblot }
16072e5016fSJean-Jacques Hiblot
161*6ef8929cSAlper Nebi Yasak ret = phy_alloc_counts(phy);
162*6ef8929cSAlper Nebi Yasak if (ret) {
163*6ef8929cSAlper Nebi Yasak debug("phy_alloc_counts() failed: %d\n", ret);
164*6ef8929cSAlper Nebi Yasak goto err;
165*6ef8929cSAlper Nebi Yasak }
166*6ef8929cSAlper Nebi Yasak
16772e5016fSJean-Jacques Hiblot return 0;
16872e5016fSJean-Jacques Hiblot
16972e5016fSJean-Jacques Hiblot err:
17072e5016fSJean-Jacques Hiblot return ret;
17172e5016fSJean-Jacques Hiblot }
17272e5016fSJean-Jacques Hiblot
generic_phy_get_by_name(struct udevice * dev,const char * phy_name,struct phy * phy)17372e5016fSJean-Jacques Hiblot int generic_phy_get_by_name(struct udevice *dev, const char *phy_name,
17472e5016fSJean-Jacques Hiblot struct phy *phy)
17572e5016fSJean-Jacques Hiblot {
17672e5016fSJean-Jacques Hiblot int index;
17772e5016fSJean-Jacques Hiblot
17872e5016fSJean-Jacques Hiblot debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy);
17972e5016fSJean-Jacques Hiblot
18023558bb6SSimon Glass index = dev_read_stringlist_search(dev, "phy-names", phy_name);
18172e5016fSJean-Jacques Hiblot if (index < 0) {
18223558bb6SSimon Glass debug("dev_read_stringlist_search() failed: %d\n", index);
18372e5016fSJean-Jacques Hiblot return index;
18472e5016fSJean-Jacques Hiblot }
18572e5016fSJean-Jacques Hiblot
18672e5016fSJean-Jacques Hiblot return generic_phy_get_by_index(dev, index, phy);
18772e5016fSJean-Jacques Hiblot }
18872e5016fSJean-Jacques Hiblot
generic_phy_init(struct phy * phy)18972e5016fSJean-Jacques Hiblot int generic_phy_init(struct phy *phy)
19072e5016fSJean-Jacques Hiblot {
191*6ef8929cSAlper Nebi Yasak struct phy_counts *counts;
1921bac1f39SJean-Jacques Hiblot struct phy_ops const *ops;
193*6ef8929cSAlper Nebi Yasak int ret;
1941bac1f39SJean-Jacques Hiblot
19537a5e4d8SVignesh Raghavendra if (!generic_phy_valid(phy))
1961bac1f39SJean-Jacques Hiblot return 0;
1971bac1f39SJean-Jacques Hiblot ops = phy_dev_ops(phy->dev);
198*6ef8929cSAlper Nebi Yasak if (!ops->init)
199*6ef8929cSAlper Nebi Yasak return 0;
20072e5016fSJean-Jacques Hiblot
201*6ef8929cSAlper Nebi Yasak counts = phy_get_counts(phy);
202*6ef8929cSAlper Nebi Yasak if (counts->init_count > 0) {
203*6ef8929cSAlper Nebi Yasak counts->init_count++;
204*6ef8929cSAlper Nebi Yasak return 0;
205*6ef8929cSAlper Nebi Yasak }
206*6ef8929cSAlper Nebi Yasak
207*6ef8929cSAlper Nebi Yasak ret = ops->init(phy);
208*6ef8929cSAlper Nebi Yasak if (ret)
209*6ef8929cSAlper Nebi Yasak dev_err(phy->dev, "PHY: Failed to init %s: %d.\n",
210*6ef8929cSAlper Nebi Yasak phy->dev->name, ret);
211*6ef8929cSAlper Nebi Yasak else
212*6ef8929cSAlper Nebi Yasak counts->init_count = 1;
213*6ef8929cSAlper Nebi Yasak
214*6ef8929cSAlper Nebi Yasak return 0;
21572e5016fSJean-Jacques Hiblot }
21672e5016fSJean-Jacques Hiblot
generic_phy_reset(struct phy * phy)21772e5016fSJean-Jacques Hiblot int generic_phy_reset(struct phy *phy)
21872e5016fSJean-Jacques Hiblot {
2191bac1f39SJean-Jacques Hiblot struct phy_ops const *ops;
2201bac1f39SJean-Jacques Hiblot
22137a5e4d8SVignesh Raghavendra if (!generic_phy_valid(phy))
2221bac1f39SJean-Jacques Hiblot return 0;
2231bac1f39SJean-Jacques Hiblot ops = phy_dev_ops(phy->dev);
22472e5016fSJean-Jacques Hiblot
22572e5016fSJean-Jacques Hiblot return ops->reset ? ops->reset(phy) : 0;
22672e5016fSJean-Jacques Hiblot }
22772e5016fSJean-Jacques Hiblot
generic_phy_exit(struct phy * phy)22872e5016fSJean-Jacques Hiblot int generic_phy_exit(struct phy *phy)
22972e5016fSJean-Jacques Hiblot {
230*6ef8929cSAlper Nebi Yasak struct phy_counts *counts;
2311bac1f39SJean-Jacques Hiblot struct phy_ops const *ops;
232*6ef8929cSAlper Nebi Yasak int ret;
2331bac1f39SJean-Jacques Hiblot
23437a5e4d8SVignesh Raghavendra if (!generic_phy_valid(phy))
2351bac1f39SJean-Jacques Hiblot return 0;
2361bac1f39SJean-Jacques Hiblot ops = phy_dev_ops(phy->dev);
237*6ef8929cSAlper Nebi Yasak if (!ops->exit)
238*6ef8929cSAlper Nebi Yasak return 0;
23972e5016fSJean-Jacques Hiblot
240*6ef8929cSAlper Nebi Yasak counts = phy_get_counts(phy);
241*6ef8929cSAlper Nebi Yasak if (counts->init_count == 0)
242*6ef8929cSAlper Nebi Yasak return 0;
243*6ef8929cSAlper Nebi Yasak if (counts->init_count > 1) {
244*6ef8929cSAlper Nebi Yasak counts->init_count--;
245*6ef8929cSAlper Nebi Yasak return 0;
246*6ef8929cSAlper Nebi Yasak }
247*6ef8929cSAlper Nebi Yasak
248*6ef8929cSAlper Nebi Yasak ret = ops->exit(phy);
249*6ef8929cSAlper Nebi Yasak if (ret)
250*6ef8929cSAlper Nebi Yasak dev_err(phy->dev, "PHY: Failed to exit %s: %d.\n",
251*6ef8929cSAlper Nebi Yasak phy->dev->name, ret);
252*6ef8929cSAlper Nebi Yasak else
253*6ef8929cSAlper Nebi Yasak counts->init_count = 0;
254*6ef8929cSAlper Nebi Yasak
255*6ef8929cSAlper Nebi Yasak return 0;
25672e5016fSJean-Jacques Hiblot }
25772e5016fSJean-Jacques Hiblot
generic_phy_power_on(struct phy * phy)25872e5016fSJean-Jacques Hiblot int generic_phy_power_on(struct phy *phy)
25972e5016fSJean-Jacques Hiblot {
260*6ef8929cSAlper Nebi Yasak struct phy_counts *counts;
2611bac1f39SJean-Jacques Hiblot struct phy_ops const *ops;
262*6ef8929cSAlper Nebi Yasak int ret;
2631bac1f39SJean-Jacques Hiblot
26437a5e4d8SVignesh Raghavendra if (!generic_phy_valid(phy))
2651bac1f39SJean-Jacques Hiblot return 0;
2661bac1f39SJean-Jacques Hiblot ops = phy_dev_ops(phy->dev);
267*6ef8929cSAlper Nebi Yasak if (!ops->power_on)
268*6ef8929cSAlper Nebi Yasak return 0;
26972e5016fSJean-Jacques Hiblot
270*6ef8929cSAlper Nebi Yasak counts = phy_get_counts(phy);
271*6ef8929cSAlper Nebi Yasak if (counts->power_on_count > 0) {
272*6ef8929cSAlper Nebi Yasak counts->power_on_count++;
273*6ef8929cSAlper Nebi Yasak return 0;
274*6ef8929cSAlper Nebi Yasak }
275*6ef8929cSAlper Nebi Yasak
276*6ef8929cSAlper Nebi Yasak ret = ops->power_on(phy);
277*6ef8929cSAlper Nebi Yasak if (ret)
278*6ef8929cSAlper Nebi Yasak dev_err(phy->dev, "PHY: Failed to power on %s: %d.\n",
279*6ef8929cSAlper Nebi Yasak phy->dev->name, ret);
280*6ef8929cSAlper Nebi Yasak else
281*6ef8929cSAlper Nebi Yasak counts->power_on_count = 1;
282*6ef8929cSAlper Nebi Yasak
283*6ef8929cSAlper Nebi Yasak return 0;
28472e5016fSJean-Jacques Hiblot }
28572e5016fSJean-Jacques Hiblot
generic_phy_power_off(struct phy * phy)28672e5016fSJean-Jacques Hiblot int generic_phy_power_off(struct phy *phy)
28772e5016fSJean-Jacques Hiblot {
288*6ef8929cSAlper Nebi Yasak struct phy_counts *counts;
2891bac1f39SJean-Jacques Hiblot struct phy_ops const *ops;
290*6ef8929cSAlper Nebi Yasak int ret;
2911bac1f39SJean-Jacques Hiblot
29237a5e4d8SVignesh Raghavendra if (!generic_phy_valid(phy))
2931bac1f39SJean-Jacques Hiblot return 0;
2941bac1f39SJean-Jacques Hiblot ops = phy_dev_ops(phy->dev);
295*6ef8929cSAlper Nebi Yasak if (!ops->power_off)
296*6ef8929cSAlper Nebi Yasak return 0;
29772e5016fSJean-Jacques Hiblot
298*6ef8929cSAlper Nebi Yasak counts = phy_get_counts(phy);
299*6ef8929cSAlper Nebi Yasak if (counts->power_on_count == 0)
300*6ef8929cSAlper Nebi Yasak return 0;
301*6ef8929cSAlper Nebi Yasak if (counts->power_on_count > 1) {
302*6ef8929cSAlper Nebi Yasak counts->power_on_count--;
303*6ef8929cSAlper Nebi Yasak return 0;
304*6ef8929cSAlper Nebi Yasak }
305*6ef8929cSAlper Nebi Yasak
306*6ef8929cSAlper Nebi Yasak ret = ops->power_off(phy);
307*6ef8929cSAlper Nebi Yasak if (ret)
308*6ef8929cSAlper Nebi Yasak dev_err(phy->dev, "PHY: Failed to power off %s: %d.\n",
309*6ef8929cSAlper Nebi Yasak phy->dev->name, ret);
310*6ef8929cSAlper Nebi Yasak else
311*6ef8929cSAlper Nebi Yasak counts->power_on_count = 0;
312*6ef8929cSAlper Nebi Yasak
313*6ef8929cSAlper Nebi Yasak return 0;
31472e5016fSJean-Jacques Hiblot }
31572e5016fSJean-Jacques Hiblot
generic_phy_configure(struct phy * phy,union phy_configure_opts * opts)3164ef09685SWyon Bi int generic_phy_configure(struct phy *phy, union phy_configure_opts *opts)
3174ef09685SWyon Bi {
3184ef09685SWyon Bi struct phy_ops const *ops;
3194ef09685SWyon Bi
3204ef09685SWyon Bi if (!generic_phy_valid(phy))
3214ef09685SWyon Bi return 0;
3224ef09685SWyon Bi ops = phy_dev_ops(phy->dev);
3234ef09685SWyon Bi
3244ef09685SWyon Bi return ops->configure ? ops->configure(phy, opts) : 0;
3254ef09685SWyon Bi }
3264ef09685SWyon Bi
generic_phy_validate(struct phy * phy,enum phy_mode mode,int submode,union phy_configure_opts * opts)3274ef09685SWyon Bi int generic_phy_validate(struct phy *phy, enum phy_mode mode, int submode,
3284ef09685SWyon Bi union phy_configure_opts *opts)
3294ef09685SWyon Bi {
3304ef09685SWyon Bi struct phy_ops const *ops;
3314ef09685SWyon Bi
3324ef09685SWyon Bi if (!generic_phy_valid(phy))
3334ef09685SWyon Bi return 0;
3344ef09685SWyon Bi ops = phy_dev_ops(phy->dev);
3354ef09685SWyon Bi
3364ef09685SWyon Bi return ops->validate ? ops->validate(phy, mode, submode, opts) : 0;
3374ef09685SWyon Bi }
3384ef09685SWyon Bi
generic_phy_set_mode_ext(struct phy * phy,enum phy_mode mode,int submode)339e9c6c0e2SWyon Bi int generic_phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode)
340e9c6c0e2SWyon Bi {
341e9c6c0e2SWyon Bi struct phy_ops const *ops;
342e9c6c0e2SWyon Bi int ret;
343e9c6c0e2SWyon Bi
344e9c6c0e2SWyon Bi if (!generic_phy_valid(phy))
345e9c6c0e2SWyon Bi return 0;
346e9c6c0e2SWyon Bi ops = phy_dev_ops(phy->dev);
347e9c6c0e2SWyon Bi
348e9c6c0e2SWyon Bi if (!ops->set_mode)
349e9c6c0e2SWyon Bi return 0;
350e9c6c0e2SWyon Bi
351e9c6c0e2SWyon Bi ret = ops->set_mode(phy, mode, submode);
352e9c6c0e2SWyon Bi if (!ret)
353e9c6c0e2SWyon Bi phy->attrs.mode = mode;
354e9c6c0e2SWyon Bi
355e9c6c0e2SWyon Bi return ret;
356e9c6c0e2SWyon Bi }
357e9c6c0e2SWyon Bi
35872e5016fSJean-Jacques Hiblot UCLASS_DRIVER(phy) = {
35972e5016fSJean-Jacques Hiblot .id = UCLASS_PHY,
36072e5016fSJean-Jacques Hiblot .name = "phy",
361*6ef8929cSAlper Nebi Yasak .pre_probe = phy_uclass_pre_probe,
362*6ef8929cSAlper Nebi Yasak .pre_remove = phy_uclass_pre_remove,
363*6ef8929cSAlper Nebi Yasak .per_device_auto_alloc_size = sizeof(struct list_head),
36472e5016fSJean-Jacques Hiblot };
365