pl080.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * Samsung's S3C64XX generic DMA support using amba-pl08x driver.
  3. *
  4. * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/amba/bus.h>
  12. #include <linux/amba/pl080.h>
  13. #include <linux/amba/pl08x.h>
  14. #include <linux/of.h>
  15. #include <mach/irqs.h>
  16. #include <mach/map.h>
  17. #include "regs-sys.h"
  18. static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
  19. {
  20. return cd->min_signal;
  21. }
  22. static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
  23. {
  24. }
  25. /*
  26. * DMA0
  27. */
  28. static struct pl08x_channel_data s3c64xx_dma0_info[] = {
  29. {
  30. .bus_id = "uart0_tx",
  31. .min_signal = 0,
  32. .max_signal = 0,
  33. .periph_buses = PL08X_AHB2,
  34. }, {
  35. .bus_id = "uart0_rx",
  36. .min_signal = 1,
  37. .max_signal = 1,
  38. .periph_buses = PL08X_AHB2,
  39. }, {
  40. .bus_id = "uart1_tx",
  41. .min_signal = 2,
  42. .max_signal = 2,
  43. .periph_buses = PL08X_AHB2,
  44. }, {
  45. .bus_id = "uart1_rx",
  46. .min_signal = 3,
  47. .max_signal = 3,
  48. .periph_buses = PL08X_AHB2,
  49. }, {
  50. .bus_id = "uart2_tx",
  51. .min_signal = 4,
  52. .max_signal = 4,
  53. .periph_buses = PL08X_AHB2,
  54. }, {
  55. .bus_id = "uart2_rx",
  56. .min_signal = 5,
  57. .max_signal = 5,
  58. .periph_buses = PL08X_AHB2,
  59. }, {
  60. .bus_id = "uart3_tx",
  61. .min_signal = 6,
  62. .max_signal = 6,
  63. .periph_buses = PL08X_AHB2,
  64. }, {
  65. .bus_id = "uart3_rx",
  66. .min_signal = 7,
  67. .max_signal = 7,
  68. .periph_buses = PL08X_AHB2,
  69. }, {
  70. .bus_id = "pcm0_tx",
  71. .min_signal = 8,
  72. .max_signal = 8,
  73. .periph_buses = PL08X_AHB2,
  74. }, {
  75. .bus_id = "pcm0_rx",
  76. .min_signal = 9,
  77. .max_signal = 9,
  78. .periph_buses = PL08X_AHB2,
  79. }, {
  80. .bus_id = "i2s0_tx",
  81. .min_signal = 10,
  82. .max_signal = 10,
  83. .periph_buses = PL08X_AHB2,
  84. }, {
  85. .bus_id = "i2s0_rx",
  86. .min_signal = 11,
  87. .max_signal = 11,
  88. .periph_buses = PL08X_AHB2,
  89. }, {
  90. .bus_id = "spi0_tx",
  91. .min_signal = 12,
  92. .max_signal = 12,
  93. .periph_buses = PL08X_AHB2,
  94. }, {
  95. .bus_id = "spi0_rx",
  96. .min_signal = 13,
  97. .max_signal = 13,
  98. .periph_buses = PL08X_AHB2,
  99. }, {
  100. .bus_id = "i2s2_tx",
  101. .min_signal = 14,
  102. .max_signal = 14,
  103. .periph_buses = PL08X_AHB2,
  104. }, {
  105. .bus_id = "i2s2_rx",
  106. .min_signal = 15,
  107. .max_signal = 15,
  108. .periph_buses = PL08X_AHB2,
  109. }
  110. };
  111. struct pl08x_platform_data s3c64xx_dma0_plat_data = {
  112. .memcpy_channel = {
  113. .bus_id = "memcpy",
  114. .cctl_memcpy =
  115. (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
  116. PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
  117. PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
  118. PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
  119. PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
  120. PL080_CONTROL_PROT_SYS),
  121. },
  122. .lli_buses = PL08X_AHB1,
  123. .mem_buses = PL08X_AHB1,
  124. .get_xfer_signal = pl08x_get_xfer_signal,
  125. .put_xfer_signal = pl08x_put_xfer_signal,
  126. .slave_channels = s3c64xx_dma0_info,
  127. .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
  128. };
  129. static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
  130. 0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
  131. /*
  132. * DMA1
  133. */
  134. static struct pl08x_channel_data s3c64xx_dma1_info[] = {
  135. {
  136. .bus_id = "pcm1_tx",
  137. .min_signal = 0,
  138. .max_signal = 0,
  139. .periph_buses = PL08X_AHB2,
  140. }, {
  141. .bus_id = "pcm1_rx",
  142. .min_signal = 1,
  143. .max_signal = 1,
  144. .periph_buses = PL08X_AHB2,
  145. }, {
  146. .bus_id = "i2s1_tx",
  147. .min_signal = 2,
  148. .max_signal = 2,
  149. .periph_buses = PL08X_AHB2,
  150. }, {
  151. .bus_id = "i2s1_rx",
  152. .min_signal = 3,
  153. .max_signal = 3,
  154. .periph_buses = PL08X_AHB2,
  155. }, {
  156. .bus_id = "spi1_tx",
  157. .min_signal = 4,
  158. .max_signal = 4,
  159. .periph_buses = PL08X_AHB2,
  160. }, {
  161. .bus_id = "spi1_rx",
  162. .min_signal = 5,
  163. .max_signal = 5,
  164. .periph_buses = PL08X_AHB2,
  165. }, {
  166. .bus_id = "ac97_out",
  167. .min_signal = 6,
  168. .max_signal = 6,
  169. .periph_buses = PL08X_AHB2,
  170. }, {
  171. .bus_id = "ac97_in",
  172. .min_signal = 7,
  173. .max_signal = 7,
  174. .periph_buses = PL08X_AHB2,
  175. }, {
  176. .bus_id = "ac97_mic",
  177. .min_signal = 8,
  178. .max_signal = 8,
  179. .periph_buses = PL08X_AHB2,
  180. }, {
  181. .bus_id = "pwm",
  182. .min_signal = 9,
  183. .max_signal = 9,
  184. .periph_buses = PL08X_AHB2,
  185. }, {
  186. .bus_id = "irda",
  187. .min_signal = 10,
  188. .max_signal = 10,
  189. .periph_buses = PL08X_AHB2,
  190. }, {
  191. .bus_id = "external",
  192. .min_signal = 11,
  193. .max_signal = 11,
  194. .periph_buses = PL08X_AHB2,
  195. },
  196. };
  197. struct pl08x_platform_data s3c64xx_dma1_plat_data = {
  198. .memcpy_channel = {
  199. .bus_id = "memcpy",
  200. .cctl_memcpy =
  201. (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
  202. PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
  203. PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
  204. PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
  205. PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
  206. PL080_CONTROL_PROT_SYS),
  207. },
  208. .lli_buses = PL08X_AHB1,
  209. .mem_buses = PL08X_AHB1,
  210. .get_xfer_signal = pl08x_get_xfer_signal,
  211. .put_xfer_signal = pl08x_put_xfer_signal,
  212. .slave_channels = s3c64xx_dma1_info,
  213. .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
  214. };
  215. static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
  216. 0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
  217. static int __init s3c64xx_pl080_init(void)
  218. {
  219. /* Set all DMA configuration to be DMA, not SDMA */
  220. writel(0xffffff, S3C64XX_SDMA_SEL);
  221. if (of_have_populated_dt())
  222. return 0;
  223. amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
  224. amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
  225. return 0;
  226. }
  227. arch_initcall(s3c64xx_pl080_init);