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