xref: /linux/drivers/phy/phy-eyeq5-eth.c (revision d2c9a99135da931377240942d44f3dea104cedb8)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <linux/auxiliary_bus.h>
4 #include <linux/bitfield.h>
5 #include <linux/bits.h>
6 #include <linux/delay.h>
7 #include <linux/device.h>
8 #include <linux/err.h>
9 #include <linux/errno.h>
10 #include <linux/gfp_types.h>
11 #include <linux/init.h>
12 #include <linux/io.h>
13 #include <linux/iopoll.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/phy.h>
17 #include <linux/phy/phy.h>
18 #include <linux/slab.h>
19 #include <linux/types.h>
20 
21 #define EQ5_PHY_COUNT	2
22 
23 #define EQ5_PHY0_GP	0x128
24 #define EQ5_PHY1_GP	0x12c
25 #define EQ5_PHY0_SGMII	0x134
26 #define EQ5_PHY1_SGMII	0x138
27 
28 #define EQ5_GP_TX_SWRST_DIS	BIT(0)		// Tx SW reset
29 #define EQ5_GP_TX_M_CLKE	BIT(1)		// Tx M clock enable
30 #define EQ5_GP_SYS_SWRST_DIS	BIT(2)		// Sys SW reset
31 #define EQ5_GP_SYS_M_CLKE	BIT(3)		// Sys clock enable
32 #define EQ5_GP_SGMII_MODE	BIT(4)		// SGMII mode
33 #define EQ5_GP_RGMII_DRV	GENMASK(8, 5)	// RGMII drive strength
34 
35 #define EQ5_SGMII_PWR_EN	BIT(0)
36 #define EQ5_SGMII_RST_DIS	BIT(1)
37 #define EQ5_SGMII_PLL_EN	BIT(2)
38 #define EQ5_SGMII_SIG_DET_SW	BIT(3)
39 #define EQ5_SGMII_PWR_STATE	BIT(4)
40 #define EQ5_SGMII_PLL_ACK	BIT(18)
41 #define EQ5_SGMII_PWR_STATE_ACK	GENMASK(24, 20)
42 
43 /*
44  * Instead of storing a phy_interface_t, we store this enum.
45  *
46  * We do not deal with RGMII timings in this generic PHY driver,
47  * it is all handled inside the net PHY.
48  */
49 enum eq5_phy_submode {
50 	EQ5_PHY_SUBMODE_SGMII,
51 	EQ5_PHY_SUBMODE_RGMII,
52 };
53 
54 struct eq5_phy_inst {
55 	struct device		*dev;
56 	struct phy		*phy;
57 	void __iomem		*gp, *sgmii;
58 	enum eq5_phy_submode	submode;
59 	bool			sgmii_support;
60 };
61 
62 struct eq5_phy_private {
63 	struct eq5_phy_inst	phys[EQ5_PHY_COUNT];
64 };
65 
eq5_phy_exit(struct phy * phy)66 static int eq5_phy_exit(struct phy *phy)
67 {
68 	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
69 
70 	writel(0, inst->gp);
71 	writel(0, inst->sgmii);
72 	udelay(5); /* settling time */
73 	return 0;
74 }
75 
eq5_phy_init(struct phy * phy)76 static int eq5_phy_init(struct phy *phy)
77 {
78 	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
79 	u32 reg;
80 
81 	/*
82 	 * Hardware stops listening to our instructions once it is started.
83 	 * It must be reset to reconfigure it.
84 	 */
85 	eq5_phy_exit(phy);
86 
87 	reg = EQ5_GP_TX_SWRST_DIS | EQ5_GP_TX_M_CLKE |
88 	      EQ5_GP_SYS_SWRST_DIS | EQ5_GP_SYS_M_CLKE |
89 	      FIELD_PREP(EQ5_GP_RGMII_DRV, 0x9);
90 	writel(reg, inst->gp);
91 
92 	return 0;
93 }
94 
eq5_phy_power_on(struct phy * phy)95 static int eq5_phy_power_on(struct phy *phy)
96 {
97 	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
98 	u32 reg;
99 
100 	if (inst->submode == EQ5_PHY_SUBMODE_SGMII) {
101 		writel(readl(inst->gp) | EQ5_GP_SGMII_MODE, inst->gp);
102 
103 		reg = EQ5_SGMII_PWR_EN | EQ5_SGMII_RST_DIS | EQ5_SGMII_PLL_EN;
104 		writel(reg, inst->sgmii);
105 
106 		if (readl_poll_timeout(inst->sgmii, reg,
107 				       reg & EQ5_SGMII_PLL_ACK, 1, 100)) {
108 			dev_err(inst->dev, "PLL timeout\n");
109 			return -ETIMEDOUT;
110 		}
111 
112 		reg = readl(inst->sgmii);
113 		reg |= EQ5_SGMII_PWR_STATE | EQ5_SGMII_SIG_DET_SW;
114 		writel(reg, inst->sgmii);
115 	} else {
116 		writel(readl(inst->gp) & ~EQ5_GP_SGMII_MODE, inst->gp);
117 		writel(0, inst->sgmii);
118 	}
119 
120 	return 0;
121 }
122 
eq5_phy_power_off(struct phy * phy)123 static int eq5_phy_power_off(struct phy *phy)
124 {
125 	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
126 
127 	writel(readl(inst->gp) & ~EQ5_GP_SGMII_MODE, inst->gp);
128 	writel(0, inst->sgmii);
129 
130 	return 0;
131 }
132 
eq5_phy_validate(struct phy * phy,enum phy_mode mode,int submode,union phy_configure_opts * opts)133 static int eq5_phy_validate(struct phy *phy, enum phy_mode mode, int submode,
134 			    union phy_configure_opts *opts)
135 {
136 	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
137 
138 	if (mode != PHY_MODE_ETHERNET)
139 		return -EINVAL;
140 
141 	if (phy_interface_mode_is_rgmii(submode))
142 		return 0;
143 
144 	if (inst->sgmii_support && submode == PHY_INTERFACE_MODE_SGMII)
145 		return 0;
146 
147 	return -EINVAL;
148 }
149 
eq5_phy_set_mode(struct phy * phy,enum phy_mode mode,int submode)150 static int eq5_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
151 {
152 	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
153 	enum eq5_phy_submode target_submode;
154 	int ret;
155 
156 	ret = eq5_phy_validate(phy, mode, submode, NULL);
157 	if (ret)
158 		return ret;
159 
160 	if (submode == PHY_INTERFACE_MODE_SGMII)
161 		target_submode = EQ5_PHY_SUBMODE_SGMII;
162 	else
163 		target_submode = EQ5_PHY_SUBMODE_RGMII;
164 
165 	if (target_submode == inst->submode)
166 		return 0;
167 
168 	inst->submode = target_submode;
169 
170 	if (phy->power_count) {
171 		eq5_phy_init(phy);
172 		return eq5_phy_power_on(phy);
173 	}
174 
175 	return 0;
176 }
177 
178 static const struct phy_ops eq5_phy_ops = {
179 	.init		= eq5_phy_init,
180 	.exit		= eq5_phy_exit,
181 	.power_on	= eq5_phy_power_on,
182 	.power_off	= eq5_phy_power_off,
183 	.set_mode	= eq5_phy_set_mode,
184 	.validate	= eq5_phy_validate,
185 };
186 
eq5_phy_xlate(struct device * dev,const struct of_phandle_args * args)187 static struct phy *eq5_phy_xlate(struct device *dev,
188 				 const struct of_phandle_args *args)
189 {
190 	struct eq5_phy_private *priv = dev_get_drvdata(dev);
191 
192 	if (args->args_count != 1 || args->args[0] >= EQ5_PHY_COUNT)
193 		return ERR_PTR(-EINVAL);
194 
195 	return priv->phys[args->args[0]].phy;
196 }
197 
eq5_phy_probe_phy(struct device * dev,struct eq5_phy_private * priv,unsigned int index,void __iomem * base,unsigned int gp,unsigned int sgmii,bool sgmii_support)198 static int eq5_phy_probe_phy(struct device *dev, struct eq5_phy_private *priv,
199 			     unsigned int index, void __iomem *base,
200 			     unsigned int gp, unsigned int sgmii,
201 			     bool sgmii_support)
202 {
203 	struct eq5_phy_inst *inst = &priv->phys[index];
204 	struct phy *phy;
205 
206 	phy = devm_phy_create(dev, dev->of_node, &eq5_phy_ops);
207 	if (IS_ERR(phy))
208 		return dev_err_probe(dev, PTR_ERR(phy),
209 				     "failed to create PHY %u\n", index);
210 
211 	inst->dev = dev;
212 	inst->phy = phy;
213 	inst->gp = base + gp;
214 	inst->sgmii = base + sgmii;
215 	inst->sgmii_support = sgmii_support;
216 	phy_set_drvdata(phy, inst);
217 
218 	/*
219 	 * Init inst->submode based on probe hardware state, allowing
220 	 * consumers to power us on without first setting the mode.
221 	 */
222 	if (sgmii_support && (readl(inst->gp) & EQ5_GP_SGMII_MODE))
223 		inst->submode = EQ5_PHY_SUBMODE_SGMII;
224 	else
225 		inst->submode = EQ5_PHY_SUBMODE_RGMII;
226 
227 	return 0;
228 }
229 
eq5_phy_probe(struct auxiliary_device * adev,const struct auxiliary_device_id * id)230 static int eq5_phy_probe(struct auxiliary_device *adev,
231 			 const struct auxiliary_device_id *id)
232 {
233 	struct device *dev = &adev->dev;
234 	struct phy_provider *provider;
235 	struct eq5_phy_private *priv;
236 	void __iomem *base;
237 	int ret;
238 
239 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
240 	if (!priv)
241 		return -ENOMEM;
242 
243 	dev_set_drvdata(dev, priv);
244 
245 	base = (void __iomem *)dev_get_platdata(dev);
246 
247 	ret = eq5_phy_probe_phy(dev, priv, 0, base, EQ5_PHY0_GP,
248 				EQ5_PHY0_SGMII, true);
249 	if (ret)
250 		return ret;
251 
252 	ret = eq5_phy_probe_phy(dev, priv, 1, base, EQ5_PHY1_GP,
253 				EQ5_PHY1_SGMII, false);
254 	if (ret)
255 		return ret;
256 
257 	provider = devm_of_phy_provider_register(dev, eq5_phy_xlate);
258 	if (IS_ERR(provider))
259 		return dev_err_probe(dev, PTR_ERR(provider),
260 				     "registering provider failed\n");
261 
262 	return 0;
263 }
264 
265 static const struct auxiliary_device_id eq5_phy_id_table[] = {
266 	{ .name = "clk_eyeq.phy" },
267 	{}
268 };
269 MODULE_DEVICE_TABLE(auxiliary, eq5_phy_id_table);
270 
271 static struct auxiliary_driver eq5_phy_driver = {
272 	.probe = eq5_phy_probe,
273 	.id_table = eq5_phy_id_table,
274 };
275 module_auxiliary_driver(eq5_phy_driver);
276 
277 MODULE_DESCRIPTION("EyeQ5 Ethernet PHY driver");
278 MODULE_AUTHOR("Théo Lebrun <theo.lebrun@bootlin.com>");
279 MODULE_LICENSE("GPL");
280