k3-udma-u-boot.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com
  4. */
  5. #define UDMA_RCHAN_RFLOW_RNG_FLOWID_CNT_SHIFT (16)
  6. /* How SRC/DST tag should be updated by UDMA in the descriptor's Word 3 */
  7. #define UDMA_RFLOW_SRCTAG_NONE 0
  8. #define UDMA_RFLOW_SRCTAG_CFG_TAG 1
  9. #define UDMA_RFLOW_SRCTAG_FLOW_ID 2
  10. #define UDMA_RFLOW_SRCTAG_SRC_TAG 4
  11. #define UDMA_RFLOW_DSTTAG_NONE 0
  12. #define UDMA_RFLOW_DSTTAG_CFG_TAG 1
  13. #define UDMA_RFLOW_DSTTAG_FLOW_ID 2
  14. #define UDMA_RFLOW_DSTTAG_DST_TAG_LO 4
  15. #define UDMA_RFLOW_DSTTAG_DST_TAG_HI 5
  16. #define UDMA_RFLOW_RFC_DEFAULT \
  17. ((UDMA_RFLOW_SRCTAG_NONE << UDMA_RFLOW_RFC_SRC_TAG_HI_SEL_SHIFT) | \
  18. (UDMA_RFLOW_SRCTAG_SRC_TAG << UDMA_RFLOW_RFC_SRC_TAG_LO_SEL_SHIFT) | \
  19. (UDMA_RFLOW_DSTTAG_DST_TAG_HI << UDMA_RFLOW_RFC_DST_TAG_HI_SEL_SHIFT) | \
  20. (UDMA_RFLOW_DSTTAG_DST_TAG_LO << UDMA_RFLOW_RFC_DST_TAG_LO_SE_SHIFT))
  21. #define UDMA_RFLOW_RFx_REG_FDQ_SIZE_SHIFT (16)
  22. /* TCHAN */
  23. static inline u32 udma_tchan_read(struct udma_tchan *tchan, int reg)
  24. {
  25. if (!tchan)
  26. return 0;
  27. return udma_read(tchan->reg_chan, reg);
  28. }
  29. static inline void udma_tchan_write(struct udma_tchan *tchan, int reg, u32 val)
  30. {
  31. if (!tchan)
  32. return;
  33. udma_write(tchan->reg_chan, reg, val);
  34. }
  35. static inline void udma_tchan_update_bits(struct udma_tchan *tchan, int reg,
  36. u32 mask, u32 val)
  37. {
  38. if (!tchan)
  39. return;
  40. udma_update_bits(tchan->reg_chan, reg, mask, val);
  41. }
  42. /* RCHAN */
  43. static inline u32 udma_rchan_read(struct udma_rchan *rchan, int reg)
  44. {
  45. if (!rchan)
  46. return 0;
  47. return udma_read(rchan->reg_chan, reg);
  48. }
  49. static inline void udma_rchan_write(struct udma_rchan *rchan, int reg, u32 val)
  50. {
  51. if (!rchan)
  52. return;
  53. udma_write(rchan->reg_chan, reg, val);
  54. }
  55. static inline void udma_rchan_update_bits(struct udma_rchan *rchan, int reg,
  56. u32 mask, u32 val)
  57. {
  58. if (!rchan)
  59. return;
  60. udma_update_bits(rchan->reg_chan, reg, mask, val);
  61. }
  62. /* RFLOW */
  63. static inline u32 udma_rflow_read(struct udma_rflow *rflow, int reg)
  64. {
  65. if (!rflow)
  66. return 0;
  67. return udma_read(rflow->reg_rflow, reg);
  68. }
  69. static inline void udma_rflow_write(struct udma_rflow *rflow, int reg, u32 val)
  70. {
  71. if (!rflow)
  72. return;
  73. udma_write(rflow->reg_rflow, reg, val);
  74. }
  75. static inline void udma_rflow_update_bits(struct udma_rflow *rflow, int reg,
  76. u32 mask, u32 val)
  77. {
  78. if (!rflow)
  79. return;
  80. udma_update_bits(rflow->reg_rflow, reg, mask, val);
  81. }
  82. static void udma_alloc_tchan_raw(struct udma_chan *uc)
  83. {
  84. u32 mode, fetch_size;
  85. if (uc->config.pkt_mode)
  86. mode = UDMA_CHAN_CFG_CHAN_TYPE_PACKET_PBRR;
  87. else
  88. mode = UDMA_CHAN_CFG_CHAN_TYPE_3RDP_BC_PBRR;
  89. udma_tchan_update_bits(uc->tchan, UDMA_TCHAN_TCFG_REG,
  90. UDMA_CHAN_CFG_CHAN_TYPE_MASK, mode);
  91. if (uc->config.dir == DMA_MEM_TO_MEM)
  92. fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2;
  93. else
  94. fetch_size = cppi5_hdesc_calc_size(uc->config.needs_epib,
  95. uc->config.psd_size, 0) >> 2;
  96. udma_tchan_update_bits(uc->tchan, UDMA_TCHAN_TCFG_REG,
  97. UDMA_CHAN_CFG_FETCH_SIZE_MASK, fetch_size);
  98. udma_tchan_write(uc->tchan, UDMA_TCHAN_TCQ_REG,
  99. k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring));
  100. }
  101. static void udma_alloc_rchan_raw(struct udma_chan *uc)
  102. {
  103. struct udma_dev *ud = uc->ud;
  104. int fd_ring = k3_nav_ringacc_get_ring_id(uc->rflow->fd_ring);
  105. int rx_ring = k3_nav_ringacc_get_ring_id(uc->rflow->r_ring);
  106. int tc_ring = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring);
  107. u32 rx_einfo_present = 0, rx_psinfo_present = 0;
  108. u32 mode, fetch_size, rxcq_num;
  109. if (uc->config.pkt_mode)
  110. mode = UDMA_CHAN_CFG_CHAN_TYPE_PACKET_PBRR;
  111. else
  112. mode = UDMA_CHAN_CFG_CHAN_TYPE_3RDP_BC_PBRR;
  113. udma_rchan_update_bits(uc->rchan, UDMA_RCHAN_RCFG_REG,
  114. UDMA_CHAN_CFG_CHAN_TYPE_MASK, mode);
  115. if (uc->config.dir == DMA_MEM_TO_MEM) {
  116. fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2;
  117. rxcq_num = tc_ring;
  118. } else {
  119. fetch_size = cppi5_hdesc_calc_size(uc->config.needs_epib,
  120. uc->config.psd_size, 0) >> 2;
  121. rxcq_num = rx_ring;
  122. }
  123. udma_rchan_update_bits(uc->rchan, UDMA_RCHAN_RCFG_REG,
  124. UDMA_CHAN_CFG_FETCH_SIZE_MASK, fetch_size);
  125. udma_rchan_write(uc->rchan, UDMA_RCHAN_RCQ_REG, rxcq_num);
  126. if (uc->config.dir == DMA_MEM_TO_MEM)
  127. return;
  128. if (ud->match_data->type == DMA_TYPE_UDMA &&
  129. uc->rflow->id != uc->rchan->id &&
  130. uc->config.dir != DMA_MEM_TO_MEM)
  131. udma_rchan_write(uc->rchan, UDMA_RCHAN_RFLOW_RNG_REG, uc->rflow->id |
  132. 1 << UDMA_RCHAN_RFLOW_RNG_FLOWID_CNT_SHIFT);
  133. if (uc->config.needs_epib)
  134. rx_einfo_present = UDMA_RFLOW_RFA_EINFO;
  135. if (uc->config.psd_size)
  136. rx_psinfo_present = UDMA_RFLOW_RFA_PSINFO;
  137. udma_rflow_write(uc->rflow, UDMA_RFLOW_REG(A),
  138. rx_einfo_present | rx_psinfo_present | rxcq_num);
  139. udma_rflow_write(uc->rflow, UDMA_RFLOW_REG(C), UDMA_RFLOW_RFC_DEFAULT);
  140. udma_rflow_write(uc->rflow, UDMA_RFLOW_REG(D),
  141. fd_ring | fd_ring << UDMA_RFLOW_RFx_REG_FDQ_SIZE_SHIFT);
  142. udma_rflow_write(uc->rflow, UDMA_RFLOW_REG(E),
  143. fd_ring | fd_ring << UDMA_RFLOW_RFx_REG_FDQ_SIZE_SHIFT);
  144. udma_rflow_write(uc->rflow, UDMA_RFLOW_REG(G), fd_ring);
  145. udma_rflow_write(uc->rflow, UDMA_RFLOW_REG(H),
  146. fd_ring | fd_ring << UDMA_RFLOW_RFx_REG_FDQ_SIZE_SHIFT);
  147. }