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 <dm.h>
8 #include <generic-phy.h>
9 
10 #define DRIVER_DATA 0x12345678
11 
12 struct sandbox_phy_priv {
13 	bool initialized;
14 	bool on;
15 	bool broken;
16 };
17 
sandbox_phy_power_on(struct phy * phy)18 static int sandbox_phy_power_on(struct phy *phy)
19 {
20 	struct sandbox_phy_priv *priv = dev_get_priv(phy->dev);
21 
22 	if (!priv->initialized)
23 		return -EIO;
24 
25 	if (priv->broken)
26 		return -EIO;
27 
28 	priv->on = true;
29 
30 	return 0;
31 }
32 
sandbox_phy_power_off(struct phy * phy)33 static int sandbox_phy_power_off(struct phy *phy)
34 {
35 	struct sandbox_phy_priv *priv = dev_get_priv(phy->dev);
36 
37 	if (!priv->initialized)
38 		return -EIO;
39 
40 	if (priv->broken)
41 		return -EIO;
42 
43 	/*
44 	 * for validation purpose, let's says that power off
45 	 * works only for PHY 0
46 	 */
47 	if (phy->id)
48 		return -EIO;
49 
50 	priv->on = false;
51 
52 	return 0;
53 }
54 
sandbox_phy_init(struct phy * phy)55 static int sandbox_phy_init(struct phy *phy)
56 {
57 	struct sandbox_phy_priv *priv = dev_get_priv(phy->dev);
58 
59 	priv->initialized = true;
60 	priv->on = true;
61 
62 	return 0;
63 }
64 
sandbox_phy_exit(struct phy * phy)65 static int sandbox_phy_exit(struct phy *phy)
66 {
67 	struct sandbox_phy_priv *priv = dev_get_priv(phy->dev);
68 
69 	priv->initialized = false;
70 	priv->on = false;
71 
72 	return 0;
73 }
74 
75 static int
sandbox_phy_set_mode(struct phy * phy,enum phy_mode mode,int submode)76 sandbox_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
77 {
78 	if (submode)
79 		return -EOPNOTSUPP;
80 
81 	if (mode != PHY_MODE_USB_HOST)
82 		return -EINVAL;
83 
84 	return 0;
85 }
86 
sandbox_phy_bind(struct udevice * dev)87 static int sandbox_phy_bind(struct udevice *dev)
88 {
89 	if (dev_get_driver_data(dev) != DRIVER_DATA)
90 		return -ENODATA;
91 
92 	return 0;
93 }
94 
sandbox_phy_probe(struct udevice * dev)95 static int sandbox_phy_probe(struct udevice *dev)
96 {
97 	struct sandbox_phy_priv *priv = dev_get_priv(dev);
98 
99 	priv->initialized = false;
100 	priv->on = false;
101 	priv->broken = dev_read_bool(dev, "broken");
102 
103 	return 0;
104 }
105 
106 static struct phy_ops sandbox_phy_ops = {
107 	.power_on = sandbox_phy_power_on,
108 	.power_off = sandbox_phy_power_off,
109 	.init = sandbox_phy_init,
110 	.exit = sandbox_phy_exit,
111 	.set_mode = sandbox_phy_set_mode,
112 };
113 
114 static const struct udevice_id sandbox_phy_ids[] = {
115 	{ .compatible = "sandbox,phy_no_driver_data",
116 	},
117 
118 	{ .compatible = "sandbox,phy",
119 	  .data = DRIVER_DATA
120 	},
121 	{ }
122 };
123 
124 U_BOOT_DRIVER(phy_sandbox) = {
125 	.name		= "phy_sandbox",
126 	.id		= UCLASS_PHY,
127 	.bind		= sandbox_phy_bind,
128 	.of_match	= sandbox_phy_ids,
129 	.ops		= &sandbox_phy_ops,
130 	.probe		= sandbox_phy_probe,
131 	.priv_auto	= sizeof(struct sandbox_phy_priv),
132 };
133