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