ucc_fast.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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: Illagal 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 = (struct ucc_fast_private *)
  192. kmalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
  193. if (!uccf) {
  194. uccf_err
  195. ("ucc_fast_init: No memory for UCC slow data structure!");
  196. return -ENOMEM;
  197. }
  198. memset(uccf, 0, sizeof(struct ucc_fast_private));
  199. /* Fill fast UCC structure */
  200. uccf->uf_info = uf_info;
  201. /* Set the PHY base address */
  202. uccf->uf_regs =
  203. (struct ucc_fast *) ioremap(uf_info->regs, sizeof(struct ucc_fast));
  204. if (uccf->uf_regs == NULL) {
  205. uccf_err
  206. ("ucc_fast_init: No memory map for UCC slow controller!");
  207. return -ENOMEM;
  208. }
  209. uccf->enabled_tx = 0;
  210. uccf->enabled_rx = 0;
  211. uccf->stopped_tx = 0;
  212. uccf->stopped_rx = 0;
  213. uf_regs = uccf->uf_regs;
  214. uccf->p_ucce = (u32 *) & (uf_regs->ucce);
  215. uccf->p_uccm = (u32 *) & (uf_regs->uccm);
  216. #ifdef STATISTICS
  217. uccf->tx_frames = 0;
  218. uccf->rx_frames = 0;
  219. uccf->rx_discarded = 0;
  220. #endif /* STATISTICS */
  221. /* Init Guemr register */
  222. if ((ret = ucc_init_guemr((struct ucc_common *) (uf_regs)))) {
  223. uccf_err("ucc_fast_init: Could not init the guemr register.");
  224. ucc_fast_free(uccf);
  225. return ret;
  226. }
  227. /* Set UCC to fast type */
  228. if ((ret = ucc_set_type(uf_info->ucc_num,
  229. (struct ucc_common *) (uf_regs),
  230. UCC_SPEED_TYPE_FAST))) {
  231. uccf_err("ucc_fast_init: Could not set type to fast.");
  232. ucc_fast_free(uccf);
  233. return ret;
  234. }
  235. uccf->mrblr = uf_info->max_rx_buf_length;
  236. /* Set GUMR */
  237. /* For more details see the hardware spec. */
  238. /* gumr starts as zero. */
  239. if (uf_info->tci)
  240. gumr |= UCC_FAST_GUMR_TCI;
  241. gumr |= uf_info->ttx_trx;
  242. if (uf_info->cdp)
  243. gumr |= UCC_FAST_GUMR_CDP;
  244. if (uf_info->ctsp)
  245. gumr |= UCC_FAST_GUMR_CTSP;
  246. if (uf_info->cds)
  247. gumr |= UCC_FAST_GUMR_CDS;
  248. if (uf_info->ctss)
  249. gumr |= UCC_FAST_GUMR_CTSS;
  250. if (uf_info->txsy)
  251. gumr |= UCC_FAST_GUMR_TXSY;
  252. if (uf_info->rsyn)
  253. gumr |= UCC_FAST_GUMR_RSYN;
  254. gumr |= uf_info->synl;
  255. if (uf_info->rtsm)
  256. gumr |= UCC_FAST_GUMR_RTSM;
  257. gumr |= uf_info->renc;
  258. if (uf_info->revd)
  259. gumr |= UCC_FAST_GUMR_REVD;
  260. gumr |= uf_info->tenc;
  261. gumr |= uf_info->tcrc;
  262. gumr |= uf_info->mode;
  263. out_be32(&uf_regs->gumr, gumr);
  264. /* Allocate memory for Tx Virtual Fifo */
  265. uccf->ucc_fast_tx_virtual_fifo_base_offset =
  266. qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
  267. if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
  268. uccf_err
  269. ("ucc_fast_init: Can not allocate MURAM memory for "
  270. "struct ucc_fastx_virtual_fifo_base_offset.");
  271. uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
  272. ucc_fast_free(uccf);
  273. return -ENOMEM;
  274. }
  275. /* Allocate memory for Rx Virtual Fifo */
  276. uccf->ucc_fast_rx_virtual_fifo_base_offset =
  277. qe_muram_alloc(uf_info->urfs +
  278. (u32)
  279. UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
  280. UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
  281. if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
  282. uccf_err
  283. ("ucc_fast_init: Can not allocate MURAM memory for "
  284. "ucc_fast_rx_virtual_fifo_base_offset.");
  285. uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
  286. ucc_fast_free(uccf);
  287. return -ENOMEM;
  288. }
  289. /* Set Virtual Fifo registers */
  290. out_be16(&uf_regs->urfs, uf_info->urfs);
  291. out_be16(&uf_regs->urfet, uf_info->urfet);
  292. out_be16(&uf_regs->urfset, uf_info->urfset);
  293. out_be16(&uf_regs->utfs, uf_info->utfs);
  294. out_be16(&uf_regs->utfet, uf_info->utfet);
  295. out_be16(&uf_regs->utftt, uf_info->utftt);
  296. /* utfb, urfb are offsets from MURAM base */
  297. out_be32(&uf_regs->utfb, uccf->ucc_fast_tx_virtual_fifo_base_offset);
  298. out_be32(&uf_regs->urfb, uccf->ucc_fast_rx_virtual_fifo_base_offset);
  299. /* Mux clocking */
  300. /* Grant Support */
  301. ucc_set_qe_mux_grant(uf_info->ucc_num, uf_info->grant_support);
  302. /* Breakpoint Support */
  303. ucc_set_qe_mux_bkpt(uf_info->ucc_num, uf_info->brkpt_support);
  304. /* Set Tsa or NMSI mode. */
  305. ucc_set_qe_mux_tsa(uf_info->ucc_num, uf_info->tsa);
  306. /* If NMSI (not Tsa), set Tx and Rx clock. */
  307. if (!uf_info->tsa) {
  308. /* Rx clock routing */
  309. if (uf_info->rx_clock != QE_CLK_NONE) {
  310. if (ucc_set_qe_mux_rxtx
  311. (uf_info->ucc_num, uf_info->rx_clock,
  312. COMM_DIR_RX)) {
  313. uccf_err
  314. ("ucc_fast_init: Illegal value for parameter 'RxClock'.");
  315. ucc_fast_free(uccf);
  316. return -EINVAL;
  317. }
  318. }
  319. /* Tx clock routing */
  320. if (uf_info->tx_clock != QE_CLK_NONE) {
  321. if (ucc_set_qe_mux_rxtx
  322. (uf_info->ucc_num, uf_info->tx_clock,
  323. COMM_DIR_TX)) {
  324. uccf_err
  325. ("ucc_fast_init: Illegal value for parameter 'TxClock'.");
  326. ucc_fast_free(uccf);
  327. return -EINVAL;
  328. }
  329. }
  330. }
  331. /* Set interrupt mask register at UCC level. */
  332. out_be32(&uf_regs->uccm, uf_info->uccm_mask);
  333. /* First, clear anything pending at UCC level,
  334. * otherwise, old garbage may come through
  335. * as soon as the dam is opened
  336. * Writing '1' clears
  337. */
  338. out_be32(&uf_regs->ucce, 0xffffffff);
  339. *uccf_ret = uccf;
  340. return 0;
  341. }
  342. void ucc_fast_free(struct ucc_fast_private * uccf)
  343. {
  344. if (!uccf)
  345. return;
  346. if (uccf->ucc_fast_tx_virtual_fifo_base_offset)
  347. qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset);
  348. if (uccf->ucc_fast_rx_virtual_fifo_base_offset)
  349. qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset);
  350. kfree(uccf);
  351. }