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); 48*b9688df3SPatrice 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 { 10172e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 10272e5016fSJean-Jacques Hiblot 10372e5016fSJean-Jacques Hiblot return ops->init ? ops->init(phy) : 0; 10472e5016fSJean-Jacques Hiblot } 10572e5016fSJean-Jacques Hiblot 10672e5016fSJean-Jacques Hiblot int generic_phy_reset(struct phy *phy) 10772e5016fSJean-Jacques Hiblot { 10872e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 10972e5016fSJean-Jacques Hiblot 11072e5016fSJean-Jacques Hiblot return ops->reset ? ops->reset(phy) : 0; 11172e5016fSJean-Jacques Hiblot } 11272e5016fSJean-Jacques Hiblot 11372e5016fSJean-Jacques Hiblot int generic_phy_exit(struct phy *phy) 11472e5016fSJean-Jacques Hiblot { 11572e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 11672e5016fSJean-Jacques Hiblot 11772e5016fSJean-Jacques Hiblot return ops->exit ? ops->exit(phy) : 0; 11872e5016fSJean-Jacques Hiblot } 11972e5016fSJean-Jacques Hiblot 12072e5016fSJean-Jacques Hiblot int generic_phy_power_on(struct phy *phy) 12172e5016fSJean-Jacques Hiblot { 12272e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 12372e5016fSJean-Jacques Hiblot 12472e5016fSJean-Jacques Hiblot return ops->power_on ? ops->power_on(phy) : 0; 12572e5016fSJean-Jacques Hiblot } 12672e5016fSJean-Jacques Hiblot 12772e5016fSJean-Jacques Hiblot int generic_phy_power_off(struct phy *phy) 12872e5016fSJean-Jacques Hiblot { 12972e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 13072e5016fSJean-Jacques Hiblot 13172e5016fSJean-Jacques Hiblot return ops->power_off ? ops->power_off(phy) : 0; 13272e5016fSJean-Jacques Hiblot } 13372e5016fSJean-Jacques Hiblot 13472e5016fSJean-Jacques Hiblot UCLASS_DRIVER(phy) = { 13572e5016fSJean-Jacques Hiblot .id = UCLASS_PHY, 13672e5016fSJean-Jacques Hiblot .name = "phy", 13772e5016fSJean-Jacques Hiblot }; 138