1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ 4 * Written by Jean-Jacques Hiblot <jjhiblot@ti.com> 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <generic-phy.h> 10 11 static inline struct phy_ops *phy_dev_ops(struct udevice *dev) 12 { 13 return (struct phy_ops *)dev->driver->ops; 14 } 15 16 static int generic_phy_xlate_offs_flags(struct phy *phy, 17 struct ofnode_phandle_args *args) 18 { 19 debug("%s(phy=%p)\n", __func__, phy); 20 21 if (args->args_count > 1) { 22 debug("Invaild args_count: %d\n", args->args_count); 23 return -EINVAL; 24 } 25 26 if (args->args_count) 27 phy->id = args->args[0]; 28 else 29 phy->id = 0; 30 31 return 0; 32 } 33 34 int generic_phy_get_by_index(struct udevice *dev, int index, 35 struct phy *phy) 36 { 37 struct ofnode_phandle_args args; 38 struct phy_ops *ops; 39 int ret; 40 struct udevice *phydev; 41 42 debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy); 43 44 assert(phy); 45 phy->dev = NULL; 46 ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index, 47 &args); 48 if (ret) { 49 debug("%s: dev_read_phandle_with_args failed: err=%d\n", 50 __func__, ret); 51 return ret; 52 } 53 54 ret = uclass_get_device_by_ofnode(UCLASS_PHY, args.node, &phydev); 55 if (ret) { 56 debug("%s: uclass_get_device_by_ofnode failed: err=%d\n", 57 __func__, ret); 58 return ret; 59 } 60 61 phy->dev = phydev; 62 63 ops = phy_dev_ops(phydev); 64 65 if (ops->of_xlate) 66 ret = ops->of_xlate(phy, &args); 67 else 68 ret = generic_phy_xlate_offs_flags(phy, &args); 69 if (ret) { 70 debug("of_xlate() failed: %d\n", ret); 71 goto err; 72 } 73 74 return 0; 75 76 err: 77 return ret; 78 } 79 80 int generic_phy_get_by_name(struct udevice *dev, const char *phy_name, 81 struct phy *phy) 82 { 83 int index; 84 85 debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy); 86 87 index = dev_read_stringlist_search(dev, "phy-names", phy_name); 88 if (index < 0) { 89 debug("dev_read_stringlist_search() failed: %d\n", index); 90 return index; 91 } 92 93 return generic_phy_get_by_index(dev, index, phy); 94 } 95 96 int generic_phy_init(struct phy *phy) 97 { 98 struct phy_ops const *ops = phy_dev_ops(phy->dev); 99 100 return ops->init ? ops->init(phy) : 0; 101 } 102 103 int generic_phy_reset(struct phy *phy) 104 { 105 struct phy_ops const *ops = phy_dev_ops(phy->dev); 106 107 return ops->reset ? ops->reset(phy) : 0; 108 } 109 110 int generic_phy_exit(struct phy *phy) 111 { 112 struct phy_ops const *ops = phy_dev_ops(phy->dev); 113 114 return ops->exit ? ops->exit(phy) : 0; 115 } 116 117 int generic_phy_power_on(struct phy *phy) 118 { 119 struct phy_ops const *ops = phy_dev_ops(phy->dev); 120 121 return ops->power_on ? ops->power_on(phy) : 0; 122 } 123 124 int generic_phy_power_off(struct phy *phy) 125 { 126 struct phy_ops const *ops = phy_dev_ops(phy->dev); 127 128 return ops->power_off ? ops->power_off(phy) : 0; 129 } 130 131 UCLASS_DRIVER(phy) = { 132 .id = UCLASS_PHY, 133 .name = "phy", 134 }; 135