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