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