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