xref: /OK3568_Linux_fs/external/dpdk/gmac/kernel5.10/kernel_net_stmmac.diff (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1From 23f2752638f0ec22fb848b46b2d16d65bd98b49d Mon Sep 17 00:00:00 2001
2From: David Wu <david.wu@rock-chips.com>
3Date: Thu, 03 Nov 2022 10:47:48 +0800
4Subject: [PATCH] net: ethernet: stmmac: Add uio support for stmmac
5
6Currently only supports single channel, and the network card
7name needs to be eth0 and eth1.
8
9Signed-off-by: David Wu <david.wu@rock-chips.com>
10Change-Id: I19975b10e2ed12931edc2e8bd50c003416a1109c
11---
12
13diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
14index 38039c9..c19cdd6 100644
15--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
16+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
17@@ -52,6 +52,13 @@
18
19 	  If unsure, say N.
20
21+config STMMAC_UIO
22+	tristate "STMMAC_UIO ethernet controller"
23+	default n
24+	select UIO
25+	help
26+	  Say M here if you want to use the stmmac_uio.ko for DPDK.
27+
28 if STMMAC_PLATFORM
29
30 config DWMAC_DWC_QOS_ETH
31diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
32index 05c792e..d017cbc 100644
33--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
34+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
35@@ -27,6 +27,7 @@
36 obj-$(CONFIG_DWMAC_ROCKCHIP)	+= dwmac-rockchip.o
37 dwmac-rockchip-objs := dwmac-rk.o
38 dwmac-rockchip-$(CONFIG_DWMAC_ROCKCHIP_TOOL) += dwmac-rk-tool.o
39+obj-$(CONFIG_STMMAC_UIO) += stmmac_uio.o
40 obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-altr-socfpga.o
41 obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
42 obj-$(CONFIG_DWMAC_STM32)	+= dwmac-stm32.o
43diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
44index df7de50..37658d7 100644
45--- a/drivers/net/ethernet/stmicro/stmmac/common.h
46+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
47@@ -48,10 +48,18 @@
48  */
49 #define DMA_MIN_TX_SIZE		64
50 #define DMA_MAX_TX_SIZE		1024
51+#if IS_ENABLED(CONFIG_STMMAC_UIO)
52+#define DMA_DEFAULT_TX_SIZE	1024
53+#else
54 #define DMA_DEFAULT_TX_SIZE	512
55+#endif
56 #define DMA_MIN_RX_SIZE		64
57 #define DMA_MAX_RX_SIZE		1024
58+#if IS_ENABLED(CONFIG_STMMAC_UIO)
59+#define DMA_DEFAULT_RX_SIZE	1024
60+#else
61 #define DMA_DEFAULT_RX_SIZE	512
62+#endif
63 #define STMMAC_GET_ENTRY(x, size)	((x + 1) & (size - 1))
64
65 #undef FRAME_FILTER_DEBUG
66diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
67index 7c1a14b..8a29921 100644
68--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
69+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
70@@ -396,6 +396,7 @@
71 #endif
72 	return 0;
73 }
74+EXPORT_SYMBOL(stmmac_mdio_reset);
75
76 /**
77  * stmmac_mdio_register
78diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_uio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_uio.c
79new file mode 100644
80index 0000000..11ec4b7
81--- /dev/null
82+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_uio.c
83@@ -0,0 +1,1050 @@
84+// SPDX-License-Identifier: GPL-2.0
85+/**
86+ * Copyright 2023 ROCKCHIP
87+ */
88+
89+#include <linux/module.h>
90+#include <linux/kernel.h>
91+#include <linux/of_address.h>
92+#include <linux/of_platform.h>
93+#include <linux/of_net.h>
94+#include <linux/uio_driver.h>
95+#include <linux/list.h>
96+
97+#include <linux/clk.h>
98+#include <linux/kernel.h>
99+#include <linux/interrupt.h>
100+#include <linux/ip.h>
101+#include <linux/tcp.h>
102+#include <linux/ethtool.h>
103+#include <linux/if_ether.h>
104+#include <linux/crc32.h>
105+#include <linux/mii.h>
106+#include <linux/if.h>
107+#include <linux/if_vlan.h>
108+#include <linux/dma-mapping.h>
109+#include <linux/slab.h>
110+#include <linux/prefetch.h>
111+#include <linux/pinctrl/consumer.h>
112+#ifdef CONFIG_DEBUG_FS
113+#include <linux/debugfs.h>
114+#include <linux/seq_file.h>
115+#endif /* CONFIG_DEBUG_FS */
116+#include <linux/net_tstamp.h>
117+#include <linux/udp.h>
118+#include <net/pkt_cls.h>
119+#include "stmmac_ptp.h"
120+#include "stmmac.h"
121+#include <linux/reset.h>
122+#include <linux/of_mdio.h>
123+#include "dwmac1000.h"
124+#include "dwxgmac2.h"
125+#include "hwif.h"
126+#include "mmc.h"
127+
128+#define DRIVER_NAME	"rockchip_gmac_uio_drv"
129+#define DRIVER_VERSION	"0.1"
130+
131+#define TC_DEFAULT 64
132+static int tc = TC_DEFAULT;
133+
134+#define DEFAULT_BUFSIZE	1536
135+static int buf_sz = DEFAULT_BUFSIZE;
136+
137+#define STMMAC_RX_COPYBREAK	256
138+
139+/**
140+ * rockchip_gmac_uio_pdev_info
141+ * local information for uio module driver
142+ *
143+ * @dev:      device pointer
144+ * @ndev:     network device pointer
145+ * @name:     uio name
146+ * @uio:      uio information
147+ * @map_num:  number of uio memory regions
148+ */
149+struct rockchip_gmac_uio_pdev_info {
150+	struct device *dev;
151+	struct net_device *ndev;
152+	char name[16];
153+	struct uio_info uio;
154+	int map_num;
155+};
156+
157+static int rockchip_gmac_uio_open(struct uio_info *info, struct inode *inode)
158+{
159+	return 0;
160+}
161+
162+static int rockchip_gmac_uio_release(struct uio_info *info,
163+				     struct inode *inode)
164+{
165+	return 0;
166+}
167+
168+static int rockchip_gmac_uio_mmap(struct uio_info *info,
169+				  struct vm_area_struct *vma)
170+{
171+	u32 ret;
172+	u32 pfn;
173+
174+	pfn = (info->mem[vma->vm_pgoff].addr) >> PAGE_SHIFT;
175+
176+	if (vma->vm_pgoff)
177+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
178+	else
179+		vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
180+
181+	ret = remap_pfn_range(vma, vma->vm_start, pfn,
182+			      vma->vm_end - vma->vm_start, vma->vm_page_prot);
183+	if (ret) {
184+		/* Error Handle */
185+		pr_err("remap_pfn_range failed");
186+	}
187+	return ret;
188+}
189+
190+/**
191+ * uio_free_dma_rx_desc_resources - free RX dma desc resources
192+ * @priv: private structure
193+ */
194+static void uio_free_dma_rx_desc_resources(struct stmmac_priv *priv)
195+{
196+	u32 rx_count = priv->plat->rx_queues_to_use;
197+	u32 queue;
198+
199+	/* Free RX queue resources */
200+	for (queue = 0; queue < rx_count; queue++) {
201+		struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
202+
203+		/* Free DMA regions of consistent memory previously allocated */
204+		if (!priv->extend_desc)
205+			dma_free_coherent(priv->device, priv->dma_rx_size *
206+					  sizeof(struct dma_desc),
207+					  rx_q->dma_rx, rx_q->dma_rx_phy);
208+		else
209+			dma_free_coherent(priv->device, priv->dma_rx_size *
210+					  sizeof(struct dma_extended_desc),
211+					  rx_q->dma_erx, rx_q->dma_rx_phy);
212+	}
213+}
214+
215+/**
216+ * uio_free_dma_tx_desc_resources - free TX dma desc resources
217+ * @priv: private structure
218+ */
219+static void uio_free_dma_tx_desc_resources(struct stmmac_priv *priv)
220+{
221+	u32 tx_count = priv->plat->tx_queues_to_use;
222+	u32 queue;
223+
224+	/* Free TX queue resources */
225+	for (queue = 0; queue < tx_count; queue++) {
226+		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
227+		size_t size;
228+		void *addr;
229+
230+		if (priv->extend_desc) {
231+			size = sizeof(struct dma_extended_desc);
232+			addr = tx_q->dma_etx;
233+		} else if (tx_q->tbs & STMMAC_TBS_AVAIL) {
234+			size = sizeof(struct dma_edesc);
235+			addr = tx_q->dma_entx;
236+		} else {
237+			size = sizeof(struct dma_desc);
238+			addr = tx_q->dma_tx;
239+		}
240+
241+		size *= priv->dma_tx_size;
242+
243+		dma_free_coherent(priv->device, size, addr, tx_q->dma_tx_phy);
244+	}
245+}
246+
247+/**
248+ * uio_alloc_dma_rx_desc_resources - alloc RX resources.
249+ * @priv: private structure
250+ * Description: according to which descriptor can be used (extend or basic)
251+ * this function allocates the resources for TX and RX paths. In case of
252+ * reception, for example, it pre-allocated the RX socket buffer in order to
253+ * allow zero-copy mechanism.
254+ */
255+static int uio_alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
256+{
257+	u32 rx_count = priv->plat->rx_queues_to_use;
258+	int ret = -ENOMEM;
259+	u32 queue;
260+
261+	/* RX queues buffers and DMA */
262+	for (queue = 0; queue < rx_count; queue++) {
263+		struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
264+
265+		if (priv->extend_desc) {
266+			rx_q->dma_erx = dma_alloc_coherent(priv->device,
267+							   priv->dma_rx_size *
268+							   sizeof(struct dma_extended_desc),
269+							   &rx_q->dma_rx_phy,
270+							   GFP_KERNEL);
271+			if (!rx_q->dma_erx)
272+				goto err_dma;
273+		} else {
274+			rx_q->dma_rx = dma_alloc_coherent(priv->device,
275+							  priv->dma_rx_size *
276+							  sizeof(struct dma_desc),
277+							  &rx_q->dma_rx_phy,
278+							  GFP_KERNEL);
279+			if (!rx_q->dma_rx)
280+				goto err_dma;
281+		}
282+	}
283+
284+	return 0;
285+
286+err_dma:
287+	uio_free_dma_rx_desc_resources(priv);
288+
289+	return ret;
290+}
291+
292+/**
293+ * uio_alloc_dma_tx_desc_resources - alloc TX resources.
294+ * @priv: private structure
295+ * Description: according to which descriptor can be used (extend or basic)
296+ * this function allocates the resources for TX and RX paths. In case of
297+ * reception, for example, it pre-allocated the RX socket buffer in order to
298+ * allow zero-copy mechanism.
299+ */
300+static int uio_alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
301+{
302+	u32 tx_count = priv->plat->tx_queues_to_use;
303+	int ret = -ENOMEM;
304+	u32 queue;
305+
306+	/* TX queues buffers and DMA */
307+	for (queue = 0; queue < tx_count; queue++) {
308+		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
309+		size_t size;
310+		void *addr;
311+
312+		tx_q->queue_index = queue;
313+		tx_q->priv_data = priv;
314+
315+		if (priv->extend_desc)
316+			size = sizeof(struct dma_extended_desc);
317+		else if (tx_q->tbs & STMMAC_TBS_AVAIL)
318+			size = sizeof(struct dma_edesc);
319+		else
320+			size = sizeof(struct dma_desc);
321+
322+		size *= priv->dma_tx_size;
323+
324+		addr = dma_alloc_coherent(priv->device, size,
325+					  &tx_q->dma_tx_phy, GFP_KERNEL);
326+		if (!addr)
327+			goto err_dma;
328+
329+		if (priv->extend_desc)
330+			tx_q->dma_etx = addr;
331+		else if (tx_q->tbs & STMMAC_TBS_AVAIL)
332+			tx_q->dma_entx = addr;
333+		else
334+			tx_q->dma_tx = addr;
335+	}
336+
337+	return 0;
338+
339+err_dma:
340+	uio_free_dma_tx_desc_resources(priv);
341+	return ret;
342+}
343+
344+/**
345+ * uio_alloc_dma_desc_resources - alloc TX/RX resources.
346+ * @priv: private structure
347+ * Description: according to which descriptor can be used (extend or basic)
348+ * this function allocates the resources for TX and RX paths. In case of
349+ * reception, for example, it pre-allocated the RX socket buffer in order to
350+ * allow zero-copy mechanism.
351+ */
352+static int uio_alloc_dma_desc_resources(struct stmmac_priv *priv)
353+{
354+	/* RX Allocation */
355+	int ret = uio_alloc_dma_rx_desc_resources(priv);
356+
357+	if (ret)
358+		return ret;
359+
360+	ret = uio_alloc_dma_tx_desc_resources(priv);
361+
362+	return ret;
363+}
364+
365+/**
366+ * uio_free_dma_desc_resources - free dma desc resources
367+ * @priv: private structure
368+ */
369+static void uio_free_dma_desc_resources(struct stmmac_priv *priv)
370+{
371+	/* Release the DMA RX socket buffers */
372+	uio_free_dma_rx_desc_resources(priv);
373+
374+	/* Release the DMA TX socket buffers */
375+	uio_free_dma_tx_desc_resources(priv);
376+}
377+
378+/**
379+ * rockchip_gmac_uio_init_phy - PHY initialization
380+ * @dev: net device structure
381+ * Description: it initializes the driver's PHY state, and attaches the PHY
382+ * to the mac driver.
383+ *  Return value:
384+ *  0 on success
385+ */
386+static int rockchip_gmac_uio_init_phy(struct net_device *dev)
387+{
388+	struct stmmac_priv *priv = netdev_priv(dev);
389+	struct device_node *node;
390+	int ret;
391+
392+	node = priv->plat->phylink_node;
393+
394+	if (node)
395+		ret = phylink_of_phy_connect(priv->phylink, node, 0);
396+
397+	/* Some DT bindings do not set-up the PHY handle. Let's try to
398+	 * manually parse it
399+	 */
400+	if (!node || ret) {
401+		int addr = priv->plat->phy_addr;
402+		struct phy_device *phydev;
403+
404+		phydev = mdiobus_get_phy(priv->mii, addr);
405+		if (!phydev) {
406+			netdev_err(priv->dev, "no phy at addr %d\n", addr);
407+			return -ENODEV;
408+		}
409+
410+		ret = phylink_connect_phy(priv->phylink, phydev);
411+	}
412+
413+	if (!priv->plat->pmt) {
414+		struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
415+
416+		phylink_ethtool_get_wol(priv->phylink, &wol);
417+		device_set_wakeup_capable(priv->device, !!wol.supported);
418+	}
419+
420+	return ret;
421+}
422+
423+/**
424+ * rockchip_gmac_uio_init_dma_engine - DMA init.
425+ * @priv: driver private structure
426+ * Description:
427+ * It inits the DMA invoking the specific MAC/GMAC callback.
428+ * Some DMA parameters can be passed from the platform;
429+ * in case of these are not passed a default is kept for the MAC or GMAC.
430+ */
431+static int rockchip_gmac_uio_init_dma_engine(struct stmmac_priv *priv)
432+{
433+	u32 rx_channels_count = priv->plat->rx_queues_to_use;
434+	u32 tx_channels_count = priv->plat->tx_queues_to_use;
435+	u32 dma_csr_ch = max(rx_channels_count, tx_channels_count);
436+	struct stmmac_rx_queue *rx_q;
437+	struct stmmac_tx_queue *tx_q;
438+	u32 chan = 0;
439+	int atds = 0;
440+	int ret = 0;
441+
442+	if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) {
443+		dev_err(priv->device, "Invalid DMA configuration\n");
444+		return -EINVAL;
445+	}
446+
447+	if (priv->extend_desc && priv->mode == STMMAC_RING_MODE)
448+		atds = 1;
449+
450+	ret = stmmac_reset(priv, priv->ioaddr);
451+	if (ret) {
452+		dev_err(priv->device, "Failed to reset the dma\n");
453+		return ret;
454+	}
455+
456+	/* DMA Configuration */
457+	stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg, atds);
458+
459+	if (priv->plat->axi)
460+		stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
461+
462+	/* DMA CSR Channel configuration */
463+	for (chan = 0; chan < dma_csr_ch; chan++)
464+		stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
465+
466+	/* DMA RX Channel Configuration */
467+	for (chan = 0; chan < rx_channels_count; chan++) {
468+		rx_q = &priv->rx_queue[chan];
469+
470+		stmmac_init_rx_chan(priv, priv->ioaddr, priv->plat->dma_cfg,
471+				    rx_q->dma_rx_phy, chan);
472+
473+		rx_q->rx_tail_addr = rx_q->dma_rx_phy +
474+				     (priv->dma_rx_size *
475+				      sizeof(struct dma_desc));
476+		stmmac_set_rx_tail_ptr(priv, priv->ioaddr,
477+				       rx_q->rx_tail_addr, chan);
478+	}
479+
480+	/* DMA TX Channel Configuration */
481+	for (chan = 0; chan < tx_channels_count; chan++) {
482+		tx_q = &priv->tx_queue[chan];
483+
484+		stmmac_init_tx_chan(priv, priv->ioaddr, priv->plat->dma_cfg,
485+				    tx_q->dma_tx_phy, chan);
486+
487+		tx_q->tx_tail_addr = tx_q->dma_tx_phy;
488+		stmmac_set_tx_tail_ptr(priv, priv->ioaddr,
489+				       tx_q->tx_tail_addr, chan);
490+	}
491+
492+	return ret;
493+}
494+
495+static void uio_set_rings_length(struct stmmac_priv *priv)
496+{
497+	u32 rx_channels_count = priv->plat->rx_queues_to_use;
498+	u32 tx_channels_count = priv->plat->tx_queues_to_use;
499+	u32 chan;
500+
501+	/* set TX ring length */
502+	for (chan = 0; chan < tx_channels_count; chan++)
503+		stmmac_set_tx_ring_len(priv, priv->ioaddr,
504+				       (priv->dma_tx_size - 1), chan);
505+
506+	/* set RX ring length */
507+	for (chan = 0; chan < rx_channels_count; chan++)
508+		stmmac_set_rx_ring_len(priv, priv->ioaddr,
509+				       (priv->dma_rx_size - 1), chan);
510+}
511+
512+/**
513+ *  uio_set_tx_queue_weight - Set TX queue weight
514+ *  @priv: driver private structure
515+ *  Description: It is used for setting TX queues weight
516+ */
517+static void uio_set_tx_queue_weight(struct stmmac_priv *priv)
518+{
519+	u32 tx_queues_count = priv->plat->tx_queues_to_use;
520+	u32 weight;
521+	u32 queue;
522+
523+	for (queue = 0; queue < tx_queues_count; queue++) {
524+		weight = priv->plat->tx_queues_cfg[queue].weight;
525+		stmmac_set_mtl_tx_queue_weight(priv, priv->hw, weight, queue);
526+	}
527+}
528+
529+/**
530+ *  uio_configure_cbs - Configure CBS in TX queue
531+ *  @priv: driver private structure
532+ *  Description: It is used for configuring CBS in AVB TX queues
533+ */
534+static void uio_configure_cbs(struct stmmac_priv *priv)
535+{
536+	u32 tx_queues_count = priv->plat->tx_queues_to_use;
537+	u32 mode_to_use;
538+	u32 queue;
539+
540+	/* queue 0 is reserved for legacy traffic */
541+	for (queue = 1; queue < tx_queues_count; queue++) {
542+		mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use;
543+		if (mode_to_use == MTL_QUEUE_DCB)
544+			continue;
545+
546+		stmmac_config_cbs(priv, priv->hw,
547+				  priv->plat->tx_queues_cfg[queue].send_slope,
548+				  priv->plat->tx_queues_cfg[queue].idle_slope,
549+				  priv->plat->tx_queues_cfg[queue].high_credit,
550+				  priv->plat->tx_queues_cfg[queue].low_credit,
551+				  queue);
552+	}
553+}
554+
555+/**
556+ *  uio_rx_queue_dma_chan_map - Map RX queue to RX dma channel
557+ *  @priv: driver private structure
558+ *  Description: It is used for mapping RX queues to RX dma channels
559+ */
560+static void uio_rx_queue_dma_chan_map(struct stmmac_priv *priv)
561+{
562+	u32 rx_queues_count = priv->plat->rx_queues_to_use;
563+	u32 queue;
564+	u32 chan;
565+
566+	for (queue = 0; queue < rx_queues_count; queue++) {
567+		chan = priv->plat->rx_queues_cfg[queue].chan;
568+		stmmac_map_mtl_to_dma(priv, priv->hw, queue, chan);
569+	}
570+}
571+
572+/**
573+ *  uio_mac_config_rx_queues_prio - Configure RX Queue priority
574+ *  @priv: driver private structure
575+ *  Description: It is used for configuring the RX Queue Priority
576+ */
577+static void uio_mac_config_rx_queues_prio(struct stmmac_priv *priv)
578+{
579+	u32 rx_queues_count = priv->plat->rx_queues_to_use;
580+	u32 queue;
581+	u32 prio;
582+
583+	for (queue = 0; queue < rx_queues_count; queue++) {
584+		if (!priv->plat->rx_queues_cfg[queue].use_prio)
585+			continue;
586+
587+		prio = priv->plat->rx_queues_cfg[queue].prio;
588+		stmmac_rx_queue_prio(priv, priv->hw, prio, queue);
589+	}
590+}
591+
592+/**
593+ *  uio_mac_config_tx_queues_prio - Configure TX Queue priority
594+ *  @priv: driver private structure
595+ *  Description: It is used for configuring the TX Queue Priority
596+ */
597+static void uio_mac_config_tx_queues_prio(struct stmmac_priv *priv)
598+{
599+	u32 tx_queues_count = priv->plat->tx_queues_to_use;
600+	u32 queue;
601+	u32 prio;
602+
603+	for (queue = 0; queue < tx_queues_count; queue++) {
604+		if (!priv->plat->tx_queues_cfg[queue].use_prio)
605+			continue;
606+
607+		prio = priv->plat->tx_queues_cfg[queue].prio;
608+		stmmac_tx_queue_prio(priv, priv->hw, prio, queue);
609+	}
610+}
611+
612+/**
613+ *  uio_mac_config_rx_queues_routing - Configure RX Queue Routing
614+ *  @priv: driver private structure
615+ *  Description: It is used for configuring the RX queue routing
616+ */
617+static void uio_mac_config_rx_queues_routing(struct stmmac_priv *priv)
618+{
619+	u32 rx_queues_count = priv->plat->rx_queues_to_use;
620+	u32 queue;
621+	u8 packet;
622+
623+	for (queue = 0; queue < rx_queues_count; queue++) {
624+		/* no specific packet type routing specified for the queue */
625+		if (priv->plat->rx_queues_cfg[queue].pkt_route == 0x0)
626+			continue;
627+
628+		packet = priv->plat->rx_queues_cfg[queue].pkt_route;
629+		stmmac_rx_queue_routing(priv, priv->hw, packet, queue);
630+	}
631+}
632+
633+static void uio_mac_config_rss(struct stmmac_priv *priv)
634+{
635+	if (!priv->dma_cap.rssen || !priv->plat->rss_en) {
636+		priv->rss.enable = false;
637+		return;
638+	}
639+
640+	if (priv->dev->features & NETIF_F_RXHASH)
641+		priv->rss.enable = true;
642+	else
643+		priv->rss.enable = false;
644+
645+	stmmac_rss_configure(priv, priv->hw, &priv->rss,
646+			     priv->plat->rx_queues_to_use);
647+}
648+
649+/**
650+ *  uio_mac_enable_rx_queues - Enable MAC rx queues
651+ *  @priv: driver private structure
652+ *  Description: It is used for enabling the rx queues in the MAC
653+ */
654+static void uio_mac_enable_rx_queues(struct stmmac_priv *priv)
655+{
656+	u32 rx_queues_count = priv->plat->rx_queues_to_use;
657+	int queue;
658+	u8 mode;
659+
660+	for (queue = 0; queue < rx_queues_count; queue++) {
661+		mode = priv->plat->rx_queues_cfg[queue].mode_to_use;
662+		stmmac_rx_queue_enable(priv, priv->hw, mode, queue);
663+	}
664+}
665+
666+/**
667+ *  rockchip_gmac_uio_mtl_configuration - Configure MTL
668+ *  @priv: driver private structure
669+ *  Description: It is used for configuring MTL
670+ */
671+static void rockchip_gmac_uio_mtl_configuration(struct stmmac_priv *priv)
672+{
673+	u32 rx_queues_count = priv->plat->rx_queues_to_use;
674+	u32 tx_queues_count = priv->plat->tx_queues_to_use;
675+
676+	if (tx_queues_count > 1)
677+		uio_set_tx_queue_weight(priv);
678+
679+	/* Configure MTL RX algorithms */
680+	if (rx_queues_count > 1)
681+		stmmac_prog_mtl_rx_algorithms(priv, priv->hw,
682+				priv->plat->rx_sched_algorithm);
683+
684+	/* Configure MTL TX algorithms */
685+	if (tx_queues_count > 1)
686+		stmmac_prog_mtl_tx_algorithms(priv, priv->hw,
687+				priv->plat->tx_sched_algorithm);
688+
689+	/* Configure CBS in AVB TX queues */
690+	if (tx_queues_count > 1)
691+		uio_configure_cbs(priv);
692+
693+	/* Map RX MTL to DMA channels */
694+	uio_rx_queue_dma_chan_map(priv);
695+
696+	/* Enable MAC RX Queues */
697+	uio_mac_enable_rx_queues(priv);
698+
699+	/* Set RX priorities */
700+	if (rx_queues_count > 1)
701+		uio_mac_config_rx_queues_prio(priv);
702+
703+	/* Set TX priorities */
704+	if (tx_queues_count > 1)
705+		uio_mac_config_tx_queues_prio(priv);
706+
707+	/* Set RX routing */
708+	if (rx_queues_count > 1)
709+		uio_mac_config_rx_queues_routing(priv);
710+
711+	/* Receive Side Scaling */
712+	if (rx_queues_count > 1)
713+		uio_mac_config_rss(priv);
714+}
715+
716+static void uio_safety_feat_configuration(struct stmmac_priv *priv)
717+{
718+	if (priv->dma_cap.asp) {
719+		netdev_info(priv->dev, "Enabling Safety Features\n");
720+		stmmac_safety_feat_config(priv, priv->ioaddr, priv->dma_cap.asp);
721+	} else {
722+		netdev_info(priv->dev, "No Safety Features support found\n");
723+	}
724+}
725+
726+/**
727+ *  uio_dma_operation_mode - HW DMA operation mode
728+ *  @priv: driver private structure
729+ *  Description: it is used for configuring the DMA operation mode register in
730+ *  order to program the tx/rx DMA thresholds or Store-And-Forward mode.
731+ */
732+static void uio_dma_operation_mode(struct stmmac_priv *priv)
733+{
734+	u32 rx_channels_count = priv->plat->rx_queues_to_use;
735+	u32 tx_channels_count = priv->plat->tx_queues_to_use;
736+	int rxfifosz = priv->plat->rx_fifo_size;
737+	int txfifosz = priv->plat->tx_fifo_size;
738+	u32 txmode = 0;
739+	u32 rxmode = 0;
740+	u32 chan = 0;
741+	u8 qmode = 0;
742+
743+	if (rxfifosz == 0)
744+		rxfifosz = priv->dma_cap.rx_fifo_size;
745+	if (txfifosz == 0)
746+		txfifosz = priv->dma_cap.tx_fifo_size;
747+
748+	/* Adjust for real per queue fifo size */
749+	rxfifosz /= rx_channels_count;
750+	txfifosz /= tx_channels_count;
751+
752+	if (priv->plat->force_thresh_dma_mode) {
753+		txmode = tc;
754+		rxmode = tc;
755+	} else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
756+		/* In case of GMAC, SF mode can be enabled
757+		 * to perform the TX COE in HW. This depends on:
758+		 * 1) TX COE if actually supported
759+		 * 2) There is no bugged Jumbo frame support
760+		 *    that needs to not insert csum in the TDES.
761+		 */
762+		txmode = SF_DMA_MODE;
763+		rxmode = SF_DMA_MODE;
764+		priv->xstats.threshold = SF_DMA_MODE;
765+	} else {
766+		txmode = tc;
767+		rxmode = SF_DMA_MODE;
768+	}
769+
770+	/* configure all channels */
771+	for (chan = 0; chan < rx_channels_count; chan++) {
772+		qmode = priv->plat->rx_queues_cfg[chan].mode_to_use;
773+
774+		stmmac_dma_rx_mode(priv, priv->ioaddr, rxmode, chan,
775+				   rxfifosz, qmode);
776+		stmmac_set_dma_bfsize(priv, priv->ioaddr, priv->dma_buf_sz,
777+				      chan);
778+	}
779+
780+	for (chan = 0; chan < tx_channels_count; chan++) {
781+		qmode = priv->plat->tx_queues_cfg[chan].mode_to_use;
782+
783+		stmmac_dma_tx_mode(priv, priv->ioaddr, txmode, chan,
784+				   txfifosz, qmode);
785+	}
786+}
787+
788+/**
789+ *  rockchip_gmac_uio_hw_setup - setup mac in a usable state.
790+ *  @dev : pointer to the device structure.
791+ *  @init_ptp: initialize PTP if set
792+ *  Description:
793+ *  this is the main function to setup the HW in a usable state because the
794+ *  dma engine is reset, the core registers are configured (e.g. AXI,
795+ *  Checksum features, timers). The DMA is ready to start receiving and
796+ *  transmitting.
797+ *  Return value:
798+ *  0 on success and an appropriate (-)ve integer as defined in errno.h
799+ *  file on failure.
800+ */
801+static int rockchip_gmac_uio_hw_setup(struct net_device *dev, bool init_ptp)
802+{
803+	struct stmmac_priv *priv = netdev_priv(dev);
804+	int ret;
805+
806+	/* DMA initialization and SW reset */
807+	ret = rockchip_gmac_uio_init_dma_engine(priv);
808+	if (ret < 0) {
809+		netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
810+			   __func__);
811+		return ret;
812+	}
813+
814+	/* Copy the MAC addr into the HW  */
815+	stmmac_set_umac_addr(priv, priv->hw, dev->dev_addr, 0);
816+
817+	/* PS and related bits will be programmed according to the speed */
818+	if (priv->hw->pcs) {
819+		int speed = priv->plat->mac_port_sel_speed;
820+
821+		if (speed == SPEED_10 || speed == SPEED_100 ||
822+		    speed == SPEED_1000) {
823+			priv->hw->ps = speed;
824+		} else {
825+			dev_warn(priv->device, "invalid port speed\n");
826+			priv->hw->ps = 0;
827+		}
828+	}
829+
830+	/* Initialize the MAC Core */
831+	stmmac_core_init(priv, priv->hw, dev);
832+
833+	/* Initialize MTL*/
834+	rockchip_gmac_uio_mtl_configuration(priv);
835+
836+	/* Initialize Safety Features */
837+	uio_safety_feat_configuration(priv);
838+
839+	ret = stmmac_rx_ipc(priv, priv->hw);
840+	if (!ret) {
841+		netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n");
842+		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
843+		priv->hw->rx_csum = 0;
844+	}
845+
846+	/* Enable the MAC Rx/Tx */
847+	stmmac_mac_set(priv, priv->ioaddr, true);
848+
849+	/* Set the HW DMA mode and the COE */
850+	uio_dma_operation_mode(priv);
851+
852+	if (priv->hw->pcs)
853+		stmmac_pcs_ctrl_ane(priv, priv->hw, 1, priv->hw->ps, 0);
854+
855+	/* set TX and RX rings length */
856+	uio_set_rings_length(priv);
857+
858+	return 0;
859+}
860+
861+static int uio_set_bfsize(int mtu, int bufsize)
862+{
863+	int ret = bufsize;
864+
865+	if (mtu >= BUF_SIZE_8KiB)
866+		ret = BUF_SIZE_16KiB;
867+	else if (mtu >= BUF_SIZE_4KiB)
868+		ret = BUF_SIZE_8KiB;
869+	else if (mtu >= BUF_SIZE_2KiB)
870+		ret = BUF_SIZE_4KiB;
871+	else if (mtu > DEFAULT_BUFSIZE)
872+		ret = BUF_SIZE_2KiB;
873+	else
874+		ret = DEFAULT_BUFSIZE;
875+
876+	return ret;
877+}
878+
879+/**
880+ *  uio_open - open entry point of the driver
881+ *  @dev : pointer to the device structure.
882+ *  Description:
883+ *  This function is the open entry point of the driver.
884+ *  Return value:
885+ *  0 on success and an appropriate (-)ve integer as defined in errno.h
886+ *  file on failure.
887+ */
888+static int uio_open(struct net_device *dev)
889+{
890+	struct stmmac_priv *priv = netdev_priv(dev);
891+	int bfsize = 0;
892+	int ret;
893+
894+	if (priv->hw->pcs != STMMAC_PCS_TBI &&
895+	    priv->hw->pcs != STMMAC_PCS_RTBI &&
896+	    !priv->hw->xpcs) {
897+		ret = rockchip_gmac_uio_init_phy(dev);
898+		if (ret) {
899+			netdev_err(priv->dev,
900+				   "%s: Cannot attach to PHY (error: %d)\n",
901+				   __func__, ret);
902+			return ret;
903+		}
904+	}
905+
906+	/* Extra statistics */
907+	priv->xstats.threshold = tc;
908+
909+	bfsize = stmmac_set_16kib_bfsize(priv, dev->mtu);
910+	if (bfsize < 0)
911+		bfsize = 0;
912+
913+	if (bfsize < BUF_SIZE_16KiB)
914+		bfsize = uio_set_bfsize(dev->mtu, priv->dma_buf_sz);
915+
916+	priv->dma_buf_sz = bfsize;
917+	buf_sz = bfsize;
918+
919+	priv->rx_copybreak = STMMAC_RX_COPYBREAK;
920+
921+	if (!priv->dma_tx_size)
922+		priv->dma_tx_size = DMA_DEFAULT_TX_SIZE;
923+	if (!priv->dma_rx_size)
924+		priv->dma_rx_size = DMA_DEFAULT_RX_SIZE;
925+
926+	ret = uio_alloc_dma_desc_resources(priv);
927+	if (ret < 0) {
928+		netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n",
929+			   __func__);
930+		goto dma_desc_error;
931+	}
932+
933+	ret = rockchip_gmac_uio_hw_setup(dev, true);
934+	if (ret < 0) {
935+		netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
936+		goto init_error;
937+	}
938+
939+	phylink_start(priv->phylink);
940+	/* We may have called phylink_speed_down before */
941+	phylink_speed_up(priv->phylink);
942+
943+	return 0;
944+
945+init_error:
946+	uio_free_dma_desc_resources(priv);
947+dma_desc_error:
948+	phylink_disconnect_phy(priv->phylink);
949+	return ret;
950+}
951+
952+/**
953+ *  uio_release - close entry point of the driver
954+ *  @dev : device pointer.
955+ *  Description:
956+ *  This is the stop entry point of the driver.
957+ */
958+static int uio_release(struct net_device *dev)
959+{
960+	struct stmmac_priv *priv = netdev_priv(dev);
961+
962+	/* Stop and disconnect the PHY */
963+	if (dev->phydev) {
964+		phy_stop(dev->phydev);
965+		phy_disconnect(dev->phydev);
966+		if (priv->plat->integrated_phy_power)
967+			priv->plat->integrated_phy_power(priv->plat->bsp_priv,
968+							 false);
969+	}
970+
971+	/* Release and free the Rx/Tx resources */
972+	uio_free_dma_desc_resources(priv);
973+
974+	/* Disable the MAC Rx/Tx */
975+	stmmac_mac_set(priv, priv->ioaddr, false);
976+
977+	netif_carrier_off(dev);
978+
979+	return 0;
980+}
981+
982+/**
983+ * rockchip_gmac_uio_probe() platform driver probe routine
984+ * - register uio devices filled with memory maps retrieved
985+ * from device tree
986+ */
987+static int rockchip_gmac_uio_probe(struct platform_device *pdev)
988+{
989+	struct device *dev = &pdev->dev;
990+	struct device_node *np = dev->of_node, *mac_node;
991+	struct rockchip_gmac_uio_pdev_info *pdev_info;
992+	struct net_device *netdev;
993+	struct stmmac_priv *priv;
994+	struct uio_info *uio;
995+	struct resource *res;
996+	int err = 0;
997+
998+	pdev_info = devm_kzalloc(dev, sizeof(struct rockchip_gmac_uio_pdev_info),
999+				 GFP_KERNEL);
1000+	if (!pdev_info)
1001+		return -ENOMEM;
1002+
1003+	uio = &pdev_info->uio;
1004+	pdev_info->dev = dev;
1005+	mac_node = of_parse_phandle(np, "rockchip,ethernet", 0);
1006+	if (!mac_node)
1007+		return -ENODEV;
1008+
1009+	if (of_device_is_available(mac_node)) {
1010+		netdev = of_find_net_device_by_node(mac_node);
1011+		of_node_put(mac_node);
1012+		if (!netdev)
1013+			return -ENODEV;
1014+	} else {
1015+		of_node_put(mac_node);
1016+		return -EINVAL;
1017+	}
1018+
1019+	pdev_info->ndev = netdev;
1020+	rtnl_lock();
1021+	dev_close(netdev);
1022+	rtnl_unlock();
1023+
1024+	rtnl_lock();
1025+	err = uio_open(netdev);
1026+	if (err) {
1027+		rtnl_unlock();
1028+		dev_err(dev, "Failed to open stmmac resource: %d\n", err);
1029+		return err;
1030+	}
1031+	rtnl_unlock();
1032+
1033+	priv = netdev_priv(netdev);
1034+	snprintf(pdev_info->name, sizeof(pdev_info->name), "uio_%s",
1035+		 netdev->name);
1036+	uio->name = pdev_info->name;
1037+	uio->version = DRIVER_VERSION;
1038+
1039+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1040+	if (!res)
1041+		return -ENODEV;
1042+
1043+	uio->mem[0].name = "eth_regs";
1044+	uio->mem[0].addr = res->start & PAGE_MASK;
1045+	uio->mem[0].size = PAGE_ALIGN(resource_size(res));
1046+	uio->mem[0].memtype = UIO_MEM_PHYS;
1047+
1048+	uio->mem[1].name = "eth_rx_bd";
1049+	uio->mem[1].addr = priv->rx_queue[0].dma_rx_phy;
1050+	uio->mem[1].size = priv->dma_rx_size * sizeof(struct dma_desc);
1051+	uio->mem[1].memtype = UIO_MEM_PHYS;
1052+
1053+	uio->mem[2].name = "eth_tx_bd";
1054+	uio->mem[2].addr = priv->tx_queue[0].dma_tx_phy;
1055+	uio->mem[2].size = priv->dma_tx_size * sizeof(struct dma_desc);
1056+	uio->mem[2].memtype = UIO_MEM_PHYS;
1057+
1058+	uio->open = rockchip_gmac_uio_open;
1059+	uio->release = rockchip_gmac_uio_release;
1060+	/* Custom mmap function. */
1061+	uio->mmap = rockchip_gmac_uio_mmap;
1062+	uio->priv = pdev_info;
1063+
1064+	err = uio_register_device(dev, uio);
1065+	if (err) {
1066+		dev_err(dev, "Failed to register uio device: %d\n", err);
1067+		return err;
1068+	}
1069+
1070+	pdev_info->map_num = 3;
1071+
1072+	dev_info(dev, "Registered %s uio devices, %d register maps attached\n",
1073+		 pdev_info->name, pdev_info->map_num);
1074+
1075+	platform_set_drvdata(pdev, pdev_info);
1076+
1077+	return 0;
1078+}
1079+
1080+/**
1081+ * rockchip_gmac_uio_remove() - ROCKCHIP ETH UIO platform driver release
1082+ * routine - unregister uio devices
1083+ */
1084+static int rockchip_gmac_uio_remove(struct platform_device *pdev)
1085+{
1086+	struct rockchip_gmac_uio_pdev_info *pdev_info =
1087+					platform_get_drvdata(pdev);
1088+	struct net_device *netdev;
1089+
1090+	if (!pdev_info)
1091+		return -EINVAL;
1092+
1093+	netdev = pdev_info->ndev;
1094+
1095+	uio_unregister_device(&pdev_info->uio);
1096+
1097+	if (netdev) {
1098+		rtnl_lock();
1099+		uio_release(netdev);
1100+		rtnl_unlock();
1101+	}
1102+
1103+	platform_set_drvdata(pdev, NULL);
1104+
1105+	if (netdev) {
1106+		rtnl_lock();
1107+		dev_open(netdev, NULL);
1108+		rtnl_unlock();
1109+	}
1110+
1111+	return 0;
1112+}
1113+
1114+static const struct of_device_id rockchip_gmac_uio_of_match[] = {
1115+	{ .compatible	= "rockchip,uio-gmac", },
1116+	{ }
1117+};
1118+
1119+static struct platform_driver rockchip_gmac_uio_driver = {
1120+	.driver = {
1121+		.owner		= THIS_MODULE,
1122+		.name		= DRIVER_NAME,
1123+		.of_match_table	= rockchip_gmac_uio_of_match,
1124+	},
1125+	.probe	= rockchip_gmac_uio_probe,
1126+	.remove	= rockchip_gmac_uio_remove,
1127+};
1128+
1129+module_platform_driver(rockchip_gmac_uio_driver);
1130+
1131+MODULE_LICENSE("GPL");
1132+MODULE_AUTHOR("ROCKCHIP");
1133+MODULE_DESCRIPTION("ROCKCHIP GMAC UIO Driver");
1134