Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fsl/qe: Add QE TDM lib

QE has module to support TDM, some other protocols
supported by QE are based on TDM.
add a qe-tdm lib, this lib provides functions to the protocols
using TDM to configurate QE-TDM.

Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Zhao Qiang and committed by
David S. Miller
35ef1c20 19163ac3

+377 -5
+5 -1
drivers/soc/fsl/qe/Kconfig
··· 22 22 23 23 config UCC_FAST 24 24 bool 25 - default y if UCC_GETH 25 + default y if UCC_GETH || QE_TDM 26 26 help 27 27 This option provides qe_lib support to UCC fast 28 28 protocols: HDLC, Ethernet, ATM, transparent ··· 30 30 config UCC 31 31 bool 32 32 default y if UCC_FAST || UCC_SLOW 33 + 34 + config QE_TDM 35 + bool 36 + default y if FSL_UCC_HDLC 33 37 34 38 config QE_USB 35 39 bool
+1
drivers/soc/fsl/qe/Makefile
··· 6 6 obj-$(CONFIG_UCC) += ucc.o 7 7 obj-$(CONFIG_UCC_SLOW) += ucc_slow.o 8 8 obj-$(CONFIG_UCC_FAST) += ucc_fast.o 9 + obj-$(CONFIG_QE_TDM) += qe_tdm.o 9 10 obj-$(CONFIG_QE_USB) += usb.o 10 11 obj-$(CONFIG_QE_GPIO) += gpio.o
+276
drivers/soc/fsl/qe/qe_tdm.c
··· 1 + /* 2 + * Copyright (C) 2015 Freescale Semiconductor, Inc. All rights reserved. 3 + * 4 + * Authors: Zhao Qiang <qiang.zhao@nxp.com> 5 + * 6 + * Description: 7 + * QE TDM API Set - TDM specific routines implementations. 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License as published by the 11 + * Free Software Foundation; either version 2 of the License, or (at your 12 + * option) any later version. 13 + */ 14 + #include <linux/io.h> 15 + #include <linux/kernel.h> 16 + #include <linux/of_address.h> 17 + #include <linux/of_irq.h> 18 + #include <linux/of_platform.h> 19 + #include <soc/fsl/qe/qe_tdm.h> 20 + 21 + static int set_tdm_framer(const char *tdm_framer_type) 22 + { 23 + if (strcmp(tdm_framer_type, "e1") == 0) 24 + return TDM_FRAMER_E1; 25 + else if (strcmp(tdm_framer_type, "t1") == 0) 26 + return TDM_FRAMER_T1; 27 + else 28 + return -EINVAL; 29 + } 30 + 31 + static void set_si_param(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info) 32 + { 33 + struct si_mode_info *si_info = &ut_info->si_info; 34 + 35 + if (utdm->tdm_mode == TDM_INTERNAL_LOOPBACK) { 36 + si_info->simr_crt = 1; 37 + si_info->simr_rfsd = 0; 38 + } 39 + } 40 + 41 + int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm, 42 + struct ucc_tdm_info *ut_info) 43 + { 44 + const char *sprop; 45 + int ret = 0; 46 + u32 val; 47 + struct resource *res; 48 + struct device_node *np2; 49 + static int siram_init_flag; 50 + struct platform_device *pdev; 51 + 52 + sprop = of_get_property(np, "fsl,rx-sync-clock", NULL); 53 + if (sprop) { 54 + ut_info->uf_info.rx_sync = qe_clock_source(sprop); 55 + if ((ut_info->uf_info.rx_sync < QE_CLK_NONE) || 56 + (ut_info->uf_info.rx_sync > QE_RSYNC_PIN)) { 57 + pr_err("QE-TDM: Invalid rx-sync-clock property\n"); 58 + return -EINVAL; 59 + } 60 + } else { 61 + pr_err("QE-TDM: Invalid rx-sync-clock property\n"); 62 + return -EINVAL; 63 + } 64 + 65 + sprop = of_get_property(np, "fsl,tx-sync-clock", NULL); 66 + if (sprop) { 67 + ut_info->uf_info.tx_sync = qe_clock_source(sprop); 68 + if ((ut_info->uf_info.tx_sync < QE_CLK_NONE) || 69 + (ut_info->uf_info.tx_sync > QE_TSYNC_PIN)) { 70 + pr_err("QE-TDM: Invalid tx-sync-clock property\n"); 71 + return -EINVAL; 72 + } 73 + } else { 74 + pr_err("QE-TDM: Invalid tx-sync-clock property\n"); 75 + return -EINVAL; 76 + } 77 + 78 + ret = of_property_read_u32_index(np, "fsl,tx-timeslot-mask", 0, &val); 79 + if (ret) { 80 + pr_err("QE-TDM: Invalid tx-timeslot-mask property\n"); 81 + return -EINVAL; 82 + } 83 + utdm->tx_ts_mask = val; 84 + 85 + ret = of_property_read_u32_index(np, "fsl,rx-timeslot-mask", 0, &val); 86 + if (ret) { 87 + ret = -EINVAL; 88 + pr_err("QE-TDM: Invalid rx-timeslot-mask property\n"); 89 + return ret; 90 + } 91 + utdm->rx_ts_mask = val; 92 + 93 + ret = of_property_read_u32_index(np, "fsl,tdm-id", 0, &val); 94 + if (ret) { 95 + ret = -EINVAL; 96 + pr_err("QE-TDM: No fsl,tdm-id property for this UCC\n"); 97 + return ret; 98 + } 99 + utdm->tdm_port = val; 100 + ut_info->uf_info.tdm_num = utdm->tdm_port; 101 + 102 + if (of_get_property(np, "fsl,tdm-internal-loopback", NULL)) 103 + utdm->tdm_mode = TDM_INTERNAL_LOOPBACK; 104 + else 105 + utdm->tdm_mode = TDM_NORMAL; 106 + 107 + sprop = of_get_property(np, "fsl,tdm-framer-type", NULL); 108 + if (!sprop) { 109 + ret = -EINVAL; 110 + pr_err("QE-TDM: No tdm-framer-type property for UCC\n"); 111 + return ret; 112 + } 113 + ret = set_tdm_framer(sprop); 114 + if (ret < 0) 115 + return -EINVAL; 116 + utdm->tdm_framer_type = ret; 117 + 118 + ret = of_property_read_u32_index(np, "fsl,siram-entry-id", 0, &val); 119 + if (ret) { 120 + ret = -EINVAL; 121 + pr_err("QE-TDM: No siram entry id for UCC\n"); 122 + return ret; 123 + } 124 + utdm->siram_entry_id = val; 125 + 126 + set_si_param(utdm, ut_info); 127 + 128 + np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-si"); 129 + if (!np2) 130 + return -EINVAL; 131 + 132 + pdev = of_find_device_by_node(np2); 133 + if (!pdev) { 134 + pr_err("%s: failed to lookup pdev\n", np2->name); 135 + of_node_put(np2); 136 + return -EINVAL; 137 + } 138 + 139 + of_node_put(np2); 140 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 141 + utdm->si_regs = devm_ioremap_resource(&pdev->dev, res); 142 + if (IS_ERR(utdm->si_regs)) { 143 + ret = PTR_ERR(utdm->si_regs); 144 + goto err_miss_siram_property; 145 + } 146 + 147 + np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-siram"); 148 + if (!np2) { 149 + ret = -EINVAL; 150 + goto err_miss_siram_property; 151 + } 152 + 153 + pdev = of_find_device_by_node(np2); 154 + if (!pdev) { 155 + ret = -EINVAL; 156 + pr_err("%s: failed to lookup pdev\n", np2->name); 157 + of_node_put(np2); 158 + goto err_miss_siram_property; 159 + } 160 + 161 + of_node_put(np2); 162 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 163 + utdm->siram = devm_ioremap_resource(&pdev->dev, res); 164 + if (IS_ERR(utdm->siram)) { 165 + ret = PTR_ERR(utdm->siram); 166 + goto err_miss_siram_property; 167 + } 168 + 169 + if (siram_init_flag == 0) { 170 + memset_io(utdm->siram, 0, res->end - res->start + 1); 171 + siram_init_flag = 1; 172 + } 173 + 174 + return ret; 175 + 176 + err_miss_siram_property: 177 + devm_iounmap(&pdev->dev, utdm->si_regs); 178 + return ret; 179 + } 180 + 181 + void ucc_tdm_init(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info) 182 + { 183 + struct si1 __iomem *si_regs; 184 + u16 __iomem *siram; 185 + u16 siram_entry_valid; 186 + u16 siram_entry_closed; 187 + u16 ucc_num; 188 + u8 csel; 189 + u16 sixmr; 190 + u16 tdm_port; 191 + u32 siram_entry_id; 192 + u32 mask; 193 + int i; 194 + 195 + si_regs = utdm->si_regs; 196 + siram = utdm->siram; 197 + ucc_num = ut_info->uf_info.ucc_num; 198 + tdm_port = utdm->tdm_port; 199 + siram_entry_id = utdm->siram_entry_id; 200 + 201 + if (utdm->tdm_framer_type == TDM_FRAMER_T1) 202 + utdm->num_of_ts = 24; 203 + if (utdm->tdm_framer_type == TDM_FRAMER_E1) 204 + utdm->num_of_ts = 32; 205 + 206 + /* set siram table */ 207 + csel = (ucc_num < 4) ? ucc_num + 9 : ucc_num - 3; 208 + 209 + siram_entry_valid = SIR_CSEL(csel) | SIR_BYTE | SIR_CNT(0); 210 + siram_entry_closed = SIR_IDLE | SIR_BYTE | SIR_CNT(0); 211 + 212 + for (i = 0; i < utdm->num_of_ts; i++) { 213 + mask = 0x01 << i; 214 + 215 + if (utdm->tx_ts_mask & mask) 216 + iowrite16be(siram_entry_valid, 217 + &siram[siram_entry_id * 32 + i]); 218 + else 219 + iowrite16be(siram_entry_closed, 220 + &siram[siram_entry_id * 32 + i]); 221 + 222 + if (utdm->rx_ts_mask & mask) 223 + iowrite16be(siram_entry_valid, 224 + &siram[siram_entry_id * 32 + 0x200 + i]); 225 + else 226 + iowrite16be(siram_entry_closed, 227 + &siram[siram_entry_id * 32 + 0x200 + i]); 228 + } 229 + 230 + setbits16(&siram[(siram_entry_id * 32) + (utdm->num_of_ts - 1)], 231 + SIR_LAST); 232 + setbits16(&siram[(siram_entry_id * 32) + 0x200 + (utdm->num_of_ts - 1)], 233 + SIR_LAST); 234 + 235 + /* Set SIxMR register */ 236 + sixmr = SIMR_SAD(siram_entry_id); 237 + 238 + sixmr &= ~SIMR_SDM_MASK; 239 + 240 + if (utdm->tdm_mode == TDM_INTERNAL_LOOPBACK) 241 + sixmr |= SIMR_SDM_INTERNAL_LOOPBACK; 242 + else 243 + sixmr |= SIMR_SDM_NORMAL; 244 + 245 + sixmr |= SIMR_RFSD(ut_info->si_info.simr_rfsd) | 246 + SIMR_TFSD(ut_info->si_info.simr_tfsd); 247 + 248 + if (ut_info->si_info.simr_crt) 249 + sixmr |= SIMR_CRT; 250 + if (ut_info->si_info.simr_sl) 251 + sixmr |= SIMR_SL; 252 + if (ut_info->si_info.simr_ce) 253 + sixmr |= SIMR_CE; 254 + if (ut_info->si_info.simr_fe) 255 + sixmr |= SIMR_FE; 256 + if (ut_info->si_info.simr_gm) 257 + sixmr |= SIMR_GM; 258 + 259 + switch (tdm_port) { 260 + case 0: 261 + iowrite16be(sixmr, &si_regs->sixmr1[0]); 262 + break; 263 + case 1: 264 + iowrite16be(sixmr, &si_regs->sixmr1[1]); 265 + break; 266 + case 2: 267 + iowrite16be(sixmr, &si_regs->sixmr1[2]); 268 + break; 269 + case 3: 270 + iowrite16be(sixmr, &si_regs->sixmr1[3]); 271 + break; 272 + default: 273 + pr_err("QE-TDM: can not find tdm sixmr reg\n"); 274 + break; 275 + } 276 + }
+1 -4
include/soc/fsl/qe/immap_qe.h
··· 159 159 160 160 /* SI */ 161 161 struct si1 { 162 - __be16 siamr1; /* SI1 TDMA mode register */ 163 - __be16 sibmr1; /* SI1 TDMB mode register */ 164 - __be16 sicmr1; /* SI1 TDMC mode register */ 165 - __be16 sidmr1; /* SI1 TDMD mode register */ 162 + __be16 sixmr1[4]; /* SI1 TDMx (x = A B C D) mode register */ 166 163 u8 siglmr1_h; /* SI1 global mode register high */ 167 164 u8 res0[0x1]; 168 165 u8 sicmdr1_h; /* SI1 command register high */
+94
include/soc/fsl/qe/qe_tdm.h
··· 1 + /* 2 + * Internal header file for QE TDM mode routines. 3 + * 4 + * Copyright (C) 2016 Freescale Semiconductor, Inc. All rights reserved. 5 + * 6 + * Authors: Zhao Qiang <qiang.zhao@nxp.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version 12 + */ 13 + 14 + #ifndef CONFIG_QE_TDM_H 15 + #define CONFIG_QE_TDM_H 16 + 17 + #include <linux/kernel.h> 18 + #include <linux/list.h> 19 + 20 + #include <soc/fsl/qe/immap_qe.h> 21 + #include <soc/fsl/qe/qe.h> 22 + 23 + #include <soc/fsl/qe/ucc.h> 24 + #include <soc/fsl/qe/ucc_fast.h> 25 + 26 + /* SI RAM entries */ 27 + #define SIR_LAST 0x0001 28 + #define SIR_BYTE 0x0002 29 + #define SIR_CNT(x) ((x) << 2) 30 + #define SIR_CSEL(x) ((x) << 5) 31 + #define SIR_SGS 0x0200 32 + #define SIR_SWTR 0x4000 33 + #define SIR_MCC 0x8000 34 + #define SIR_IDLE 0 35 + 36 + /* SIxMR fields */ 37 + #define SIMR_SAD(x) ((x) << 12) 38 + #define SIMR_SDM_NORMAL 0x0000 39 + #define SIMR_SDM_INTERNAL_LOOPBACK 0x0800 40 + #define SIMR_SDM_MASK 0x0c00 41 + #define SIMR_CRT 0x0040 42 + #define SIMR_SL 0x0020 43 + #define SIMR_CE 0x0010 44 + #define SIMR_FE 0x0008 45 + #define SIMR_GM 0x0004 46 + #define SIMR_TFSD(n) (n) 47 + #define SIMR_RFSD(n) ((n) << 8) 48 + 49 + enum tdm_ts_t { 50 + TDM_TX_TS, 51 + TDM_RX_TS 52 + }; 53 + 54 + enum tdm_framer_t { 55 + TDM_FRAMER_T1, 56 + TDM_FRAMER_E1 57 + }; 58 + 59 + enum tdm_mode_t { 60 + TDM_INTERNAL_LOOPBACK, 61 + TDM_NORMAL 62 + }; 63 + 64 + struct si_mode_info { 65 + u8 simr_rfsd; 66 + u8 simr_tfsd; 67 + u8 simr_crt; 68 + u8 simr_sl; 69 + u8 simr_ce; 70 + u8 simr_fe; 71 + u8 simr_gm; 72 + }; 73 + 74 + struct ucc_tdm_info { 75 + struct ucc_fast_info uf_info; 76 + struct si_mode_info si_info; 77 + }; 78 + 79 + struct ucc_tdm { 80 + u16 tdm_port; /* port for this tdm:TDMA,TDMB */ 81 + u32 siram_entry_id; 82 + u16 __iomem *siram; 83 + struct si1 __iomem *si_regs; 84 + enum tdm_framer_t tdm_framer_type; 85 + enum tdm_mode_t tdm_mode; 86 + u8 num_of_ts; /* the number of timeslots in this tdm frame */ 87 + u32 tx_ts_mask; /* tx time slot mask */ 88 + u32 rx_ts_mask; /* rx time slot mask */ 89 + }; 90 + 91 + int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm, 92 + struct ucc_tdm_info *ut_info); 93 + void ucc_tdm_init(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info); 94 + #endif