1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 2 * 3 * Copyright 2010-2016 Freescale Semiconductor Inc. 4 * Copyright 2017 NXP 5 * 6 */ 7 8 #include <sys/types.h> 9 #include <sys/ioctl.h> 10 #include <ifaddrs.h> 11 12 /* This header declares the driver interface we implement */ 13 #include <fman.h> 14 #include <of.h> 15 #include <rte_dpaa_logs.h> 16 #include <rte_string_fns.h> 17 18 #define QMI_PORT_REGS_OFFSET 0x400 19 20 /* CCSR map address to access ccsr based register */ 21 void *fman_ccsr_map; 22 /* fman version info */ 23 u16 fman_ip_rev; 24 static int get_once; 25 u32 fman_dealloc_bufs_mask_hi; 26 u32 fman_dealloc_bufs_mask_lo; 27 28 int fman_ccsr_map_fd = -1; 29 static COMPAT_LIST_HEAD(__ifs); 30 31 /* This is the (const) global variable that callers have read-only access to. 32 * Internally, we have read-write access directly to __ifs. 33 */ 34 const struct list_head *fman_if_list = &__ifs; 35 36 static void 37 if_destructor(struct __fman_if *__if) 38 { 39 struct fman_if_bpool *bp, *tmpbp; 40 41 if (!__if) 42 return; 43 44 if (__if->__if.mac_type == fman_offline) 45 goto cleanup; 46 47 list_for_each_entry_safe(bp, tmpbp, &__if->__if.bpool_list, node) { 48 list_del(&bp->node); 49 free(bp); 50 } 51 cleanup: 52 free(__if); 53 } 54 55 static int 56 fman_get_ip_rev(const struct device_node *fman_node) 57 { 58 const uint32_t *fman_addr; 59 uint64_t phys_addr; 60 uint64_t regs_size; 61 uint32_t ip_rev_1; 62 int _errno; 63 64 fman_addr = of_get_address(fman_node, 0, ®s_size, NULL); 65 if (!fman_addr) { 66 pr_err("of_get_address cannot return fman address\n"); 67 return -EINVAL; 68 } 69 phys_addr = of_translate_address(fman_node, fman_addr); 70 if (!phys_addr) { 71 pr_err("of_translate_address failed\n"); 72 return -EINVAL; 73 } 74 fman_ccsr_map = mmap(NULL, regs_size, PROT_READ | PROT_WRITE, 75 MAP_SHARED, fman_ccsr_map_fd, phys_addr); 76 if (fman_ccsr_map == MAP_FAILED) { 77 pr_err("Can not map FMan ccsr base"); 78 return -EINVAL; 79 } 80 81 ip_rev_1 = in_be32(fman_ccsr_map + FMAN_IP_REV_1); 82 fman_ip_rev = (ip_rev_1 & FMAN_IP_REV_1_MAJOR_MASK) >> 83 FMAN_IP_REV_1_MAJOR_SHIFT; 84 85 _errno = munmap(fman_ccsr_map, regs_size); 86 if (_errno) 87 pr_err("munmap() of FMan ccsr failed"); 88 89 return 0; 90 } 91 92 static int 93 fman_get_mac_index(uint64_t regs_addr_host, uint8_t *mac_idx) 94 { 95 int ret = 0; 96 97 /* 98 * MAC1 : E_0000h 99 * MAC2 : E_2000h 100 * MAC3 : E_4000h 101 * MAC4 : E_6000h 102 * MAC5 : E_8000h 103 * MAC6 : E_A000h 104 * MAC7 : E_C000h 105 * MAC8 : E_E000h 106 * MAC9 : F_0000h 107 * MAC10: F_2000h 108 */ 109 switch (regs_addr_host) { 110 case 0xE0000: 111 *mac_idx = 1; 112 break; 113 case 0xE2000: 114 *mac_idx = 2; 115 break; 116 case 0xE4000: 117 *mac_idx = 3; 118 break; 119 case 0xE6000: 120 *mac_idx = 4; 121 break; 122 case 0xE8000: 123 *mac_idx = 5; 124 break; 125 case 0xEA000: 126 *mac_idx = 6; 127 break; 128 case 0xEC000: 129 *mac_idx = 7; 130 break; 131 case 0xEE000: 132 *mac_idx = 8; 133 break; 134 case 0xF0000: 135 *mac_idx = 9; 136 break; 137 case 0xF2000: 138 *mac_idx = 10; 139 break; 140 default: 141 ret = -EINVAL; 142 } 143 144 return ret; 145 } 146 147 static int 148 fman_if_init(const struct device_node *dpa_node) 149 { 150 const char *rprop, *mprop; 151 uint64_t phys_addr; 152 struct __fman_if *__if; 153 struct fman_if_bpool *bpool; 154 155 const phandle *mac_phandle, *ports_phandle, *pools_phandle; 156 const phandle *tx_channel_id = NULL, *mac_addr, *cell_idx; 157 const phandle *rx_phandle, *tx_phandle; 158 uint64_t tx_phandle_host[4] = {0}; 159 uint64_t rx_phandle_host[4] = {0}; 160 uint64_t regs_addr_host = 0; 161 uint64_t cell_idx_host = 0; 162 163 const struct device_node *mac_node = NULL, *tx_node; 164 const struct device_node *pool_node, *fman_node, *rx_node; 165 const uint32_t *regs_addr = NULL; 166 const char *mname, *fname; 167 const char *dname = dpa_node->full_name; 168 size_t lenp; 169 int _errno; 170 const char *char_prop; 171 uint32_t na; 172 173 if (of_device_is_available(dpa_node) == false) 174 return 0; 175 176 rprop = "fsl,qman-frame-queues-rx"; 177 mprop = "fsl,fman-mac"; 178 179 /* Allocate an object for this network interface */ 180 __if = malloc(sizeof(*__if)); 181 if (!__if) { 182 FMAN_ERR(-ENOMEM, "malloc(%zu)\n", sizeof(*__if)); 183 goto err; 184 } 185 memset(__if, 0, sizeof(*__if)); 186 INIT_LIST_HEAD(&__if->__if.bpool_list); 187 strlcpy(__if->node_path, dpa_node->full_name, PATH_MAX - 1); 188 __if->node_path[PATH_MAX - 1] = '\0'; 189 190 /* Obtain the MAC node used by this interface except macless */ 191 mac_phandle = of_get_property(dpa_node, mprop, &lenp); 192 if (!mac_phandle) { 193 FMAN_ERR(-EINVAL, "%s: no %s\n", dname, mprop); 194 goto err; 195 } 196 assert(lenp == sizeof(phandle)); 197 mac_node = of_find_node_by_phandle(*mac_phandle); 198 if (!mac_node) { 199 FMAN_ERR(-ENXIO, "%s: bad 'fsl,fman-mac\n", dname); 200 goto err; 201 } 202 mname = mac_node->full_name; 203 204 /* Map the CCSR regs for the MAC node */ 205 regs_addr = of_get_address(mac_node, 0, &__if->regs_size, NULL); 206 if (!regs_addr) { 207 FMAN_ERR(-EINVAL, "of_get_address(%s)\n", mname); 208 goto err; 209 } 210 phys_addr = of_translate_address(mac_node, regs_addr); 211 if (!phys_addr) { 212 FMAN_ERR(-EINVAL, "of_translate_address(%s, %p)\n", 213 mname, regs_addr); 214 goto err; 215 } 216 __if->ccsr_map = mmap(NULL, __if->regs_size, 217 PROT_READ | PROT_WRITE, MAP_SHARED, 218 fman_ccsr_map_fd, phys_addr); 219 if (__if->ccsr_map == MAP_FAILED) { 220 FMAN_ERR(-errno, "mmap(0x%"PRIx64")\n", phys_addr); 221 goto err; 222 } 223 na = of_n_addr_cells(mac_node); 224 /* Get rid of endianness (issues). Convert to host byte order */ 225 regs_addr_host = of_read_number(regs_addr, na); 226 227 228 /* Get the index of the Fman this i/f belongs to */ 229 fman_node = of_get_parent(mac_node); 230 na = of_n_addr_cells(mac_node); 231 if (!fman_node) { 232 FMAN_ERR(-ENXIO, "of_get_parent(%s)\n", mname); 233 goto err; 234 } 235 fname = fman_node->full_name; 236 cell_idx = of_get_property(fman_node, "cell-index", &lenp); 237 if (!cell_idx) { 238 FMAN_ERR(-ENXIO, "%s: no cell-index)\n", fname); 239 goto err; 240 } 241 assert(lenp == sizeof(*cell_idx)); 242 cell_idx_host = of_read_number(cell_idx, lenp / sizeof(phandle)); 243 __if->__if.fman_idx = cell_idx_host; 244 if (!get_once) { 245 _errno = fman_get_ip_rev(fman_node); 246 if (_errno) { 247 FMAN_ERR(-ENXIO, "%s: ip_rev is not available\n", 248 fname); 249 goto err; 250 } 251 } 252 253 if (fman_ip_rev >= FMAN_V3) { 254 /* 255 * Set A2V, OVOM, EBD bits in contextA to allow external 256 * buffer deallocation by fman. 257 */ 258 fman_dealloc_bufs_mask_hi = FMAN_V3_CONTEXTA_EN_A2V | 259 FMAN_V3_CONTEXTA_EN_OVOM; 260 fman_dealloc_bufs_mask_lo = FMAN_V3_CONTEXTA_EN_EBD; 261 } else { 262 fman_dealloc_bufs_mask_hi = 0; 263 fman_dealloc_bufs_mask_lo = 0; 264 } 265 /* Is the MAC node 1G, 10G? */ 266 __if->__if.is_memac = 0; 267 268 if (of_device_is_compatible(mac_node, "fsl,fman-1g-mac")) 269 __if->__if.mac_type = fman_mac_1g; 270 else if (of_device_is_compatible(mac_node, "fsl,fman-10g-mac")) 271 __if->__if.mac_type = fman_mac_10g; 272 else if (of_device_is_compatible(mac_node, "fsl,fman-memac")) { 273 __if->__if.is_memac = 1; 274 char_prop = of_get_property(mac_node, "phy-connection-type", 275 NULL); 276 if (!char_prop) { 277 printf("memac: unknown MII type assuming 1G\n"); 278 /* Right now forcing memac to 1g in case of error*/ 279 __if->__if.mac_type = fman_mac_1g; 280 } else { 281 if (strstr(char_prop, "sgmii")) 282 __if->__if.mac_type = fman_mac_1g; 283 else if (strstr(char_prop, "rgmii")) { 284 __if->__if.mac_type = fman_mac_1g; 285 __if->__if.is_rgmii = 1; 286 } else if (strstr(char_prop, "xgmii")) 287 __if->__if.mac_type = fman_mac_10g; 288 } 289 } else { 290 FMAN_ERR(-EINVAL, "%s: unknown MAC type\n", mname); 291 goto err; 292 } 293 294 /* 295 * For MAC ports, we cannot rely on cell-index. In 296 * T2080, two of the 10G ports on single FMAN have same 297 * duplicate cell-indexes as the other two 10G ports on 298 * same FMAN. Hence, we now rely upon addresses of the 299 * ports from device tree to deduce the index. 300 */ 301 302 _errno = fman_get_mac_index(regs_addr_host, &__if->__if.mac_idx); 303 if (_errno) { 304 FMAN_ERR(-EINVAL, "Invalid register address: %" PRIx64, 305 regs_addr_host); 306 goto err; 307 } 308 309 /* Extract the MAC address for private and shared interfaces */ 310 mac_addr = of_get_property(mac_node, "local-mac-address", 311 &lenp); 312 if (!mac_addr) { 313 FMAN_ERR(-EINVAL, "%s: no local-mac-address\n", 314 mname); 315 goto err; 316 } 317 memcpy(&__if->__if.mac_addr, mac_addr, ETHER_ADDR_LEN); 318 319 /* Extract the Tx port (it's the second of the two port handles) 320 * and get its channel ID 321 */ 322 ports_phandle = of_get_property(mac_node, "fsl,port-handles", 323 &lenp); 324 if (!ports_phandle) 325 ports_phandle = of_get_property(mac_node, "fsl,fman-ports", 326 &lenp); 327 if (!ports_phandle) { 328 FMAN_ERR(-EINVAL, "%s: no fsl,port-handles\n", 329 mname); 330 goto err; 331 } 332 assert(lenp == (2 * sizeof(phandle))); 333 tx_node = of_find_node_by_phandle(ports_phandle[1]); 334 if (!tx_node) { 335 FMAN_ERR(-ENXIO, "%s: bad fsl,port-handle[1]\n", mname); 336 goto err; 337 } 338 /* Extract the channel ID (from tx-port-handle) */ 339 tx_channel_id = of_get_property(tx_node, "fsl,qman-channel-id", 340 &lenp); 341 if (!tx_channel_id) { 342 FMAN_ERR(-EINVAL, "%s: no fsl-qman-channel-id\n", 343 tx_node->full_name); 344 goto err; 345 } 346 347 rx_node = of_find_node_by_phandle(ports_phandle[0]); 348 if (!rx_node) { 349 FMAN_ERR(-ENXIO, "%s: bad fsl,port-handle[0]\n", mname); 350 goto err; 351 } 352 regs_addr = of_get_address(rx_node, 0, &__if->regs_size, NULL); 353 if (!regs_addr) { 354 FMAN_ERR(-EINVAL, "of_get_address(%s)\n", mname); 355 goto err; 356 } 357 phys_addr = of_translate_address(rx_node, regs_addr); 358 if (!phys_addr) { 359 FMAN_ERR(-EINVAL, "of_translate_address(%s, %p)\n", 360 mname, regs_addr); 361 goto err; 362 } 363 __if->bmi_map = mmap(NULL, __if->regs_size, 364 PROT_READ | PROT_WRITE, MAP_SHARED, 365 fman_ccsr_map_fd, phys_addr); 366 if (__if->bmi_map == MAP_FAILED) { 367 FMAN_ERR(-errno, "mmap(0x%"PRIx64")\n", phys_addr); 368 goto err; 369 } 370 371 /* No channel ID for MAC-less */ 372 assert(lenp == sizeof(*tx_channel_id)); 373 na = of_n_addr_cells(mac_node); 374 __if->__if.tx_channel_id = of_read_number(tx_channel_id, na); 375 376 /* Extract the Rx FQIDs. (Note, the device representation is silly, 377 * there are "counts" that must always be 1.) 378 */ 379 rx_phandle = of_get_property(dpa_node, rprop, &lenp); 380 if (!rx_phandle) { 381 FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-rx\n", dname); 382 goto err; 383 } 384 385 assert(lenp == (4 * sizeof(phandle))); 386 387 na = of_n_addr_cells(mac_node); 388 /* Get rid of endianness (issues). Convert to host byte order */ 389 rx_phandle_host[0] = of_read_number(&rx_phandle[0], na); 390 rx_phandle_host[1] = of_read_number(&rx_phandle[1], na); 391 rx_phandle_host[2] = of_read_number(&rx_phandle[2], na); 392 rx_phandle_host[3] = of_read_number(&rx_phandle[3], na); 393 394 assert((rx_phandle_host[1] == 1) && (rx_phandle_host[3] == 1)); 395 __if->__if.fqid_rx_err = rx_phandle_host[0]; 396 __if->__if.fqid_rx_def = rx_phandle_host[2]; 397 398 /* Extract the Tx FQIDs */ 399 tx_phandle = of_get_property(dpa_node, 400 "fsl,qman-frame-queues-tx", &lenp); 401 if (!tx_phandle) { 402 FMAN_ERR(-EINVAL, "%s: no fsl,qman-frame-queues-tx\n", dname); 403 goto err; 404 } 405 406 assert(lenp == (4 * sizeof(phandle))); 407 /*TODO: Fix for other cases also */ 408 na = of_n_addr_cells(mac_node); 409 /* Get rid of endianness (issues). Convert to host byte order */ 410 tx_phandle_host[0] = of_read_number(&tx_phandle[0], na); 411 tx_phandle_host[1] = of_read_number(&tx_phandle[1], na); 412 tx_phandle_host[2] = of_read_number(&tx_phandle[2], na); 413 tx_phandle_host[3] = of_read_number(&tx_phandle[3], na); 414 assert((tx_phandle_host[1] == 1) && (tx_phandle_host[3] == 1)); 415 __if->__if.fqid_tx_err = tx_phandle_host[0]; 416 __if->__if.fqid_tx_confirm = tx_phandle_host[2]; 417 418 /* Obtain the buffer pool nodes used by this interface */ 419 pools_phandle = of_get_property(dpa_node, "fsl,bman-buffer-pools", 420 &lenp); 421 if (!pools_phandle) { 422 FMAN_ERR(-EINVAL, "%s: no fsl,bman-buffer-pools\n", dname); 423 goto err; 424 } 425 /* For each pool, parse the corresponding node and add a pool object 426 * to the interface's "bpool_list" 427 */ 428 assert(lenp && !(lenp % sizeof(phandle))); 429 while (lenp) { 430 size_t proplen; 431 const phandle *prop; 432 uint64_t bpid_host = 0; 433 uint64_t bpool_host[6] = {0}; 434 const char *pname; 435 /* Allocate an object for the pool */ 436 bpool = malloc(sizeof(*bpool)); 437 if (!bpool) { 438 FMAN_ERR(-ENOMEM, "malloc(%zu)\n", sizeof(*bpool)); 439 goto err; 440 } 441 /* Find the pool node */ 442 pool_node = of_find_node_by_phandle(*pools_phandle); 443 if (!pool_node) { 444 FMAN_ERR(-ENXIO, "%s: bad fsl,bman-buffer-pools\n", 445 dname); 446 free(bpool); 447 goto err; 448 } 449 pname = pool_node->full_name; 450 /* Extract the BPID property */ 451 prop = of_get_property(pool_node, "fsl,bpid", &proplen); 452 if (!prop) { 453 FMAN_ERR(-EINVAL, "%s: no fsl,bpid\n", pname); 454 free(bpool); 455 goto err; 456 } 457 assert(proplen == sizeof(*prop)); 458 na = of_n_addr_cells(mac_node); 459 /* Get rid of endianness (issues). 460 * Convert to host byte-order 461 */ 462 bpid_host = of_read_number(prop, na); 463 bpool->bpid = bpid_host; 464 /* Extract the cfg property (count/size/addr). "fsl,bpool-cfg" 465 * indicates for the Bman driver to seed the pool. 466 * "fsl,bpool-ethernet-cfg" is used by the network driver. The 467 * two are mutually exclusive, so check for either of them. 468 */ 469 prop = of_get_property(pool_node, "fsl,bpool-cfg", 470 &proplen); 471 if (!prop) 472 prop = of_get_property(pool_node, 473 "fsl,bpool-ethernet-cfg", 474 &proplen); 475 if (!prop) { 476 /* It's OK for there to be no bpool-cfg */ 477 bpool->count = bpool->size = bpool->addr = 0; 478 } else { 479 assert(proplen == (6 * sizeof(*prop))); 480 na = of_n_addr_cells(mac_node); 481 /* Get rid of endianness (issues). 482 * Convert to host byte order 483 */ 484 bpool_host[0] = of_read_number(&prop[0], na); 485 bpool_host[1] = of_read_number(&prop[1], na); 486 bpool_host[2] = of_read_number(&prop[2], na); 487 bpool_host[3] = of_read_number(&prop[3], na); 488 bpool_host[4] = of_read_number(&prop[4], na); 489 bpool_host[5] = of_read_number(&prop[5], na); 490 491 bpool->count = ((uint64_t)bpool_host[0] << 32) | 492 bpool_host[1]; 493 bpool->size = ((uint64_t)bpool_host[2] << 32) | 494 bpool_host[3]; 495 bpool->addr = ((uint64_t)bpool_host[4] << 32) | 496 bpool_host[5]; 497 } 498 /* Parsing of the pool is complete, add it to the interface 499 * list. 500 */ 501 list_add_tail(&bpool->node, &__if->__if.bpool_list); 502 lenp -= sizeof(phandle); 503 pools_phandle++; 504 } 505 506 /* Parsing of the network interface is complete, add it to the list */ 507 DPAA_BUS_LOG(DEBUG, "Found %s, Tx Channel = %x, FMAN = %x," 508 "Port ID = %x", 509 dname, __if->__if.tx_channel_id, __if->__if.fman_idx, 510 __if->__if.mac_idx); 511 512 list_add_tail(&__if->__if.node, &__ifs); 513 return 0; 514 err: 515 if_destructor(__if); 516 return _errno; 517 } 518 519 int 520 fman_init(void) 521 { 522 const struct device_node *dpa_node; 523 int _errno; 524 525 /* If multiple dependencies try to initialise the Fman driver, don't 526 * panic. 527 */ 528 if (fman_ccsr_map_fd != -1) 529 return 0; 530 531 fman_ccsr_map_fd = open(FMAN_DEVICE_PATH, O_RDWR); 532 if (unlikely(fman_ccsr_map_fd < 0)) { 533 DPAA_BUS_LOG(ERR, "Unable to open (/dev/mem)"); 534 return fman_ccsr_map_fd; 535 } 536 537 for_each_compatible_node(dpa_node, NULL, "fsl,dpa-ethernet-init") { 538 _errno = fman_if_init(dpa_node); 539 if (_errno) { 540 FMAN_ERR(_errno, "if_init(%s)\n", dpa_node->full_name); 541 goto err; 542 } 543 } 544 545 return 0; 546 err: 547 fman_finish(); 548 return _errno; 549 } 550 551 void 552 fman_finish(void) 553 { 554 struct __fman_if *__if, *tmpif; 555 556 assert(fman_ccsr_map_fd != -1); 557 558 list_for_each_entry_safe(__if, tmpif, &__ifs, __if.node) { 559 int _errno; 560 561 /* disable Rx and Tx */ 562 if ((__if->__if.mac_type == fman_mac_1g) && 563 (!__if->__if.is_memac)) 564 out_be32(__if->ccsr_map + 0x100, 565 in_be32(__if->ccsr_map + 0x100) & ~(u32)0x5); 566 else 567 out_be32(__if->ccsr_map + 8, 568 in_be32(__if->ccsr_map + 8) & ~(u32)3); 569 /* release the mapping */ 570 _errno = munmap(__if->ccsr_map, __if->regs_size); 571 if (unlikely(_errno < 0)) 572 fprintf(stderr, "%s:%d:%s(): munmap() = %d (%s)\n", 573 __FILE__, __LINE__, __func__, 574 -errno, strerror(errno)); 575 printf("Tearing down %s\n", __if->node_path); 576 list_del(&__if->__if.node); 577 free(__if); 578 } 579 580 close(fman_ccsr_map_fd); 581 fman_ccsr_map_fd = -1; 582 } 583