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