dwmac4_lib.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2007-2015 STMicroelectronics Ltd
  4. *
  5. * Author: Alexandre Torgue <alexandre.torgue@st.com>
  6. */
  7. #include <linux/io.h>
  8. #include <linux/iopoll.h>
  9. #include <linux/delay.h>
  10. #include "common.h"
  11. #include "dwmac4_dma.h"
  12. #include "dwmac4.h"
  13. #include "stmmac.h"
  14. int dwmac4_dma_reset(void __iomem *ioaddr)
  15. {
  16. u32 value = readl(ioaddr + DMA_BUS_MODE);
  17. /* DMA SW reset */
  18. value |= DMA_BUS_MODE_SFT_RESET;
  19. writel(value, ioaddr + DMA_BUS_MODE);
  20. return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
  21. !(value & DMA_BUS_MODE_SFT_RESET),
  22. 10000, 1000000);
  23. }
  24. void dwmac4_set_rx_tail_ptr(struct stmmac_priv *priv, void __iomem *ioaddr,
  25. u32 tail_ptr, u32 chan)
  26. {
  27. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  28. writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(dwmac4_addrs, chan));
  29. }
  30. void dwmac4_set_tx_tail_ptr(struct stmmac_priv *priv, void __iomem *ioaddr,
  31. u32 tail_ptr, u32 chan)
  32. {
  33. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  34. writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(dwmac4_addrs, chan));
  35. }
  36. void dwmac4_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
  37. u32 chan)
  38. {
  39. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  40. u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan));
  41. value |= DMA_CONTROL_ST;
  42. writel(value, ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan));
  43. value = readl(ioaddr + GMAC_CONFIG);
  44. value |= GMAC_CONFIG_TE;
  45. writel(value, ioaddr + GMAC_CONFIG);
  46. }
  47. void dwmac4_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
  48. u32 chan)
  49. {
  50. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  51. u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan));
  52. value &= ~DMA_CONTROL_ST;
  53. writel(value, ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan));
  54. }
  55. void dwmac4_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
  56. u32 chan)
  57. {
  58. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  59. u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan));
  60. value |= DMA_CONTROL_SR;
  61. writel(value, ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan));
  62. value = readl(ioaddr + GMAC_CONFIG);
  63. value |= GMAC_CONFIG_RE;
  64. writel(value, ioaddr + GMAC_CONFIG);
  65. }
  66. void dwmac4_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
  67. u32 chan)
  68. {
  69. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  70. u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan));
  71. value &= ~DMA_CONTROL_SR;
  72. writel(value, ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan));
  73. }
  74. void dwmac4_set_tx_ring_len(struct stmmac_priv *priv, void __iomem *ioaddr,
  75. u32 len, u32 chan)
  76. {
  77. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  78. writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(dwmac4_addrs, chan));
  79. }
  80. void dwmac4_set_rx_ring_len(struct stmmac_priv *priv, void __iomem *ioaddr,
  81. u32 len, u32 chan)
  82. {
  83. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  84. writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(dwmac4_addrs, chan));
  85. }
  86. void dwmac4_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
  87. u32 chan, bool rx, bool tx)
  88. {
  89. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  90. u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
  91. if (rx)
  92. value |= DMA_CHAN_INTR_DEFAULT_RX;
  93. if (tx)
  94. value |= DMA_CHAN_INTR_DEFAULT_TX;
  95. writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
  96. }
  97. void dwmac410_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
  98. u32 chan, bool rx, bool tx)
  99. {
  100. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  101. u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
  102. if (rx)
  103. value |= DMA_CHAN_INTR_DEFAULT_RX_4_10;
  104. if (tx)
  105. value |= DMA_CHAN_INTR_DEFAULT_TX_4_10;
  106. writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
  107. }
  108. void dwmac4_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
  109. u32 chan, bool rx, bool tx)
  110. {
  111. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  112. u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
  113. if (rx)
  114. value &= ~DMA_CHAN_INTR_DEFAULT_RX;
  115. if (tx)
  116. value &= ~DMA_CHAN_INTR_DEFAULT_TX;
  117. writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
  118. }
  119. void dwmac410_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
  120. u32 chan, bool rx, bool tx)
  121. {
  122. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  123. u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
  124. if (rx)
  125. value &= ~DMA_CHAN_INTR_DEFAULT_RX_4_10;
  126. if (tx)
  127. value &= ~DMA_CHAN_INTR_DEFAULT_TX_4_10;
  128. writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
  129. }
  130. int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
  131. struct stmmac_extra_stats *x, u32 chan, u32 dir)
  132. {
  133. const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
  134. u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan));
  135. u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
  136. struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
  137. int ret = 0;
  138. if (dir == DMA_DIR_RX)
  139. intr_status &= DMA_CHAN_STATUS_MSK_RX;
  140. else if (dir == DMA_DIR_TX)
  141. intr_status &= DMA_CHAN_STATUS_MSK_TX;
  142. /* ABNORMAL interrupts */
  143. if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) {
  144. if (unlikely(intr_status & DMA_CHAN_STATUS_RBU))
  145. x->rx_buf_unav_irq++;
  146. if (unlikely(intr_status & DMA_CHAN_STATUS_RPS))
  147. x->rx_process_stopped_irq++;
  148. if (unlikely(intr_status & DMA_CHAN_STATUS_ETI))
  149. x->tx_early_irq++;
  150. if (unlikely(intr_status & DMA_CHAN_STATUS_TPS)) {
  151. x->tx_process_stopped_irq++;
  152. ret = tx_hard_error;
  153. }
  154. if (unlikely(intr_status & DMA_CHAN_STATUS_FBE)) {
  155. x->fatal_bus_error_irq++;
  156. ret = tx_hard_error;
  157. }
  158. }
  159. if (unlikely(intr_status & DMA_CHAN_STATUS_RWT))
  160. x->rx_watchdog_irq++;
  161. /* TX/RX NORMAL interrupts */
  162. if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
  163. u64_stats_update_begin(&stats->syncp);
  164. u64_stats_inc(&stats->rx_normal_irq_n[chan]);
  165. u64_stats_update_end(&stats->syncp);
  166. ret |= handle_rx;
  167. }
  168. if (likely(intr_status & DMA_CHAN_STATUS_TI)) {
  169. u64_stats_update_begin(&stats->syncp);
  170. u64_stats_inc(&stats->tx_normal_irq_n[chan]);
  171. u64_stats_update_end(&stats->syncp);
  172. ret |= handle_tx;
  173. }
  174. if (unlikely(intr_status & DMA_CHAN_STATUS_TBU))
  175. ret |= handle_tx;
  176. if (unlikely(intr_status & DMA_CHAN_STATUS_ERI))
  177. x->rx_early_irq++;
  178. writel(intr_status & intr_en,
  179. ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan));
  180. return ret;
  181. }
  182. void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
  183. unsigned int high, unsigned int low)
  184. {
  185. unsigned long data;
  186. data = (addr[5] << 8) | addr[4];
  187. /* For MAC Addr registers se have to set the Address Enable (AE)
  188. * bit that has no effect on the High Reg 0 where the bit 31 (MO)
  189. * is RO.
  190. */
  191. data |= FIELD_PREP(GMAC_HI_DCS, STMMAC_CHAN0);
  192. writel(data | GMAC_HI_REG_AE, ioaddr + high);
  193. data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
  194. writel(data, ioaddr + low);
  195. }
  196. /* Enable disable MAC RX/TX */
  197. void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable)
  198. {
  199. u32 value = readl(ioaddr + GMAC_CONFIG);
  200. u32 old_val = value;
  201. if (enable)
  202. value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE;
  203. else
  204. value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE);
  205. if (value != old_val)
  206. writel(value, ioaddr + GMAC_CONFIG);
  207. }
  208. void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
  209. unsigned int high, unsigned int low)
  210. {
  211. unsigned int hi_addr, lo_addr;
  212. /* Read the MAC address from the hardware */
  213. hi_addr = readl(ioaddr + high);
  214. lo_addr = readl(ioaddr + low);
  215. /* Extract the MAC address from the high and low words */
  216. addr[0] = lo_addr & 0xff;
  217. addr[1] = (lo_addr >> 8) & 0xff;
  218. addr[2] = (lo_addr >> 16) & 0xff;
  219. addr[3] = (lo_addr >> 24) & 0xff;
  220. addr[4] = hi_addr & 0xff;
  221. addr[5] = (hi_addr >> 8) & 0xff;
  222. }