.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * This contains the functions to handle the descriptors for DesignWare databook |
---|
3 | 4 | * 4.xx. |
---|
4 | 5 | * |
---|
5 | 6 | * Copyright (C) 2015 STMicroelectronics Ltd |
---|
6 | 7 | * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify it |
---|
8 | | - * under the terms and conditions of the GNU General Public License, |
---|
9 | | - * version 2, as published by the Free Software Foundation. |
---|
10 | | - * |
---|
11 | 8 | * Author: Alexandre Torgue <alexandre.torgue@st.com> |
---|
12 | 9 | */ |
---|
13 | 10 | |
---|
14 | 11 | #include <linux/stmmac.h> |
---|
15 | 12 | #include "common.h" |
---|
| 13 | +#include "dwmac4.h" |
---|
16 | 14 | #include "dwmac4_descs.h" |
---|
17 | 15 | |
---|
18 | 16 | static int dwmac4_wrback_get_tx_status(void *data, struct stmmac_extra_stats *x, |
---|
.. | .. |
---|
86 | 84 | if (unlikely(rdes3 & RDES3_OWN)) |
---|
87 | 85 | return dma_own; |
---|
88 | 86 | |
---|
89 | | - /* Verify rx error by looking at the last segment. */ |
---|
90 | | - if (likely(!(rdes3 & RDES3_LAST_DESCRIPTOR))) |
---|
| 87 | + if (unlikely(rdes3 & RDES3_CONTEXT_DESCRIPTOR)) |
---|
91 | 88 | return discard_frame; |
---|
| 89 | + if (likely(!(rdes3 & RDES3_LAST_DESCRIPTOR))) |
---|
| 90 | + return rx_not_ls; |
---|
92 | 91 | |
---|
93 | 92 | if (unlikely(rdes3 & RDES3_ERROR_SUMMARY)) { |
---|
94 | 93 | if (unlikely(rdes3 & RDES3_GIANT_PACKET)) |
---|
.. | .. |
---|
191 | 190 | |
---|
192 | 191 | static void dwmac4_set_rx_owner(struct dma_desc *p, int disable_rx_ic) |
---|
193 | 192 | { |
---|
194 | | - p->des3 = cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR); |
---|
| 193 | + p->des3 |= cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR); |
---|
195 | 194 | |
---|
196 | 195 | if (!disable_rx_ic) |
---|
197 | 196 | p->des3 |= cpu_to_le32(RDES3_INT_ON_COMPLETION_EN); |
---|
.. | .. |
---|
271 | 270 | int ret = -EINVAL; |
---|
272 | 271 | |
---|
273 | 272 | /* Get the status from normal w/b descriptor */ |
---|
274 | | - if (likely(p->des3 & TDES3_RS1V)) { |
---|
| 273 | + if (likely(le32_to_cpu(p->des3) & RDES3_RDES1_VALID)) { |
---|
275 | 274 | if (likely(le32_to_cpu(p->des1) & RDES1_TIMESTAMP_AVAILABLE)) { |
---|
276 | 275 | int i = 0; |
---|
277 | 276 | |
---|
.. | .. |
---|
403 | 402 | p->des2 |= cpu_to_le32(TDES2_INTERRUPT_ON_COMPLETION); |
---|
404 | 403 | } |
---|
405 | 404 | |
---|
406 | | -static void dwmac4_display_ring(void *head, unsigned int size, bool rx) |
---|
| 405 | +static void dwmac4_display_ring(void *head, unsigned int size, bool rx, |
---|
| 406 | + dma_addr_t dma_rx_phy, unsigned int desc_size) |
---|
407 | 407 | { |
---|
408 | | - struct dma_desc *p = (struct dma_desc *)head; |
---|
| 408 | + dma_addr_t dma_addr; |
---|
409 | 409 | int i; |
---|
410 | 410 | |
---|
411 | 411 | pr_info("%s descriptor ring:\n", rx ? "RX" : "TX"); |
---|
412 | 412 | |
---|
413 | | - for (i = 0; i < size; i++) { |
---|
414 | | - pr_info("%03d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", |
---|
415 | | - i, (unsigned int)virt_to_phys(p), |
---|
416 | | - le32_to_cpu(p->des0), le32_to_cpu(p->des1), |
---|
417 | | - le32_to_cpu(p->des2), le32_to_cpu(p->des3)); |
---|
418 | | - p++; |
---|
| 413 | + if (desc_size == sizeof(struct dma_desc)) { |
---|
| 414 | + struct dma_desc *p = (struct dma_desc *)head; |
---|
| 415 | + |
---|
| 416 | + for (i = 0; i < size; i++) { |
---|
| 417 | + dma_addr = dma_rx_phy + i * sizeof(*p); |
---|
| 418 | + pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x\n", |
---|
| 419 | + i, &dma_addr, |
---|
| 420 | + le32_to_cpu(p->des0), le32_to_cpu(p->des1), |
---|
| 421 | + le32_to_cpu(p->des2), le32_to_cpu(p->des3)); |
---|
| 422 | + p++; |
---|
| 423 | + } |
---|
| 424 | + } else if (desc_size == sizeof(struct dma_extended_desc)) { |
---|
| 425 | + struct dma_extended_desc *extp = (struct dma_extended_desc *)head; |
---|
| 426 | + |
---|
| 427 | + for (i = 0; i < size; i++) { |
---|
| 428 | + dma_addr = dma_rx_phy + i * sizeof(*extp); |
---|
| 429 | + pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", |
---|
| 430 | + i, &dma_addr, |
---|
| 431 | + le32_to_cpu(extp->basic.des0), le32_to_cpu(extp->basic.des1), |
---|
| 432 | + le32_to_cpu(extp->basic.des2), le32_to_cpu(extp->basic.des3), |
---|
| 433 | + le32_to_cpu(extp->des4), le32_to_cpu(extp->des5), |
---|
| 434 | + le32_to_cpu(extp->des6), le32_to_cpu(extp->des7)); |
---|
| 435 | + extp++; |
---|
| 436 | + } |
---|
| 437 | + } else if (desc_size == sizeof(struct dma_edesc)) { |
---|
| 438 | + struct dma_edesc *ep = (struct dma_edesc *)head; |
---|
| 439 | + |
---|
| 440 | + for (i = 0; i < size; i++) { |
---|
| 441 | + dma_addr = dma_rx_phy + i * sizeof(*ep); |
---|
| 442 | + pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", |
---|
| 443 | + i, &dma_addr, |
---|
| 444 | + le32_to_cpu(ep->des4), le32_to_cpu(ep->des5), |
---|
| 445 | + le32_to_cpu(ep->des6), le32_to_cpu(ep->des7), |
---|
| 446 | + le32_to_cpu(ep->basic.des0), le32_to_cpu(ep->basic.des1), |
---|
| 447 | + le32_to_cpu(ep->basic.des2), le32_to_cpu(ep->basic.des3)); |
---|
| 448 | + ep++; |
---|
| 449 | + } |
---|
| 450 | + } else { |
---|
| 451 | + pr_err("unsupported descriptor!"); |
---|
419 | 452 | } |
---|
420 | 453 | } |
---|
421 | 454 | |
---|
.. | .. |
---|
434 | 467 | |
---|
435 | 468 | static void dwmac4_set_addr(struct dma_desc *p, dma_addr_t addr) |
---|
436 | 469 | { |
---|
437 | | - p->des0 = cpu_to_le32(addr); |
---|
438 | | - p->des1 = 0; |
---|
| 470 | + p->des0 = cpu_to_le32(lower_32_bits(addr)); |
---|
| 471 | + p->des1 = cpu_to_le32(upper_32_bits(addr)); |
---|
439 | 472 | } |
---|
440 | 473 | |
---|
441 | 474 | static void dwmac4_clear(struct dma_desc *p) |
---|
.. | .. |
---|
444 | 477 | p->des1 = 0; |
---|
445 | 478 | p->des2 = 0; |
---|
446 | 479 | p->des3 = 0; |
---|
| 480 | +} |
---|
| 481 | + |
---|
| 482 | +static void dwmac4_set_sarc(struct dma_desc *p, u32 sarc_type) |
---|
| 483 | +{ |
---|
| 484 | + sarc_type <<= TDES3_SA_INSERT_CTRL_SHIFT; |
---|
| 485 | + |
---|
| 486 | + p->des3 |= cpu_to_le32(sarc_type & TDES3_SA_INSERT_CTRL_MASK); |
---|
| 487 | +} |
---|
| 488 | + |
---|
| 489 | +static int set_16kib_bfsize(int mtu) |
---|
| 490 | +{ |
---|
| 491 | + int ret = 0; |
---|
| 492 | + |
---|
| 493 | + if (unlikely(mtu >= BUF_SIZE_8KiB)) |
---|
| 494 | + ret = BUF_SIZE_16KiB; |
---|
| 495 | + return ret; |
---|
| 496 | +} |
---|
| 497 | + |
---|
| 498 | +static void dwmac4_set_vlan_tag(struct dma_desc *p, u16 tag, u16 inner_tag, |
---|
| 499 | + u32 inner_type) |
---|
| 500 | +{ |
---|
| 501 | + p->des0 = 0; |
---|
| 502 | + p->des1 = 0; |
---|
| 503 | + p->des2 = 0; |
---|
| 504 | + p->des3 = 0; |
---|
| 505 | + |
---|
| 506 | + /* Inner VLAN */ |
---|
| 507 | + if (inner_type) { |
---|
| 508 | + u32 des = inner_tag << TDES2_IVT_SHIFT; |
---|
| 509 | + |
---|
| 510 | + des &= TDES2_IVT_MASK; |
---|
| 511 | + p->des2 = cpu_to_le32(des); |
---|
| 512 | + |
---|
| 513 | + des = inner_type << TDES3_IVTIR_SHIFT; |
---|
| 514 | + des &= TDES3_IVTIR_MASK; |
---|
| 515 | + p->des3 = cpu_to_le32(des | TDES3_IVLTV); |
---|
| 516 | + } |
---|
| 517 | + |
---|
| 518 | + /* Outer VLAN */ |
---|
| 519 | + p->des3 |= cpu_to_le32(tag & TDES3_VLAN_TAG); |
---|
| 520 | + p->des3 |= cpu_to_le32(TDES3_VLTV); |
---|
| 521 | + |
---|
| 522 | + p->des3 |= cpu_to_le32(TDES3_CONTEXT_TYPE); |
---|
| 523 | +} |
---|
| 524 | + |
---|
| 525 | +static void dwmac4_set_vlan(struct dma_desc *p, u32 type) |
---|
| 526 | +{ |
---|
| 527 | + type <<= TDES2_VLAN_TAG_SHIFT; |
---|
| 528 | + p->des2 |= cpu_to_le32(type & TDES2_VLAN_TAG_MASK); |
---|
| 529 | +} |
---|
| 530 | + |
---|
| 531 | +static void dwmac4_get_rx_header_len(struct dma_desc *p, unsigned int *len) |
---|
| 532 | +{ |
---|
| 533 | + *len = le32_to_cpu(p->des2) & RDES2_HL; |
---|
| 534 | +} |
---|
| 535 | + |
---|
| 536 | +static void dwmac4_set_sec_addr(struct dma_desc *p, dma_addr_t addr, bool buf2_valid) |
---|
| 537 | +{ |
---|
| 538 | + p->des2 = cpu_to_le32(lower_32_bits(addr)); |
---|
| 539 | + p->des3 = cpu_to_le32(upper_32_bits(addr)); |
---|
| 540 | + |
---|
| 541 | + if (buf2_valid) |
---|
| 542 | + p->des3 |= cpu_to_le32(RDES3_BUFFER2_VALID_ADDR); |
---|
| 543 | + else |
---|
| 544 | + p->des3 &= cpu_to_le32(~RDES3_BUFFER2_VALID_ADDR); |
---|
| 545 | +} |
---|
| 546 | + |
---|
| 547 | +static void dwmac4_set_tbs(struct dma_edesc *p, u32 sec, u32 nsec) |
---|
| 548 | +{ |
---|
| 549 | + p->des4 = cpu_to_le32((sec & TDES4_LT) | TDES4_LTV); |
---|
| 550 | + p->des5 = cpu_to_le32(nsec & TDES5_LT); |
---|
| 551 | + p->des6 = 0; |
---|
| 552 | + p->des7 = 0; |
---|
447 | 553 | } |
---|
448 | 554 | |
---|
449 | 555 | const struct stmmac_desc_ops dwmac4_desc_ops = { |
---|
.. | .. |
---|
470 | 576 | .get_addr = dwmac4_get_addr, |
---|
471 | 577 | .set_addr = dwmac4_set_addr, |
---|
472 | 578 | .clear = dwmac4_clear, |
---|
| 579 | + .set_sarc = dwmac4_set_sarc, |
---|
| 580 | + .set_vlan_tag = dwmac4_set_vlan_tag, |
---|
| 581 | + .set_vlan = dwmac4_set_vlan, |
---|
| 582 | + .get_rx_header_len = dwmac4_get_rx_header_len, |
---|
| 583 | + .set_sec_addr = dwmac4_set_sec_addr, |
---|
| 584 | + .set_tbs = dwmac4_set_tbs, |
---|
473 | 585 | }; |
---|
474 | 586 | |
---|
475 | | -const struct stmmac_mode_ops dwmac4_ring_mode_ops = { }; |
---|
| 587 | +const struct stmmac_mode_ops dwmac4_ring_mode_ops = { |
---|
| 588 | + .set_16kib_bfsize = set_16kib_bfsize, |
---|
| 589 | +}; |
---|