dwmac5.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. // SPDX-License-Identifier: (GPL-2.0 OR MIT)
  2. // Copyright (c) 2017 Synopsys, Inc. and/or its affiliates.
  3. // stmmac Support for 5.xx Ethernet QoS cores
  4. #include <linux/bitops.h>
  5. #include <linux/iopoll.h>
  6. #include "common.h"
  7. #include "dwmac4.h"
  8. #include "dwmac5.h"
  9. struct dwmac5_error_desc {
  10. bool valid;
  11. const char *desc;
  12. const char *detailed_desc;
  13. };
  14. #define STAT_OFF(field) offsetof(struct stmmac_safety_stats, field)
  15. static void dwmac5_log_error(struct net_device *ndev, u32 value, bool corr,
  16. const char *module_name, const struct dwmac5_error_desc *desc,
  17. unsigned long field_offset, struct stmmac_safety_stats *stats)
  18. {
  19. unsigned long loc, mask;
  20. u8 *bptr = (u8 *)stats;
  21. unsigned long *ptr;
  22. ptr = (unsigned long *)(bptr + field_offset);
  23. mask = value;
  24. for_each_set_bit(loc, &mask, 32) {
  25. netdev_err(ndev, "Found %s error in %s: '%s: %s'\n", corr ?
  26. "correctable" : "uncorrectable", module_name,
  27. desc[loc].desc, desc[loc].detailed_desc);
  28. /* Update counters */
  29. ptr[loc]++;
  30. }
  31. }
  32. static const struct dwmac5_error_desc dwmac5_mac_errors[32]= {
  33. { true, "ATPES", "Application Transmit Interface Parity Check Error" },
  34. { true, "TPES", "TSO Data Path Parity Check Error" },
  35. { true, "RDPES", "Read Descriptor Parity Check Error" },
  36. { true, "MPES", "MTL Data Path Parity Check Error" },
  37. { true, "MTSPES", "MTL TX Status Data Path Parity Check Error" },
  38. { true, "ARPES", "Application Receive Interface Data Path Parity Check Error" },
  39. { true, "CWPES", "CSR Write Data Path Parity Check Error" },
  40. { true, "ASRPES", "AXI Slave Read Data Path Parity Check Error" },
  41. { true, "TTES", "TX FSM Timeout Error" },
  42. { true, "RTES", "RX FSM Timeout Error" },
  43. { true, "CTES", "CSR FSM Timeout Error" },
  44. { true, "ATES", "APP FSM Timeout Error" },
  45. { true, "PTES", "PTP FSM Timeout Error" },
  46. { true, "T125ES", "TX125 FSM Timeout Error" },
  47. { true, "R125ES", "RX125 FSM Timeout Error" },
  48. { true, "RVCTES", "REV MDC FSM Timeout Error" },
  49. { true, "MSTTES", "Master Read/Write Timeout Error" },
  50. { true, "SLVTES", "Slave Read/Write Timeout Error" },
  51. { true, "ATITES", "Application Timeout on ATI Interface Error" },
  52. { true, "ARITES", "Application Timeout on ARI Interface Error" },
  53. { false, "UNKNOWN", "Unknown Error" }, /* 20 */
  54. { false, "UNKNOWN", "Unknown Error" }, /* 21 */
  55. { false, "UNKNOWN", "Unknown Error" }, /* 22 */
  56. { false, "UNKNOWN", "Unknown Error" }, /* 23 */
  57. { true, "FSMPES", "FSM State Parity Error" },
  58. { false, "UNKNOWN", "Unknown Error" }, /* 25 */
  59. { false, "UNKNOWN", "Unknown Error" }, /* 26 */
  60. { false, "UNKNOWN", "Unknown Error" }, /* 27 */
  61. { false, "UNKNOWN", "Unknown Error" }, /* 28 */
  62. { false, "UNKNOWN", "Unknown Error" }, /* 29 */
  63. { false, "UNKNOWN", "Unknown Error" }, /* 30 */
  64. { false, "UNKNOWN", "Unknown Error" }, /* 31 */
  65. };
  66. static void dwmac5_handle_mac_err(struct net_device *ndev,
  67. void __iomem *ioaddr, bool correctable,
  68. struct stmmac_safety_stats *stats)
  69. {
  70. u32 value;
  71. value = readl(ioaddr + MAC_DPP_FSM_INT_STATUS);
  72. writel(value, ioaddr + MAC_DPP_FSM_INT_STATUS);
  73. dwmac5_log_error(ndev, value, correctable, "MAC", dwmac5_mac_errors,
  74. STAT_OFF(mac_errors), stats);
  75. }
  76. static const struct dwmac5_error_desc dwmac5_mtl_errors[32]= {
  77. { true, "TXCES", "MTL TX Memory Error" },
  78. { true, "TXAMS", "MTL TX Memory Address Mismatch Error" },
  79. { true, "TXUES", "MTL TX Memory Error" },
  80. { false, "UNKNOWN", "Unknown Error" }, /* 3 */
  81. { true, "RXCES", "MTL RX Memory Error" },
  82. { true, "RXAMS", "MTL RX Memory Address Mismatch Error" },
  83. { true, "RXUES", "MTL RX Memory Error" },
  84. { false, "UNKNOWN", "Unknown Error" }, /* 7 */
  85. { true, "ECES", "MTL EST Memory Error" },
  86. { true, "EAMS", "MTL EST Memory Address Mismatch Error" },
  87. { true, "EUES", "MTL EST Memory Error" },
  88. { false, "UNKNOWN", "Unknown Error" }, /* 11 */
  89. { true, "RPCES", "MTL RX Parser Memory Error" },
  90. { true, "RPAMS", "MTL RX Parser Memory Address Mismatch Error" },
  91. { true, "RPUES", "MTL RX Parser Memory Error" },
  92. { false, "UNKNOWN", "Unknown Error" }, /* 15 */
  93. { false, "UNKNOWN", "Unknown Error" }, /* 16 */
  94. { false, "UNKNOWN", "Unknown Error" }, /* 17 */
  95. { false, "UNKNOWN", "Unknown Error" }, /* 18 */
  96. { false, "UNKNOWN", "Unknown Error" }, /* 19 */
  97. { false, "UNKNOWN", "Unknown Error" }, /* 20 */
  98. { false, "UNKNOWN", "Unknown Error" }, /* 21 */
  99. { false, "UNKNOWN", "Unknown Error" }, /* 22 */
  100. { false, "UNKNOWN", "Unknown Error" }, /* 23 */
  101. { false, "UNKNOWN", "Unknown Error" }, /* 24 */
  102. { false, "UNKNOWN", "Unknown Error" }, /* 25 */
  103. { false, "UNKNOWN", "Unknown Error" }, /* 26 */
  104. { false, "UNKNOWN", "Unknown Error" }, /* 27 */
  105. { false, "UNKNOWN", "Unknown Error" }, /* 28 */
  106. { false, "UNKNOWN", "Unknown Error" }, /* 29 */
  107. { false, "UNKNOWN", "Unknown Error" }, /* 30 */
  108. { false, "UNKNOWN", "Unknown Error" }, /* 31 */
  109. };
  110. static void dwmac5_handle_mtl_err(struct net_device *ndev,
  111. void __iomem *ioaddr, bool correctable,
  112. struct stmmac_safety_stats *stats)
  113. {
  114. u32 value;
  115. value = readl(ioaddr + MTL_ECC_INT_STATUS);
  116. writel(value, ioaddr + MTL_ECC_INT_STATUS);
  117. dwmac5_log_error(ndev, value, correctable, "MTL", dwmac5_mtl_errors,
  118. STAT_OFF(mtl_errors), stats);
  119. }
  120. static const struct dwmac5_error_desc dwmac5_dma_errors[32]= {
  121. { true, "TCES", "DMA TSO Memory Error" },
  122. { true, "TAMS", "DMA TSO Memory Address Mismatch Error" },
  123. { true, "TUES", "DMA TSO Memory Error" },
  124. { false, "UNKNOWN", "Unknown Error" }, /* 3 */
  125. { false, "UNKNOWN", "Unknown Error" }, /* 4 */
  126. { false, "UNKNOWN", "Unknown Error" }, /* 5 */
  127. { false, "UNKNOWN", "Unknown Error" }, /* 6 */
  128. { false, "UNKNOWN", "Unknown Error" }, /* 7 */
  129. { false, "UNKNOWN", "Unknown Error" }, /* 8 */
  130. { false, "UNKNOWN", "Unknown Error" }, /* 9 */
  131. { false, "UNKNOWN", "Unknown Error" }, /* 10 */
  132. { false, "UNKNOWN", "Unknown Error" }, /* 11 */
  133. { false, "UNKNOWN", "Unknown Error" }, /* 12 */
  134. { false, "UNKNOWN", "Unknown Error" }, /* 13 */
  135. { false, "UNKNOWN", "Unknown Error" }, /* 14 */
  136. { false, "UNKNOWN", "Unknown Error" }, /* 15 */
  137. { false, "UNKNOWN", "Unknown Error" }, /* 16 */
  138. { false, "UNKNOWN", "Unknown Error" }, /* 17 */
  139. { false, "UNKNOWN", "Unknown Error" }, /* 18 */
  140. { false, "UNKNOWN", "Unknown Error" }, /* 19 */
  141. { false, "UNKNOWN", "Unknown Error" }, /* 20 */
  142. { false, "UNKNOWN", "Unknown Error" }, /* 21 */
  143. { false, "UNKNOWN", "Unknown Error" }, /* 22 */
  144. { false, "UNKNOWN", "Unknown Error" }, /* 23 */
  145. { false, "UNKNOWN", "Unknown Error" }, /* 24 */
  146. { false, "UNKNOWN", "Unknown Error" }, /* 25 */
  147. { false, "UNKNOWN", "Unknown Error" }, /* 26 */
  148. { false, "UNKNOWN", "Unknown Error" }, /* 27 */
  149. { false, "UNKNOWN", "Unknown Error" }, /* 28 */
  150. { false, "UNKNOWN", "Unknown Error" }, /* 29 */
  151. { false, "UNKNOWN", "Unknown Error" }, /* 30 */
  152. { false, "UNKNOWN", "Unknown Error" }, /* 31 */
  153. };
  154. static void dwmac5_handle_dma_err(struct net_device *ndev,
  155. void __iomem *ioaddr, bool correctable,
  156. struct stmmac_safety_stats *stats)
  157. {
  158. u32 value;
  159. value = readl(ioaddr + DMA_ECC_INT_STATUS);
  160. writel(value, ioaddr + DMA_ECC_INT_STATUS);
  161. dwmac5_log_error(ndev, value, correctable, "DMA", dwmac5_dma_errors,
  162. STAT_OFF(dma_errors), stats);
  163. }
  164. int dwmac5_safety_feat_config(void __iomem *ioaddr, unsigned int asp)
  165. {
  166. u32 value;
  167. if (!asp)
  168. return -EINVAL;
  169. /* 1. Enable Safety Features */
  170. value = readl(ioaddr + MTL_ECC_CONTROL);
  171. value |= TSOEE; /* TSO ECC */
  172. value |= MRXPEE; /* MTL RX Parser ECC */
  173. value |= MESTEE; /* MTL EST ECC */
  174. value |= MRXEE; /* MTL RX FIFO ECC */
  175. value |= MTXEE; /* MTL TX FIFO ECC */
  176. writel(value, ioaddr + MTL_ECC_CONTROL);
  177. /* 2. Enable MTL Safety Interrupts */
  178. value = readl(ioaddr + MTL_ECC_INT_ENABLE);
  179. value |= RPCEIE; /* RX Parser Memory Correctable Error */
  180. value |= ECEIE; /* EST Memory Correctable Error */
  181. value |= RXCEIE; /* RX Memory Correctable Error */
  182. value |= TXCEIE; /* TX Memory Correctable Error */
  183. writel(value, ioaddr + MTL_ECC_INT_ENABLE);
  184. /* 3. Enable DMA Safety Interrupts */
  185. value = readl(ioaddr + DMA_ECC_INT_ENABLE);
  186. value |= TCEIE; /* TSO Memory Correctable Error */
  187. writel(value, ioaddr + DMA_ECC_INT_ENABLE);
  188. /* Only ECC Protection for External Memory feature is selected */
  189. if (asp <= 0x1)
  190. return 0;
  191. /* 5. Enable Parity and Timeout for FSM */
  192. value = readl(ioaddr + MAC_FSM_CONTROL);
  193. value |= PRTYEN; /* FSM Parity Feature */
  194. value |= TMOUTEN; /* FSM Timeout Feature */
  195. writel(value, ioaddr + MAC_FSM_CONTROL);
  196. /* 4. Enable Data Parity Protection */
  197. value = readl(ioaddr + MTL_DPP_CONTROL);
  198. value |= EDPP;
  199. writel(value, ioaddr + MTL_DPP_CONTROL);
  200. /*
  201. * All the Automotive Safety features are selected without the "Parity
  202. * Port Enable for external interface" feature.
  203. */
  204. if (asp <= 0x2)
  205. return 0;
  206. value |= EPSI;
  207. writel(value, ioaddr + MTL_DPP_CONTROL);
  208. return 0;
  209. }
  210. bool dwmac5_safety_feat_irq_status(struct net_device *ndev,
  211. void __iomem *ioaddr, unsigned int asp,
  212. struct stmmac_safety_stats *stats)
  213. {
  214. bool ret = false, err, corr;
  215. u32 mtl, dma;
  216. if (!asp)
  217. return false;
  218. mtl = readl(ioaddr + MTL_SAFETY_INT_STATUS);
  219. dma = readl(ioaddr + DMA_SAFETY_INT_STATUS);
  220. err = (mtl & MCSIS) || (dma & MCSIS);
  221. corr = false;
  222. if (err) {
  223. dwmac5_handle_mac_err(ndev, ioaddr, corr, stats);
  224. ret |= !corr;
  225. }
  226. err = (mtl & (MEUIS | MECIS)) || (dma & (MSUIS | MSCIS));
  227. corr = (mtl & MECIS) || (dma & MSCIS);
  228. if (err) {
  229. dwmac5_handle_mtl_err(ndev, ioaddr, corr, stats);
  230. ret |= !corr;
  231. }
  232. err = dma & (DEUIS | DECIS);
  233. corr = dma & DECIS;
  234. if (err) {
  235. dwmac5_handle_dma_err(ndev, ioaddr, corr, stats);
  236. ret |= !corr;
  237. }
  238. return ret;
  239. }
  240. static const struct dwmac5_error {
  241. const struct dwmac5_error_desc *desc;
  242. } dwmac5_all_errors[] = {
  243. { dwmac5_mac_errors },
  244. { dwmac5_mtl_errors },
  245. { dwmac5_dma_errors },
  246. };
  247. const char *dwmac5_safety_feat_dump(struct stmmac_safety_stats *stats,
  248. int index, unsigned long *count)
  249. {
  250. int module = index / 32, offset = index % 32;
  251. unsigned long *ptr = (unsigned long *)stats;
  252. if (module >= ARRAY_SIZE(dwmac5_all_errors))
  253. return NULL;
  254. if (!dwmac5_all_errors[module].desc[offset].valid)
  255. return NULL;
  256. if (count)
  257. *count = *(ptr + index);
  258. return dwmac5_all_errors[module].desc[offset].desc;
  259. }