2 * Copyright (C) 2015 Freescale Semiconductor, Inc. All rights reserved.
4 * Authors: Zhao Qiang <qiang.zhao@nxp.com>
7 * QE TDM API Set - TDM specific routines implementations.
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.
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>
21 static int set_tdm_framer(const char *tdm_framer_type
)
23 if (strcmp(tdm_framer_type
, "e1") == 0)
25 else if (strcmp(tdm_framer_type
, "t1") == 0)
31 static void set_si_param(struct ucc_tdm
*utdm
, struct ucc_tdm_info
*ut_info
)
33 struct si_mode_info
*si_info
= &ut_info
->si_info
;
35 if (utdm
->tdm_mode
== TDM_INTERNAL_LOOPBACK
) {
36 si_info
->simr_crt
= 1;
37 si_info
->simr_rfsd
= 0;
41 int ucc_of_parse_tdm(struct device_node
*np
, struct ucc_tdm
*utdm
,
42 struct ucc_tdm_info
*ut_info
)
48 struct device_node
*np2
;
49 static int siram_init_flag
;
50 struct platform_device
*pdev
;
52 sprop
= of_get_property(np
, "fsl,rx-sync-clock", NULL
);
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");
61 pr_err("QE-TDM: Invalid rx-sync-clock property\n");
65 sprop
= of_get_property(np
, "fsl,tx-sync-clock", NULL
);
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");
74 pr_err("QE-TDM: Invalid tx-sync-clock property\n");
78 ret
= of_property_read_u32_index(np
, "fsl,tx-timeslot-mask", 0, &val
);
80 pr_err("QE-TDM: Invalid tx-timeslot-mask property\n");
83 utdm
->tx_ts_mask
= val
;
85 ret
= of_property_read_u32_index(np
, "fsl,rx-timeslot-mask", 0, &val
);
88 pr_err("QE-TDM: Invalid rx-timeslot-mask property\n");
91 utdm
->rx_ts_mask
= val
;
93 ret
= of_property_read_u32_index(np
, "fsl,tdm-id", 0, &val
);
96 pr_err("QE-TDM: No fsl,tdm-id property for this UCC\n");
100 ut_info
->uf_info
.tdm_num
= utdm
->tdm_port
;
102 if (of_property_read_bool(np
, "fsl,tdm-internal-loopback"))
103 utdm
->tdm_mode
= TDM_INTERNAL_LOOPBACK
;
105 utdm
->tdm_mode
= TDM_NORMAL
;
107 sprop
= of_get_property(np
, "fsl,tdm-framer-type", NULL
);
110 pr_err("QE-TDM: No tdm-framer-type property for UCC\n");
113 ret
= set_tdm_framer(sprop
);
116 utdm
->tdm_framer_type
= ret
;
118 ret
= of_property_read_u32_index(np
, "fsl,siram-entry-id", 0, &val
);
121 pr_err("QE-TDM: No siram entry id for UCC\n");
124 utdm
->siram_entry_id
= val
;
126 set_si_param(utdm
, ut_info
);
128 np2
= of_find_compatible_node(NULL
, NULL
, "fsl,t1040-qe-si");
132 pdev
= of_find_device_by_node(np2
);
134 pr_err("%s: failed to lookup pdev\n", np2
->name
);
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
;
147 np2
= of_find_compatible_node(NULL
, NULL
, "fsl,t1040-qe-siram");
150 goto err_miss_siram_property
;
153 pdev
= of_find_device_by_node(np2
);
156 pr_err("%s: failed to lookup pdev\n", np2
->name
);
158 goto err_miss_siram_property
;
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
;
169 if (siram_init_flag
== 0) {
170 memset_io(utdm
->siram
, 0, resource_size(res
));
176 err_miss_siram_property
:
177 devm_iounmap(&pdev
->dev
, utdm
->si_regs
);
180 EXPORT_SYMBOL(ucc_of_parse_tdm
);
182 void ucc_tdm_init(struct ucc_tdm
*utdm
, struct ucc_tdm_info
*ut_info
)
184 struct si1 __iomem
*si_regs
;
186 u16 siram_entry_valid
;
187 u16 siram_entry_closed
;
196 si_regs
= utdm
->si_regs
;
198 ucc_num
= ut_info
->uf_info
.ucc_num
;
199 tdm_port
= utdm
->tdm_port
;
200 siram_entry_id
= utdm
->siram_entry_id
;
202 if (utdm
->tdm_framer_type
== TDM_FRAMER_T1
)
203 utdm
->num_of_ts
= 24;
204 if (utdm
->tdm_framer_type
== TDM_FRAMER_E1
)
205 utdm
->num_of_ts
= 32;
207 /* set siram table */
208 csel
= (ucc_num
< 4) ? ucc_num
+ 9 : ucc_num
- 3;
210 siram_entry_valid
= SIR_CSEL(csel
) | SIR_BYTE
| SIR_CNT(0);
211 siram_entry_closed
= SIR_IDLE
| SIR_BYTE
| SIR_CNT(0);
213 for (i
= 0; i
< utdm
->num_of_ts
; i
++) {
216 if (utdm
->tx_ts_mask
& mask
)
217 iowrite16be(siram_entry_valid
,
218 &siram
[siram_entry_id
* 32 + i
]);
220 iowrite16be(siram_entry_closed
,
221 &siram
[siram_entry_id
* 32 + i
]);
223 if (utdm
->rx_ts_mask
& mask
)
224 iowrite16be(siram_entry_valid
,
225 &siram
[siram_entry_id
* 32 + 0x200 + i
]);
227 iowrite16be(siram_entry_closed
,
228 &siram
[siram_entry_id
* 32 + 0x200 + i
]);
231 setbits16(&siram
[(siram_entry_id
* 32) + (utdm
->num_of_ts
- 1)],
233 setbits16(&siram
[(siram_entry_id
* 32) + 0x200 + (utdm
->num_of_ts
- 1)],
236 /* Set SIxMR register */
237 sixmr
= SIMR_SAD(siram_entry_id
);
239 sixmr
&= ~SIMR_SDM_MASK
;
241 if (utdm
->tdm_mode
== TDM_INTERNAL_LOOPBACK
)
242 sixmr
|= SIMR_SDM_INTERNAL_LOOPBACK
;
244 sixmr
|= SIMR_SDM_NORMAL
;
246 sixmr
|= SIMR_RFSD(ut_info
->si_info
.simr_rfsd
) |
247 SIMR_TFSD(ut_info
->si_info
.simr_tfsd
);
249 if (ut_info
->si_info
.simr_crt
)
251 if (ut_info
->si_info
.simr_sl
)
253 if (ut_info
->si_info
.simr_ce
)
255 if (ut_info
->si_info
.simr_fe
)
257 if (ut_info
->si_info
.simr_gm
)
262 iowrite16be(sixmr
, &si_regs
->sixmr1
[0]);
265 iowrite16be(sixmr
, &si_regs
->sixmr1
[1]);
268 iowrite16be(sixmr
, &si_regs
->sixmr1
[2]);
271 iowrite16be(sixmr
, &si_regs
->sixmr1
[3]);
274 pr_err("QE-TDM: can not find tdm sixmr reg\n");
278 EXPORT_SYMBOL(ucc_tdm_init
);