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