1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Synopsys DWC Ethernet Quality-of-Service v4.10a linux driver
4 *
5 * Copyright (C) 2016 Joao Pinto <jpinto@synopsys.com>
6 */
7
8 #include <linux/clk.h>
9 #include <linux/clk-provider.h>
10 #include <linux/device.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/ethtool.h>
13 #include <linux/io.h>
14 #include <linux/iopoll.h>
15 #include <linux/ioport.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <linux/of_net.h>
19 #include <linux/mfd/syscon.h>
20 #include <linux/platform_device.h>
21 #include <linux/reset.h>
22 #include <linux/stmmac.h>
23
24 #include "stmmac_platform.h"
25 #include "dwmac4.h"
26
27 struct tegra_eqos {
28 struct device *dev;
29 void __iomem *regs;
30
31 struct reset_control *rst;
32 struct clk *clk_slave;
33
34 struct gpio_desc *reset;
35 };
36
dwc_eth_find_clk(struct plat_stmmacenet_data * plat_dat,const char * name)37 static struct clk *dwc_eth_find_clk(struct plat_stmmacenet_data *plat_dat,
38 const char *name)
39 {
40 for (int i = 0; i < plat_dat->num_clks; i++)
41 if (strcmp(plat_dat->clks[i].id, name) == 0)
42 return plat_dat->clks[i].clk;
43
44 return NULL;
45 }
46
dwc_eth_dwmac_config_dt(struct platform_device * pdev,struct plat_stmmacenet_data * plat_dat)47 static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
48 struct plat_stmmacenet_data *plat_dat)
49 {
50 struct device *dev = &pdev->dev;
51 u32 burst_map = 0;
52 u32 bit_index = 0;
53 u32 a_index = 0;
54
55 if (!plat_dat->axi) {
56 plat_dat->axi = devm_kzalloc(&pdev->dev,
57 sizeof(struct stmmac_axi),
58 GFP_KERNEL);
59
60 if (!plat_dat->axi)
61 return -ENOMEM;
62 }
63
64 plat_dat->axi->axi_lpi_en = device_property_read_bool(dev,
65 "snps,en-lpi");
66 if (device_property_read_u32(dev, "snps,write-requests",
67 &plat_dat->axi->axi_wr_osr_lmt)) {
68 /**
69 * Since the register has a reset value of 1, if property
70 * is missing, default to 1.
71 */
72 plat_dat->axi->axi_wr_osr_lmt = 1;
73 } else {
74 /**
75 * If property exists, to keep the behavior from dwc_eth_qos,
76 * subtract one after parsing.
77 */
78 plat_dat->axi->axi_wr_osr_lmt--;
79 }
80
81 if (device_property_read_u32(dev, "snps,read-requests",
82 &plat_dat->axi->axi_rd_osr_lmt)) {
83 /**
84 * Since the register has a reset value of 1, if property
85 * is missing, default to 1.
86 */
87 plat_dat->axi->axi_rd_osr_lmt = 1;
88 } else {
89 /**
90 * If property exists, to keep the behavior from dwc_eth_qos,
91 * subtract one after parsing.
92 */
93 plat_dat->axi->axi_rd_osr_lmt--;
94 }
95 device_property_read_u32(dev, "snps,burst-map", &burst_map);
96
97 /* converts burst-map bitmask to burst array */
98 for (bit_index = 0; bit_index < 7; bit_index++) {
99 if (burst_map & (1 << bit_index)) {
100 switch (bit_index) {
101 case 0:
102 plat_dat->axi->axi_blen[a_index] = 4; break;
103 case 1:
104 plat_dat->axi->axi_blen[a_index] = 8; break;
105 case 2:
106 plat_dat->axi->axi_blen[a_index] = 16; break;
107 case 3:
108 plat_dat->axi->axi_blen[a_index] = 32; break;
109 case 4:
110 plat_dat->axi->axi_blen[a_index] = 64; break;
111 case 5:
112 plat_dat->axi->axi_blen[a_index] = 128; break;
113 case 6:
114 plat_dat->axi->axi_blen[a_index] = 256; break;
115 default:
116 break;
117 }
118 a_index++;
119 }
120 }
121
122 /* dwc-qos needs GMAC4, AAL, TSO and PMT */
123 plat_dat->has_gmac4 = 1;
124 plat_dat->dma_cfg->aal = 1;
125 plat_dat->flags |= STMMAC_FLAG_TSO_EN;
126 plat_dat->pmt = 1;
127
128 return 0;
129 }
130
dwc_qos_probe(struct platform_device * pdev,struct plat_stmmacenet_data * plat_dat,struct stmmac_resources * stmmac_res)131 static int dwc_qos_probe(struct platform_device *pdev,
132 struct plat_stmmacenet_data *plat_dat,
133 struct stmmac_resources *stmmac_res)
134 {
135 plat_dat->pclk = dwc_eth_find_clk(plat_dat, "phy_ref_clk");
136
137 return 0;
138 }
139
140 #define SDMEMCOMPPADCTRL 0x8800
141 #define SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31)
142
143 #define AUTO_CAL_CONFIG 0x8804
144 #define AUTO_CAL_CONFIG_START BIT(31)
145 #define AUTO_CAL_CONFIG_ENABLE BIT(29)
146
147 #define AUTO_CAL_STATUS 0x880c
148 #define AUTO_CAL_STATUS_ACTIVE BIT(31)
149
tegra_eqos_fix_speed(void * priv,int speed,unsigned int mode)150 static void tegra_eqos_fix_speed(void *priv, int speed, unsigned int mode)
151 {
152 struct tegra_eqos *eqos = priv;
153 bool needs_calibration = false;
154 u32 value;
155 int err;
156
157 switch (speed) {
158 case SPEED_1000:
159 case SPEED_100:
160 needs_calibration = true;
161 fallthrough;
162
163 case SPEED_10:
164 break;
165
166 default:
167 dev_err(eqos->dev, "invalid speed %d\n", speed);
168 break;
169 }
170
171 if (needs_calibration) {
172 /* calibrate */
173 value = readl(eqos->regs + SDMEMCOMPPADCTRL);
174 value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
175 writel(value, eqos->regs + SDMEMCOMPPADCTRL);
176
177 udelay(1);
178
179 value = readl(eqos->regs + AUTO_CAL_CONFIG);
180 value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE;
181 writel(value, eqos->regs + AUTO_CAL_CONFIG);
182
183 err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS,
184 value,
185 value & AUTO_CAL_STATUS_ACTIVE,
186 1, 10);
187 if (err < 0) {
188 dev_err(eqos->dev, "calibration did not start\n");
189 goto failed;
190 }
191
192 err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS,
193 value,
194 (value & AUTO_CAL_STATUS_ACTIVE) == 0,
195 20, 200);
196 if (err < 0) {
197 dev_err(eqos->dev, "calibration didn't finish\n");
198 goto failed;
199 }
200
201 failed:
202 value = readl(eqos->regs + SDMEMCOMPPADCTRL);
203 value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
204 writel(value, eqos->regs + SDMEMCOMPPADCTRL);
205 } else {
206 value = readl(eqos->regs + AUTO_CAL_CONFIG);
207 value &= ~AUTO_CAL_CONFIG_ENABLE;
208 writel(value, eqos->regs + AUTO_CAL_CONFIG);
209 }
210 }
211
tegra_eqos_init(struct platform_device * pdev,void * priv)212 static int tegra_eqos_init(struct platform_device *pdev, void *priv)
213 {
214 struct tegra_eqos *eqos = priv;
215 unsigned long rate;
216 u32 value;
217
218 rate = clk_get_rate(eqos->clk_slave);
219
220 value = (rate / 1000000) - 1;
221 writel(value, eqos->regs + GMAC_1US_TIC_COUNTER);
222
223 return 0;
224 }
225
tegra_eqos_probe(struct platform_device * pdev,struct plat_stmmacenet_data * plat_dat,struct stmmac_resources * res)226 static int tegra_eqos_probe(struct platform_device *pdev,
227 struct plat_stmmacenet_data *plat_dat,
228 struct stmmac_resources *res)
229 {
230 struct device *dev = &pdev->dev;
231 struct tegra_eqos *eqos;
232 int err;
233
234 eqos = devm_kzalloc(&pdev->dev, sizeof(*eqos), GFP_KERNEL);
235 if (!eqos)
236 return -ENOMEM;
237
238 eqos->dev = &pdev->dev;
239 eqos->regs = res->addr;
240 eqos->clk_slave = plat_dat->stmmac_clk;
241
242 if (!is_of_node(dev->fwnode))
243 goto bypass_clk_reset_gpio;
244
245 plat_dat->clk_tx_i = dwc_eth_find_clk(plat_dat, "tx");
246
247 eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH);
248 if (IS_ERR(eqos->reset)) {
249 err = PTR_ERR(eqos->reset);
250 return err;
251 }
252
253 usleep_range(2000, 4000);
254 gpiod_set_value(eqos->reset, 0);
255
256 /* MDIO bus was already reset just above */
257 plat_dat->mdio_bus_data->needs_reset = false;
258
259 eqos->rst = devm_reset_control_get(&pdev->dev, "eqos");
260 if (IS_ERR(eqos->rst)) {
261 err = PTR_ERR(eqos->rst);
262 goto reset_phy;
263 }
264
265 err = reset_control_assert(eqos->rst);
266 if (err < 0)
267 goto reset_phy;
268
269 usleep_range(2000, 4000);
270
271 err = reset_control_deassert(eqos->rst);
272 if (err < 0)
273 goto reset_phy;
274
275 usleep_range(2000, 4000);
276
277 bypass_clk_reset_gpio:
278 plat_dat->fix_mac_speed = tegra_eqos_fix_speed;
279 plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;
280 plat_dat->init = tegra_eqos_init;
281 plat_dat->bsp_priv = eqos;
282 plat_dat->flags |= STMMAC_FLAG_SPH_DISABLE;
283
284 err = tegra_eqos_init(pdev, eqos);
285 if (err < 0)
286 goto reset;
287
288 return 0;
289 reset:
290 reset_control_assert(eqos->rst);
291 reset_phy:
292 gpiod_set_value(eqos->reset, 1);
293
294 return err;
295 }
296
tegra_eqos_remove(struct platform_device * pdev)297 static void tegra_eqos_remove(struct platform_device *pdev)
298 {
299 struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev);
300
301 reset_control_assert(eqos->rst);
302 gpiod_set_value(eqos->reset, 1);
303 }
304
305 struct dwc_eth_dwmac_data {
306 int (*probe)(struct platform_device *pdev,
307 struct plat_stmmacenet_data *plat_dat,
308 struct stmmac_resources *res);
309 void (*remove)(struct platform_device *pdev);
310 const char *stmmac_clk_name;
311 };
312
313 static const struct dwc_eth_dwmac_data dwc_qos_data = {
314 .probe = dwc_qos_probe,
315 .stmmac_clk_name = "apb_pclk",
316 };
317
318 static const struct dwc_eth_dwmac_data tegra_eqos_data = {
319 .probe = tegra_eqos_probe,
320 .remove = tegra_eqos_remove,
321 .stmmac_clk_name = "slave_bus",
322 };
323
324 static const struct dwc_eth_dwmac_data fsd_eqos_data = {
325 .stmmac_clk_name = "slave_bus",
326 };
327
dwc_eth_dwmac_probe(struct platform_device * pdev)328 static int dwc_eth_dwmac_probe(struct platform_device *pdev)
329 {
330 const struct dwc_eth_dwmac_data *data;
331 struct plat_stmmacenet_data *plat_dat;
332 struct stmmac_resources stmmac_res;
333 int ret;
334
335 data = device_get_match_data(&pdev->dev);
336
337 memset(&stmmac_res, 0, sizeof(struct stmmac_resources));
338
339 /**
340 * Since stmmac_platform supports name IRQ only, basic platform
341 * resource initialization is done in the glue logic.
342 */
343 stmmac_res.irq = platform_get_irq(pdev, 0);
344 if (stmmac_res.irq < 0)
345 return stmmac_res.irq;
346 stmmac_res.wol_irq = stmmac_res.irq;
347
348 stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0);
349 if (IS_ERR(stmmac_res.addr))
350 return PTR_ERR(stmmac_res.addr);
351
352 plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
353 if (IS_ERR(plat_dat))
354 return PTR_ERR(plat_dat);
355
356 ret = devm_clk_bulk_get_all(&pdev->dev, &plat_dat->clks);
357 if (ret < 0)
358 return dev_err_probe(&pdev->dev, ret, "Failed to retrieve all required clocks\n");
359 plat_dat->num_clks = ret;
360
361 ret = clk_bulk_prepare_enable(plat_dat->num_clks, plat_dat->clks);
362 if (ret)
363 return dev_err_probe(&pdev->dev, ret, "Failed to enable clocks\n");
364
365 plat_dat->stmmac_clk = dwc_eth_find_clk(plat_dat,
366 data->stmmac_clk_name);
367
368 if (data->probe)
369 ret = data->probe(pdev, plat_dat, &stmmac_res);
370 if (ret < 0) {
371 dev_err_probe(&pdev->dev, ret, "failed to probe subdriver\n");
372 clk_bulk_disable_unprepare(plat_dat->num_clks, plat_dat->clks);
373 return ret;
374 }
375
376 ret = dwc_eth_dwmac_config_dt(pdev, plat_dat);
377 if (ret)
378 goto remove;
379
380 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
381 if (ret)
382 goto remove;
383
384 return ret;
385
386 remove:
387 if (data->remove)
388 data->remove(pdev);
389
390 return ret;
391 }
392
dwc_eth_dwmac_remove(struct platform_device * pdev)393 static void dwc_eth_dwmac_remove(struct platform_device *pdev)
394 {
395 const struct dwc_eth_dwmac_data *data = device_get_match_data(&pdev->dev);
396 struct plat_stmmacenet_data *plat_dat = dev_get_platdata(&pdev->dev);
397
398 stmmac_dvr_remove(&pdev->dev);
399
400 if (data->remove)
401 data->remove(pdev);
402
403 if (plat_dat)
404 clk_bulk_disable_unprepare(plat_dat->num_clks, plat_dat->clks);
405 }
406
407 static const struct of_device_id dwc_eth_dwmac_match[] = {
408 { .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data },
409 { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data },
410 { .compatible = "tesla,fsd-ethqos", .data = &fsd_eqos_data },
411 { }
412 };
413 MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
414
415 static struct platform_driver dwc_eth_dwmac_driver = {
416 .probe = dwc_eth_dwmac_probe,
417 .remove = dwc_eth_dwmac_remove,
418 .driver = {
419 .name = "dwc-eth-dwmac",
420 .pm = &stmmac_pltfr_pm_ops,
421 .of_match_table = dwc_eth_dwmac_match,
422 },
423 };
424 module_platform_driver(dwc_eth_dwmac_driver);
425
426 MODULE_AUTHOR("Joao Pinto <jpinto@synopsys.com>");
427 MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver");
428 MODULE_LICENSE("GPL v2");
429