xref: /dpdk/drivers/net/dpaa2/dpaa2_recycle.c (revision e77506397fc8005c5129e22e9e2d15d5876790fd)
1f023d059SJun Yang /* * SPDX-License-Identifier: BSD-3-Clause
2f023d059SJun Yang  *
3f023d059SJun Yang  *   Copyright 2019-2021 NXP
4f023d059SJun Yang  *
5f023d059SJun Yang  */
6f023d059SJun Yang 
7f023d059SJun Yang #include <time.h>
8f023d059SJun Yang #include <net/if.h>
9f023d059SJun Yang 
10f023d059SJun Yang #include <rte_mbuf.h>
11f023d059SJun Yang #include <ethdev_driver.h>
12f023d059SJun Yang #include <rte_malloc.h>
13f023d059SJun Yang #include <rte_memcpy.h>
14f023d059SJun Yang #include <rte_string_fns.h>
15f023d059SJun Yang #include <rte_cycles.h>
16f023d059SJun Yang #include <rte_kvargs.h>
171acb7f54SDavid Marchand #include <dev_driver.h>
18b4f22ca5SDavid Marchand #include <bus_fslmc_driver.h>
19f023d059SJun Yang #include <rte_flow_driver.h>
20f023d059SJun Yang 
21f023d059SJun Yang #include "dpaa2_pmd_logs.h"
22f023d059SJun Yang #include <fslmc_vfio.h>
23f023d059SJun Yang #include <dpaa2_hw_pvt.h>
24f023d059SJun Yang #include <dpaa2_hw_mempool.h>
25f023d059SJun Yang #include <dpaa2_hw_dpio.h>
26f023d059SJun Yang #include <mc/fsl_dpmng.h>
27f023d059SJun Yang #include "dpaa2_ethdev.h"
28f023d059SJun Yang #include "dpaa2_sparser.h"
29f023d059SJun Yang #include <fsl_qbman_debug.h>
30f023d059SJun Yang 
31f023d059SJun Yang #include <rte_io.h>
32f023d059SJun Yang #include <unistd.h>
33f023d059SJun Yang #include <sys/mman.h>
34f023d059SJun Yang 
35dad04403SThomas Monjalon #ifndef PAGE_SIZE
36f023d059SJun Yang #define PAGE_SIZE			(sysconf(_SC_PAGESIZE))
37dad04403SThomas Monjalon #endif
38f023d059SJun Yang #define PAGE_MASK			(~(PAGE_SIZE - 1))
39f023d059SJun Yang 
40f023d059SJun Yang #define LSX_SERDES_LAN_NB		8
41f023d059SJun Yang #define LSX_SERDES_REG_BASE		0x1ea0000
42f023d059SJun Yang #define LSX_LB_EN_BIT			0x10000000
43f023d059SJun Yang 
44f023d059SJun Yang #define CONFIG_SYS_IMMR			0x01000000
45f023d059SJun Yang 
46f023d059SJun Yang #define CONFIG_SYS_FSL_GUTS_ADDR	(CONFIG_SYS_IMMR + 0x00E00000)
47f023d059SJun Yang #define CONFIG_SYS_FSL_SERDES_ADDR	(CONFIG_SYS_IMMR + 0xEA0000)
48f023d059SJun Yang 
49f023d059SJun Yang #define FSL_LX_SRDS1_PRTCL_SHIFT	16
50f023d059SJun Yang #define FSL_LX_SRDS2_PRTCL_SHIFT	21
51f023d059SJun Yang #define FSL_LX_SRDS3_PRTCL_SHIFT	26
52f023d059SJun Yang 
53f023d059SJun Yang #define FSL_LS_SRDS1_PRTCL_SHIFT	16
54f023d059SJun Yang #define FSL_LS_SRDS2_PRTCL_SHIFT	0
55f023d059SJun Yang 
56f023d059SJun Yang #define FSL_LX_SRDS1_REGSR		29
57f023d059SJun Yang #define FSL_LX_SRDS2_REGSR		29
58f023d059SJun Yang #define FSL_LX_SRDS3_REGSR		29
59f023d059SJun Yang 
60f023d059SJun Yang #define FSL_LS_SRDS1_REGSR		29
61f023d059SJun Yang #define FSL_LS_SRDS2_REGSR		30
62f023d059SJun Yang 
63f023d059SJun Yang #define FSL_LX_SRDS1_PRTCL_MASK		0x001F0000
64f023d059SJun Yang #define FSL_LX_SRDS2_PRTCL_MASK		0x03E00000
65f023d059SJun Yang #define FSL_LX_SRDS3_PRTCL_MASK		0x7C000000
66f023d059SJun Yang 
67f023d059SJun Yang #define FSL_LS_SRDS1_PRTCL_MASK		0xFFFF0000
68f023d059SJun Yang #define FSL_LS_SRDS2_PRTCL_MASK		0x0000FFFF
69f023d059SJun Yang 
70*e7750639SAndre Muezerie struct __rte_packed_begin ccsr_lx_serdes_lan {
71f023d059SJun Yang 	uint8_t unused1[0xa0];
72f023d059SJun Yang 	uint32_t lnatcsr0;
73f023d059SJun Yang 	uint8_t unused2[0x100 - 0xa4];
74*e7750639SAndre Muezerie } __rte_packed_end;
75f023d059SJun Yang 
76*e7750639SAndre Muezerie struct __rte_packed_begin ccsr_lx_serdes {
77f023d059SJun Yang 	uint8_t unused0[0x800];
78f023d059SJun Yang 	struct ccsr_lx_serdes_lan lane[LSX_SERDES_LAN_NB];
79*e7750639SAndre Muezerie } __rte_packed_end;
80f023d059SJun Yang 
81*e7750639SAndre Muezerie struct __rte_packed_begin ccsr_ls_serdes {
82f023d059SJun Yang 	uint8_t unused[0x800];
83f023d059SJun Yang 	struct serdes_lane {
84f023d059SJun Yang 		uint32_t gcr0;   /* General Control Register 0 */
85f023d059SJun Yang 		uint32_t gcr1;   /* General Control Register 1 */
86f023d059SJun Yang 		uint32_t gcr2;   /* General Control Register 2 */
87f023d059SJun Yang 		uint32_t ssc0;   /* Speed Switch Control 0 */
88f023d059SJun Yang 		uint32_t rec0;   /* Receive Equalization Control 0 */
89f023d059SJun Yang 		uint32_t rec1;   /* Receive Equalization Control 1 */
90f023d059SJun Yang 		uint32_t tec0;   /* Transmit Equalization Control 0 */
91f023d059SJun Yang 		uint32_t ssc1;   /* Speed Switch Control 1 */
92f023d059SJun Yang 		uint32_t ttlc;
93f023d059SJun Yang 		uint32_t rev[6];
94f023d059SJun Yang 		uint32_t tsc3;
95f023d059SJun Yang 	} lane[LSX_SERDES_LAN_NB];
96f023d059SJun Yang 	uint8_t res5[0x19fc - 0xa00];
97*e7750639SAndre Muezerie } __rte_packed_end;
98f023d059SJun Yang 
99*e7750639SAndre Muezerie struct __rte_packed_begin ccsr_gur {
100f023d059SJun Yang 	uint32_t	porsr1;		/* POR status 1 */
101f023d059SJun Yang 	uint32_t	porsr2;		/* POR status 2 */
102f023d059SJun Yang 	uint8_t	res_008[0x20 - 0x8];
103f023d059SJun Yang 	uint32_t	gpporcr1; /* General-purpose POR configuration */
104f023d059SJun Yang 	uint32_t	gpporcr2; /* General-purpose POR configuration 2 */
105f023d059SJun Yang 	uint32_t	gpporcr3;
106f023d059SJun Yang 	uint32_t	gpporcr4;
107f023d059SJun Yang 	uint8_t	res_030[0x60 - 0x30];
108f023d059SJun Yang 	uint32_t	dcfg_fusesr;	/* Fuse status register */
109f023d059SJun Yang 	uint8_t	res_064[0x70 - 0x64];
110f023d059SJun Yang 	uint32_t	devdisr;	/* Device disable control 1 */
111f023d059SJun Yang 	uint32_t	devdisr2;	/* Device disable control 2 */
112f023d059SJun Yang 	uint32_t	devdisr3;	/* Device disable control 3 */
113f023d059SJun Yang 	uint32_t	devdisr4;	/* Device disable control 4 */
114f023d059SJun Yang 	uint32_t	devdisr5;	/* Device disable control 5 */
115f023d059SJun Yang 	uint32_t	devdisr6;	/* Device disable control 6 */
116f023d059SJun Yang 	uint8_t	res_088[0x94 - 0x88];
117f023d059SJun Yang 	uint32_t	coredisr;	/* Device disable control 7 */
118f023d059SJun Yang 	uint8_t	res_098[0xa0 - 0x98];
119f023d059SJun Yang 	uint32_t	pvr;		/* Processor version */
120f023d059SJun Yang 	uint32_t	svr;		/* System version */
121f023d059SJun Yang 	uint8_t	res_0a8[0x100 - 0xa8];
122f023d059SJun Yang 	uint32_t	rcwsr[30];	/* Reset control word status */
123f023d059SJun Yang 
124f023d059SJun Yang 	uint8_t	res_178[0x200 - 0x178];
125f023d059SJun Yang 	uint32_t	scratchrw[16];	/* Scratch Read/Write */
126f023d059SJun Yang 	uint8_t	res_240[0x300 - 0x240];
127f023d059SJun Yang 	uint32_t	scratchw1r[4];	/* Scratch Read (Write once) */
128f023d059SJun Yang 	uint8_t	res_310[0x400 - 0x310];
129f023d059SJun Yang 	uint32_t	bootlocptrl; /* Boot location pointer low-order addr */
130f023d059SJun Yang 	uint32_t	bootlocptrh; /* Boot location pointer high-order addr */
131f023d059SJun Yang 	uint8_t	res_408[0x520 - 0x408];
132f023d059SJun Yang 	uint32_t	usb1_amqr;
133f023d059SJun Yang 	uint32_t	usb2_amqr;
134f023d059SJun Yang 	uint8_t	res_528[0x530 - 0x528];	/* add more registers when needed */
135f023d059SJun Yang 	uint32_t	sdmm1_amqr;
136f023d059SJun Yang 	uint32_t	sdmm2_amqr;
137f023d059SJun Yang 	uint8_t	res_538[0x550 - 0x538];	/* add more registers when needed */
138f023d059SJun Yang 	uint32_t	sata1_amqr;
139f023d059SJun Yang 	uint32_t	sata2_amqr;
140f023d059SJun Yang 	uint32_t	sata3_amqr;
141f023d059SJun Yang 	uint32_t	sata4_amqr;
142f023d059SJun Yang 	uint8_t	res_560[0x570 - 0x560];	/* add more registers when needed */
143f023d059SJun Yang 	uint32_t	misc1_amqr;
144f023d059SJun Yang 	uint8_t	res_574[0x590 - 0x574];	/* add more registers when needed */
145f023d059SJun Yang 	uint32_t	spare1_amqr;
146f023d059SJun Yang 	uint32_t	spare2_amqr;
147f023d059SJun Yang 	uint32_t	spare3_amqr;
148f023d059SJun Yang 	uint8_t	res_59c[0x620 - 0x59c];	/* add more registers when needed */
149f023d059SJun Yang 	uint32_t	gencr[7];	/* General Control Registers */
150f023d059SJun Yang 	uint8_t	res_63c[0x640 - 0x63c];	/* add more registers when needed */
151f023d059SJun Yang 	uint32_t	cgensr1;	/* Core General Status Register */
152f023d059SJun Yang 	uint8_t	res_644[0x660 - 0x644];	/* add more registers when needed */
153f023d059SJun Yang 	uint32_t	cgencr1;	/* Core General Control Register */
154f023d059SJun Yang 	uint8_t	res_664[0x740 - 0x664];	/* add more registers when needed */
155f023d059SJun Yang 	uint32_t	tp_ityp[64];	/* Topology Initiator Type Register */
156f023d059SJun Yang 	struct {
157f023d059SJun Yang 		uint32_t	upper;
158f023d059SJun Yang 		uint32_t	lower;
159f023d059SJun Yang 	} tp_cluster[4];	/* Core cluster n Topology Register */
160f023d059SJun Yang 	uint8_t	res_864[0x920 - 0x864];	/* add more registers when needed */
161f023d059SJun Yang 	uint32_t ioqoscr[8];	/*I/O Quality of Services Register */
162f023d059SJun Yang 	uint32_t uccr;
163f023d059SJun Yang 	uint8_t	res_944[0x960 - 0x944];	/* add more registers when needed */
164f023d059SJun Yang 	uint32_t ftmcr;
165f023d059SJun Yang 	uint8_t	res_964[0x990 - 0x964];	/* add more registers when needed */
166f023d059SJun Yang 	uint32_t coredisablesr;
167f023d059SJun Yang 	uint8_t	res_994[0xa00 - 0x994];	/* add more registers when needed */
168f023d059SJun Yang 	uint32_t sdbgcr; /*Secure Debug Configuration Register */
169f023d059SJun Yang 	uint8_t	res_a04[0xbf8 - 0xa04];	/* add more registers when needed */
170f023d059SJun Yang 	uint32_t ipbrr1;
171f023d059SJun Yang 	uint32_t ipbrr2;
172f023d059SJun Yang 	uint8_t	res_858[0x1000 - 0xc00];
173*e7750639SAndre Muezerie } __rte_packed_end;
174f023d059SJun Yang 
175f023d059SJun Yang static void *lsx_ccsr_map_region(uint64_t addr, size_t len)
176f023d059SJun Yang {
177f023d059SJun Yang 	int fd;
178f023d059SJun Yang 	void *tmp;
179f023d059SJun Yang 	uint64_t start;
180f023d059SJun Yang 	uint64_t offset;
181f023d059SJun Yang 
182f023d059SJun Yang 	fd = open("/dev/mem", O_RDWR);
183f023d059SJun Yang 	if (fd < 0) {
184f023d059SJun Yang 		DPAA2_PMD_ERR("Fail to open /dev/mem");
185f023d059SJun Yang 		return NULL;
186f023d059SJun Yang 	}
187f023d059SJun Yang 
188f023d059SJun Yang 	start = addr & PAGE_MASK;
189f023d059SJun Yang 	offset = addr - start;
190f023d059SJun Yang 	len = len & PAGE_MASK;
191f023d059SJun Yang 	if (len < (size_t)PAGE_SIZE)
192f023d059SJun Yang 		len = PAGE_SIZE;
193f023d059SJun Yang 
194f023d059SJun Yang 	tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start);
195f023d059SJun Yang 
196f023d059SJun Yang 	close(fd);
197f023d059SJun Yang 
198f023d059SJun Yang 	if (tmp != MAP_FAILED)
199f023d059SJun Yang 		return (uint8_t *)tmp + offset;
200f023d059SJun Yang 	else
201f023d059SJun Yang 		return NULL;
202f023d059SJun Yang }
203f023d059SJun Yang 
204f023d059SJun Yang static const uint8_t ls_sd1_prot_idx_map[] = {
205f023d059SJun Yang 	0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0e,
206f023d059SJun Yang 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c,
207f023d059SJun Yang 	0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a,
208f023d059SJun Yang 	0x2b, 0x2d, 0x2e, 0x30, 0x32, 0x33, 0x35,
209f023d059SJun Yang 	0x37, 0x39, 0x3b, 0x4b, 0x4c, 0x4d, 0x58
210f023d059SJun Yang };
211f023d059SJun Yang 
212f023d059SJun Yang static const uint8_t ls_sd2_prot_idx_map[] = {
213f023d059SJun Yang 	0x07, 0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x12,
214f023d059SJun Yang 	0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20,
215f023d059SJun Yang 	0x22, 0x24, 0x3d, 0x3f, 0x41, 0x43, 0x45,
216f023d059SJun Yang 	0x47, 0x49, 0x4f, 0x50, 0x51, 0x52, 0x53,
217f023d059SJun Yang 	0x54, 0x55, 0x56, 0x57
218f023d059SJun Yang };
219f023d059SJun Yang 
220f023d059SJun Yang static const uint8_t ls_sd1_eth_loopback_support[][LSX_SERDES_LAN_NB] = {
221f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x03*/
222f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x05*/
223f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x07*/
224f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x09*/
225f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0a*/
226f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0c*/
227f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0e*/
228f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x10*/
229f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x12*/
230f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x14*/
231f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x16*/
232f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x18*/
233f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1a*/
234f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1c*/
235f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1e*/
236f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x20*/
237f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x22*/
238f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x24*/
239f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x26*/
240f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x28*/
241f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x2a*/
242f023d059SJun Yang 
243f023d059SJun Yang 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x2b*/
244f023d059SJun Yang 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x2d*/
245f023d059SJun Yang 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x2e*/
246f023d059SJun Yang 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x30*/
247f023d059SJun Yang 
248f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x32*/
249f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x33*/
250f023d059SJun Yang 
251f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x35*/
252f023d059SJun Yang 	{1, 1, 0, 0, 0, 0, 0, 0}, /* 0x37*/
253f023d059SJun Yang 
254f023d059SJun Yang 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x39*/
255f023d059SJun Yang 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x3b*/
256f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x4b*/
257f023d059SJun Yang 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x4c*/
258f023d059SJun Yang 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x4d*/
259f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 1, 1}  /* 0x58*/
260f023d059SJun Yang };
261f023d059SJun Yang 
262f023d059SJun Yang static const uint8_t ls_sd2_eth_loopback_support[][LSX_SERDES_LAN_NB] = {
263f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x07*/
264f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x09*/
265f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0a*/
266f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0c*/
267f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0e*/
268f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x10*/
269f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x12*/
270f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x14*/
271f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x16*/
272f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x18*/
273f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1a*/
274f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1c*/
275f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1e*/
276f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x20*/
277f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x22*/
278f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x24*/
279f023d059SJun Yang 
280f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x3d*/
281f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x3f*/
282f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x41*/
283f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x43*/
284f023d059SJun Yang 
285f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x45*/
286f023d059SJun Yang 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x47*/
287f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x49*/
288f023d059SJun Yang 
289f023d059SJun Yang 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x4f*/
290f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x50*/
291f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x51*/
292f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x52*/
293f023d059SJun Yang 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x53*/
294f023d059SJun Yang 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x54*/
295f023d059SJun Yang 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x55*/
296f023d059SJun Yang 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x56*/
297f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 1, 1}  /* 0x57*/
298f023d059SJun Yang };
299f023d059SJun Yang 
300f023d059SJun Yang enum lsx_serdes_id {
301f023d059SJun Yang 	LSX_SERDES_1 = 1,
302f023d059SJun Yang 	LSX_SERDES_2 = 2
303f023d059SJun Yang };
304f023d059SJun Yang 
305f023d059SJun Yang static const uint8_t lx_sd1_loopback_support[][LSX_SERDES_LAN_NB] = {
306f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0 prot*/
307f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 1 prot*/
308f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 2 prot*/
309f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 3 prot*/
310f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 4 prot*/
311f023d059SJun Yang 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 5 prot*/
312f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 6 prot*/
313f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 7 prot*/
314f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 8 prot*/
315f023d059SJun Yang 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 9 prot*/
316f023d059SJun Yang 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 10 prot*/
317f023d059SJun Yang 	{0, 0, 1, 1, 0, 0, 1, 1}, /* 11 prot*/
318f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 1, 1}, /* 12 prot*/
319f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 13 prot*/
320f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 14 prot*/
321f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 15 prot*/
322f023d059SJun Yang 	{0, 0, 1, 1, 0, 0, 0, 0}, /* 16 prot*/
323f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 17 prot*/
324f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 18 prot*/
325f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 19 prot*/
326f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 20 prot*/
327f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 1, 1}, /* 21 prot*/
328f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 1, 1}  /* 22 prot*/
329f023d059SJun Yang };
330f023d059SJun Yang 
331f023d059SJun Yang static const uint8_t lx_sd2_loopback_support[][LSX_SERDES_LAN_NB] = {
332f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 0 prot*/
333f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 1 prot*/
334f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 2 prot*/
335f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 3 prot*/
336f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 4 prot*/
337f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 0, 0}, /* 5 prot*/
338f023d059SJun Yang 	{0, 0, 0, 0, 1, 1, 1, 1}, /* 6 prot*/
339f023d059SJun Yang 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 7 prot*/
340f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 1, 1}, /* 8 prot*/
341f023d059SJun Yang 	{1, 1, 1, 1, 1, 1, 1, 1}, /* 9 prot*/
342f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 10 prot*/
343f023d059SJun Yang 	{0, 1, 1, 1, 0, 1, 1, 1}, /* 11 prot*/
344f023d059SJun Yang 	{1, 1, 1, 1, 0, 0, 0, 0}, /* 12 prot*/
345f023d059SJun Yang 	{0, 0, 0, 0, 0, 0, 1, 1}, /* 13 prot*/
346f023d059SJun Yang 	{0, 0, 1, 1, 0, 0, 1, 1}  /* 14 prot*/
347f023d059SJun Yang };
348f023d059SJun Yang 
349f023d059SJun Yang static inline int
350f023d059SJun Yang ls_mac_to_serdes_id(uint8_t mac_id)
351f023d059SJun Yang {
352f023d059SJun Yang 	if (mac_id >= 1 && mac_id <= 8)
353f023d059SJun Yang 		return LSX_SERDES_1;
354f023d059SJun Yang 	if (mac_id >= 9 && mac_id <= 16)
355f023d059SJun Yang 		return LSX_SERDES_2;
356f023d059SJun Yang 
357f023d059SJun Yang 	return -1;
358f023d059SJun Yang }
359f023d059SJun Yang 
360f023d059SJun Yang static inline int
361f023d059SJun Yang lx_mac_to_serdes_id(uint8_t mac_id)
362f023d059SJun Yang {
363f023d059SJun Yang 	if (mac_id >= 1 && mac_id <= 10)
364f023d059SJun Yang 		return LSX_SERDES_1;
365f023d059SJun Yang 	if (mac_id >= 11 && mac_id <= 18)
366f023d059SJun Yang 		return LSX_SERDES_2;
367f023d059SJun Yang 
368f023d059SJun Yang 	return -1;
369f023d059SJun Yang }
370f023d059SJun Yang 
371f023d059SJun Yang static inline int
372f023d059SJun Yang ls_serdes_cfg_to_idx(uint8_t sd_cfg, int sd_id)
373f023d059SJun Yang {
374f023d059SJun Yang 	int i;
375f023d059SJun Yang 
376f023d059SJun Yang 	if (sd_id == LSX_SERDES_1) {
377f023d059SJun Yang 		for (i = 0; i < (int)sizeof(ls_sd1_prot_idx_map); i++) {
378f023d059SJun Yang 			if (ls_sd1_prot_idx_map[i] == sd_cfg)
379f023d059SJun Yang 				return i;
380f023d059SJun Yang 		}
381f023d059SJun Yang 	} else if (sd_id == LSX_SERDES_2) {
382f023d059SJun Yang 		for (i = 0; i < (int)sizeof(ls_sd2_prot_idx_map); i++) {
383f023d059SJun Yang 			if (ls_sd2_prot_idx_map[i] == sd_cfg)
384f023d059SJun Yang 				return i;
385f023d059SJun Yang 		}
386f023d059SJun Yang 	}
387f023d059SJun Yang 
388f023d059SJun Yang 	return -1;
389f023d059SJun Yang }
390f023d059SJun Yang 
391f023d059SJun Yang static inline int
392f023d059SJun Yang lx_serdes_cfg_to_idx(uint8_t sd_cfg, int sd_id __rte_unused)
393f023d059SJun Yang {
394f023d059SJun Yang 	return sd_cfg;
395f023d059SJun Yang }
396f023d059SJun Yang 
397f023d059SJun Yang static inline int
398f023d059SJun Yang ls_mac_serdes_lpbk_support(uint16_t mac_id,
399f023d059SJun Yang 	uint16_t *serdes_id, uint16_t *lan_id)
400f023d059SJun Yang {
401f023d059SJun Yang 	struct ccsr_gur *gur_base =
402f023d059SJun Yang 		lsx_ccsr_map_region(CONFIG_SYS_FSL_GUTS_ADDR,
403f023d059SJun Yang 			sizeof(struct ccsr_gur) / 64 * 64 + 64);
404f023d059SJun Yang 	uint32_t sd_cfg;
405f023d059SJun Yang 	int sd_id, sd_idx;
406f023d059SJun Yang 	uint16_t lan_id_tmp = 0;
407f023d059SJun Yang 	const uint8_t *ls_sd_loopback_support;
408f023d059SJun Yang 
409f023d059SJun Yang 	sd_id = ls_mac_to_serdes_id(mac_id);
410f023d059SJun Yang 
411f023d059SJun Yang 	if (sd_id == LSX_SERDES_1) {
412f023d059SJun Yang 		sd_cfg = rte_read32(&gur_base->rcwsr[FSL_LS_SRDS1_REGSR - 1]) &
413f023d059SJun Yang 				FSL_LS_SRDS1_PRTCL_MASK;
414f023d059SJun Yang 		sd_cfg >>= FSL_LS_SRDS1_PRTCL_SHIFT;
415f023d059SJun Yang 	} else if (sd_id == LSX_SERDES_2) {
416f023d059SJun Yang 		sd_cfg = rte_read32(&gur_base->rcwsr[FSL_LS_SRDS2_REGSR - 1]) &
417f023d059SJun Yang 				FSL_LS_SRDS2_PRTCL_MASK;
418f023d059SJun Yang 		sd_cfg >>= FSL_LS_SRDS2_PRTCL_SHIFT;
419f023d059SJun Yang 	} else {
420f023d059SJun Yang 		return false;
421f023d059SJun Yang 	}
422f023d059SJun Yang 	sd_cfg = sd_cfg & 0xff;
423f023d059SJun Yang 
424f023d059SJun Yang 	sd_idx = ls_serdes_cfg_to_idx(sd_cfg, sd_id);
425f023d059SJun Yang 	if (sd_idx < 0) {
426f665790aSDavid Marchand 		DPAA2_PMD_ERR("Serdes protocol(0x%02x) does not exist",
427f023d059SJun Yang 			sd_cfg);
428f023d059SJun Yang 		return false;
429f023d059SJun Yang 	}
430f023d059SJun Yang 
431f023d059SJun Yang 	if (sd_id == LSX_SERDES_1) {
432f023d059SJun Yang 		ls_sd_loopback_support =
433f023d059SJun Yang 			&ls_sd1_eth_loopback_support[sd_idx][0];
434f023d059SJun Yang 	} else {
435f023d059SJun Yang 		ls_sd_loopback_support =
436f023d059SJun Yang 			&ls_sd2_eth_loopback_support[sd_idx][0];
437f023d059SJun Yang 	}
438f023d059SJun Yang 
439f023d059SJun Yang 	if (sd_id == LSX_SERDES_1)
440f023d059SJun Yang 		lan_id_tmp = (mac_id - 1);
441f023d059SJun Yang 	else
442f023d059SJun Yang 		lan_id_tmp = (mac_id - 9);
443f023d059SJun Yang 
444f023d059SJun Yang 	if (lan_id_tmp >= LSX_SERDES_LAN_NB) {
445f023d059SJun Yang 		DPAA2_PMD_ERR("Invalid serdes lan(%d).", lan_id_tmp);
446f023d059SJun Yang 		return false;
447f023d059SJun Yang 	}
448f023d059SJun Yang 
449f023d059SJun Yang 	if (!ls_sd_loopback_support[lan_id_tmp])
450f023d059SJun Yang 		return false;
451f023d059SJun Yang 
452f023d059SJun Yang 	if (lan_id)
453f023d059SJun Yang 		*lan_id = lan_id_tmp;
454f023d059SJun Yang 	if (serdes_id)
455f023d059SJun Yang 		*serdes_id = sd_id;
456f023d059SJun Yang 
457f023d059SJun Yang 	return true;
458f023d059SJun Yang }
459f023d059SJun Yang 
460f023d059SJun Yang static inline int
461f023d059SJun Yang lx_mac_serdes_lpbk_support(uint16_t mac_id,
462f023d059SJun Yang 	uint16_t *serdes_id, uint16_t *lan_id)
463f023d059SJun Yang {
464f023d059SJun Yang 	struct ccsr_gur *gur_base =
465f023d059SJun Yang 		lsx_ccsr_map_region(CONFIG_SYS_FSL_GUTS_ADDR,
466f023d059SJun Yang 			sizeof(struct ccsr_gur) / 64 * 64 + 64);
467f023d059SJun Yang 	uint32_t sd_cfg;
468f023d059SJun Yang 	int sd_id, sd_idx;
469f023d059SJun Yang 	uint16_t lan_id_tmp = 0;
470f023d059SJun Yang 	const uint8_t *lx_sd_loopback_support;
471f023d059SJun Yang 
472f023d059SJun Yang 	sd_id = lx_mac_to_serdes_id(mac_id);
473f023d059SJun Yang 
474f023d059SJun Yang 	if (sd_id == LSX_SERDES_1) {
475f023d059SJun Yang 		sd_cfg = rte_read32(&gur_base->rcwsr[FSL_LX_SRDS1_REGSR - 1]) &
476f023d059SJun Yang 				FSL_LX_SRDS1_PRTCL_MASK;
477f023d059SJun Yang 		sd_cfg >>= FSL_LX_SRDS1_PRTCL_SHIFT;
478f023d059SJun Yang 	} else if (sd_id == LSX_SERDES_2) {
479f023d059SJun Yang 		sd_cfg = rte_read32(&gur_base->rcwsr[FSL_LX_SRDS2_REGSR - 1]) &
480f023d059SJun Yang 				FSL_LX_SRDS2_PRTCL_MASK;
481f023d059SJun Yang 		sd_cfg >>= FSL_LX_SRDS2_PRTCL_SHIFT;
482f023d059SJun Yang 	} else {
483f023d059SJun Yang 		return false;
484f023d059SJun Yang 	}
485f023d059SJun Yang 	sd_cfg = sd_cfg & 0xff;
486f023d059SJun Yang 
487f023d059SJun Yang 	sd_idx = lx_serdes_cfg_to_idx(sd_cfg, sd_id);
488f023d059SJun Yang 	if (sd_idx < 0)
489f023d059SJun Yang 		return false;
490f023d059SJun Yang 
491f023d059SJun Yang 	if (sd_id == LSX_SERDES_1)
492f023d059SJun Yang 		lx_sd_loopback_support = &lx_sd1_loopback_support[sd_idx][0];
493f023d059SJun Yang 	else
494f023d059SJun Yang 		lx_sd_loopback_support = &lx_sd2_loopback_support[sd_idx][0];
495f023d059SJun Yang 
496f023d059SJun Yang 	if (sd_id == LSX_SERDES_1) {
497f023d059SJun Yang 		if (mac_id == 1)
498f023d059SJun Yang 			lan_id_tmp = 0;
499f023d059SJun Yang 		else if (mac_id == 2)
500f023d059SJun Yang 			lan_id_tmp = 4;
501f023d059SJun Yang 		else
502f023d059SJun Yang 			lan_id_tmp = (mac_id - 3);
503f023d059SJun Yang 	} else {
504f023d059SJun Yang 		if (mac_id == 11)
505f023d059SJun Yang 			lan_id_tmp = 0;
506f023d059SJun Yang 		else if (mac_id == 12)
507f023d059SJun Yang 			lan_id_tmp = 1;
508f023d059SJun Yang 		else if (mac_id == 13)
509f023d059SJun Yang 			lan_id_tmp = 6;
510f023d059SJun Yang 		else if (mac_id == 14)
511f023d059SJun Yang 			lan_id_tmp = 7;
512f023d059SJun Yang 		else if (mac_id == 15)
513f023d059SJun Yang 			lan_id_tmp = 4;
514f023d059SJun Yang 		else if (mac_id == 16)
515f023d059SJun Yang 			lan_id_tmp = 5;
516f023d059SJun Yang 		else if (mac_id == 17)
517f023d059SJun Yang 			lan_id_tmp = 2;
518f023d059SJun Yang 		else if (mac_id == 18)
519f023d059SJun Yang 			lan_id_tmp = 3;
520f023d059SJun Yang 		else
521f023d059SJun Yang 			return false;
522f023d059SJun Yang 	}
523f023d059SJun Yang 
524f023d059SJun Yang 	if (lan_id_tmp >= LSX_SERDES_LAN_NB)
525f023d059SJun Yang 		return false;
526f023d059SJun Yang 
527f023d059SJun Yang 	if (!lx_sd_loopback_support[lan_id_tmp])
528f023d059SJun Yang 		return false;
529f023d059SJun Yang 
530f023d059SJun Yang 	if (lan_id)
531f023d059SJun Yang 		*lan_id = lan_id_tmp;
532f023d059SJun Yang 	if (serdes_id)
533f023d059SJun Yang 		*serdes_id = sd_id;
534f023d059SJun Yang 
535f023d059SJun Yang 	return true;
536f023d059SJun Yang }
537f023d059SJun Yang 
538f023d059SJun Yang static inline int
539f023d059SJun Yang ls_serdes_eth_lpbk(uint16_t mac_id, int en)
540f023d059SJun Yang {
541f023d059SJun Yang 	uint16_t serdes_id, lan_id;
542f023d059SJun Yang 	int ret;
543f023d059SJun Yang 	uint32_t data;
544f023d059SJun Yang 	struct ccsr_ls_serdes *serdes_base;
545f023d059SJun Yang 	void *reg = 0;
546f023d059SJun Yang 
547f023d059SJun Yang 	ret = ls_mac_serdes_lpbk_support(mac_id, &serdes_id, &lan_id);
548f023d059SJun Yang 	if (!ret)
549f023d059SJun Yang 		return -ENOTSUP;
550f023d059SJun Yang 
551f023d059SJun Yang 	serdes_base = lsx_ccsr_map_region(CONFIG_SYS_FSL_SERDES_ADDR +
552f023d059SJun Yang 				(serdes_id - LSX_SERDES_1) * 0x10000,
553f023d059SJun Yang 				sizeof(struct ccsr_ls_serdes) / 64 * 64 + 64);
554f023d059SJun Yang 	if (!serdes_base) {
555f665790aSDavid Marchand 		DPAA2_PMD_ERR("Serdes register map failed");
556f023d059SJun Yang 		return -ENOMEM;
557f023d059SJun Yang 	}
558f023d059SJun Yang 
559f023d059SJun Yang 	if (serdes_id == LSX_SERDES_1)
560f023d059SJun Yang 		lan_id = LSX_SERDES_LAN_NB - lan_id - 1;
561f023d059SJun Yang 
562f023d059SJun Yang 	reg = &serdes_base->lane[lan_id].tsc3;
563f023d059SJun Yang 
564f023d059SJun Yang 	data = rte_read32(reg);
565f023d059SJun Yang 	if (en)
566f023d059SJun Yang 		rte_write32(data | LSX_LB_EN_BIT, reg);
567f023d059SJun Yang 	else
568f023d059SJun Yang 		rte_write32(data & (~LSX_LB_EN_BIT), reg);
569f023d059SJun Yang 
570f023d059SJun Yang 	return 0;
571f023d059SJun Yang }
572f023d059SJun Yang 
573f023d059SJun Yang static inline int
574f023d059SJun Yang lx_serdes_eth_lpbk(uint16_t mac_id, int en)
575f023d059SJun Yang {
576f023d059SJun Yang 	uint16_t serdes_id = 0xffff, lan_id = 0xffff;
577f023d059SJun Yang 	int ret;
578f023d059SJun Yang 	uint32_t data;
579f023d059SJun Yang 	struct ccsr_lx_serdes *serdes_base;
580f023d059SJun Yang 	void *reg = 0;
581f023d059SJun Yang 
582f023d059SJun Yang 	ret = lx_mac_serdes_lpbk_support(mac_id, &serdes_id, &lan_id);
583f023d059SJun Yang 	if (!ret)
584f023d059SJun Yang 		return -ENOTSUP;
585f023d059SJun Yang 
586f023d059SJun Yang 	serdes_base = lsx_ccsr_map_region(CONFIG_SYS_FSL_SERDES_ADDR +
587f023d059SJun Yang 					(serdes_id - LSX_SERDES_1) * 0x10000,
588f023d059SJun Yang 					sizeof(struct ccsr_lx_serdes) / 64 * 64 + 64);
589f023d059SJun Yang 	if (!serdes_base) {
590f665790aSDavid Marchand 		DPAA2_PMD_ERR("Serdes register map failed");
591f023d059SJun Yang 		return -ENOMEM;
592f023d059SJun Yang 	}
593f023d059SJun Yang 
594f023d059SJun Yang 	if (serdes_id == LSX_SERDES_1)
595f023d059SJun Yang 		lan_id = LSX_SERDES_LAN_NB - lan_id - 1;
596f023d059SJun Yang 
597f023d059SJun Yang 	reg = &serdes_base->lane[lan_id].lnatcsr0;
598f023d059SJun Yang 
599f023d059SJun Yang 	data = rte_read32(reg);
600f023d059SJun Yang 	if (en)
601f023d059SJun Yang 		rte_write32(data | LSX_LB_EN_BIT, reg);
602f023d059SJun Yang 	else
603f023d059SJun Yang 		rte_write32(data & (~LSX_LB_EN_BIT), reg);
604f023d059SJun Yang 
605f023d059SJun Yang 	return 0;
606f023d059SJun Yang }
607f023d059SJun Yang 
608f023d059SJun Yang /* Configure dpaa2 port as recycle port */
609f023d059SJun Yang int
610f023d059SJun Yang dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev)
611f023d059SJun Yang {
612f023d059SJun Yang 	struct rte_device *dev = eth_dev->device;
613f023d059SJun Yang 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
614f023d059SJun Yang 	struct rte_dpaa2_device *dpaa2_dev =
615f023d059SJun Yang 			container_of(dev, struct rte_dpaa2_device, device);
616f023d059SJun Yang 	struct fsl_mc_io *dpni_dev = eth_dev->process_private;
617f023d059SJun Yang 	struct dpni_port_cfg port_cfg;
618f023d059SJun Yang 	int ret;
619f023d059SJun Yang 
620f023d059SJun Yang 	if (priv->flags & DPAA2_TX_LOOPBACK_MODE) {
621f023d059SJun Yang 		DPAA2_PMD_INFO("%s has been configured recycle device.",
622f023d059SJun Yang 			eth_dev->data->name);
623f023d059SJun Yang 
624f023d059SJun Yang 		return 0;
625f023d059SJun Yang 	}
626f023d059SJun Yang 
627f023d059SJun Yang 	if (dpaa2_dev->ep_dev_type == DPAA2_MAC) {
628f023d059SJun Yang 		/** For dpmac-dpni connection,
629f023d059SJun Yang 		 * try setting serdes loopback as recycle device at first.
630f023d059SJun Yang 		 */
631f023d059SJun Yang 		if (dpaa2_svr_family == SVR_LS2088A) {
632f023d059SJun Yang 			ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1);
633f023d059SJun Yang 			if (!ret) {
634f023d059SJun Yang 				priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE;
635f023d059SJun Yang 				return 0;
636f023d059SJun Yang 			}
637f023d059SJun Yang 		} else if (dpaa2_svr_family == SVR_LX2160A) {
638f023d059SJun Yang 			ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1);
639f023d059SJun Yang 			if (!ret) {
640f023d059SJun Yang 				priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE;
641f023d059SJun Yang 				return 0;
642f023d059SJun Yang 			}
643f023d059SJun Yang 		} else {
644f023d059SJun Yang 			DPAA2_PMD_DEBUG("Serdes loopback not support SoC(0x%08x)",
645f023d059SJun Yang 				dpaa2_svr_family);
646f023d059SJun Yang 		}
647f023d059SJun Yang 
648f023d059SJun Yang 		/** If serdes loopback is not supported for this mac,
649f023d059SJun Yang 		 * trying set mac loopback.
650f023d059SJun Yang 		 */
651f023d059SJun Yang 
652f023d059SJun Yang 		port_cfg.loopback_en = 1;
653f023d059SJun Yang 		ret = dpni_set_port_cfg(dpni_dev, CMD_PRI_LOW,
654f023d059SJun Yang 				priv->token,
655f023d059SJun Yang 				DPNI_PORT_CFG_LOOPBACK,
656f023d059SJun Yang 				&port_cfg);
657f023d059SJun Yang 		if (ret) {
658f023d059SJun Yang 			DPAA2_PMD_ERR("Error(%d) to enable loopback", ret);
659f023d059SJun Yang 			return -ENOTSUP;
660f023d059SJun Yang 		}
661f023d059SJun Yang 
662f023d059SJun Yang 		priv->flags |= DPAA2_TX_MAC_LOOPBACK_MODE;
663f023d059SJun Yang 
664f023d059SJun Yang 		return 0;
665f023d059SJun Yang 	}
666f023d059SJun Yang 
667f023d059SJun Yang 	if (dpaa2_dev->ep_dev_type == DPAA2_ETH &&
668f023d059SJun Yang 		dpaa2_dev->object_id == dpaa2_dev->ep_object_id) {
669f023d059SJun Yang 		priv->flags |= DPAA2_TX_DPNI_LOOPBACK_MODE;
670f023d059SJun Yang 
671f023d059SJun Yang 		return 0;
672f023d059SJun Yang 	}
673f023d059SJun Yang 
674f023d059SJun Yang 	return -ENOTSUP;
675f023d059SJun Yang }
676f023d059SJun Yang 
677f023d059SJun Yang int
678f023d059SJun Yang dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev)
679f023d059SJun Yang {
680f023d059SJun Yang 	struct rte_device *dev = eth_dev->device;
681f023d059SJun Yang 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
682f023d059SJun Yang 	struct rte_dpaa2_device *dpaa2_dev =
683f023d059SJun Yang 			container_of(dev, struct rte_dpaa2_device, device);
684f023d059SJun Yang 	struct fsl_mc_io *dpni_dev = eth_dev->process_private;
685f023d059SJun Yang 	struct dpni_port_cfg port_cfg;
686f023d059SJun Yang 	int ret = 0;
687f023d059SJun Yang 
688f023d059SJun Yang 	if (!(priv->flags & DPAA2_TX_LOOPBACK_MODE))
689f023d059SJun Yang 		return 0;
690f023d059SJun Yang 
691f023d059SJun Yang 	if (priv->flags & DPAA2_TX_SERDES_LOOPBACK_MODE) {
692f023d059SJun Yang 		if (dpaa2_svr_family == SVR_LS2088A) {
693f023d059SJun Yang 			ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0);
694f023d059SJun Yang 			if (ret) {
695f023d059SJun Yang 				DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback",
696f023d059SJun Yang 					ret);
697f023d059SJun Yang 			} else {
698f023d059SJun Yang 				priv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE;
699f023d059SJun Yang 			}
700f023d059SJun Yang 		} else if (dpaa2_svr_family == SVR_LX2160A) {
701f023d059SJun Yang 			ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0);
702f023d059SJun Yang 			if (ret) {
703f023d059SJun Yang 				DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback",
704f023d059SJun Yang 					ret);
705f023d059SJun Yang 			} else {
706f023d059SJun Yang 				priv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE;
707f023d059SJun Yang 			}
708f023d059SJun Yang 		} else {
709f023d059SJun Yang 			DPAA2_PMD_DEBUG("Serdes loopback not support SoC(0x%08x)",
710f023d059SJun Yang 				dpaa2_svr_family);
711f023d059SJun Yang 		}
712f023d059SJun Yang 	}
713f023d059SJun Yang 
714f023d059SJun Yang 	if (priv->flags & DPAA2_TX_MAC_LOOPBACK_MODE) {
715f023d059SJun Yang 		port_cfg.loopback_en = 0;
716f023d059SJun Yang 		ret = dpni_set_port_cfg(dpni_dev, CMD_PRI_LOW,
717f023d059SJun Yang 				priv->token,
718f023d059SJun Yang 				DPNI_PORT_CFG_LOOPBACK,
719f023d059SJun Yang 				&port_cfg);
720f023d059SJun Yang 		if (ret) {
721f023d059SJun Yang 			DPAA2_PMD_ERR("Error(%d) to disable TX mac loopback",
722f023d059SJun Yang 				ret);
723f023d059SJun Yang 		} else {
724f023d059SJun Yang 			priv->flags &= ~DPAA2_TX_MAC_LOOPBACK_MODE;
725f023d059SJun Yang 		}
726f023d059SJun Yang 	}
727f023d059SJun Yang 
728f023d059SJun Yang 	if (priv->flags & DPAA2_TX_DPNI_LOOPBACK_MODE)
729f023d059SJun Yang 		priv->flags &= ~DPAA2_TX_DPNI_LOOPBACK_MODE;
730f023d059SJun Yang 
731f023d059SJun Yang 	return ret;
732f023d059SJun Yang }
733f023d059SJun Yang 
734f023d059SJun Yang int
735f023d059SJun Yang dpaa2_dev_recycle_qp_setup(struct rte_dpaa2_device *dpaa2_dev,
736f023d059SJun Yang 	uint16_t qidx, uint64_t cntx,
737f023d059SJun Yang 	eth_rx_burst_t tx_lpbk, eth_tx_burst_t rx_lpbk,
738f023d059SJun Yang 	struct dpaa2_queue **txq,
739f023d059SJun Yang 	struct dpaa2_queue **rxq)
740f023d059SJun Yang {
741f023d059SJun Yang 	struct rte_eth_dev *dev;
742f023d059SJun Yang 	struct rte_eth_dev_data *data;
743f023d059SJun Yang 	struct dpaa2_queue *txq_tmp;
744f023d059SJun Yang 	struct dpaa2_queue *rxq_tmp;
745f023d059SJun Yang 	struct dpaa2_dev_priv *priv;
746f023d059SJun Yang 
747f023d059SJun Yang 	dev = dpaa2_dev->eth_dev;
748f023d059SJun Yang 	data = dev->data;
749f023d059SJun Yang 	priv = data->dev_private;
750f023d059SJun Yang 
751f023d059SJun Yang 	if (!(priv->flags & DPAA2_TX_LOOPBACK_MODE) &&
752f023d059SJun Yang 		(tx_lpbk || rx_lpbk)) {
753f023d059SJun Yang 		DPAA2_PMD_ERR("%s is NOT recycle device!", data->name);
754f023d059SJun Yang 
755f023d059SJun Yang 		return -EINVAL;
756f023d059SJun Yang 	}
757f023d059SJun Yang 
758f023d059SJun Yang 	if (qidx >= data->nb_rx_queues || qidx >= data->nb_tx_queues)
759f023d059SJun Yang 		return -EINVAL;
760f023d059SJun Yang 
761f023d059SJun Yang 	rte_spinlock_lock(&priv->lpbk_qp_lock);
762f023d059SJun Yang 
763f023d059SJun Yang 	if (tx_lpbk)
764f023d059SJun Yang 		dev->tx_pkt_burst = tx_lpbk;
765f023d059SJun Yang 
766f023d059SJun Yang 	if (rx_lpbk)
767f023d059SJun Yang 		dev->rx_pkt_burst = rx_lpbk;
768f023d059SJun Yang 
769f023d059SJun Yang 	txq_tmp = data->tx_queues[qidx];
770f023d059SJun Yang 	txq_tmp->lpbk_cntx = cntx;
771f023d059SJun Yang 	rxq_tmp = data->rx_queues[qidx];
772f023d059SJun Yang 	rxq_tmp->lpbk_cntx = cntx;
773f023d059SJun Yang 
774f023d059SJun Yang 	if (txq)
775f023d059SJun Yang 		*txq = txq_tmp;
776f023d059SJun Yang 	if (rxq)
777f023d059SJun Yang 		*rxq = rxq_tmp;
778f023d059SJun Yang 
779f023d059SJun Yang 	rte_spinlock_unlock(&priv->lpbk_qp_lock);
780f023d059SJun Yang 
781f023d059SJun Yang 	return 0;
782f023d059SJun Yang }
783