pl080.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Samsung's S3C64XX generic DMA support using amba-pl08x driver.
  4. //
  5. // Copyright (c) 2013 Tomasz Figa <[email protected]>
  6. #include <linux/kernel.h>
  7. #include <linux/amba/bus.h>
  8. #include <linux/amba/pl080.h>
  9. #include <linux/amba/pl08x.h>
  10. #include <linux/of.h>
  11. #include "cpu.h"
  12. #include "irqs.h"
  13. #include "map.h"
  14. #include "regs-sys-s3c64xx.h"
  15. static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
  16. {
  17. return cd->min_signal;
  18. }
  19. static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
  20. {
  21. }
  22. /*
  23. * DMA0
  24. */
  25. static struct pl08x_channel_data s3c64xx_dma0_info[] = {
  26. {
  27. .bus_id = "uart0_tx",
  28. .min_signal = 0,
  29. .max_signal = 0,
  30. .periph_buses = PL08X_AHB2,
  31. }, {
  32. .bus_id = "uart0_rx",
  33. .min_signal = 1,
  34. .max_signal = 1,
  35. .periph_buses = PL08X_AHB2,
  36. }, {
  37. .bus_id = "uart1_tx",
  38. .min_signal = 2,
  39. .max_signal = 2,
  40. .periph_buses = PL08X_AHB2,
  41. }, {
  42. .bus_id = "uart1_rx",
  43. .min_signal = 3,
  44. .max_signal = 3,
  45. .periph_buses = PL08X_AHB2,
  46. }, {
  47. .bus_id = "uart2_tx",
  48. .min_signal = 4,
  49. .max_signal = 4,
  50. .periph_buses = PL08X_AHB2,
  51. }, {
  52. .bus_id = "uart2_rx",
  53. .min_signal = 5,
  54. .max_signal = 5,
  55. .periph_buses = PL08X_AHB2,
  56. }, {
  57. .bus_id = "uart3_tx",
  58. .min_signal = 6,
  59. .max_signal = 6,
  60. .periph_buses = PL08X_AHB2,
  61. }, {
  62. .bus_id = "uart3_rx",
  63. .min_signal = 7,
  64. .max_signal = 7,
  65. .periph_buses = PL08X_AHB2,
  66. }, {
  67. .bus_id = "pcm0_tx",
  68. .min_signal = 8,
  69. .max_signal = 8,
  70. .periph_buses = PL08X_AHB2,
  71. }, {
  72. .bus_id = "pcm0_rx",
  73. .min_signal = 9,
  74. .max_signal = 9,
  75. .periph_buses = PL08X_AHB2,
  76. }, {
  77. .bus_id = "i2s0_tx",
  78. .min_signal = 10,
  79. .max_signal = 10,
  80. .periph_buses = PL08X_AHB2,
  81. }, {
  82. .bus_id = "i2s0_rx",
  83. .min_signal = 11,
  84. .max_signal = 11,
  85. .periph_buses = PL08X_AHB2,
  86. }, {
  87. .bus_id = "spi0_tx",
  88. .min_signal = 12,
  89. .max_signal = 12,
  90. .periph_buses = PL08X_AHB2,
  91. }, {
  92. .bus_id = "spi0_rx",
  93. .min_signal = 13,
  94. .max_signal = 13,
  95. .periph_buses = PL08X_AHB2,
  96. }, {
  97. .bus_id = "i2s2_tx",
  98. .min_signal = 14,
  99. .max_signal = 14,
  100. .periph_buses = PL08X_AHB2,
  101. }, {
  102. .bus_id = "i2s2_rx",
  103. .min_signal = 15,
  104. .max_signal = 15,
  105. .periph_buses = PL08X_AHB2,
  106. }
  107. };
  108. static const struct dma_slave_map s3c64xx_dma0_slave_map[] = {
  109. { "s3c6400-uart.0", "tx", &s3c64xx_dma0_info[0] },
  110. { "s3c6400-uart.0", "rx", &s3c64xx_dma0_info[1] },
  111. { "s3c6400-uart.1", "tx", &s3c64xx_dma0_info[2] },
  112. { "s3c6400-uart.1", "rx", &s3c64xx_dma0_info[3] },
  113. { "s3c6400-uart.2", "tx", &s3c64xx_dma0_info[4] },
  114. { "s3c6400-uart.2", "rx", &s3c64xx_dma0_info[5] },
  115. { "s3c6400-uart.3", "tx", &s3c64xx_dma0_info[6] },
  116. { "s3c6400-uart.3", "rx", &s3c64xx_dma0_info[7] },
  117. { "samsung-pcm.0", "tx", &s3c64xx_dma0_info[8] },
  118. { "samsung-pcm.0", "rx", &s3c64xx_dma0_info[9] },
  119. { "samsung-i2s.0", "tx", &s3c64xx_dma0_info[10] },
  120. { "samsung-i2s.0", "rx", &s3c64xx_dma0_info[11] },
  121. { "s3c6410-spi.0", "tx", &s3c64xx_dma0_info[12] },
  122. { "s3c6410-spi.0", "rx", &s3c64xx_dma0_info[13] },
  123. { "samsung-i2s.2", "tx", &s3c64xx_dma0_info[14] },
  124. { "samsung-i2s.2", "rx", &s3c64xx_dma0_info[15] },
  125. };
  126. struct pl08x_platform_data s3c64xx_dma0_plat_data = {
  127. .memcpy_burst_size = PL08X_BURST_SZ_4,
  128. .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
  129. .memcpy_prot_buff = true,
  130. .memcpy_prot_cache = true,
  131. .lli_buses = PL08X_AHB1,
  132. .mem_buses = PL08X_AHB1,
  133. .get_xfer_signal = pl08x_get_xfer_signal,
  134. .put_xfer_signal = pl08x_put_xfer_signal,
  135. .slave_channels = s3c64xx_dma0_info,
  136. .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
  137. .slave_map = s3c64xx_dma0_slave_map,
  138. .slave_map_len = ARRAY_SIZE(s3c64xx_dma0_slave_map),
  139. };
  140. static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
  141. 0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
  142. /*
  143. * DMA1
  144. */
  145. static struct pl08x_channel_data s3c64xx_dma1_info[] = {
  146. {
  147. .bus_id = "pcm1_tx",
  148. .min_signal = 0,
  149. .max_signal = 0,
  150. .periph_buses = PL08X_AHB2,
  151. }, {
  152. .bus_id = "pcm1_rx",
  153. .min_signal = 1,
  154. .max_signal = 1,
  155. .periph_buses = PL08X_AHB2,
  156. }, {
  157. .bus_id = "i2s1_tx",
  158. .min_signal = 2,
  159. .max_signal = 2,
  160. .periph_buses = PL08X_AHB2,
  161. }, {
  162. .bus_id = "i2s1_rx",
  163. .min_signal = 3,
  164. .max_signal = 3,
  165. .periph_buses = PL08X_AHB2,
  166. }, {
  167. .bus_id = "spi1_tx",
  168. .min_signal = 4,
  169. .max_signal = 4,
  170. .periph_buses = PL08X_AHB2,
  171. }, {
  172. .bus_id = "spi1_rx",
  173. .min_signal = 5,
  174. .max_signal = 5,
  175. .periph_buses = PL08X_AHB2,
  176. }, {
  177. .bus_id = "ac97_out",
  178. .min_signal = 6,
  179. .max_signal = 6,
  180. .periph_buses = PL08X_AHB2,
  181. }, {
  182. .bus_id = "ac97_in",
  183. .min_signal = 7,
  184. .max_signal = 7,
  185. .periph_buses = PL08X_AHB2,
  186. }, {
  187. .bus_id = "ac97_mic",
  188. .min_signal = 8,
  189. .max_signal = 8,
  190. .periph_buses = PL08X_AHB2,
  191. }, {
  192. .bus_id = "pwm",
  193. .min_signal = 9,
  194. .max_signal = 9,
  195. .periph_buses = PL08X_AHB2,
  196. }, {
  197. .bus_id = "irda",
  198. .min_signal = 10,
  199. .max_signal = 10,
  200. .periph_buses = PL08X_AHB2,
  201. }, {
  202. .bus_id = "external",
  203. .min_signal = 11,
  204. .max_signal = 11,
  205. .periph_buses = PL08X_AHB2,
  206. },
  207. };
  208. static const struct dma_slave_map s3c64xx_dma1_slave_map[] = {
  209. { "samsung-pcm.1", "tx", &s3c64xx_dma1_info[0] },
  210. { "samsung-pcm.1", "rx", &s3c64xx_dma1_info[1] },
  211. { "samsung-i2s.1", "tx", &s3c64xx_dma1_info[2] },
  212. { "samsung-i2s.1", "rx", &s3c64xx_dma1_info[3] },
  213. { "s3c6410-spi.1", "tx", &s3c64xx_dma1_info[4] },
  214. { "s3c6410-spi.1", "rx", &s3c64xx_dma1_info[5] },
  215. };
  216. struct pl08x_platform_data s3c64xx_dma1_plat_data = {
  217. .memcpy_burst_size = PL08X_BURST_SZ_4,
  218. .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
  219. .memcpy_prot_buff = true,
  220. .memcpy_prot_cache = true,
  221. .lli_buses = PL08X_AHB1,
  222. .mem_buses = PL08X_AHB1,
  223. .get_xfer_signal = pl08x_get_xfer_signal,
  224. .put_xfer_signal = pl08x_put_xfer_signal,
  225. .slave_channels = s3c64xx_dma1_info,
  226. .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
  227. .slave_map = s3c64xx_dma1_slave_map,
  228. .slave_map_len = ARRAY_SIZE(s3c64xx_dma1_slave_map),
  229. };
  230. static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
  231. 0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
  232. static int __init s3c64xx_pl080_init(void)
  233. {
  234. if (!soc_is_s3c64xx())
  235. return 0;
  236. /* Set all DMA configuration to be DMA, not SDMA */
  237. writel(0xffffff, S3C64XX_SDMA_SEL);
  238. if (of_have_populated_dt())
  239. return 0;
  240. amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
  241. amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
  242. return 0;
  243. }
  244. arch_initcall(s3c64xx_pl080_init);