xref: /rk3399_rockchip-uboot/drivers/phy/phy-uclass.c (revision e9c6c0e2da670f7da222c2c7b1f992fda0ffb66a)
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>
1172e5016fSJean-Jacques Hiblot 
1272e5016fSJean-Jacques Hiblot DECLARE_GLOBAL_DATA_PTR;
1372e5016fSJean-Jacques Hiblot 
1472e5016fSJean-Jacques Hiblot static inline struct phy_ops *phy_dev_ops(struct udevice *dev)
1572e5016fSJean-Jacques Hiblot {
1672e5016fSJean-Jacques Hiblot 	return (struct phy_ops *)dev->driver->ops;
1772e5016fSJean-Jacques Hiblot }
1872e5016fSJean-Jacques Hiblot 
1972e5016fSJean-Jacques Hiblot static int generic_phy_xlate_offs_flags(struct phy *phy,
2023558bb6SSimon Glass 					struct ofnode_phandle_args *args)
2172e5016fSJean-Jacques Hiblot {
2272e5016fSJean-Jacques Hiblot 	debug("%s(phy=%p)\n", __func__, phy);
2372e5016fSJean-Jacques Hiblot 
2472e5016fSJean-Jacques Hiblot 	if (args->args_count > 1) {
2572e5016fSJean-Jacques Hiblot 		debug("Invaild args_count: %d\n", args->args_count);
2672e5016fSJean-Jacques Hiblot 		return -EINVAL;
2772e5016fSJean-Jacques Hiblot 	}
2872e5016fSJean-Jacques Hiblot 
2972e5016fSJean-Jacques Hiblot 	if (args->args_count)
3072e5016fSJean-Jacques Hiblot 		phy->id = args->args[0];
3172e5016fSJean-Jacques Hiblot 	else
3272e5016fSJean-Jacques Hiblot 		phy->id = 0;
3372e5016fSJean-Jacques Hiblot 
3472e5016fSJean-Jacques Hiblot 	return 0;
3572e5016fSJean-Jacques Hiblot }
3672e5016fSJean-Jacques Hiblot 
3772e5016fSJean-Jacques Hiblot int generic_phy_get_by_index(struct udevice *dev, int index,
3872e5016fSJean-Jacques Hiblot 			     struct phy *phy)
3972e5016fSJean-Jacques Hiblot {
4023558bb6SSimon Glass 	struct ofnode_phandle_args args;
4172e5016fSJean-Jacques Hiblot 	struct phy_ops *ops;
4272e5016fSJean-Jacques Hiblot 	int ret;
4372e5016fSJean-Jacques Hiblot 	struct udevice *phydev;
4472e5016fSJean-Jacques Hiblot 
4572e5016fSJean-Jacques Hiblot 	debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy);
4672e5016fSJean-Jacques Hiblot 
4772e5016fSJean-Jacques Hiblot 	assert(phy);
48b9688df3SPatrice Chotard 	phy->dev = NULL;
4923558bb6SSimon Glass 	ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index,
5072e5016fSJean-Jacques Hiblot 					 &args);
5172e5016fSJean-Jacques Hiblot 	if (ret) {
5223558bb6SSimon Glass 		debug("%s: dev_read_phandle_with_args failed: err=%d\n",
5372e5016fSJean-Jacques Hiblot 		      __func__, ret);
5472e5016fSJean-Jacques Hiblot 		return ret;
5572e5016fSJean-Jacques Hiblot 	}
5672e5016fSJean-Jacques Hiblot 
5723558bb6SSimon Glass 	ret = uclass_get_device_by_ofnode(UCLASS_PHY, args.node, &phydev);
5872e5016fSJean-Jacques Hiblot 	if (ret) {
5923558bb6SSimon Glass 		debug("%s: uclass_get_device_by_ofnode failed: err=%d\n",
6072e5016fSJean-Jacques Hiblot 		      __func__, ret);
6172e5016fSJean-Jacques Hiblot 		return ret;
6272e5016fSJean-Jacques Hiblot 	}
6372e5016fSJean-Jacques Hiblot 
6472e5016fSJean-Jacques Hiblot 	phy->dev = phydev;
6572e5016fSJean-Jacques Hiblot 
6672e5016fSJean-Jacques Hiblot 	ops = phy_dev_ops(phydev);
6772e5016fSJean-Jacques Hiblot 
6872e5016fSJean-Jacques Hiblot 	if (ops->of_xlate)
6972e5016fSJean-Jacques Hiblot 		ret = ops->of_xlate(phy, &args);
7072e5016fSJean-Jacques Hiblot 	else
7172e5016fSJean-Jacques Hiblot 		ret = generic_phy_xlate_offs_flags(phy, &args);
7272e5016fSJean-Jacques Hiblot 	if (ret) {
7372e5016fSJean-Jacques Hiblot 		debug("of_xlate() failed: %d\n", ret);
7472e5016fSJean-Jacques Hiblot 		goto err;
7572e5016fSJean-Jacques Hiblot 	}
7672e5016fSJean-Jacques Hiblot 
7772e5016fSJean-Jacques Hiblot 	return 0;
7872e5016fSJean-Jacques Hiblot 
7972e5016fSJean-Jacques Hiblot err:
8072e5016fSJean-Jacques Hiblot 	return ret;
8172e5016fSJean-Jacques Hiblot }
8272e5016fSJean-Jacques Hiblot 
8372e5016fSJean-Jacques Hiblot int generic_phy_get_by_name(struct udevice *dev, const char *phy_name,
8472e5016fSJean-Jacques Hiblot 			    struct phy *phy)
8572e5016fSJean-Jacques Hiblot {
8672e5016fSJean-Jacques Hiblot 	int index;
8772e5016fSJean-Jacques Hiblot 
8872e5016fSJean-Jacques Hiblot 	debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy);
8972e5016fSJean-Jacques Hiblot 
9023558bb6SSimon Glass 	index = dev_read_stringlist_search(dev, "phy-names", phy_name);
9172e5016fSJean-Jacques Hiblot 	if (index < 0) {
9223558bb6SSimon Glass 		debug("dev_read_stringlist_search() failed: %d\n", index);
9372e5016fSJean-Jacques Hiblot 		return index;
9472e5016fSJean-Jacques Hiblot 	}
9572e5016fSJean-Jacques Hiblot 
9672e5016fSJean-Jacques Hiblot 	return generic_phy_get_by_index(dev, index, phy);
9772e5016fSJean-Jacques Hiblot }
9872e5016fSJean-Jacques Hiblot 
9972e5016fSJean-Jacques Hiblot int generic_phy_init(struct phy *phy)
10072e5016fSJean-Jacques Hiblot {
1011bac1f39SJean-Jacques Hiblot 	struct phy_ops const *ops;
1021bac1f39SJean-Jacques Hiblot 
10337a5e4d8SVignesh Raghavendra 	if (!generic_phy_valid(phy))
1041bac1f39SJean-Jacques Hiblot 		return 0;
1051bac1f39SJean-Jacques Hiblot 	ops = phy_dev_ops(phy->dev);
10672e5016fSJean-Jacques Hiblot 
10772e5016fSJean-Jacques Hiblot 	return ops->init ? ops->init(phy) : 0;
10872e5016fSJean-Jacques Hiblot }
10972e5016fSJean-Jacques Hiblot 
11072e5016fSJean-Jacques Hiblot int generic_phy_reset(struct phy *phy)
11172e5016fSJean-Jacques Hiblot {
1121bac1f39SJean-Jacques Hiblot 	struct phy_ops const *ops;
1131bac1f39SJean-Jacques Hiblot 
11437a5e4d8SVignesh Raghavendra 	if (!generic_phy_valid(phy))
1151bac1f39SJean-Jacques Hiblot 		return 0;
1161bac1f39SJean-Jacques Hiblot 	ops = phy_dev_ops(phy->dev);
11772e5016fSJean-Jacques Hiblot 
11872e5016fSJean-Jacques Hiblot 	return ops->reset ? ops->reset(phy) : 0;
11972e5016fSJean-Jacques Hiblot }
12072e5016fSJean-Jacques Hiblot 
12172e5016fSJean-Jacques Hiblot int generic_phy_exit(struct phy *phy)
12272e5016fSJean-Jacques Hiblot {
1231bac1f39SJean-Jacques Hiblot 	struct phy_ops const *ops;
1241bac1f39SJean-Jacques Hiblot 
12537a5e4d8SVignesh Raghavendra 	if (!generic_phy_valid(phy))
1261bac1f39SJean-Jacques Hiblot 		return 0;
1271bac1f39SJean-Jacques Hiblot 	ops = phy_dev_ops(phy->dev);
12872e5016fSJean-Jacques Hiblot 
12972e5016fSJean-Jacques Hiblot 	return ops->exit ? ops->exit(phy) : 0;
13072e5016fSJean-Jacques Hiblot }
13172e5016fSJean-Jacques Hiblot 
13272e5016fSJean-Jacques Hiblot int generic_phy_power_on(struct phy *phy)
13372e5016fSJean-Jacques Hiblot {
1341bac1f39SJean-Jacques Hiblot 	struct phy_ops const *ops;
1351bac1f39SJean-Jacques Hiblot 
13637a5e4d8SVignesh Raghavendra 	if (!generic_phy_valid(phy))
1371bac1f39SJean-Jacques Hiblot 		return 0;
1381bac1f39SJean-Jacques Hiblot 	ops = phy_dev_ops(phy->dev);
13972e5016fSJean-Jacques Hiblot 
14072e5016fSJean-Jacques Hiblot 	return ops->power_on ? ops->power_on(phy) : 0;
14172e5016fSJean-Jacques Hiblot }
14272e5016fSJean-Jacques Hiblot 
14372e5016fSJean-Jacques Hiblot int generic_phy_power_off(struct phy *phy)
14472e5016fSJean-Jacques Hiblot {
1451bac1f39SJean-Jacques Hiblot 	struct phy_ops const *ops;
1461bac1f39SJean-Jacques Hiblot 
14737a5e4d8SVignesh Raghavendra 	if (!generic_phy_valid(phy))
1481bac1f39SJean-Jacques Hiblot 		return 0;
1491bac1f39SJean-Jacques Hiblot 	ops = phy_dev_ops(phy->dev);
15072e5016fSJean-Jacques Hiblot 
15172e5016fSJean-Jacques Hiblot 	return ops->power_off ? ops->power_off(phy) : 0;
15272e5016fSJean-Jacques Hiblot }
15372e5016fSJean-Jacques Hiblot 
1544ef09685SWyon Bi int generic_phy_configure(struct phy *phy, union phy_configure_opts *opts)
1554ef09685SWyon Bi {
1564ef09685SWyon Bi 	struct phy_ops const *ops;
1574ef09685SWyon Bi 
1584ef09685SWyon Bi 	if (!generic_phy_valid(phy))
1594ef09685SWyon Bi 		return 0;
1604ef09685SWyon Bi 	ops = phy_dev_ops(phy->dev);
1614ef09685SWyon Bi 
1624ef09685SWyon Bi 	return ops->configure ? ops->configure(phy, opts) : 0;
1634ef09685SWyon Bi }
1644ef09685SWyon Bi 
1654ef09685SWyon Bi int generic_phy_validate(struct phy *phy, enum phy_mode mode, int submode,
1664ef09685SWyon Bi 			 union phy_configure_opts *opts)
1674ef09685SWyon Bi {
1684ef09685SWyon Bi 	struct phy_ops const *ops;
1694ef09685SWyon Bi 
1704ef09685SWyon Bi 	if (!generic_phy_valid(phy))
1714ef09685SWyon Bi 		return 0;
1724ef09685SWyon Bi 	ops = phy_dev_ops(phy->dev);
1734ef09685SWyon Bi 
1744ef09685SWyon Bi 	return ops->validate ? ops->validate(phy, mode, submode, opts) : 0;
1754ef09685SWyon Bi }
1764ef09685SWyon Bi 
177*e9c6c0e2SWyon Bi int generic_phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode)
178*e9c6c0e2SWyon Bi {
179*e9c6c0e2SWyon Bi 	struct phy_ops const *ops;
180*e9c6c0e2SWyon Bi 	int ret;
181*e9c6c0e2SWyon Bi 
182*e9c6c0e2SWyon Bi 	if (!generic_phy_valid(phy))
183*e9c6c0e2SWyon Bi 		return 0;
184*e9c6c0e2SWyon Bi 	ops = phy_dev_ops(phy->dev);
185*e9c6c0e2SWyon Bi 
186*e9c6c0e2SWyon Bi 	if (!ops->set_mode)
187*e9c6c0e2SWyon Bi 		return 0;
188*e9c6c0e2SWyon Bi 
189*e9c6c0e2SWyon Bi 	ret = ops->set_mode(phy, mode, submode);
190*e9c6c0e2SWyon Bi 	if (!ret)
191*e9c6c0e2SWyon Bi 		phy->attrs.mode = mode;
192*e9c6c0e2SWyon Bi 
193*e9c6c0e2SWyon Bi 	return ret;
194*e9c6c0e2SWyon Bi }
195*e9c6c0e2SWyon Bi 
19672e5016fSJean-Jacques Hiblot UCLASS_DRIVER(phy) = {
19772e5016fSJean-Jacques Hiblot 	.id		= UCLASS_PHY,
19872e5016fSJean-Jacques Hiblot 	.name		= "phy",
19972e5016fSJean-Jacques Hiblot };
200