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