133-dmaengine-at_xdmac-add-support-for-sama7g5-based-at_.patch 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. From 613af756b93fe005d9db11ea26fd0318f239d5a2 Mon Sep 17 00:00:00 2001
  2. From: Eugen Hristev <[email protected]>
  3. Date: Fri, 16 Oct 2020 12:38:50 +0300
  4. Subject: [PATCH 133/247] dmaengine: at_xdmac: add support for sama7g5 based
  5. at_xdmac
  6. SAMA7G5 SoC uses a slightly different variant of the AT_XDMAC.
  7. Added support by a new compatible and a layout struct that copes
  8. to the specific version considering the compatible string.
  9. Only the differences in register map are present in the layout struct.
  10. I reworked the register access for this part that has the differences.
  11. Also the Source/Destination Interface bits are no longer valid for this
  12. variant of the XDMAC. Thus, the layout also has a bool for specifying
  13. whether these bits are required or not.
  14. Signed-off-by: Eugen Hristev <[email protected]>
  15. Link: https://lore.kernel.org/r/[email protected]
  16. Signed-off-by: Vinod Koul <[email protected]>
  17. ---
  18. drivers/dma/at_xdmac.c | 110 +++++++++++++++++++++++++++++++----------
  19. 1 file changed, 84 insertions(+), 26 deletions(-)
  20. --- a/drivers/dma/at_xdmac.c
  21. +++ b/drivers/dma/at_xdmac.c
  22. @@ -38,13 +38,6 @@
  23. #define AT_XDMAC_GE 0x1C /* Global Channel Enable Register */
  24. #define AT_XDMAC_GD 0x20 /* Global Channel Disable Register */
  25. #define AT_XDMAC_GS 0x24 /* Global Channel Status Register */
  26. -#define AT_XDMAC_GRS 0x28 /* Global Channel Read Suspend Register */
  27. -#define AT_XDMAC_GWS 0x2C /* Global Write Suspend Register */
  28. -#define AT_XDMAC_GRWS 0x30 /* Global Channel Read Write Suspend Register */
  29. -#define AT_XDMAC_GRWR 0x34 /* Global Channel Read Write Resume Register */
  30. -#define AT_XDMAC_GSWR 0x38 /* Global Channel Software Request Register */
  31. -#define AT_XDMAC_GSWS 0x3C /* Global channel Software Request Status Register */
  32. -#define AT_XDMAC_GSWF 0x40 /* Global Channel Software Flush Request Register */
  33. #define AT_XDMAC_VERSION 0xFFC /* XDMAC Version Register */
  34. /* Channel relative registers offsets */
  35. @@ -151,8 +144,6 @@
  36. #define AT_XDMAC_CSUS 0x30 /* Channel Source Microblock Stride */
  37. #define AT_XDMAC_CDUS 0x34 /* Channel Destination Microblock Stride */
  38. -#define AT_XDMAC_CHAN_REG_BASE 0x50 /* Channel registers base address */
  39. -
  40. /* Microblock control members */
  41. #define AT_XDMAC_MBR_UBC_UBLEN_MAX 0xFFFFFFUL /* Maximum Microblock Length */
  42. #define AT_XDMAC_MBR_UBC_NDE (0x1 << 24) /* Next Descriptor Enable */
  43. @@ -180,6 +171,27 @@ enum atc_status {
  44. AT_XDMAC_CHAN_IS_PAUSED,
  45. };
  46. +struct at_xdmac_layout {
  47. + /* Global Channel Read Suspend Register */
  48. + u8 grs;
  49. + /* Global Write Suspend Register */
  50. + u8 gws;
  51. + /* Global Channel Read Write Suspend Register */
  52. + u8 grws;
  53. + /* Global Channel Read Write Resume Register */
  54. + u8 grwr;
  55. + /* Global Channel Software Request Register */
  56. + u8 gswr;
  57. + /* Global channel Software Request Status Register */
  58. + u8 gsws;
  59. + /* Global Channel Software Flush Request Register */
  60. + u8 gswf;
  61. + /* Channel reg base */
  62. + u8 chan_cc_reg_base;
  63. + /* Source/Destination Interface must be specified or not */
  64. + bool sdif;
  65. +};
  66. +
  67. /* ----- Channels ----- */
  68. struct at_xdmac_chan {
  69. struct dma_chan chan;
  70. @@ -213,6 +225,7 @@ struct at_xdmac {
  71. struct clk *clk;
  72. u32 save_gim;
  73. struct dma_pool *at_xdmac_desc_pool;
  74. + const struct at_xdmac_layout *layout;
  75. struct at_xdmac_chan chan[];
  76. };
  77. @@ -245,9 +258,33 @@ struct at_xdmac_desc {
  78. struct list_head xfer_node;
  79. } __aligned(sizeof(u64));
  80. +static const struct at_xdmac_layout at_xdmac_sama5d4_layout = {
  81. + .grs = 0x28,
  82. + .gws = 0x2C,
  83. + .grws = 0x30,
  84. + .grwr = 0x34,
  85. + .gswr = 0x38,
  86. + .gsws = 0x3C,
  87. + .gswf = 0x40,
  88. + .chan_cc_reg_base = 0x50,
  89. + .sdif = true,
  90. +};
  91. +
  92. +static const struct at_xdmac_layout at_xdmac_sama7g5_layout = {
  93. + .grs = 0x30,
  94. + .gws = 0x38,
  95. + .grws = 0x40,
  96. + .grwr = 0x44,
  97. + .gswr = 0x48,
  98. + .gsws = 0x4C,
  99. + .gswf = 0x50,
  100. + .chan_cc_reg_base = 0x60,
  101. + .sdif = false,
  102. +};
  103. +
  104. static inline void __iomem *at_xdmac_chan_reg_base(struct at_xdmac *atxdmac, unsigned int chan_nb)
  105. {
  106. - return atxdmac->regs + (AT_XDMAC_CHAN_REG_BASE + chan_nb * 0x40);
  107. + return atxdmac->regs + (atxdmac->layout->chan_cc_reg_base + chan_nb * 0x40);
  108. }
  109. #define at_xdmac_read(atxdmac, reg) readl_relaxed((atxdmac)->regs + (reg))
  110. @@ -343,8 +380,10 @@ static void at_xdmac_start_xfer(struct a
  111. first->active_xfer = true;
  112. /* Tell xdmac where to get the first descriptor. */
  113. - reg = AT_XDMAC_CNDA_NDA(first->tx_dma_desc.phys)
  114. - | AT_XDMAC_CNDA_NDAIF(atchan->memif);
  115. + reg = AT_XDMAC_CNDA_NDA(first->tx_dma_desc.phys);
  116. + if (atxdmac->layout->sdif)
  117. + reg |= AT_XDMAC_CNDA_NDAIF(atchan->memif);
  118. +
  119. at_xdmac_chan_write(atchan, AT_XDMAC_CNDA, reg);
  120. /*
  121. @@ -539,6 +578,7 @@ static int at_xdmac_compute_chan_conf(st
  122. enum dma_transfer_direction direction)
  123. {
  124. struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
  125. + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device);
  126. int csize, dwidth;
  127. if (direction == DMA_DEV_TO_MEM) {
  128. @@ -546,12 +586,14 @@ static int at_xdmac_compute_chan_conf(st
  129. AT91_XDMAC_DT_PERID(atchan->perid)
  130. | AT_XDMAC_CC_DAM_INCREMENTED_AM
  131. | AT_XDMAC_CC_SAM_FIXED_AM
  132. - | AT_XDMAC_CC_DIF(atchan->memif)
  133. - | AT_XDMAC_CC_SIF(atchan->perif)
  134. | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
  135. | AT_XDMAC_CC_DSYNC_PER2MEM
  136. | AT_XDMAC_CC_MBSIZE_SIXTEEN
  137. | AT_XDMAC_CC_TYPE_PER_TRAN;
  138. + if (atxdmac->layout->sdif)
  139. + atchan->cfg |= AT_XDMAC_CC_DIF(atchan->memif) |
  140. + AT_XDMAC_CC_SIF(atchan->perif);
  141. +
  142. csize = ffs(atchan->sconfig.src_maxburst) - 1;
  143. if (csize < 0) {
  144. dev_err(chan2dev(chan), "invalid src maxburst value\n");
  145. @@ -569,12 +611,14 @@ static int at_xdmac_compute_chan_conf(st
  146. AT91_XDMAC_DT_PERID(atchan->perid)
  147. | AT_XDMAC_CC_DAM_FIXED_AM
  148. | AT_XDMAC_CC_SAM_INCREMENTED_AM
  149. - | AT_XDMAC_CC_DIF(atchan->perif)
  150. - | AT_XDMAC_CC_SIF(atchan->memif)
  151. | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
  152. | AT_XDMAC_CC_DSYNC_MEM2PER
  153. | AT_XDMAC_CC_MBSIZE_SIXTEEN
  154. | AT_XDMAC_CC_TYPE_PER_TRAN;
  155. + if (atxdmac->layout->sdif)
  156. + atchan->cfg |= AT_XDMAC_CC_DIF(atchan->perif) |
  157. + AT_XDMAC_CC_SIF(atchan->memif);
  158. +
  159. csize = ffs(atchan->sconfig.dst_maxburst) - 1;
  160. if (csize < 0) {
  161. dev_err(chan2dev(chan), "invalid src maxburst value\n");
  162. @@ -864,10 +908,12 @@ at_xdmac_interleaved_queue_desc(struct d
  163. * ERRATA: Even if useless for memory transfers, the PERID has to not
  164. * match the one of another channel. If not, it could lead to spurious
  165. * flag status.
  166. + * For SAMA7G5x case, the SIF and DIF fields are no longer used.
  167. + * Thus, no need to have the SIF/DIF interfaces here.
  168. + * For SAMA5D4x and SAMA5D2x the SIF and DIF are already configured as
  169. + * zero.
  170. */
  171. u32 chan_cc = AT_XDMAC_CC_PERID(0x7f)
  172. - | AT_XDMAC_CC_DIF(0)
  173. - | AT_XDMAC_CC_SIF(0)
  174. | AT_XDMAC_CC_MBSIZE_SIXTEEN
  175. | AT_XDMAC_CC_TYPE_MEM_TRAN;
  176. @@ -1046,12 +1092,14 @@ at_xdmac_prep_dma_memcpy(struct dma_chan
  177. * ERRATA: Even if useless for memory transfers, the PERID has to not
  178. * match the one of another channel. If not, it could lead to spurious
  179. * flag status.
  180. + * For SAMA7G5x case, the SIF and DIF fields are no longer used.
  181. + * Thus, no need to have the SIF/DIF interfaces here.
  182. + * For SAMA5D4x and SAMA5D2x the SIF and DIF are already configured as
  183. + * zero.
  184. */
  185. u32 chan_cc = AT_XDMAC_CC_PERID(0x7f)
  186. | AT_XDMAC_CC_DAM_INCREMENTED_AM
  187. | AT_XDMAC_CC_SAM_INCREMENTED_AM
  188. - | AT_XDMAC_CC_DIF(0)
  189. - | AT_XDMAC_CC_SIF(0)
  190. | AT_XDMAC_CC_MBSIZE_SIXTEEN
  191. | AT_XDMAC_CC_TYPE_MEM_TRAN;
  192. unsigned long irqflags;
  193. @@ -1152,12 +1200,14 @@ static struct at_xdmac_desc *at_xdmac_me
  194. * ERRATA: Even if useless for memory transfers, the PERID has to not
  195. * match the one of another channel. If not, it could lead to spurious
  196. * flag status.
  197. + * For SAMA7G5x case, the SIF and DIF fields are no longer used.
  198. + * Thus, no need to have the SIF/DIF interfaces here.
  199. + * For SAMA5D4x and SAMA5D2x the SIF and DIF are already configured as
  200. + * zero.
  201. */
  202. u32 chan_cc = AT_XDMAC_CC_PERID(0x7f)
  203. | AT_XDMAC_CC_DAM_UBS_AM
  204. | AT_XDMAC_CC_SAM_INCREMENTED_AM
  205. - | AT_XDMAC_CC_DIF(0)
  206. - | AT_XDMAC_CC_SIF(0)
  207. | AT_XDMAC_CC_MBSIZE_SIXTEEN
  208. | AT_XDMAC_CC_MEMSET_HW_MODE
  209. | AT_XDMAC_CC_TYPE_MEM_TRAN;
  210. @@ -1436,7 +1486,7 @@ at_xdmac_tx_status(struct dma_chan *chan
  211. mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC;
  212. value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM;
  213. if ((desc->lld.mbr_cfg & mask) == value) {
  214. - at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask);
  215. + at_xdmac_write(atxdmac, atxdmac->layout->gswf, atchan->mask);
  216. while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS))
  217. cpu_relax();
  218. }
  219. @@ -1494,7 +1544,7 @@ at_xdmac_tx_status(struct dma_chan *chan
  220. * FIFO flush ensures that data are really written.
  221. */
  222. if ((desc->lld.mbr_cfg & mask) == value) {
  223. - at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask);
  224. + at_xdmac_write(atxdmac, atxdmac->layout->gswf, atchan->mask);
  225. while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS))
  226. cpu_relax();
  227. }
  228. @@ -1762,7 +1812,7 @@ static int at_xdmac_device_pause(struct
  229. return 0;
  230. spin_lock_irqsave(&atchan->lock, flags);
  231. - at_xdmac_write(atxdmac, AT_XDMAC_GRWS, atchan->mask);
  232. + at_xdmac_write(atxdmac, atxdmac->layout->grws, atchan->mask);
  233. while (at_xdmac_chan_read(atchan, AT_XDMAC_CC)
  234. & (AT_XDMAC_CC_WRIP | AT_XDMAC_CC_RDIP))
  235. cpu_relax();
  236. @@ -1785,7 +1835,7 @@ static int at_xdmac_device_resume(struct
  237. return 0;
  238. }
  239. - at_xdmac_write(atxdmac, AT_XDMAC_GRWR, atchan->mask);
  240. + at_xdmac_write(atxdmac, atxdmac->layout->grwr, atchan->mask);
  241. clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status);
  242. spin_unlock_irqrestore(&atchan->lock, flags);
  243. @@ -1992,6 +2042,10 @@ static int at_xdmac_probe(struct platfor
  244. atxdmac->regs = base;
  245. atxdmac->irq = irq;
  246. + atxdmac->layout = of_device_get_match_data(&pdev->dev);
  247. + if (!atxdmac->layout)
  248. + return -ENODEV;
  249. +
  250. atxdmac->clk = devm_clk_get(&pdev->dev, "dma_clk");
  251. if (IS_ERR(atxdmac->clk)) {
  252. dev_err(&pdev->dev, "can't get dma_clk\n");
  253. @@ -2134,6 +2188,10 @@ static const struct dev_pm_ops atmel_xdm
  254. static const struct of_device_id atmel_xdmac_dt_ids[] = {
  255. {
  256. .compatible = "atmel,sama5d4-dma",
  257. + .data = &at_xdmac_sama5d4_layout,
  258. + }, {
  259. + .compatible = "microchip,sama7g5-dma",
  260. + .data = &at_xdmac_sama7g5_layout,
  261. }, {
  262. /* sentinel */
  263. }