gen_bd.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Driver for MPC52xx processor BestComm General Buffer Descriptor
  4. *
  5. * Copyright (C) 2007 Sylvain Munaut <[email protected]>
  6. * Copyright (C) 2006 AppSpec Computer Technologies Corp.
  7. * Jeff Gibbons <[email protected]>
  8. */
  9. #include <linux/module.h>
  10. #include <linux/kernel.h>
  11. #include <linux/string.h>
  12. #include <linux/types.h>
  13. #include <asm/errno.h>
  14. #include <asm/io.h>
  15. #include <asm/mpc52xx.h>
  16. #include <asm/mpc52xx_psc.h>
  17. #include <linux/fsl/bestcomm/bestcomm.h>
  18. #include <linux/fsl/bestcomm/bestcomm_priv.h>
  19. #include <linux/fsl/bestcomm/gen_bd.h>
  20. /* ======================================================================== */
  21. /* Task image/var/inc */
  22. /* ======================================================================== */
  23. /* gen_bd tasks images */
  24. extern u32 bcom_gen_bd_rx_task[];
  25. extern u32 bcom_gen_bd_tx_task[];
  26. /* rx task vars that need to be set before enabling the task */
  27. struct bcom_gen_bd_rx_var {
  28. u32 enable; /* (u16*) address of task's control register */
  29. u32 fifo; /* (u32*) address of gen_bd's fifo */
  30. u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
  31. u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
  32. u32 bd_start; /* (struct bcom_bd*) current bd */
  33. u32 buffer_size; /* size of receive buffer */
  34. };
  35. /* rx task incs that need to be set before enabling the task */
  36. struct bcom_gen_bd_rx_inc {
  37. u16 pad0;
  38. s16 incr_bytes;
  39. u16 pad1;
  40. s16 incr_dst;
  41. };
  42. /* tx task vars that need to be set before enabling the task */
  43. struct bcom_gen_bd_tx_var {
  44. u32 fifo; /* (u32*) address of gen_bd's fifo */
  45. u32 enable; /* (u16*) address of task's control register */
  46. u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
  47. u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
  48. u32 bd_start; /* (struct bcom_bd*) current bd */
  49. u32 buffer_size; /* set by uCode for each packet */
  50. };
  51. /* tx task incs that need to be set before enabling the task */
  52. struct bcom_gen_bd_tx_inc {
  53. u16 pad0;
  54. s16 incr_bytes;
  55. u16 pad1;
  56. s16 incr_src;
  57. u16 pad2;
  58. s16 incr_src_ma;
  59. };
  60. /* private structure */
  61. struct bcom_gen_bd_priv {
  62. phys_addr_t fifo;
  63. int initiator;
  64. int ipr;
  65. int maxbufsize;
  66. };
  67. /* ======================================================================== */
  68. /* Task support code */
  69. /* ======================================================================== */
  70. struct bcom_task *
  71. bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
  72. int initiator, int ipr, int maxbufsize)
  73. {
  74. struct bcom_task *tsk;
  75. struct bcom_gen_bd_priv *priv;
  76. tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
  77. sizeof(struct bcom_gen_bd_priv));
  78. if (!tsk)
  79. return NULL;
  80. tsk->flags = BCOM_FLAGS_NONE;
  81. priv = tsk->priv;
  82. priv->fifo = fifo;
  83. priv->initiator = initiator;
  84. priv->ipr = ipr;
  85. priv->maxbufsize = maxbufsize;
  86. if (bcom_gen_bd_rx_reset(tsk)) {
  87. bcom_task_free(tsk);
  88. return NULL;
  89. }
  90. return tsk;
  91. }
  92. EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
  93. int
  94. bcom_gen_bd_rx_reset(struct bcom_task *tsk)
  95. {
  96. struct bcom_gen_bd_priv *priv = tsk->priv;
  97. struct bcom_gen_bd_rx_var *var;
  98. struct bcom_gen_bd_rx_inc *inc;
  99. /* Shutdown the task */
  100. bcom_disable_task(tsk->tasknum);
  101. /* Reset the microcode */
  102. var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);
  103. inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);
  104. if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))
  105. return -1;
  106. var->enable = bcom_eng->regs_base +
  107. offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
  108. var->fifo = (u32) priv->fifo;
  109. var->bd_base = tsk->bd_pa;
  110. var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
  111. var->bd_start = tsk->bd_pa;
  112. var->buffer_size = priv->maxbufsize;
  113. inc->incr_bytes = -(s16)sizeof(u32);
  114. inc->incr_dst = sizeof(u32);
  115. /* Reset the BDs */
  116. tsk->index = 0;
  117. tsk->outdex = 0;
  118. memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
  119. /* Configure some stuff */
  120. bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
  121. bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
  122. out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
  123. bcom_set_initiator(tsk->tasknum, priv->initiator);
  124. out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
  125. return 0;
  126. }
  127. EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
  128. void
  129. bcom_gen_bd_rx_release(struct bcom_task *tsk)
  130. {
  131. /* Nothing special for the GenBD tasks */
  132. bcom_task_free(tsk);
  133. }
  134. EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
  135. extern struct bcom_task *
  136. bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
  137. int initiator, int ipr)
  138. {
  139. struct bcom_task *tsk;
  140. struct bcom_gen_bd_priv *priv;
  141. tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
  142. sizeof(struct bcom_gen_bd_priv));
  143. if (!tsk)
  144. return NULL;
  145. tsk->flags = BCOM_FLAGS_NONE;
  146. priv = tsk->priv;
  147. priv->fifo = fifo;
  148. priv->initiator = initiator;
  149. priv->ipr = ipr;
  150. if (bcom_gen_bd_tx_reset(tsk)) {
  151. bcom_task_free(tsk);
  152. return NULL;
  153. }
  154. return tsk;
  155. }
  156. EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
  157. int
  158. bcom_gen_bd_tx_reset(struct bcom_task *tsk)
  159. {
  160. struct bcom_gen_bd_priv *priv = tsk->priv;
  161. struct bcom_gen_bd_tx_var *var;
  162. struct bcom_gen_bd_tx_inc *inc;
  163. /* Shutdown the task */
  164. bcom_disable_task(tsk->tasknum);
  165. /* Reset the microcode */
  166. var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);
  167. inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);
  168. if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))
  169. return -1;
  170. var->enable = bcom_eng->regs_base +
  171. offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
  172. var->fifo = (u32) priv->fifo;
  173. var->bd_base = tsk->bd_pa;
  174. var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
  175. var->bd_start = tsk->bd_pa;
  176. inc->incr_bytes = -(s16)sizeof(u32);
  177. inc->incr_src = sizeof(u32);
  178. inc->incr_src_ma = sizeof(u8);
  179. /* Reset the BDs */
  180. tsk->index = 0;
  181. tsk->outdex = 0;
  182. memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
  183. /* Configure some stuff */
  184. bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
  185. bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
  186. out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
  187. bcom_set_initiator(tsk->tasknum, priv->initiator);
  188. out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
  189. return 0;
  190. }
  191. EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
  192. void
  193. bcom_gen_bd_tx_release(struct bcom_task *tsk)
  194. {
  195. /* Nothing special for the GenBD tasks */
  196. bcom_task_free(tsk);
  197. }
  198. EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
  199. /* ---------------------------------------------------------------------
  200. * PSC support code
  201. */
  202. /**
  203. * bcom_psc_parameters - Bestcomm initialization value table for PSC devices
  204. *
  205. * This structure is only used internally. It is a lookup table for PSC
  206. * specific parameters to bestcomm tasks.
  207. */
  208. static struct bcom_psc_params {
  209. int rx_initiator;
  210. int rx_ipr;
  211. int tx_initiator;
  212. int tx_ipr;
  213. } bcom_psc_params[] = {
  214. [0] = {
  215. .rx_initiator = BCOM_INITIATOR_PSC1_RX,
  216. .rx_ipr = BCOM_IPR_PSC1_RX,
  217. .tx_initiator = BCOM_INITIATOR_PSC1_TX,
  218. .tx_ipr = BCOM_IPR_PSC1_TX,
  219. },
  220. [1] = {
  221. .rx_initiator = BCOM_INITIATOR_PSC2_RX,
  222. .rx_ipr = BCOM_IPR_PSC2_RX,
  223. .tx_initiator = BCOM_INITIATOR_PSC2_TX,
  224. .tx_ipr = BCOM_IPR_PSC2_TX,
  225. },
  226. [2] = {
  227. .rx_initiator = BCOM_INITIATOR_PSC3_RX,
  228. .rx_ipr = BCOM_IPR_PSC3_RX,
  229. .tx_initiator = BCOM_INITIATOR_PSC3_TX,
  230. .tx_ipr = BCOM_IPR_PSC3_TX,
  231. },
  232. [3] = {
  233. .rx_initiator = BCOM_INITIATOR_PSC4_RX,
  234. .rx_ipr = BCOM_IPR_PSC4_RX,
  235. .tx_initiator = BCOM_INITIATOR_PSC4_TX,
  236. .tx_ipr = BCOM_IPR_PSC4_TX,
  237. },
  238. [4] = {
  239. .rx_initiator = BCOM_INITIATOR_PSC5_RX,
  240. .rx_ipr = BCOM_IPR_PSC5_RX,
  241. .tx_initiator = BCOM_INITIATOR_PSC5_TX,
  242. .tx_ipr = BCOM_IPR_PSC5_TX,
  243. },
  244. [5] = {
  245. .rx_initiator = BCOM_INITIATOR_PSC6_RX,
  246. .rx_ipr = BCOM_IPR_PSC6_RX,
  247. .tx_initiator = BCOM_INITIATOR_PSC6_TX,
  248. .tx_ipr = BCOM_IPR_PSC6_TX,
  249. },
  250. };
  251. /**
  252. * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port
  253. * @psc_num: Number of the PSC to allocate a task for
  254. * @queue_len: number of buffer descriptors to allocate for the task
  255. * @fifo: physical address of FIFO register
  256. * @maxbufsize: Maximum receive data size in bytes.
  257. *
  258. * Allocate a bestcomm task structure for receiving data from a PSC.
  259. */
  260. struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
  261. phys_addr_t fifo, int maxbufsize)
  262. {
  263. if (psc_num >= MPC52xx_PSC_MAXNUM)
  264. return NULL;
  265. return bcom_gen_bd_rx_init(queue_len, fifo,
  266. bcom_psc_params[psc_num].rx_initiator,
  267. bcom_psc_params[psc_num].rx_ipr,
  268. maxbufsize);
  269. }
  270. EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);
  271. /**
  272. * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port
  273. * @psc_num: Number of the PSC to allocate a task for
  274. * @queue_len: number of buffer descriptors to allocate for the task
  275. * @fifo: physical address of FIFO register
  276. *
  277. * Allocate a bestcomm task structure for transmitting data to a PSC.
  278. */
  279. struct bcom_task *
  280. bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)
  281. {
  282. struct psc;
  283. return bcom_gen_bd_tx_init(queue_len, fifo,
  284. bcom_psc_params[psc_num].tx_initiator,
  285. bcom_psc_params[psc_num].tx_ipr);
  286. }
  287. EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
  288. MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
  289. MODULE_AUTHOR("Jeff Gibbons <[email protected]>");
  290. MODULE_LICENSE("GPL v2");