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