net: stmmac: replace the serdes_up_after_phy_linkup field with a flag
[platform/kernel/linux-rpi.git] / drivers / net / ethernet / stmicro / stmmac / dwmac-tegra.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/platform_device.h>
3 #include <linux/of_device.h>
4 #include <linux/module.h>
5 #include <linux/stmmac.h>
6 #include <linux/clk.h>
7
8 #include "stmmac_platform.h"
9
10 static const char *const mgbe_clks[] = {
11         "rx-pcs", "tx", "tx-pcs", "mac-divider", "mac", "mgbe", "ptp-ref", "mac"
12 };
13
14 struct tegra_mgbe {
15         struct device *dev;
16
17         struct clk_bulk_data *clks;
18
19         struct reset_control *rst_mac;
20         struct reset_control *rst_pcs;
21
22         void __iomem *hv;
23         void __iomem *regs;
24         void __iomem *xpcs;
25
26         struct mii_bus *mii;
27 };
28
29 #define XPCS_WRAP_UPHY_RX_CONTROL 0x801c
30 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_SW_OVRD BIT(31)
31 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_PCS_PHY_RDY BIT(10)
32 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_CDR_RESET BIT(9)
33 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_CAL_EN BIT(8)
34 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_SLEEP (BIT(7) | BIT(6))
35 #define XPCS_WRAP_UPHY_RX_CONTROL_AUX_RX_IDDQ BIT(5)
36 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_IDDQ BIT(4)
37 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_DATA_EN BIT(0)
38 #define XPCS_WRAP_UPHY_HW_INIT_CTRL 0x8020
39 #define XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN BIT(0)
40 #define XPCS_WRAP_UPHY_HW_INIT_CTRL_RX_EN BIT(2)
41 #define XPCS_WRAP_UPHY_STATUS 0x8044
42 #define XPCS_WRAP_UPHY_STATUS_TX_P_UP BIT(0)
43 #define XPCS_WRAP_IRQ_STATUS 0x8050
44 #define XPCS_WRAP_IRQ_STATUS_PCS_LINK_STS BIT(6)
45
46 #define XPCS_REG_ADDR_SHIFT 10
47 #define XPCS_REG_ADDR_MASK 0x1fff
48 #define XPCS_ADDR 0x3fc
49
50 #define MGBE_WRAP_COMMON_INTR_ENABLE    0x8704
51 #define MAC_SBD_INTR                    BIT(2)
52 #define MGBE_WRAP_AXI_ASID0_CTRL        0x8400
53 #define MGBE_SID                        0x6
54
55 static int __maybe_unused tegra_mgbe_suspend(struct device *dev)
56 {
57         struct tegra_mgbe *mgbe = get_stmmac_bsp_priv(dev);
58         int err;
59
60         err = stmmac_suspend(dev);
61         if (err)
62                 return err;
63
64         clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks);
65
66         return reset_control_assert(mgbe->rst_mac);
67 }
68
69 static int __maybe_unused tegra_mgbe_resume(struct device *dev)
70 {
71         struct tegra_mgbe *mgbe = get_stmmac_bsp_priv(dev);
72         u32 value;
73         int err;
74
75         err = clk_bulk_prepare_enable(ARRAY_SIZE(mgbe_clks), mgbe->clks);
76         if (err < 0)
77                 return err;
78
79         err = reset_control_deassert(mgbe->rst_mac);
80         if (err < 0)
81                 return err;
82
83         /* Enable common interrupt at wrapper level */
84         writel(MAC_SBD_INTR, mgbe->regs + MGBE_WRAP_COMMON_INTR_ENABLE);
85
86         /* Program SID */
87         writel(MGBE_SID, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL);
88
89         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_STATUS);
90         if ((value & XPCS_WRAP_UPHY_STATUS_TX_P_UP) == 0) {
91                 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL);
92                 value |= XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN;
93                 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL);
94         }
95
96         err = readl_poll_timeout(mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL, value,
97                                  (value & XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN) == 0,
98                                  500, 500 * 2000);
99         if (err < 0) {
100                 dev_err(mgbe->dev, "timeout waiting for TX lane to become enabled\n");
101                 clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks);
102                 return err;
103         }
104
105         err = stmmac_resume(dev);
106         if (err < 0)
107                 clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks);
108
109         return err;
110 }
111
112 static int mgbe_uphy_lane_bringup_serdes_up(struct net_device *ndev, void *mgbe_data)
113 {
114         struct tegra_mgbe *mgbe = (struct tegra_mgbe *)mgbe_data;
115         u32 value;
116         int err;
117
118         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
119         value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_SW_OVRD;
120         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
121
122         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
123         value &= ~XPCS_WRAP_UPHY_RX_CONTROL_RX_IDDQ;
124         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
125
126         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
127         value &= ~XPCS_WRAP_UPHY_RX_CONTROL_AUX_RX_IDDQ;
128         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
129
130         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
131         value &= ~XPCS_WRAP_UPHY_RX_CONTROL_RX_SLEEP;
132         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
133
134         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
135         value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_CAL_EN;
136         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
137
138         err = readl_poll_timeout(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL, value,
139                                  (value & XPCS_WRAP_UPHY_RX_CONTROL_RX_CAL_EN) == 0,
140                                  1000, 1000 * 2000);
141         if (err < 0) {
142                 dev_err(mgbe->dev, "timeout waiting for RX calibration to become enabled\n");
143                 return err;
144         }
145
146         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
147         value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_DATA_EN;
148         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
149
150         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
151         value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_CDR_RESET;
152         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
153
154         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
155         value &= ~XPCS_WRAP_UPHY_RX_CONTROL_RX_CDR_RESET;
156         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
157
158         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
159         value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_PCS_PHY_RDY;
160         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
161
162         err = readl_poll_timeout(mgbe->xpcs + XPCS_WRAP_IRQ_STATUS, value,
163                                  value & XPCS_WRAP_IRQ_STATUS_PCS_LINK_STS,
164                                  500, 500 * 2000);
165         if (err < 0) {
166                 dev_err(mgbe->dev, "timeout waiting for link to become ready\n");
167                 return err;
168         }
169
170         /* clear status */
171         writel(value, mgbe->xpcs + XPCS_WRAP_IRQ_STATUS);
172
173         return 0;
174 }
175
176 static void mgbe_uphy_lane_bringup_serdes_down(struct net_device *ndev, void *mgbe_data)
177 {
178         struct tegra_mgbe *mgbe = (struct tegra_mgbe *)mgbe_data;
179         u32 value;
180
181         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
182         value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_SW_OVRD;
183         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
184
185         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
186         value &= ~XPCS_WRAP_UPHY_RX_CONTROL_RX_DATA_EN;
187         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
188
189         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
190         value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_SLEEP;
191         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
192
193         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
194         value |= XPCS_WRAP_UPHY_RX_CONTROL_AUX_RX_IDDQ;
195         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
196
197         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
198         value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_IDDQ;
199         writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL);
200 }
201
202 static int tegra_mgbe_probe(struct platform_device *pdev)
203 {
204         struct plat_stmmacenet_data *plat;
205         struct stmmac_resources res;
206         struct tegra_mgbe *mgbe;
207         int irq, err, i;
208         u32 value;
209
210         mgbe = devm_kzalloc(&pdev->dev, sizeof(*mgbe), GFP_KERNEL);
211         if (!mgbe)
212                 return -ENOMEM;
213
214         mgbe->dev = &pdev->dev;
215
216         memset(&res, 0, sizeof(res));
217
218         irq = platform_get_irq(pdev, 0);
219         if (irq < 0)
220                 return irq;
221
222         mgbe->hv = devm_platform_ioremap_resource_byname(pdev, "hypervisor");
223         if (IS_ERR(mgbe->hv))
224                 return PTR_ERR(mgbe->hv);
225
226         mgbe->regs = devm_platform_ioremap_resource_byname(pdev, "mac");
227         if (IS_ERR(mgbe->regs))
228                 return PTR_ERR(mgbe->regs);
229
230         mgbe->xpcs = devm_platform_ioremap_resource_byname(pdev, "xpcs");
231         if (IS_ERR(mgbe->xpcs))
232                 return PTR_ERR(mgbe->xpcs);
233
234         res.addr = mgbe->regs;
235         res.irq = irq;
236
237         mgbe->clks = devm_kzalloc(&pdev->dev, sizeof(*mgbe->clks), GFP_KERNEL);
238         if (!mgbe->clks)
239                 return -ENOMEM;
240
241         for (i = 0; i <  ARRAY_SIZE(mgbe_clks); i++)
242                 mgbe->clks[i].id = mgbe_clks[i];
243
244         err = devm_clk_bulk_get(mgbe->dev, ARRAY_SIZE(mgbe_clks), mgbe->clks);
245         if (err < 0)
246                 return err;
247
248         err = clk_bulk_prepare_enable(ARRAY_SIZE(mgbe_clks), mgbe->clks);
249         if (err < 0)
250                 return err;
251
252         /* Perform MAC reset */
253         mgbe->rst_mac = devm_reset_control_get(&pdev->dev, "mac");
254         if (IS_ERR(mgbe->rst_mac)) {
255                 err = PTR_ERR(mgbe->rst_mac);
256                 goto disable_clks;
257         }
258
259         err = reset_control_assert(mgbe->rst_mac);
260         if (err < 0)
261                 goto disable_clks;
262
263         usleep_range(2000, 4000);
264
265         err = reset_control_deassert(mgbe->rst_mac);
266         if (err < 0)
267                 goto disable_clks;
268
269         /* Perform PCS reset */
270         mgbe->rst_pcs = devm_reset_control_get(&pdev->dev, "pcs");
271         if (IS_ERR(mgbe->rst_pcs)) {
272                 err = PTR_ERR(mgbe->rst_pcs);
273                 goto disable_clks;
274         }
275
276         err = reset_control_assert(mgbe->rst_pcs);
277         if (err < 0)
278                 goto disable_clks;
279
280         usleep_range(2000, 4000);
281
282         err = reset_control_deassert(mgbe->rst_pcs);
283         if (err < 0)
284                 goto disable_clks;
285
286         plat = stmmac_probe_config_dt(pdev, res.mac);
287         if (IS_ERR(plat)) {
288                 err = PTR_ERR(plat);
289                 goto disable_clks;
290         }
291
292         plat->has_xgmac = 1;
293         plat->flags |= STMMAC_FLAG_TSO_EN;
294         plat->pmt = 1;
295         plat->bsp_priv = mgbe;
296
297         if (!plat->mdio_node)
298                 plat->mdio_node = of_get_child_by_name(pdev->dev.of_node, "mdio");
299
300         if (!plat->mdio_bus_data) {
301                 plat->mdio_bus_data = devm_kzalloc(&pdev->dev, sizeof(*plat->mdio_bus_data),
302                                                    GFP_KERNEL);
303                 if (!plat->mdio_bus_data) {
304                         err = -ENOMEM;
305                         goto remove;
306                 }
307         }
308
309         plat->mdio_bus_data->needs_reset = true;
310
311         value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_STATUS);
312         if ((value & XPCS_WRAP_UPHY_STATUS_TX_P_UP) == 0) {
313                 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL);
314                 value |= XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN;
315                 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL);
316         }
317
318         err = readl_poll_timeout(mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL, value,
319                                  (value & XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN) == 0,
320                                  500, 500 * 2000);
321         if (err < 0) {
322                 dev_err(mgbe->dev, "timeout waiting for TX lane to become enabled\n");
323                 goto remove;
324         }
325
326         plat->serdes_powerup = mgbe_uphy_lane_bringup_serdes_up;
327         plat->serdes_powerdown = mgbe_uphy_lane_bringup_serdes_down;
328
329         /* Tx FIFO Size - 128KB */
330         plat->tx_fifo_size = 131072;
331         /* Rx FIFO Size - 192KB */
332         plat->rx_fifo_size = 196608;
333
334         /* Enable common interrupt at wrapper level */
335         writel(MAC_SBD_INTR, mgbe->regs + MGBE_WRAP_COMMON_INTR_ENABLE);
336
337         /* Program SID */
338         writel(MGBE_SID, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL);
339
340         plat->flags |= STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP;
341
342         err = stmmac_dvr_probe(&pdev->dev, plat, &res);
343         if (err < 0)
344                 goto remove;
345
346         return 0;
347
348 remove:
349         stmmac_remove_config_dt(pdev, plat);
350 disable_clks:
351         clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks);
352
353         return err;
354 }
355
356 static void tegra_mgbe_remove(struct platform_device *pdev)
357 {
358         struct tegra_mgbe *mgbe = get_stmmac_bsp_priv(&pdev->dev);
359
360         clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks);
361
362         stmmac_pltfr_remove(pdev);
363 }
364
365 static const struct of_device_id tegra_mgbe_match[] = {
366         { .compatible = "nvidia,tegra234-mgbe", },
367         { }
368 };
369 MODULE_DEVICE_TABLE(of, tegra_mgbe_match);
370
371 static SIMPLE_DEV_PM_OPS(tegra_mgbe_pm_ops, tegra_mgbe_suspend, tegra_mgbe_resume);
372
373 static struct platform_driver tegra_mgbe_driver = {
374         .probe = tegra_mgbe_probe,
375         .remove_new = tegra_mgbe_remove,
376         .driver = {
377                 .name = "tegra-mgbe",
378                 .pm             = &tegra_mgbe_pm_ops,
379                 .of_match_table = tegra_mgbe_match,
380         },
381 };
382 module_platform_driver(tegra_mgbe_driver);
383
384 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
385 MODULE_DESCRIPTION("NVIDIA Tegra MGBE driver");
386 MODULE_LICENSE("GPL");