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