gen_bd.c 9.3 KB

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