qe_tdm.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2015 Freescale Semiconductor, Inc. All rights reserved.
  4. *
  5. * Authors: Zhao Qiang <[email protected]>
  6. *
  7. * Description:
  8. * QE TDM API Set - TDM specific routines implementations.
  9. */
  10. #include <linux/io.h>
  11. #include <linux/kernel.h>
  12. #include <linux/of_address.h>
  13. #include <linux/of_irq.h>
  14. #include <linux/of_platform.h>
  15. #include <soc/fsl/qe/qe_tdm.h>
  16. static int set_tdm_framer(const char *tdm_framer_type)
  17. {
  18. if (strcmp(tdm_framer_type, "e1") == 0)
  19. return TDM_FRAMER_E1;
  20. else if (strcmp(tdm_framer_type, "t1") == 0)
  21. return TDM_FRAMER_T1;
  22. else
  23. return -EINVAL;
  24. }
  25. static void set_si_param(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info)
  26. {
  27. struct si_mode_info *si_info = &ut_info->si_info;
  28. if (utdm->tdm_mode == TDM_INTERNAL_LOOPBACK) {
  29. si_info->simr_crt = 1;
  30. si_info->simr_rfsd = 0;
  31. }
  32. }
  33. int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
  34. struct ucc_tdm_info *ut_info)
  35. {
  36. const char *sprop;
  37. int ret = 0;
  38. u32 val;
  39. sprop = of_get_property(np, "fsl,rx-sync-clock", NULL);
  40. if (sprop) {
  41. ut_info->uf_info.rx_sync = qe_clock_source(sprop);
  42. if ((ut_info->uf_info.rx_sync < QE_CLK_NONE) ||
  43. (ut_info->uf_info.rx_sync > QE_RSYNC_PIN)) {
  44. pr_err("QE-TDM: Invalid rx-sync-clock property\n");
  45. return -EINVAL;
  46. }
  47. } else {
  48. pr_err("QE-TDM: Invalid rx-sync-clock property\n");
  49. return -EINVAL;
  50. }
  51. sprop = of_get_property(np, "fsl,tx-sync-clock", NULL);
  52. if (sprop) {
  53. ut_info->uf_info.tx_sync = qe_clock_source(sprop);
  54. if ((ut_info->uf_info.tx_sync < QE_CLK_NONE) ||
  55. (ut_info->uf_info.tx_sync > QE_TSYNC_PIN)) {
  56. pr_err("QE-TDM: Invalid tx-sync-clock property\n");
  57. return -EINVAL;
  58. }
  59. } else {
  60. pr_err("QE-TDM: Invalid tx-sync-clock property\n");
  61. return -EINVAL;
  62. }
  63. ret = of_property_read_u32_index(np, "fsl,tx-timeslot-mask", 0, &val);
  64. if (ret) {
  65. pr_err("QE-TDM: Invalid tx-timeslot-mask property\n");
  66. return -EINVAL;
  67. }
  68. utdm->tx_ts_mask = val;
  69. ret = of_property_read_u32_index(np, "fsl,rx-timeslot-mask", 0, &val);
  70. if (ret) {
  71. ret = -EINVAL;
  72. pr_err("QE-TDM: Invalid rx-timeslot-mask property\n");
  73. return ret;
  74. }
  75. utdm->rx_ts_mask = val;
  76. ret = of_property_read_u32_index(np, "fsl,tdm-id", 0, &val);
  77. if (ret) {
  78. ret = -EINVAL;
  79. pr_err("QE-TDM: No fsl,tdm-id property for this UCC\n");
  80. return ret;
  81. }
  82. utdm->tdm_port = val;
  83. ut_info->uf_info.tdm_num = utdm->tdm_port;
  84. if (of_property_read_bool(np, "fsl,tdm-internal-loopback"))
  85. utdm->tdm_mode = TDM_INTERNAL_LOOPBACK;
  86. else
  87. utdm->tdm_mode = TDM_NORMAL;
  88. sprop = of_get_property(np, "fsl,tdm-framer-type", NULL);
  89. if (!sprop) {
  90. ret = -EINVAL;
  91. pr_err("QE-TDM: No tdm-framer-type property for UCC\n");
  92. return ret;
  93. }
  94. ret = set_tdm_framer(sprop);
  95. if (ret < 0)
  96. return -EINVAL;
  97. utdm->tdm_framer_type = ret;
  98. ret = of_property_read_u32_index(np, "fsl,siram-entry-id", 0, &val);
  99. if (ret) {
  100. ret = -EINVAL;
  101. pr_err("QE-TDM: No siram entry id for UCC\n");
  102. return ret;
  103. }
  104. utdm->siram_entry_id = val;
  105. set_si_param(utdm, ut_info);
  106. return ret;
  107. }
  108. EXPORT_SYMBOL(ucc_of_parse_tdm);
  109. void ucc_tdm_init(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info)
  110. {
  111. struct si1 __iomem *si_regs;
  112. u16 __iomem *siram;
  113. u16 siram_entry_valid;
  114. u16 siram_entry_closed;
  115. u16 ucc_num;
  116. u8 csel;
  117. u16 sixmr;
  118. u16 tdm_port;
  119. u32 siram_entry_id;
  120. u32 mask;
  121. int i;
  122. si_regs = utdm->si_regs;
  123. siram = utdm->siram;
  124. ucc_num = ut_info->uf_info.ucc_num;
  125. tdm_port = utdm->tdm_port;
  126. siram_entry_id = utdm->siram_entry_id;
  127. if (utdm->tdm_framer_type == TDM_FRAMER_T1)
  128. utdm->num_of_ts = 24;
  129. if (utdm->tdm_framer_type == TDM_FRAMER_E1)
  130. utdm->num_of_ts = 32;
  131. /* set siram table */
  132. csel = (ucc_num < 4) ? ucc_num + 9 : ucc_num - 3;
  133. siram_entry_valid = SIR_CSEL(csel) | SIR_BYTE | SIR_CNT(0);
  134. siram_entry_closed = SIR_IDLE | SIR_BYTE | SIR_CNT(0);
  135. for (i = 0; i < utdm->num_of_ts; i++) {
  136. mask = 0x01 << i;
  137. if (utdm->tx_ts_mask & mask)
  138. iowrite16be(siram_entry_valid,
  139. &siram[siram_entry_id * 32 + i]);
  140. else
  141. iowrite16be(siram_entry_closed,
  142. &siram[siram_entry_id * 32 + i]);
  143. if (utdm->rx_ts_mask & mask)
  144. iowrite16be(siram_entry_valid,
  145. &siram[siram_entry_id * 32 + 0x200 + i]);
  146. else
  147. iowrite16be(siram_entry_closed,
  148. &siram[siram_entry_id * 32 + 0x200 + i]);
  149. }
  150. qe_setbits_be16(&siram[(siram_entry_id * 32) + (utdm->num_of_ts - 1)],
  151. SIR_LAST);
  152. qe_setbits_be16(&siram[(siram_entry_id * 32) + 0x200 + (utdm->num_of_ts - 1)],
  153. SIR_LAST);
  154. /* Set SIxMR register */
  155. sixmr = SIMR_SAD(siram_entry_id);
  156. sixmr &= ~SIMR_SDM_MASK;
  157. if (utdm->tdm_mode == TDM_INTERNAL_LOOPBACK)
  158. sixmr |= SIMR_SDM_INTERNAL_LOOPBACK;
  159. else
  160. sixmr |= SIMR_SDM_NORMAL;
  161. sixmr |= SIMR_RFSD(ut_info->si_info.simr_rfsd) |
  162. SIMR_TFSD(ut_info->si_info.simr_tfsd);
  163. if (ut_info->si_info.simr_crt)
  164. sixmr |= SIMR_CRT;
  165. if (ut_info->si_info.simr_sl)
  166. sixmr |= SIMR_SL;
  167. if (ut_info->si_info.simr_ce)
  168. sixmr |= SIMR_CE;
  169. if (ut_info->si_info.simr_fe)
  170. sixmr |= SIMR_FE;
  171. if (ut_info->si_info.simr_gm)
  172. sixmr |= SIMR_GM;
  173. switch (tdm_port) {
  174. case 0:
  175. iowrite16be(sixmr, &si_regs->sixmr1[0]);
  176. break;
  177. case 1:
  178. iowrite16be(sixmr, &si_regs->sixmr1[1]);
  179. break;
  180. case 2:
  181. iowrite16be(sixmr, &si_regs->sixmr1[2]);
  182. break;
  183. case 3:
  184. iowrite16be(sixmr, &si_regs->sixmr1[3]);
  185. break;
  186. default:
  187. pr_err("QE-TDM: can not find tdm sixmr reg\n");
  188. break;
  189. }
  190. }
  191. EXPORT_SYMBOL(ucc_tdm_init);