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 fdtdec_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 35 return 0; 36 } 37 38 int generic_phy_get_by_index(struct udevice *dev, int index, 39 struct phy *phy) 40 { 41 struct fdtdec_phandle_args args; 42 struct phy_ops *ops; 43 int ret; 44 struct udevice *phydev; 45 46 debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy); 47 48 assert(phy); 49 ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), 50 "phys", "#phy-cells", 0, index, 51 &args); 52 if (ret) { 53 debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n", 54 __func__, ret); 55 return ret; 56 } 57 58 ret = uclass_get_device_by_of_offset(UCLASS_PHY, args.node, &phydev); 59 if (ret) { 60 debug("%s: uclass_get_device_by_of_offset failed: err=%d\n", 61 __func__, ret); 62 return ret; 63 } 64 65 phy->dev = phydev; 66 67 ops = phy_dev_ops(phydev); 68 69 if (ops->of_xlate) 70 ret = ops->of_xlate(phy, &args); 71 else 72 ret = generic_phy_xlate_offs_flags(phy, &args); 73 if (ret) { 74 debug("of_xlate() failed: %d\n", ret); 75 goto err; 76 } 77 78 return 0; 79 80 err: 81 return ret; 82 } 83 84 int generic_phy_get_by_name(struct udevice *dev, const char *phy_name, 85 struct phy *phy) 86 { 87 int index; 88 89 debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy); 90 91 index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev), 92 "phy-names", phy_name); 93 if (index < 0) { 94 debug("fdt_stringlist_search() failed: %d\n", index); 95 return index; 96 } 97 98 return generic_phy_get_by_index(dev, index, phy); 99 } 100 101 int generic_phy_init(struct phy *phy) 102 { 103 struct phy_ops const *ops = phy_dev_ops(phy->dev); 104 105 return ops->init ? ops->init(phy) : 0; 106 } 107 108 int generic_phy_reset(struct phy *phy) 109 { 110 struct phy_ops const *ops = phy_dev_ops(phy->dev); 111 112 return ops->reset ? ops->reset(phy) : 0; 113 } 114 115 int generic_phy_exit(struct phy *phy) 116 { 117 struct phy_ops const *ops = phy_dev_ops(phy->dev); 118 119 return ops->exit ? ops->exit(phy) : 0; 120 } 121 122 int generic_phy_power_on(struct phy *phy) 123 { 124 struct phy_ops const *ops = phy_dev_ops(phy->dev); 125 126 return ops->power_on ? ops->power_on(phy) : 0; 127 } 128 129 int generic_phy_power_off(struct phy *phy) 130 { 131 struct phy_ops const *ops = phy_dev_ops(phy->dev); 132 133 return ops->power_off ? ops->power_off(phy) : 0; 134 } 135 136 UCLASS_DRIVER(phy) = { 137 .id = UCLASS_PHY, 138 .name = "phy", 139 }; 140