Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: dwc2: Add function to calculate correct FIFO sizes

The dwc2 IP on the SOCFPGA cannot use the default HW configured
FIFO sizes. The total FIFO depth as read from GHWCFG3 reports 0x1f80 or 8064
32-bit words. But the GRXFSIZ, GNPTXFSIZ, and HPTXFSIZ register defaults
to 0x2000 or 8192 32-bit words. So the driver cannot just use the fifo sizes
as read from those registers.

For platforms that face the same issue, this commits sets the RX, periodic TX,
and non-periodic TX fifo size to those that are recommended v2.93a spec for
the DWC2 IP. Implements Method #2 from the Synopsys v2.93a spec for the DWC2.

Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
Acked-by: Paul Zimmerman <paulz@synopsys.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Dinh Nguyen and committed by
Greg Kroah-Hartman
112fe8e2 8b3e233e

+68
+68
drivers/usb/dwc2/core.c
··· 507 507 writel(intmsk, hsotg->regs + GINTMSK); 508 508 } 509 509 510 + /* 511 + * dwc2_calculate_dynamic_fifo() - Calculates the default fifo size 512 + * For system that have a total fifo depth that is smaller than the default 513 + * RX + TX fifo size. 514 + * 515 + * @hsotg: Programming view of DWC_otg controller 516 + */ 517 + static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg) 518 + { 519 + struct dwc2_core_params *params = hsotg->core_params; 520 + struct dwc2_hw_params *hw = &hsotg->hw_params; 521 + u32 rxfsiz, nptxfsiz, ptxfsiz, total_fifo_size; 522 + 523 + total_fifo_size = hw->total_fifo_size; 524 + rxfsiz = params->host_rx_fifo_size; 525 + nptxfsiz = params->host_nperio_tx_fifo_size; 526 + ptxfsiz = params->host_perio_tx_fifo_size; 527 + 528 + /* 529 + * Will use Method 2 defined in the DWC2 spec: minimum FIFO depth 530 + * allocation with support for high bandwidth endpoints. Synopsys 531 + * defines MPS(Max Packet size) for a periodic EP=1024, and for 532 + * non-periodic as 512. 533 + */ 534 + if (total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz)) { 535 + /* 536 + * For Buffer DMA mode/Scatter Gather DMA mode 537 + * 2 * ((Largest Packet size / 4) + 1 + 1) + n 538 + * with n = number of host channel. 539 + * 2 * ((1024/4) + 2) = 516 540 + */ 541 + rxfsiz = 516 + hw->host_channels; 542 + 543 + /* 544 + * min non-periodic tx fifo depth 545 + * 2 * (largest non-periodic USB packet used / 4) 546 + * 2 * (512/4) = 256 547 + */ 548 + nptxfsiz = 256; 549 + 550 + /* 551 + * min periodic tx fifo depth 552 + * (largest packet size*MC)/4 553 + * (1024 * 3)/4 = 768 554 + */ 555 + ptxfsiz = 768; 556 + 557 + params->host_rx_fifo_size = rxfsiz; 558 + params->host_nperio_tx_fifo_size = nptxfsiz; 559 + params->host_perio_tx_fifo_size = ptxfsiz; 560 + } 561 + 562 + /* 563 + * If the summation of RX, NPTX and PTX fifo sizes is still 564 + * bigger than the total_fifo_size, then we have a problem. 565 + * 566 + * We won't be able to allocate as many endpoints. Right now, 567 + * we're just printing an error message, but ideally this FIFO 568 + * allocation algorithm would be improved in the future. 569 + * 570 + * FIXME improve this FIFO allocation algorithm. 571 + */ 572 + if (unlikely(total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz))) 573 + dev_err(hsotg->dev, "invalid fifo sizes\n"); 574 + } 575 + 510 576 static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) 511 577 { 512 578 struct dwc2_core_params *params = hsotg->core_params; ··· 580 514 581 515 if (!params->enable_dynamic_fifo) 582 516 return; 517 + 518 + dwc2_calculate_dynamic_fifo(hsotg); 583 519 584 520 /* Rx FIFO */ 585 521 grxfsiz = readl(hsotg->regs + GRXFSIZ);