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, 20*23558bb6SSimon 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 { 40*23558bb6SSimon 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*23558bb6SSimon Glass ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index, 4972e5016fSJean-Jacques Hiblot &args); 5072e5016fSJean-Jacques Hiblot if (ret) { 51*23558bb6SSimon Glass debug("%s: dev_read_phandle_with_args failed: err=%d\n", 5272e5016fSJean-Jacques Hiblot __func__, ret); 5372e5016fSJean-Jacques Hiblot return ret; 5472e5016fSJean-Jacques Hiblot } 5572e5016fSJean-Jacques Hiblot 56*23558bb6SSimon Glass ret = uclass_get_device_by_ofnode(UCLASS_PHY, args.node, &phydev); 5772e5016fSJean-Jacques Hiblot if (ret) { 58*23558bb6SSimon Glass debug("%s: uclass_get_device_by_ofnode failed: err=%d\n", 5972e5016fSJean-Jacques Hiblot __func__, ret); 6072e5016fSJean-Jacques Hiblot return ret; 6172e5016fSJean-Jacques Hiblot } 6272e5016fSJean-Jacques Hiblot 6372e5016fSJean-Jacques Hiblot phy->dev = phydev; 6472e5016fSJean-Jacques Hiblot 6572e5016fSJean-Jacques Hiblot ops = phy_dev_ops(phydev); 6672e5016fSJean-Jacques Hiblot 6772e5016fSJean-Jacques Hiblot if (ops->of_xlate) 6872e5016fSJean-Jacques Hiblot ret = ops->of_xlate(phy, &args); 6972e5016fSJean-Jacques Hiblot else 7072e5016fSJean-Jacques Hiblot ret = generic_phy_xlate_offs_flags(phy, &args); 7172e5016fSJean-Jacques Hiblot if (ret) { 7272e5016fSJean-Jacques Hiblot debug("of_xlate() failed: %d\n", ret); 7372e5016fSJean-Jacques Hiblot goto err; 7472e5016fSJean-Jacques Hiblot } 7572e5016fSJean-Jacques Hiblot 7672e5016fSJean-Jacques Hiblot return 0; 7772e5016fSJean-Jacques Hiblot 7872e5016fSJean-Jacques Hiblot err: 7972e5016fSJean-Jacques Hiblot return ret; 8072e5016fSJean-Jacques Hiblot } 8172e5016fSJean-Jacques Hiblot 8272e5016fSJean-Jacques Hiblot int generic_phy_get_by_name(struct udevice *dev, const char *phy_name, 8372e5016fSJean-Jacques Hiblot struct phy *phy) 8472e5016fSJean-Jacques Hiblot { 8572e5016fSJean-Jacques Hiblot int index; 8672e5016fSJean-Jacques Hiblot 8772e5016fSJean-Jacques Hiblot debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy); 8872e5016fSJean-Jacques Hiblot 89*23558bb6SSimon Glass index = dev_read_stringlist_search(dev, "phy-names", phy_name); 9072e5016fSJean-Jacques Hiblot if (index < 0) { 91*23558bb6SSimon Glass debug("dev_read_stringlist_search() failed: %d\n", index); 9272e5016fSJean-Jacques Hiblot return index; 9372e5016fSJean-Jacques Hiblot } 9472e5016fSJean-Jacques Hiblot 9572e5016fSJean-Jacques Hiblot return generic_phy_get_by_index(dev, index, phy); 9672e5016fSJean-Jacques Hiblot } 9772e5016fSJean-Jacques Hiblot 9872e5016fSJean-Jacques Hiblot int generic_phy_init(struct phy *phy) 9972e5016fSJean-Jacques Hiblot { 10072e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 10172e5016fSJean-Jacques Hiblot 10272e5016fSJean-Jacques Hiblot return ops->init ? ops->init(phy) : 0; 10372e5016fSJean-Jacques Hiblot } 10472e5016fSJean-Jacques Hiblot 10572e5016fSJean-Jacques Hiblot int generic_phy_reset(struct phy *phy) 10672e5016fSJean-Jacques Hiblot { 10772e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 10872e5016fSJean-Jacques Hiblot 10972e5016fSJean-Jacques Hiblot return ops->reset ? ops->reset(phy) : 0; 11072e5016fSJean-Jacques Hiblot } 11172e5016fSJean-Jacques Hiblot 11272e5016fSJean-Jacques Hiblot int generic_phy_exit(struct phy *phy) 11372e5016fSJean-Jacques Hiblot { 11472e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 11572e5016fSJean-Jacques Hiblot 11672e5016fSJean-Jacques Hiblot return ops->exit ? ops->exit(phy) : 0; 11772e5016fSJean-Jacques Hiblot } 11872e5016fSJean-Jacques Hiblot 11972e5016fSJean-Jacques Hiblot int generic_phy_power_on(struct phy *phy) 12072e5016fSJean-Jacques Hiblot { 12172e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 12272e5016fSJean-Jacques Hiblot 12372e5016fSJean-Jacques Hiblot return ops->power_on ? ops->power_on(phy) : 0; 12472e5016fSJean-Jacques Hiblot } 12572e5016fSJean-Jacques Hiblot 12672e5016fSJean-Jacques Hiblot int generic_phy_power_off(struct phy *phy) 12772e5016fSJean-Jacques Hiblot { 12872e5016fSJean-Jacques Hiblot struct phy_ops const *ops = phy_dev_ops(phy->dev); 12972e5016fSJean-Jacques Hiblot 13072e5016fSJean-Jacques Hiblot return ops->power_off ? ops->power_off(phy) : 0; 13172e5016fSJean-Jacques Hiblot } 13272e5016fSJean-Jacques Hiblot 13372e5016fSJean-Jacques Hiblot UCLASS_DRIVER(phy) = { 13472e5016fSJean-Jacques Hiblot .id = UCLASS_PHY, 13572e5016fSJean-Jacques Hiblot .name = "phy", 13672e5016fSJean-Jacques Hiblot }; 137