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