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