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 <dev_driver.h> 18 #include <bus_fslmc_driver.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 __rte_packed_begin ccsr_lx_serdes_lan { 71 uint8_t unused1[0xa0]; 72 uint32_t lnatcsr0; 73 uint8_t unused2[0x100 - 0xa4]; 74 } __rte_packed_end; 75 76 struct __rte_packed_begin ccsr_lx_serdes { 77 uint8_t unused0[0x800]; 78 struct ccsr_lx_serdes_lan lane[LSX_SERDES_LAN_NB]; 79 } __rte_packed_end; 80 81 struct __rte_packed_begin 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_end; 98 99 struct __rte_packed_begin 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_end; 174 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 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 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 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 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 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", 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 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 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"); 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 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"); 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 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 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 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