1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/ 4 * Written by Jean-Jacques Hiblot <jjhiblot@ti.com> 5 */ 6 7#include <clk.h> 8#include <common.h> 9#include <dm.h> 10#include <dm/device.h> 11#include <dm/device_compat.h> 12#include <generic-phy.h> 13#include <asm-generic/gpio.h> 14 15struct nop_phy_priv { 16 struct clk_bulk bulk; 17#if CONFIG_IS_ENABLED(DM_GPIO) 18 struct gpio_desc reset_gpio; 19#endif 20}; 21 22#if CONFIG_IS_ENABLED(DM_GPIO) 23static int nop_phy_reset(struct phy *phy) 24{ 25 struct nop_phy_priv *priv = dev_get_priv(phy->dev); 26 27 /* Return if there is no gpio since it's optional */ 28 if (!dm_gpio_is_valid(&priv->reset_gpio)) 29 return 0; 30 31 return dm_gpio_set_value(&priv->reset_gpio, true); 32} 33#endif 34 35static int nop_phy_init(struct phy *phy) 36{ 37 struct nop_phy_priv *priv = dev_get_priv(phy->dev); 38 int ret = 0; 39 40 if (CONFIG_IS_ENABLED(CLK)) { 41 ret = clk_enable_bulk(&priv->bulk); 42 if (ret) 43 return ret; 44 } 45 46#if CONFIG_IS_ENABLED(DM_GPIO) 47 /* Take phy out of reset */ 48 if (dm_gpio_is_valid(&priv->reset_gpio)) { 49 ret = dm_gpio_set_value(&priv->reset_gpio, false); 50 if (ret) { 51 if (CONFIG_IS_ENABLED(CLK)) 52 clk_disable_bulk(&priv->bulk); 53 return ret; 54 } 55 } 56#endif 57 return 0; 58} 59 60static int nop_phy_probe(struct udevice *dev) 61{ 62 struct nop_phy_priv *priv = dev_get_priv(dev); 63 int ret = 0; 64 65 if (CONFIG_IS_ENABLED(CLK)) { 66 ret = clk_get_bulk(dev, &priv->bulk); 67 if (ret < 0) { 68 dev_err(dev, "Failed to get clk: %d\n", ret); 69 return ret; 70 } 71 } 72#if CONFIG_IS_ENABLED(DM_GPIO) 73 ret = gpio_request_by_name(dev, "reset-gpios", 0, 74 &priv->reset_gpio, 75 GPIOD_IS_OUT); 76#endif 77 if (ret != -ENOENT) 78 return ret; 79 80 return 0; 81} 82 83static const struct udevice_id nop_phy_ids[] = { 84 { .compatible = "nop-phy" }, 85 { .compatible = "usb-nop-xceiv" }, 86 { } 87}; 88 89static struct phy_ops nop_phy_ops = { 90 .init = nop_phy_init, 91#if CONFIG_IS_ENABLED(DM_GPIO) 92 .reset = nop_phy_reset, 93#endif 94}; 95 96U_BOOT_DRIVER(nop_phy) = { 97 .name = "nop_phy", 98 .id = UCLASS_PHY, 99 .of_match = nop_phy_ids, 100 .ops = &nop_phy_ops, 101 .probe = nop_phy_probe, 102 .priv_auto = sizeof(struct nop_phy_priv), 103}; 104