dwmac100_dma.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*******************************************************************************
  3. This is the driver for the MAC 10/100 on-chip Ethernet controller
  4. currently tested on all the ST boards based on STb7109 and stx7200 SoCs.
  5. DWC Ether MAC 10/100 Universal version 4.0 has been used for developing
  6. this code.
  7. This contains the functions to handle the dma.
  8. Copyright (C) 2007-2009 STMicroelectronics Ltd
  9. Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
  10. *******************************************************************************/
  11. #include <linux/io.h>
  12. #include "dwmac100.h"
  13. #include "dwmac_dma.h"
  14. static void dwmac100_dma_init(void __iomem *ioaddr,
  15. struct stmmac_dma_cfg *dma_cfg)
  16. {
  17. /* Enable Application Access by writing to DMA CSR0 */
  18. writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT),
  19. ioaddr + DMA_BUS_MODE);
  20. /* Mask interrupts by writing to CSR7 */
  21. writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
  22. }
  23. static void dwmac100_dma_init_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
  24. struct stmmac_dma_cfg *dma_cfg,
  25. dma_addr_t dma_rx_phy, u32 chan)
  26. {
  27. /* RX descriptor base addr lists must be written into DMA CSR3 */
  28. writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
  29. }
  30. static void dwmac100_dma_init_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
  31. struct stmmac_dma_cfg *dma_cfg,
  32. dma_addr_t dma_tx_phy, u32 chan)
  33. {
  34. /* TX descriptor base addr lists must be written into DMA CSR4 */
  35. writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
  36. }
  37. /* Store and Forward capability is not used at all.
  38. *
  39. * The transmit threshold can be programmed by setting the TTC bits in the DMA
  40. * control register.
  41. */
  42. static void dwmac100_dma_operation_mode_tx(struct stmmac_priv *priv,
  43. void __iomem *ioaddr, int mode,
  44. u32 channel, int fifosz, u8 qmode)
  45. {
  46. u32 csr6 = readl(ioaddr + DMA_CONTROL);
  47. if (mode <= 32)
  48. csr6 |= DMA_CONTROL_TTC_32;
  49. else if (mode <= 64)
  50. csr6 |= DMA_CONTROL_TTC_64;
  51. else
  52. csr6 |= DMA_CONTROL_TTC_128;
  53. writel(csr6, ioaddr + DMA_CONTROL);
  54. }
  55. static void dwmac100_dump_dma_regs(struct stmmac_priv *priv,
  56. void __iomem *ioaddr, u32 *reg_space)
  57. {
  58. int i;
  59. for (i = 0; i < NUM_DWMAC100_DMA_REGS; i++)
  60. reg_space[DMA_BUS_MODE / 4 + i] =
  61. readl(ioaddr + DMA_BUS_MODE + i * 4);
  62. reg_space[DMA_CUR_TX_BUF_ADDR / 4] =
  63. readl(ioaddr + DMA_CUR_TX_BUF_ADDR);
  64. reg_space[DMA_CUR_RX_BUF_ADDR / 4] =
  65. readl(ioaddr + DMA_CUR_RX_BUF_ADDR);
  66. }
  67. /* DMA controller has two counters to track the number of the missed frames. */
  68. static void dwmac100_dma_diagnostic_fr(struct stmmac_extra_stats *x,
  69. void __iomem *ioaddr)
  70. {
  71. u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR);
  72. if (unlikely(csr8)) {
  73. if (csr8 & DMA_MISSED_FRAME_OVE) {
  74. x->rx_overflow_cntr += 0x800;
  75. } else {
  76. unsigned int ove_cntr;
  77. ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17);
  78. x->rx_overflow_cntr += ove_cntr;
  79. }
  80. if (csr8 & DMA_MISSED_FRAME_OVE_M) {
  81. x->rx_missed_cntr += 0xffff;
  82. } else {
  83. unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR);
  84. x->rx_missed_cntr += miss_f;
  85. }
  86. }
  87. }
  88. const struct stmmac_dma_ops dwmac100_dma_ops = {
  89. .reset = dwmac_dma_reset,
  90. .init = dwmac100_dma_init,
  91. .init_rx_chan = dwmac100_dma_init_rx,
  92. .init_tx_chan = dwmac100_dma_init_tx,
  93. .dump_regs = dwmac100_dump_dma_regs,
  94. .dma_tx_mode = dwmac100_dma_operation_mode_tx,
  95. .dma_diagnostic_fr = dwmac100_dma_diagnostic_fr,
  96. .enable_dma_transmission = dwmac_enable_dma_transmission,
  97. .enable_dma_irq = dwmac_enable_dma_irq,
  98. .disable_dma_irq = dwmac_disable_dma_irq,
  99. .start_tx = dwmac_dma_start_tx,
  100. .stop_tx = dwmac_dma_stop_tx,
  101. .start_rx = dwmac_dma_start_rx,
  102. .stop_rx = dwmac_dma_stop_rx,
  103. .dma_interrupt = dwmac_dma_interrupt,
  104. };