1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 235ef1c20SZhao Qiang /* 335ef1c20SZhao Qiang * Copyright (C) 2015 Freescale Semiconductor, Inc. All rights reserved. 435ef1c20SZhao Qiang * 535ef1c20SZhao Qiang * Authors: Zhao Qiang <qiang.zhao@nxp.com> 635ef1c20SZhao Qiang * 735ef1c20SZhao Qiang * Description: 835ef1c20SZhao Qiang * QE TDM API Set - TDM specific routines implementations. 935ef1c20SZhao Qiang */ 1035ef1c20SZhao Qiang #include <linux/io.h> 1135ef1c20SZhao Qiang #include <linux/kernel.h> 1235ef1c20SZhao Qiang #include <linux/of_address.h> 1335ef1c20SZhao Qiang #include <linux/of_irq.h> 1435ef1c20SZhao Qiang #include <linux/of_platform.h> 1535ef1c20SZhao Qiang #include <soc/fsl/qe/qe_tdm.h> 1635ef1c20SZhao Qiang 1735ef1c20SZhao Qiang static int set_tdm_framer(const char *tdm_framer_type) 1835ef1c20SZhao Qiang { 1935ef1c20SZhao Qiang if (strcmp(tdm_framer_type, "e1") == 0) 2035ef1c20SZhao Qiang return TDM_FRAMER_E1; 2135ef1c20SZhao Qiang else if (strcmp(tdm_framer_type, "t1") == 0) 2235ef1c20SZhao Qiang return TDM_FRAMER_T1; 2335ef1c20SZhao Qiang else 2435ef1c20SZhao Qiang return -EINVAL; 2535ef1c20SZhao Qiang } 2635ef1c20SZhao Qiang 2735ef1c20SZhao Qiang static void set_si_param(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info) 2835ef1c20SZhao Qiang { 2935ef1c20SZhao Qiang struct si_mode_info *si_info = &ut_info->si_info; 3035ef1c20SZhao Qiang 3135ef1c20SZhao Qiang if (utdm->tdm_mode == TDM_INTERNAL_LOOPBACK) { 3235ef1c20SZhao Qiang si_info->simr_crt = 1; 3335ef1c20SZhao Qiang si_info->simr_rfsd = 0; 3435ef1c20SZhao Qiang } 3535ef1c20SZhao Qiang } 3635ef1c20SZhao Qiang 3735ef1c20SZhao Qiang int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm, 3835ef1c20SZhao Qiang struct ucc_tdm_info *ut_info) 3935ef1c20SZhao Qiang { 4035ef1c20SZhao Qiang const char *sprop; 4135ef1c20SZhao Qiang int ret = 0; 4235ef1c20SZhao Qiang u32 val; 4335ef1c20SZhao Qiang 4435ef1c20SZhao Qiang sprop = of_get_property(np, "fsl,rx-sync-clock", NULL); 4535ef1c20SZhao Qiang if (sprop) { 4635ef1c20SZhao Qiang ut_info->uf_info.rx_sync = qe_clock_source(sprop); 4735ef1c20SZhao Qiang if ((ut_info->uf_info.rx_sync < QE_CLK_NONE) || 4835ef1c20SZhao Qiang (ut_info->uf_info.rx_sync > QE_RSYNC_PIN)) { 4935ef1c20SZhao Qiang pr_err("QE-TDM: Invalid rx-sync-clock property\n"); 5035ef1c20SZhao Qiang return -EINVAL; 5135ef1c20SZhao Qiang } 5235ef1c20SZhao Qiang } else { 5335ef1c20SZhao Qiang pr_err("QE-TDM: Invalid rx-sync-clock property\n"); 5435ef1c20SZhao Qiang return -EINVAL; 5535ef1c20SZhao Qiang } 5635ef1c20SZhao Qiang 5735ef1c20SZhao Qiang sprop = of_get_property(np, "fsl,tx-sync-clock", NULL); 5835ef1c20SZhao Qiang if (sprop) { 5935ef1c20SZhao Qiang ut_info->uf_info.tx_sync = qe_clock_source(sprop); 6035ef1c20SZhao Qiang if ((ut_info->uf_info.tx_sync < QE_CLK_NONE) || 6135ef1c20SZhao Qiang (ut_info->uf_info.tx_sync > QE_TSYNC_PIN)) { 6235ef1c20SZhao Qiang pr_err("QE-TDM: Invalid tx-sync-clock property\n"); 6335ef1c20SZhao Qiang return -EINVAL; 6435ef1c20SZhao Qiang } 6535ef1c20SZhao Qiang } else { 6635ef1c20SZhao Qiang pr_err("QE-TDM: Invalid tx-sync-clock property\n"); 6735ef1c20SZhao Qiang return -EINVAL; 6835ef1c20SZhao Qiang } 6935ef1c20SZhao Qiang 7035ef1c20SZhao Qiang ret = of_property_read_u32_index(np, "fsl,tx-timeslot-mask", 0, &val); 7135ef1c20SZhao Qiang if (ret) { 7235ef1c20SZhao Qiang pr_err("QE-TDM: Invalid tx-timeslot-mask property\n"); 7335ef1c20SZhao Qiang return -EINVAL; 7435ef1c20SZhao Qiang } 7535ef1c20SZhao Qiang utdm->tx_ts_mask = val; 7635ef1c20SZhao Qiang 7735ef1c20SZhao Qiang ret = of_property_read_u32_index(np, "fsl,rx-timeslot-mask", 0, &val); 7835ef1c20SZhao Qiang if (ret) { 7935ef1c20SZhao Qiang ret = -EINVAL; 8035ef1c20SZhao Qiang pr_err("QE-TDM: Invalid rx-timeslot-mask property\n"); 8135ef1c20SZhao Qiang return ret; 8235ef1c20SZhao Qiang } 8335ef1c20SZhao Qiang utdm->rx_ts_mask = val; 8435ef1c20SZhao Qiang 8535ef1c20SZhao Qiang ret = of_property_read_u32_index(np, "fsl,tdm-id", 0, &val); 8635ef1c20SZhao Qiang if (ret) { 8735ef1c20SZhao Qiang ret = -EINVAL; 8835ef1c20SZhao Qiang pr_err("QE-TDM: No fsl,tdm-id property for this UCC\n"); 8935ef1c20SZhao Qiang return ret; 9035ef1c20SZhao Qiang } 9135ef1c20SZhao Qiang utdm->tdm_port = val; 9235ef1c20SZhao Qiang ut_info->uf_info.tdm_num = utdm->tdm_port; 9335ef1c20SZhao Qiang 9474c269f6SJulia Lawall if (of_property_read_bool(np, "fsl,tdm-internal-loopback")) 9535ef1c20SZhao Qiang utdm->tdm_mode = TDM_INTERNAL_LOOPBACK; 9635ef1c20SZhao Qiang else 9735ef1c20SZhao Qiang utdm->tdm_mode = TDM_NORMAL; 9835ef1c20SZhao Qiang 9935ef1c20SZhao Qiang sprop = of_get_property(np, "fsl,tdm-framer-type", NULL); 10035ef1c20SZhao Qiang if (!sprop) { 10135ef1c20SZhao Qiang ret = -EINVAL; 10235ef1c20SZhao Qiang pr_err("QE-TDM: No tdm-framer-type property for UCC\n"); 10335ef1c20SZhao Qiang return ret; 10435ef1c20SZhao Qiang } 10535ef1c20SZhao Qiang ret = set_tdm_framer(sprop); 10635ef1c20SZhao Qiang if (ret < 0) 10735ef1c20SZhao Qiang return -EINVAL; 10835ef1c20SZhao Qiang utdm->tdm_framer_type = ret; 10935ef1c20SZhao Qiang 11035ef1c20SZhao Qiang ret = of_property_read_u32_index(np, "fsl,siram-entry-id", 0, &val); 11135ef1c20SZhao Qiang if (ret) { 11235ef1c20SZhao Qiang ret = -EINVAL; 11335ef1c20SZhao Qiang pr_err("QE-TDM: No siram entry id for UCC\n"); 11435ef1c20SZhao Qiang return ret; 11535ef1c20SZhao Qiang } 11635ef1c20SZhao Qiang utdm->siram_entry_id = val; 11735ef1c20SZhao Qiang 11835ef1c20SZhao Qiang set_si_param(utdm, ut_info); 11935ef1c20SZhao Qiang return ret; 12035ef1c20SZhao Qiang } 1214ba25162SValentin Longchamp EXPORT_SYMBOL(ucc_of_parse_tdm); 12235ef1c20SZhao Qiang 12335ef1c20SZhao Qiang void ucc_tdm_init(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info) 12435ef1c20SZhao Qiang { 12535ef1c20SZhao Qiang struct si1 __iomem *si_regs; 12635ef1c20SZhao Qiang u16 __iomem *siram; 12735ef1c20SZhao Qiang u16 siram_entry_valid; 12835ef1c20SZhao Qiang u16 siram_entry_closed; 12935ef1c20SZhao Qiang u16 ucc_num; 13035ef1c20SZhao Qiang u8 csel; 13135ef1c20SZhao Qiang u16 sixmr; 13235ef1c20SZhao Qiang u16 tdm_port; 13335ef1c20SZhao Qiang u32 siram_entry_id; 13435ef1c20SZhao Qiang u32 mask; 13535ef1c20SZhao Qiang int i; 13635ef1c20SZhao Qiang 13735ef1c20SZhao Qiang si_regs = utdm->si_regs; 13835ef1c20SZhao Qiang siram = utdm->siram; 13935ef1c20SZhao Qiang ucc_num = ut_info->uf_info.ucc_num; 14035ef1c20SZhao Qiang tdm_port = utdm->tdm_port; 14135ef1c20SZhao Qiang siram_entry_id = utdm->siram_entry_id; 14235ef1c20SZhao Qiang 14335ef1c20SZhao Qiang if (utdm->tdm_framer_type == TDM_FRAMER_T1) 14435ef1c20SZhao Qiang utdm->num_of_ts = 24; 14535ef1c20SZhao Qiang if (utdm->tdm_framer_type == TDM_FRAMER_E1) 14635ef1c20SZhao Qiang utdm->num_of_ts = 32; 14735ef1c20SZhao Qiang 14835ef1c20SZhao Qiang /* set siram table */ 14935ef1c20SZhao Qiang csel = (ucc_num < 4) ? ucc_num + 9 : ucc_num - 3; 15035ef1c20SZhao Qiang 15135ef1c20SZhao Qiang siram_entry_valid = SIR_CSEL(csel) | SIR_BYTE | SIR_CNT(0); 15235ef1c20SZhao Qiang siram_entry_closed = SIR_IDLE | SIR_BYTE | SIR_CNT(0); 15335ef1c20SZhao Qiang 15435ef1c20SZhao Qiang for (i = 0; i < utdm->num_of_ts; i++) { 15535ef1c20SZhao Qiang mask = 0x01 << i; 15635ef1c20SZhao Qiang 15735ef1c20SZhao Qiang if (utdm->tx_ts_mask & mask) 15835ef1c20SZhao Qiang iowrite16be(siram_entry_valid, 15935ef1c20SZhao Qiang &siram[siram_entry_id * 32 + i]); 16035ef1c20SZhao Qiang else 16135ef1c20SZhao Qiang iowrite16be(siram_entry_closed, 16235ef1c20SZhao Qiang &siram[siram_entry_id * 32 + i]); 16335ef1c20SZhao Qiang 16435ef1c20SZhao Qiang if (utdm->rx_ts_mask & mask) 16535ef1c20SZhao Qiang iowrite16be(siram_entry_valid, 16635ef1c20SZhao Qiang &siram[siram_entry_id * 32 + 0x200 + i]); 16735ef1c20SZhao Qiang else 16835ef1c20SZhao Qiang iowrite16be(siram_entry_closed, 16935ef1c20SZhao Qiang &siram[siram_entry_id * 32 + 0x200 + i]); 17035ef1c20SZhao Qiang } 17135ef1c20SZhao Qiang 17235ef1c20SZhao Qiang setbits16(&siram[(siram_entry_id * 32) + (utdm->num_of_ts - 1)], 17335ef1c20SZhao Qiang SIR_LAST); 17435ef1c20SZhao Qiang setbits16(&siram[(siram_entry_id * 32) + 0x200 + (utdm->num_of_ts - 1)], 17535ef1c20SZhao Qiang SIR_LAST); 17635ef1c20SZhao Qiang 17735ef1c20SZhao Qiang /* Set SIxMR register */ 17835ef1c20SZhao Qiang sixmr = SIMR_SAD(siram_entry_id); 17935ef1c20SZhao Qiang 18035ef1c20SZhao Qiang sixmr &= ~SIMR_SDM_MASK; 18135ef1c20SZhao Qiang 18235ef1c20SZhao Qiang if (utdm->tdm_mode == TDM_INTERNAL_LOOPBACK) 18335ef1c20SZhao Qiang sixmr |= SIMR_SDM_INTERNAL_LOOPBACK; 18435ef1c20SZhao Qiang else 18535ef1c20SZhao Qiang sixmr |= SIMR_SDM_NORMAL; 18635ef1c20SZhao Qiang 18735ef1c20SZhao Qiang sixmr |= SIMR_RFSD(ut_info->si_info.simr_rfsd) | 18835ef1c20SZhao Qiang SIMR_TFSD(ut_info->si_info.simr_tfsd); 18935ef1c20SZhao Qiang 19035ef1c20SZhao Qiang if (ut_info->si_info.simr_crt) 19135ef1c20SZhao Qiang sixmr |= SIMR_CRT; 19235ef1c20SZhao Qiang if (ut_info->si_info.simr_sl) 19335ef1c20SZhao Qiang sixmr |= SIMR_SL; 19435ef1c20SZhao Qiang if (ut_info->si_info.simr_ce) 19535ef1c20SZhao Qiang sixmr |= SIMR_CE; 19635ef1c20SZhao Qiang if (ut_info->si_info.simr_fe) 19735ef1c20SZhao Qiang sixmr |= SIMR_FE; 19835ef1c20SZhao Qiang if (ut_info->si_info.simr_gm) 19935ef1c20SZhao Qiang sixmr |= SIMR_GM; 20035ef1c20SZhao Qiang 20135ef1c20SZhao Qiang switch (tdm_port) { 20235ef1c20SZhao Qiang case 0: 20335ef1c20SZhao Qiang iowrite16be(sixmr, &si_regs->sixmr1[0]); 20435ef1c20SZhao Qiang break; 20535ef1c20SZhao Qiang case 1: 20635ef1c20SZhao Qiang iowrite16be(sixmr, &si_regs->sixmr1[1]); 20735ef1c20SZhao Qiang break; 20835ef1c20SZhao Qiang case 2: 20935ef1c20SZhao Qiang iowrite16be(sixmr, &si_regs->sixmr1[2]); 21035ef1c20SZhao Qiang break; 21135ef1c20SZhao Qiang case 3: 21235ef1c20SZhao Qiang iowrite16be(sixmr, &si_regs->sixmr1[3]); 21335ef1c20SZhao Qiang break; 21435ef1c20SZhao Qiang default: 21535ef1c20SZhao Qiang pr_err("QE-TDM: can not find tdm sixmr reg\n"); 21635ef1c20SZhao Qiang break; 21735ef1c20SZhao Qiang } 21835ef1c20SZhao Qiang } 2194ba25162SValentin Longchamp EXPORT_SYMBOL(ucc_tdm_init); 220