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