xref: /openbmc/u-boot/drivers/phy/phy-uclass.c (revision b71d9e8b)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
272e5016fSJean-Jacques Hiblot /*
372e5016fSJean-Jacques Hiblot  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
472e5016fSJean-Jacques Hiblot  * Written by Jean-Jacques Hiblot  <jjhiblot@ti.com>
572e5016fSJean-Jacques Hiblot  */
672e5016fSJean-Jacques Hiblot 
772e5016fSJean-Jacques Hiblot #include <common.h>
872e5016fSJean-Jacques Hiblot #include <dm.h>
972e5016fSJean-Jacques Hiblot #include <generic-phy.h>
1072e5016fSJean-Jacques Hiblot 
phy_dev_ops(struct udevice * dev)1172e5016fSJean-Jacques Hiblot static inline struct phy_ops *phy_dev_ops(struct udevice *dev)
1272e5016fSJean-Jacques Hiblot {
1372e5016fSJean-Jacques Hiblot 	return (struct phy_ops *)dev->driver->ops;
1472e5016fSJean-Jacques Hiblot }
1572e5016fSJean-Jacques Hiblot 
generic_phy_xlate_offs_flags(struct phy * phy,struct ofnode_phandle_args * args)1672e5016fSJean-Jacques Hiblot static int generic_phy_xlate_offs_flags(struct phy *phy,
1723558bb6SSimon Glass 					struct ofnode_phandle_args *args)
1872e5016fSJean-Jacques Hiblot {
1972e5016fSJean-Jacques Hiblot 	debug("%s(phy=%p)\n", __func__, phy);
2072e5016fSJean-Jacques Hiblot 
2172e5016fSJean-Jacques Hiblot 	if (args->args_count > 1) {
2272e5016fSJean-Jacques Hiblot 		debug("Invaild args_count: %d\n", args->args_count);
2372e5016fSJean-Jacques Hiblot 		return -EINVAL;
2472e5016fSJean-Jacques Hiblot 	}
2572e5016fSJean-Jacques Hiblot 
2672e5016fSJean-Jacques Hiblot 	if (args->args_count)
2772e5016fSJean-Jacques Hiblot 		phy->id = args->args[0];
2872e5016fSJean-Jacques Hiblot 	else
2972e5016fSJean-Jacques Hiblot 		phy->id = 0;
3072e5016fSJean-Jacques Hiblot 
3172e5016fSJean-Jacques Hiblot 	return 0;
3272e5016fSJean-Jacques Hiblot }
3372e5016fSJean-Jacques Hiblot 
generic_phy_get_by_index(struct udevice * dev,int index,struct phy * phy)3472e5016fSJean-Jacques Hiblot int generic_phy_get_by_index(struct udevice *dev, int index,
3572e5016fSJean-Jacques Hiblot 			     struct phy *phy)
3672e5016fSJean-Jacques Hiblot {
3723558bb6SSimon Glass 	struct ofnode_phandle_args args;
3872e5016fSJean-Jacques Hiblot 	struct phy_ops *ops;
3972e5016fSJean-Jacques Hiblot 	struct udevice *phydev;
40a1b2faedSPatrice Chotard 	int i, ret;
4172e5016fSJean-Jacques Hiblot 
4272e5016fSJean-Jacques Hiblot 	debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy);
4372e5016fSJean-Jacques Hiblot 
4472e5016fSJean-Jacques Hiblot 	assert(phy);
45b9688df3SPatrice Chotard 	phy->dev = NULL;
4623558bb6SSimon Glass 	ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index,
4772e5016fSJean-Jacques Hiblot 					 &args);
4872e5016fSJean-Jacques Hiblot 	if (ret) {
4923558bb6SSimon Glass 		debug("%s: dev_read_phandle_with_args failed: err=%d\n",
5072e5016fSJean-Jacques Hiblot 		      __func__, ret);
5172e5016fSJean-Jacques Hiblot 		return ret;
5272e5016fSJean-Jacques Hiblot 	}
5372e5016fSJean-Jacques Hiblot 
5423558bb6SSimon Glass 	ret = uclass_get_device_by_ofnode(UCLASS_PHY, args.node, &phydev);
5572e5016fSJean-Jacques Hiblot 	if (ret) {
5623558bb6SSimon Glass 		debug("%s: uclass_get_device_by_ofnode failed: err=%d\n",
5772e5016fSJean-Jacques Hiblot 		      __func__, ret);
58a1b2faedSPatrice Chotard 
59a1b2faedSPatrice Chotard 		/* Check if args.node's parent is a PHY provider */
60a1b2faedSPatrice Chotard 		ret = uclass_get_device_by_ofnode(UCLASS_PHY,
61a1b2faedSPatrice Chotard 						  ofnode_get_parent(args.node),
62a1b2faedSPatrice Chotard 						  &phydev);
63a1b2faedSPatrice Chotard 		if (ret)
6472e5016fSJean-Jacques Hiblot 			return ret;
65a1b2faedSPatrice Chotard 
66a1b2faedSPatrice Chotard 		/* insert phy idx at first position into args array */
67*5e50adf6SMarek Vasut 		for (i = args.args_count; i >= 1 ; i--)
68a1b2faedSPatrice Chotard 			args.args[i] = args.args[i - 1];
69a1b2faedSPatrice Chotard 
70a1b2faedSPatrice Chotard 		args.args_count++;
71a1b2faedSPatrice Chotard 		args.args[0] = ofnode_read_u32_default(args.node, "reg", -1);
7272e5016fSJean-Jacques Hiblot 	}
7372e5016fSJean-Jacques Hiblot 
7472e5016fSJean-Jacques Hiblot 	phy->dev = phydev;
7572e5016fSJean-Jacques Hiblot 
7672e5016fSJean-Jacques Hiblot 	ops = phy_dev_ops(phydev);
7772e5016fSJean-Jacques Hiblot 
7872e5016fSJean-Jacques Hiblot 	if (ops->of_xlate)
7972e5016fSJean-Jacques Hiblot 		ret = ops->of_xlate(phy, &args);
8072e5016fSJean-Jacques Hiblot 	else
8172e5016fSJean-Jacques Hiblot 		ret = generic_phy_xlate_offs_flags(phy, &args);
8272e5016fSJean-Jacques Hiblot 	if (ret) {
8372e5016fSJean-Jacques Hiblot 		debug("of_xlate() failed: %d\n", ret);
8472e5016fSJean-Jacques Hiblot 		goto err;
8572e5016fSJean-Jacques Hiblot 	}
8672e5016fSJean-Jacques Hiblot 
8772e5016fSJean-Jacques Hiblot 	return 0;
8872e5016fSJean-Jacques Hiblot 
8972e5016fSJean-Jacques Hiblot err:
9072e5016fSJean-Jacques Hiblot 	return ret;
9172e5016fSJean-Jacques Hiblot }
9272e5016fSJean-Jacques Hiblot 
generic_phy_get_by_name(struct udevice * dev,const char * phy_name,struct phy * phy)9372e5016fSJean-Jacques Hiblot int generic_phy_get_by_name(struct udevice *dev, const char *phy_name,
9472e5016fSJean-Jacques Hiblot 			    struct phy *phy)
9572e5016fSJean-Jacques Hiblot {
9672e5016fSJean-Jacques Hiblot 	int index;
9772e5016fSJean-Jacques Hiblot 
9872e5016fSJean-Jacques Hiblot 	debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy);
9972e5016fSJean-Jacques Hiblot 
10023558bb6SSimon Glass 	index = dev_read_stringlist_search(dev, "phy-names", phy_name);
10172e5016fSJean-Jacques Hiblot 	if (index < 0) {
10223558bb6SSimon Glass 		debug("dev_read_stringlist_search() failed: %d\n", index);
10372e5016fSJean-Jacques Hiblot 		return index;
10472e5016fSJean-Jacques Hiblot 	}
10572e5016fSJean-Jacques Hiblot 
10672e5016fSJean-Jacques Hiblot 	return generic_phy_get_by_index(dev, index, phy);
10772e5016fSJean-Jacques Hiblot }
10872e5016fSJean-Jacques Hiblot 
generic_phy_init(struct phy * phy)10972e5016fSJean-Jacques Hiblot int generic_phy_init(struct phy *phy)
11072e5016fSJean-Jacques Hiblot {
11172e5016fSJean-Jacques Hiblot 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
11272e5016fSJean-Jacques Hiblot 
11372e5016fSJean-Jacques Hiblot 	return ops->init ? ops->init(phy) : 0;
11472e5016fSJean-Jacques Hiblot }
11572e5016fSJean-Jacques Hiblot 
generic_phy_reset(struct phy * phy)11672e5016fSJean-Jacques Hiblot int generic_phy_reset(struct phy *phy)
11772e5016fSJean-Jacques Hiblot {
11872e5016fSJean-Jacques Hiblot 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
11972e5016fSJean-Jacques Hiblot 
12072e5016fSJean-Jacques Hiblot 	return ops->reset ? ops->reset(phy) : 0;
12172e5016fSJean-Jacques Hiblot }
12272e5016fSJean-Jacques Hiblot 
generic_phy_exit(struct phy * phy)12372e5016fSJean-Jacques Hiblot int generic_phy_exit(struct phy *phy)
12472e5016fSJean-Jacques Hiblot {
12572e5016fSJean-Jacques Hiblot 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
12672e5016fSJean-Jacques Hiblot 
12772e5016fSJean-Jacques Hiblot 	return ops->exit ? ops->exit(phy) : 0;
12872e5016fSJean-Jacques Hiblot }
12972e5016fSJean-Jacques Hiblot 
generic_phy_power_on(struct phy * phy)13072e5016fSJean-Jacques Hiblot int generic_phy_power_on(struct phy *phy)
13172e5016fSJean-Jacques Hiblot {
13272e5016fSJean-Jacques Hiblot 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
13372e5016fSJean-Jacques Hiblot 
13472e5016fSJean-Jacques Hiblot 	return ops->power_on ? ops->power_on(phy) : 0;
13572e5016fSJean-Jacques Hiblot }
13672e5016fSJean-Jacques Hiblot 
generic_phy_power_off(struct phy * phy)13772e5016fSJean-Jacques Hiblot int generic_phy_power_off(struct phy *phy)
13872e5016fSJean-Jacques Hiblot {
13972e5016fSJean-Jacques Hiblot 	struct phy_ops const *ops = phy_dev_ops(phy->dev);
14072e5016fSJean-Jacques Hiblot 
14172e5016fSJean-Jacques Hiblot 	return ops->power_off ? ops->power_off(phy) : 0;
14272e5016fSJean-Jacques Hiblot }
14372e5016fSJean-Jacques Hiblot 
14472e5016fSJean-Jacques Hiblot UCLASS_DRIVER(phy) = {
14572e5016fSJean-Jacques Hiblot 	.id		= UCLASS_PHY,
14672e5016fSJean-Jacques Hiblot 	.name		= "phy",
14772e5016fSJean-Jacques Hiblot };
148