ucc_fast.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*
  2. * arch/powerpc/sysdev/qe_lib/ucc_fast.c
  3. *
  4. * QE UCC Fast API Set - UCC Fast specific routines implementations.
  5. *
  6. * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
  7. *
  8. * Authors: Shlomi Gridish <gridish@freescale.com>
  9. * Li Yang <leoli@freescale.com>
  10. *
  11. * This program is free software; you can redistribute it and/or modify it
  12. * under the terms of the GNU General Public License as published by the
  13. * Free Software Foundation; either version 2 of the License, or (at your
  14. * option) any later version.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/init.h>
  18. #include <linux/errno.h>
  19. #include <linux/slab.h>
  20. #include <linux/stddef.h>
  21. #include <linux/interrupt.h>
  22. #include <asm/io.h>
  23. #include <asm/immap_qe.h>
  24. #include <asm/qe.h>
  25. #include <asm/ucc.h>
  26. #include <asm/ucc_fast.h>
  27. #define uccf_printk(level, format, arg...) \
  28. printk(level format "\n", ## arg)
  29. #define uccf_dbg(format, arg...) \
  30. uccf_printk(KERN_DEBUG , format , ## arg)
  31. #define uccf_err(format, arg...) \
  32. uccf_printk(KERN_ERR , format , ## arg)
  33. #define uccf_info(format, arg...) \
  34. uccf_printk(KERN_INFO , format , ## arg)
  35. #define uccf_warn(format, arg...) \
  36. uccf_printk(KERN_WARNING , format , ## arg)
  37. #ifdef UCCF_VERBOSE_DEBUG
  38. #define uccf_vdbg uccf_dbg
  39. #else
  40. #define uccf_vdbg(fmt, args...) do { } while (0)
  41. #endif /* UCCF_VERBOSE_DEBUG */
  42. void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
  43. {
  44. uccf_info("UCC%d Fast registers:", uccf->uf_info->ucc_num);
  45. uccf_info("Base address: 0x%08x", (u32) uccf->uf_regs);
  46. uccf_info("gumr : addr - 0x%08x, val - 0x%08x",
  47. (u32) & uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
  48. uccf_info("upsmr : addr - 0x%08x, val - 0x%08x",
  49. (u32) & uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
  50. uccf_info("utodr : addr - 0x%08x, val - 0x%04x",
  51. (u32) & uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
  52. uccf_info("udsr : addr - 0x%08x, val - 0x%04x",
  53. (u32) & uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
  54. uccf_info("ucce : addr - 0x%08x, val - 0x%08x",
  55. (u32) & uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
  56. uccf_info("uccm : addr - 0x%08x, val - 0x%08x",
  57. (u32) & uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
  58. uccf_info("uccs : addr - 0x%08x, val - 0x%02x",
  59. (u32) & uccf->uf_regs->uccs, uccf->uf_regs->uccs);
  60. uccf_info("urfb : addr - 0x%08x, val - 0x%08x",
  61. (u32) & uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
  62. uccf_info("urfs : addr - 0x%08x, val - 0x%04x",
  63. (u32) & uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
  64. uccf_info("urfet : addr - 0x%08x, val - 0x%04x",
  65. (u32) & uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
  66. uccf_info("urfset: addr - 0x%08x, val - 0x%04x",
  67. (u32) & uccf->uf_regs->urfset,
  68. in_be16(&uccf->uf_regs->urfset));
  69. uccf_info("utfb : addr - 0x%08x, val - 0x%08x",
  70. (u32) & uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
  71. uccf_info("utfs : addr - 0x%08x, val - 0x%04x",
  72. (u32) & uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
  73. uccf_info("utfet : addr - 0x%08x, val - 0x%04x",
  74. (u32) & uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
  75. uccf_info("utftt : addr - 0x%08x, val - 0x%04x",
  76. (u32) & uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
  77. uccf_info("utpt : addr - 0x%08x, val - 0x%04x",
  78. (u32) & uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
  79. uccf_info("urtry : addr - 0x%08x, val - 0x%08x",
  80. (u32) & uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
  81. uccf_info("guemr : addr - 0x%08x, val - 0x%02x",
  82. (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
  83. }
  84. u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
  85. {
  86. switch (uccf_num) {
  87. case 0: return QE_CR_SUBBLOCK_UCCFAST1;
  88. case 1: return QE_CR_SUBBLOCK_UCCFAST2;
  89. case 2: return QE_CR_SUBBLOCK_UCCFAST3;
  90. case 3: return QE_CR_SUBBLOCK_UCCFAST4;
  91. case 4: return QE_CR_SUBBLOCK_UCCFAST5;
  92. case 5: return QE_CR_SUBBLOCK_UCCFAST6;
  93. case 6: return QE_CR_SUBBLOCK_UCCFAST7;
  94. case 7: return QE_CR_SUBBLOCK_UCCFAST8;
  95. default: return QE_CR_SUBBLOCK_INVALID;
  96. }
  97. }
  98. void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf)
  99. {
  100. out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
  101. }
  102. void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
  103. {
  104. struct ucc_fast *uf_regs;
  105. u32 gumr;
  106. uf_regs = uccf->uf_regs;
  107. /* Enable reception and/or transmission on this UCC. */
  108. gumr = in_be32(&uf_regs->gumr);
  109. if (mode & COMM_DIR_TX) {
  110. gumr |= UCC_FAST_GUMR_ENT;
  111. uccf->enabled_tx = 1;
  112. }
  113. if (mode & COMM_DIR_RX) {
  114. gumr |= UCC_FAST_GUMR_ENR;
  115. uccf->enabled_rx = 1;
  116. }
  117. out_be32(&uf_regs->gumr, gumr);
  118. }
  119. void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
  120. {
  121. struct ucc_fast *uf_regs;
  122. u32 gumr;
  123. uf_regs = uccf->uf_regs;
  124. /* Disable reception and/or transmission on this UCC. */
  125. gumr = in_be32(&uf_regs->gumr);
  126. if (mode & COMM_DIR_TX) {
  127. gumr &= ~UCC_FAST_GUMR_ENT;
  128. uccf->enabled_tx = 0;
  129. }
  130. if (mode & COMM_DIR_RX) {
  131. gumr &= ~UCC_FAST_GUMR_ENR;
  132. uccf->enabled_rx = 0;
  133. }
  134. out_be32(&uf_regs->gumr, gumr);
  135. }
  136. int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
  137. {
  138. struct ucc_fast_private *uccf;
  139. struct ucc_fast *uf_regs;
  140. u32 gumr = 0;
  141. int ret;
  142. uccf_vdbg("%s: IN", __FUNCTION__);
  143. if (!uf_info)
  144. return -EINVAL;
  145. /* check if the UCC port number is in range. */
  146. if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
  147. uccf_err("ucc_fast_init: Illegal UCC number!");
  148. return -EINVAL;
  149. }
  150. /* Check that 'max_rx_buf_length' is properly aligned (4). */
  151. if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
  152. uccf_err("ucc_fast_init: max_rx_buf_length not aligned.");
  153. return -EINVAL;
  154. }
  155. /* Validate Virtual Fifo register values */
  156. if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
  157. uccf_err
  158. ("ucc_fast_init: Virtual Fifo register urfs too small.");
  159. return -EINVAL;
  160. }
  161. if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
  162. uccf_err
  163. ("ucc_fast_init: Virtual Fifo register urfs not aligned.");
  164. return -EINVAL;
  165. }
  166. if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
  167. uccf_err
  168. ("ucc_fast_init: Virtual Fifo register urfet not aligned.");
  169. return -EINVAL;
  170. }
  171. if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
  172. uccf_err
  173. ("ucc_fast_init: Virtual Fifo register urfset not aligned.");
  174. return -EINVAL;
  175. }
  176. if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
  177. uccf_err
  178. ("ucc_fast_init: Virtual Fifo register utfs not aligned.");
  179. return -EINVAL;
  180. }
  181. if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
  182. uccf_err
  183. ("ucc_fast_init: Virtual Fifo register utfet not aligned.");
  184. return -EINVAL;
  185. }
  186. if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
  187. uccf_err
  188. ("ucc_fast_init: Virtual Fifo register utftt not aligned.");
  189. return -EINVAL;
  190. }
  191. uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
  192. if (!uccf) {
  193. uccf_err
  194. ("ucc_fast_init: No memory for UCC slow data structure!");
  195. return -ENOMEM;
  196. }
  197. /* Fill fast UCC structure */
  198. uccf->uf_info = uf_info;
  199. /* Set the PHY base address */
  200. uccf->uf_regs =
  201. (struct ucc_fast *) ioremap(uf_info->regs, sizeof(struct ucc_fast));
  202. if (uccf->uf_regs == NULL) {
  203. uccf_err
  204. ("ucc_fast_init: No memory map for UCC slow controller!");
  205. return -ENOMEM;
  206. }
  207. uccf->enabled_tx = 0;
  208. uccf->enabled_rx = 0;
  209. uccf->stopped_tx = 0;
  210. uccf->stopped_rx = 0;
  211. uf_regs = uccf->uf_regs;
  212. uccf->p_ucce = (u32 *) & (uf_regs->ucce);
  213. uccf->p_uccm = (u32 *) & (uf_regs->uccm);
  214. #ifdef STATISTICS
  215. uccf->tx_frames = 0;
  216. uccf->rx_frames = 0;
  217. uccf->rx_discarded = 0;
  218. #endif /* STATISTICS */
  219. /* Init Guemr register */
  220. if ((ret = ucc_init_guemr((struct ucc_common *) (uf_regs)))) {
  221. uccf_err("ucc_fast_init: Could not init the guemr register.");
  222. ucc_fast_free(uccf);
  223. return ret;
  224. }
  225. /* Set UCC to fast type */
  226. if ((ret = ucc_set_type(uf_info->ucc_num,
  227. (struct ucc_common *) (uf_regs),
  228. UCC_SPEED_TYPE_FAST))) {
  229. uccf_err("ucc_fast_init: Could not set type to fast.");
  230. ucc_fast_free(uccf);
  231. return ret;
  232. }
  233. uccf->mrblr = uf_info->max_rx_buf_length;
  234. /* Set GUMR */
  235. /* For more details see the hardware spec. */
  236. /* gumr starts as zero. */
  237. if (uf_info->tci)
  238. gumr |= UCC_FAST_GUMR_TCI;
  239. gumr |= uf_info->ttx_trx;
  240. if (uf_info->cdp)
  241. gumr |= UCC_FAST_GUMR_CDP;
  242. if (uf_info->ctsp)
  243. gumr |= UCC_FAST_GUMR_CTSP;
  244. if (uf_info->cds)
  245. gumr |= UCC_FAST_GUMR_CDS;
  246. if (uf_info->ctss)
  247. gumr |= UCC_FAST_GUMR_CTSS;
  248. if (uf_info->txsy)
  249. gumr |= UCC_FAST_GUMR_TXSY;
  250. if (uf_info->rsyn)
  251. gumr |= UCC_FAST_GUMR_RSYN;
  252. gumr |= uf_info->synl;
  253. if (uf_info->rtsm)
  254. gumr |= UCC_FAST_GUMR_RTSM;
  255. gumr |= uf_info->renc;
  256. if (uf_info->revd)
  257. gumr |= UCC_FAST_GUMR_REVD;
  258. gumr |= uf_info->tenc;
  259. gumr |= uf_info->tcrc;
  260. gumr |= uf_info->mode;
  261. out_be32(&uf_regs->gumr, gumr);
  262. /* Allocate memory for Tx Virtual Fifo */
  263. uccf->ucc_fast_tx_virtual_fifo_base_offset =
  264. qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
  265. if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
  266. uccf_err
  267. ("ucc_fast_init: Can not allocate MURAM memory for "
  268. "struct ucc_fastx_virtual_fifo_base_offset.");
  269. uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
  270. ucc_fast_free(uccf);
  271. return -ENOMEM;
  272. }
  273. /* Allocate memory for Rx Virtual Fifo */
  274. uccf->ucc_fast_rx_virtual_fifo_base_offset =
  275. qe_muram_alloc(uf_info->urfs +
  276. (u32)
  277. UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
  278. UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
  279. if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
  280. uccf_err
  281. ("ucc_fast_init: Can not allocate MURAM memory for "
  282. "ucc_fast_rx_virtual_fifo_base_offset.");
  283. uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
  284. ucc_fast_free(uccf);
  285. return -ENOMEM;
  286. }
  287. /* Set Virtual Fifo registers */
  288. out_be16(&uf_regs->urfs, uf_info->urfs);
  289. out_be16(&uf_regs->urfet, uf_info->urfet);
  290. out_be16(&uf_regs->urfset, uf_info->urfset);
  291. out_be16(&uf_regs->utfs, uf_info->utfs);
  292. out_be16(&uf_regs->utfet, uf_info->utfet);
  293. out_be16(&uf_regs->utftt, uf_info->utftt);
  294. /* utfb, urfb are offsets from MURAM base */
  295. out_be32(&uf_regs->utfb, uccf->ucc_fast_tx_virtual_fifo_base_offset);
  296. out_be32(&uf_regs->urfb, uccf->ucc_fast_rx_virtual_fifo_base_offset);
  297. /* Mux clocking */
  298. /* Grant Support */
  299. ucc_set_qe_mux_grant(uf_info->ucc_num, uf_info->grant_support);
  300. /* Breakpoint Support */
  301. ucc_set_qe_mux_bkpt(uf_info->ucc_num, uf_info->brkpt_support);
  302. /* Set Tsa or NMSI mode. */
  303. ucc_set_qe_mux_tsa(uf_info->ucc_num, uf_info->tsa);
  304. /* If NMSI (not Tsa), set Tx and Rx clock. */
  305. if (!uf_info->tsa) {
  306. /* Rx clock routing */
  307. if (uf_info->rx_clock != QE_CLK_NONE) {
  308. if (ucc_set_qe_mux_rxtx
  309. (uf_info->ucc_num, uf_info->rx_clock,
  310. COMM_DIR_RX)) {
  311. uccf_err
  312. ("ucc_fast_init: Illegal value for parameter 'RxClock'.");
  313. ucc_fast_free(uccf);
  314. return -EINVAL;
  315. }
  316. }
  317. /* Tx clock routing */
  318. if (uf_info->tx_clock != QE_CLK_NONE) {
  319. if (ucc_set_qe_mux_rxtx
  320. (uf_info->ucc_num, uf_info->tx_clock,
  321. COMM_DIR_TX)) {
  322. uccf_err
  323. ("ucc_fast_init: Illegal value for parameter 'TxClock'.");
  324. ucc_fast_free(uccf);
  325. return -EINVAL;
  326. }
  327. }
  328. }
  329. /* Set interrupt mask register at UCC level. */
  330. out_be32(&uf_regs->uccm, uf_info->uccm_mask);
  331. /* First, clear anything pending at UCC level,
  332. * otherwise, old garbage may come through
  333. * as soon as the dam is opened
  334. * Writing '1' clears
  335. */
  336. out_be32(&uf_regs->ucce, 0xffffffff);
  337. *uccf_ret = uccf;
  338. return 0;
  339. }
  340. void ucc_fast_free(struct ucc_fast_private * uccf)
  341. {
  342. if (!uccf)
  343. return;
  344. if (uccf->ucc_fast_tx_virtual_fifo_base_offset)
  345. qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset);
  346. if (uccf->ucc_fast_rx_virtual_fifo_base_offset)
  347. qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset);
  348. kfree(uccf);
  349. }