1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * arch/powerpc/sysdev/qe_lib/ucc.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * QE UCC API Set - UCC specific routines implementations.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Authors: Shlomi Gridish <gridish@freescale.com>
10*4882a593Smuzhiyun * Li Yang <leoli@freescale.com>
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/errno.h>
14*4882a593Smuzhiyun #include <linux/stddef.h>
15*4882a593Smuzhiyun #include <linux/spinlock.h>
16*4882a593Smuzhiyun #include <linux/export.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include <asm/io.h>
19*4882a593Smuzhiyun #include <soc/fsl/qe/immap_qe.h>
20*4882a593Smuzhiyun #include <soc/fsl/qe/qe.h>
21*4882a593Smuzhiyun #include <soc/fsl/qe/ucc.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define UCC_TDM_NUM 8
24*4882a593Smuzhiyun #define RX_SYNC_SHIFT_BASE 30
25*4882a593Smuzhiyun #define TX_SYNC_SHIFT_BASE 14
26*4882a593Smuzhiyun #define RX_CLK_SHIFT_BASE 28
27*4882a593Smuzhiyun #define TX_CLK_SHIFT_BASE 12
28*4882a593Smuzhiyun
ucc_set_qe_mux_mii_mng(unsigned int ucc_num)29*4882a593Smuzhiyun int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun unsigned long flags;
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun if (ucc_num > UCC_MAX_NUM - 1)
34*4882a593Smuzhiyun return -EINVAL;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun spin_lock_irqsave(&cmxgcr_lock, flags);
37*4882a593Smuzhiyun qe_clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
38*4882a593Smuzhiyun ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
39*4882a593Smuzhiyun spin_unlock_irqrestore(&cmxgcr_lock, flags);
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun return 0;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /* Configure the UCC to either Slow or Fast.
46*4882a593Smuzhiyun *
47*4882a593Smuzhiyun * A given UCC can be figured to support either "slow" devices (e.g. UART)
48*4882a593Smuzhiyun * or "fast" devices (e.g. Ethernet).
49*4882a593Smuzhiyun *
50*4882a593Smuzhiyun * 'ucc_num' is the UCC number, from 0 - 7.
51*4882a593Smuzhiyun *
52*4882a593Smuzhiyun * This function also sets the UCC_GUEMR_SET_RESERVED3 bit because that bit
53*4882a593Smuzhiyun * must always be set to 1.
54*4882a593Smuzhiyun */
ucc_set_type(unsigned int ucc_num,enum ucc_speed_type speed)55*4882a593Smuzhiyun int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun u8 __iomem *guemr;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /* The GUEMR register is at the same location for both slow and fast
60*4882a593Smuzhiyun devices, so we just use uccX.slow.guemr. */
61*4882a593Smuzhiyun switch (ucc_num) {
62*4882a593Smuzhiyun case 0: guemr = &qe_immr->ucc1.slow.guemr;
63*4882a593Smuzhiyun break;
64*4882a593Smuzhiyun case 1: guemr = &qe_immr->ucc2.slow.guemr;
65*4882a593Smuzhiyun break;
66*4882a593Smuzhiyun case 2: guemr = &qe_immr->ucc3.slow.guemr;
67*4882a593Smuzhiyun break;
68*4882a593Smuzhiyun case 3: guemr = &qe_immr->ucc4.slow.guemr;
69*4882a593Smuzhiyun break;
70*4882a593Smuzhiyun case 4: guemr = &qe_immr->ucc5.slow.guemr;
71*4882a593Smuzhiyun break;
72*4882a593Smuzhiyun case 5: guemr = &qe_immr->ucc6.slow.guemr;
73*4882a593Smuzhiyun break;
74*4882a593Smuzhiyun case 6: guemr = &qe_immr->ucc7.slow.guemr;
75*4882a593Smuzhiyun break;
76*4882a593Smuzhiyun case 7: guemr = &qe_immr->ucc8.slow.guemr;
77*4882a593Smuzhiyun break;
78*4882a593Smuzhiyun default:
79*4882a593Smuzhiyun return -EINVAL;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun qe_clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK,
83*4882a593Smuzhiyun UCC_GUEMR_SET_RESERVED3 | speed);
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun return 0;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
get_cmxucr_reg(unsigned int ucc_num,__be32 __iomem ** cmxucr,unsigned int * reg_num,unsigned int * shift)88*4882a593Smuzhiyun static void get_cmxucr_reg(unsigned int ucc_num, __be32 __iomem **cmxucr,
89*4882a593Smuzhiyun unsigned int *reg_num, unsigned int *shift)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun *reg_num = cmx + 1;
94*4882a593Smuzhiyun *cmxucr = &qe_immr->qmx.cmxucr[cmx];
95*4882a593Smuzhiyun *shift = 16 - 8 * (ucc_num & 2);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num,int set,u32 mask)98*4882a593Smuzhiyun int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun __be32 __iomem *cmxucr;
101*4882a593Smuzhiyun unsigned int reg_num;
102*4882a593Smuzhiyun unsigned int shift;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /* check if the UCC number is in range. */
105*4882a593Smuzhiyun if (ucc_num > UCC_MAX_NUM - 1)
106*4882a593Smuzhiyun return -EINVAL;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun if (set)
111*4882a593Smuzhiyun qe_setbits_be32(cmxucr, mask << shift);
112*4882a593Smuzhiyun else
113*4882a593Smuzhiyun qe_clrbits_be32(cmxucr, mask << shift);
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun return 0;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
ucc_set_qe_mux_rxtx(unsigned int ucc_num,enum qe_clock clock,enum comm_dir mode)118*4882a593Smuzhiyun int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
119*4882a593Smuzhiyun enum comm_dir mode)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun __be32 __iomem *cmxucr;
122*4882a593Smuzhiyun unsigned int reg_num;
123*4882a593Smuzhiyun unsigned int shift;
124*4882a593Smuzhiyun u32 clock_bits = 0;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /* check if the UCC number is in range. */
127*4882a593Smuzhiyun if (ucc_num > UCC_MAX_NUM - 1)
128*4882a593Smuzhiyun return -EINVAL;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /* The communications direction must be RX or TX */
131*4882a593Smuzhiyun if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))
132*4882a593Smuzhiyun return -EINVAL;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun switch (reg_num) {
137*4882a593Smuzhiyun case 1:
138*4882a593Smuzhiyun switch (clock) {
139*4882a593Smuzhiyun case QE_BRG1: clock_bits = 1; break;
140*4882a593Smuzhiyun case QE_BRG2: clock_bits = 2; break;
141*4882a593Smuzhiyun case QE_BRG7: clock_bits = 3; break;
142*4882a593Smuzhiyun case QE_BRG8: clock_bits = 4; break;
143*4882a593Smuzhiyun case QE_CLK9: clock_bits = 5; break;
144*4882a593Smuzhiyun case QE_CLK10: clock_bits = 6; break;
145*4882a593Smuzhiyun case QE_CLK11: clock_bits = 7; break;
146*4882a593Smuzhiyun case QE_CLK12: clock_bits = 8; break;
147*4882a593Smuzhiyun case QE_CLK15: clock_bits = 9; break;
148*4882a593Smuzhiyun case QE_CLK16: clock_bits = 10; break;
149*4882a593Smuzhiyun default: break;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun break;
152*4882a593Smuzhiyun case 2:
153*4882a593Smuzhiyun switch (clock) {
154*4882a593Smuzhiyun case QE_BRG5: clock_bits = 1; break;
155*4882a593Smuzhiyun case QE_BRG6: clock_bits = 2; break;
156*4882a593Smuzhiyun case QE_BRG7: clock_bits = 3; break;
157*4882a593Smuzhiyun case QE_BRG8: clock_bits = 4; break;
158*4882a593Smuzhiyun case QE_CLK13: clock_bits = 5; break;
159*4882a593Smuzhiyun case QE_CLK14: clock_bits = 6; break;
160*4882a593Smuzhiyun case QE_CLK19: clock_bits = 7; break;
161*4882a593Smuzhiyun case QE_CLK20: clock_bits = 8; break;
162*4882a593Smuzhiyun case QE_CLK15: clock_bits = 9; break;
163*4882a593Smuzhiyun case QE_CLK16: clock_bits = 10; break;
164*4882a593Smuzhiyun default: break;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun break;
167*4882a593Smuzhiyun case 3:
168*4882a593Smuzhiyun switch (clock) {
169*4882a593Smuzhiyun case QE_BRG9: clock_bits = 1; break;
170*4882a593Smuzhiyun case QE_BRG10: clock_bits = 2; break;
171*4882a593Smuzhiyun case QE_BRG15: clock_bits = 3; break;
172*4882a593Smuzhiyun case QE_BRG16: clock_bits = 4; break;
173*4882a593Smuzhiyun case QE_CLK3: clock_bits = 5; break;
174*4882a593Smuzhiyun case QE_CLK4: clock_bits = 6; break;
175*4882a593Smuzhiyun case QE_CLK17: clock_bits = 7; break;
176*4882a593Smuzhiyun case QE_CLK18: clock_bits = 8; break;
177*4882a593Smuzhiyun case QE_CLK7: clock_bits = 9; break;
178*4882a593Smuzhiyun case QE_CLK8: clock_bits = 10; break;
179*4882a593Smuzhiyun case QE_CLK16: clock_bits = 11; break;
180*4882a593Smuzhiyun default: break;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun break;
183*4882a593Smuzhiyun case 4:
184*4882a593Smuzhiyun switch (clock) {
185*4882a593Smuzhiyun case QE_BRG13: clock_bits = 1; break;
186*4882a593Smuzhiyun case QE_BRG14: clock_bits = 2; break;
187*4882a593Smuzhiyun case QE_BRG15: clock_bits = 3; break;
188*4882a593Smuzhiyun case QE_BRG16: clock_bits = 4; break;
189*4882a593Smuzhiyun case QE_CLK5: clock_bits = 5; break;
190*4882a593Smuzhiyun case QE_CLK6: clock_bits = 6; break;
191*4882a593Smuzhiyun case QE_CLK21: clock_bits = 7; break;
192*4882a593Smuzhiyun case QE_CLK22: clock_bits = 8; break;
193*4882a593Smuzhiyun case QE_CLK7: clock_bits = 9; break;
194*4882a593Smuzhiyun case QE_CLK8: clock_bits = 10; break;
195*4882a593Smuzhiyun case QE_CLK16: clock_bits = 11; break;
196*4882a593Smuzhiyun default: break;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun break;
199*4882a593Smuzhiyun default: break;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /* Check for invalid combination of clock and UCC number */
203*4882a593Smuzhiyun if (!clock_bits)
204*4882a593Smuzhiyun return -ENOENT;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun if (mode == COMM_DIR_RX)
207*4882a593Smuzhiyun shift += 4;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun qe_clrsetbits_be32(cmxucr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,
210*4882a593Smuzhiyun clock_bits << shift);
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun return 0;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
ucc_get_tdm_common_clk(u32 tdm_num,enum qe_clock clock)215*4882a593Smuzhiyun static int ucc_get_tdm_common_clk(u32 tdm_num, enum qe_clock clock)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun int clock_bits = -EINVAL;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /*
220*4882a593Smuzhiyun * for TDM[0, 1, 2, 3], TX and RX use common
221*4882a593Smuzhiyun * clock source BRG3,4 and CLK1,2
222*4882a593Smuzhiyun * for TDM[4, 5, 6, 7], TX and RX use common
223*4882a593Smuzhiyun * clock source BRG12,13 and CLK23,24
224*4882a593Smuzhiyun */
225*4882a593Smuzhiyun switch (tdm_num) {
226*4882a593Smuzhiyun case 0:
227*4882a593Smuzhiyun case 1:
228*4882a593Smuzhiyun case 2:
229*4882a593Smuzhiyun case 3:
230*4882a593Smuzhiyun switch (clock) {
231*4882a593Smuzhiyun case QE_BRG3:
232*4882a593Smuzhiyun clock_bits = 1;
233*4882a593Smuzhiyun break;
234*4882a593Smuzhiyun case QE_BRG4:
235*4882a593Smuzhiyun clock_bits = 2;
236*4882a593Smuzhiyun break;
237*4882a593Smuzhiyun case QE_CLK1:
238*4882a593Smuzhiyun clock_bits = 4;
239*4882a593Smuzhiyun break;
240*4882a593Smuzhiyun case QE_CLK2:
241*4882a593Smuzhiyun clock_bits = 5;
242*4882a593Smuzhiyun break;
243*4882a593Smuzhiyun default:
244*4882a593Smuzhiyun break;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun break;
247*4882a593Smuzhiyun case 4:
248*4882a593Smuzhiyun case 5:
249*4882a593Smuzhiyun case 6:
250*4882a593Smuzhiyun case 7:
251*4882a593Smuzhiyun switch (clock) {
252*4882a593Smuzhiyun case QE_BRG12:
253*4882a593Smuzhiyun clock_bits = 1;
254*4882a593Smuzhiyun break;
255*4882a593Smuzhiyun case QE_BRG13:
256*4882a593Smuzhiyun clock_bits = 2;
257*4882a593Smuzhiyun break;
258*4882a593Smuzhiyun case QE_CLK23:
259*4882a593Smuzhiyun clock_bits = 4;
260*4882a593Smuzhiyun break;
261*4882a593Smuzhiyun case QE_CLK24:
262*4882a593Smuzhiyun clock_bits = 5;
263*4882a593Smuzhiyun break;
264*4882a593Smuzhiyun default:
265*4882a593Smuzhiyun break;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun break;
268*4882a593Smuzhiyun default:
269*4882a593Smuzhiyun break;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun return clock_bits;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
ucc_get_tdm_rx_clk(u32 tdm_num,enum qe_clock clock)275*4882a593Smuzhiyun static int ucc_get_tdm_rx_clk(u32 tdm_num, enum qe_clock clock)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun int clock_bits = -EINVAL;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun switch (tdm_num) {
280*4882a593Smuzhiyun case 0:
281*4882a593Smuzhiyun switch (clock) {
282*4882a593Smuzhiyun case QE_CLK3:
283*4882a593Smuzhiyun clock_bits = 6;
284*4882a593Smuzhiyun break;
285*4882a593Smuzhiyun case QE_CLK8:
286*4882a593Smuzhiyun clock_bits = 7;
287*4882a593Smuzhiyun break;
288*4882a593Smuzhiyun default:
289*4882a593Smuzhiyun break;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun break;
292*4882a593Smuzhiyun case 1:
293*4882a593Smuzhiyun switch (clock) {
294*4882a593Smuzhiyun case QE_CLK5:
295*4882a593Smuzhiyun clock_bits = 6;
296*4882a593Smuzhiyun break;
297*4882a593Smuzhiyun case QE_CLK10:
298*4882a593Smuzhiyun clock_bits = 7;
299*4882a593Smuzhiyun break;
300*4882a593Smuzhiyun default:
301*4882a593Smuzhiyun break;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun break;
304*4882a593Smuzhiyun case 2:
305*4882a593Smuzhiyun switch (clock) {
306*4882a593Smuzhiyun case QE_CLK7:
307*4882a593Smuzhiyun clock_bits = 6;
308*4882a593Smuzhiyun break;
309*4882a593Smuzhiyun case QE_CLK12:
310*4882a593Smuzhiyun clock_bits = 7;
311*4882a593Smuzhiyun break;
312*4882a593Smuzhiyun default:
313*4882a593Smuzhiyun break;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun break;
316*4882a593Smuzhiyun case 3:
317*4882a593Smuzhiyun switch (clock) {
318*4882a593Smuzhiyun case QE_CLK9:
319*4882a593Smuzhiyun clock_bits = 6;
320*4882a593Smuzhiyun break;
321*4882a593Smuzhiyun case QE_CLK14:
322*4882a593Smuzhiyun clock_bits = 7;
323*4882a593Smuzhiyun break;
324*4882a593Smuzhiyun default:
325*4882a593Smuzhiyun break;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun break;
328*4882a593Smuzhiyun case 4:
329*4882a593Smuzhiyun switch (clock) {
330*4882a593Smuzhiyun case QE_CLK11:
331*4882a593Smuzhiyun clock_bits = 6;
332*4882a593Smuzhiyun break;
333*4882a593Smuzhiyun case QE_CLK16:
334*4882a593Smuzhiyun clock_bits = 7;
335*4882a593Smuzhiyun break;
336*4882a593Smuzhiyun default:
337*4882a593Smuzhiyun break;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun break;
340*4882a593Smuzhiyun case 5:
341*4882a593Smuzhiyun switch (clock) {
342*4882a593Smuzhiyun case QE_CLK13:
343*4882a593Smuzhiyun clock_bits = 6;
344*4882a593Smuzhiyun break;
345*4882a593Smuzhiyun case QE_CLK18:
346*4882a593Smuzhiyun clock_bits = 7;
347*4882a593Smuzhiyun break;
348*4882a593Smuzhiyun default:
349*4882a593Smuzhiyun break;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun break;
352*4882a593Smuzhiyun case 6:
353*4882a593Smuzhiyun switch (clock) {
354*4882a593Smuzhiyun case QE_CLK15:
355*4882a593Smuzhiyun clock_bits = 6;
356*4882a593Smuzhiyun break;
357*4882a593Smuzhiyun case QE_CLK20:
358*4882a593Smuzhiyun clock_bits = 7;
359*4882a593Smuzhiyun break;
360*4882a593Smuzhiyun default:
361*4882a593Smuzhiyun break;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun break;
364*4882a593Smuzhiyun case 7:
365*4882a593Smuzhiyun switch (clock) {
366*4882a593Smuzhiyun case QE_CLK17:
367*4882a593Smuzhiyun clock_bits = 6;
368*4882a593Smuzhiyun break;
369*4882a593Smuzhiyun case QE_CLK22:
370*4882a593Smuzhiyun clock_bits = 7;
371*4882a593Smuzhiyun break;
372*4882a593Smuzhiyun default:
373*4882a593Smuzhiyun break;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun break;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun return clock_bits;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun
ucc_get_tdm_tx_clk(u32 tdm_num,enum qe_clock clock)381*4882a593Smuzhiyun static int ucc_get_tdm_tx_clk(u32 tdm_num, enum qe_clock clock)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun int clock_bits = -EINVAL;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun switch (tdm_num) {
386*4882a593Smuzhiyun case 0:
387*4882a593Smuzhiyun switch (clock) {
388*4882a593Smuzhiyun case QE_CLK4:
389*4882a593Smuzhiyun clock_bits = 6;
390*4882a593Smuzhiyun break;
391*4882a593Smuzhiyun case QE_CLK9:
392*4882a593Smuzhiyun clock_bits = 7;
393*4882a593Smuzhiyun break;
394*4882a593Smuzhiyun default:
395*4882a593Smuzhiyun break;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun break;
398*4882a593Smuzhiyun case 1:
399*4882a593Smuzhiyun switch (clock) {
400*4882a593Smuzhiyun case QE_CLK6:
401*4882a593Smuzhiyun clock_bits = 6;
402*4882a593Smuzhiyun break;
403*4882a593Smuzhiyun case QE_CLK11:
404*4882a593Smuzhiyun clock_bits = 7;
405*4882a593Smuzhiyun break;
406*4882a593Smuzhiyun default:
407*4882a593Smuzhiyun break;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun break;
410*4882a593Smuzhiyun case 2:
411*4882a593Smuzhiyun switch (clock) {
412*4882a593Smuzhiyun case QE_CLK8:
413*4882a593Smuzhiyun clock_bits = 6;
414*4882a593Smuzhiyun break;
415*4882a593Smuzhiyun case QE_CLK13:
416*4882a593Smuzhiyun clock_bits = 7;
417*4882a593Smuzhiyun break;
418*4882a593Smuzhiyun default:
419*4882a593Smuzhiyun break;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun break;
422*4882a593Smuzhiyun case 3:
423*4882a593Smuzhiyun switch (clock) {
424*4882a593Smuzhiyun case QE_CLK10:
425*4882a593Smuzhiyun clock_bits = 6;
426*4882a593Smuzhiyun break;
427*4882a593Smuzhiyun case QE_CLK15:
428*4882a593Smuzhiyun clock_bits = 7;
429*4882a593Smuzhiyun break;
430*4882a593Smuzhiyun default:
431*4882a593Smuzhiyun break;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun break;
434*4882a593Smuzhiyun case 4:
435*4882a593Smuzhiyun switch (clock) {
436*4882a593Smuzhiyun case QE_CLK12:
437*4882a593Smuzhiyun clock_bits = 6;
438*4882a593Smuzhiyun break;
439*4882a593Smuzhiyun case QE_CLK17:
440*4882a593Smuzhiyun clock_bits = 7;
441*4882a593Smuzhiyun break;
442*4882a593Smuzhiyun default:
443*4882a593Smuzhiyun break;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun break;
446*4882a593Smuzhiyun case 5:
447*4882a593Smuzhiyun switch (clock) {
448*4882a593Smuzhiyun case QE_CLK14:
449*4882a593Smuzhiyun clock_bits = 6;
450*4882a593Smuzhiyun break;
451*4882a593Smuzhiyun case QE_CLK19:
452*4882a593Smuzhiyun clock_bits = 7;
453*4882a593Smuzhiyun break;
454*4882a593Smuzhiyun default:
455*4882a593Smuzhiyun break;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun break;
458*4882a593Smuzhiyun case 6:
459*4882a593Smuzhiyun switch (clock) {
460*4882a593Smuzhiyun case QE_CLK16:
461*4882a593Smuzhiyun clock_bits = 6;
462*4882a593Smuzhiyun break;
463*4882a593Smuzhiyun case QE_CLK21:
464*4882a593Smuzhiyun clock_bits = 7;
465*4882a593Smuzhiyun break;
466*4882a593Smuzhiyun default:
467*4882a593Smuzhiyun break;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun break;
470*4882a593Smuzhiyun case 7:
471*4882a593Smuzhiyun switch (clock) {
472*4882a593Smuzhiyun case QE_CLK18:
473*4882a593Smuzhiyun clock_bits = 6;
474*4882a593Smuzhiyun break;
475*4882a593Smuzhiyun case QE_CLK3:
476*4882a593Smuzhiyun clock_bits = 7;
477*4882a593Smuzhiyun break;
478*4882a593Smuzhiyun default:
479*4882a593Smuzhiyun break;
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun break;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun return clock_bits;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun /* tdm_num: TDM A-H port num is 0-7 */
ucc_get_tdm_rxtx_clk(enum comm_dir mode,u32 tdm_num,enum qe_clock clock)488*4882a593Smuzhiyun static int ucc_get_tdm_rxtx_clk(enum comm_dir mode, u32 tdm_num,
489*4882a593Smuzhiyun enum qe_clock clock)
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun int clock_bits;
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun clock_bits = ucc_get_tdm_common_clk(tdm_num, clock);
494*4882a593Smuzhiyun if (clock_bits > 0)
495*4882a593Smuzhiyun return clock_bits;
496*4882a593Smuzhiyun if (mode == COMM_DIR_RX)
497*4882a593Smuzhiyun clock_bits = ucc_get_tdm_rx_clk(tdm_num, clock);
498*4882a593Smuzhiyun if (mode == COMM_DIR_TX)
499*4882a593Smuzhiyun clock_bits = ucc_get_tdm_tx_clk(tdm_num, clock);
500*4882a593Smuzhiyun return clock_bits;
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun
ucc_get_tdm_clk_shift(enum comm_dir mode,u32 tdm_num)503*4882a593Smuzhiyun static u32 ucc_get_tdm_clk_shift(enum comm_dir mode, u32 tdm_num)
504*4882a593Smuzhiyun {
505*4882a593Smuzhiyun u32 shift;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun shift = (mode == COMM_DIR_RX) ? RX_CLK_SHIFT_BASE : TX_CLK_SHIFT_BASE;
508*4882a593Smuzhiyun if (tdm_num < 4)
509*4882a593Smuzhiyun shift -= tdm_num * 4;
510*4882a593Smuzhiyun else
511*4882a593Smuzhiyun shift -= (tdm_num - 4) * 4;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun return shift;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun
ucc_set_tdm_rxtx_clk(u32 tdm_num,enum qe_clock clock,enum comm_dir mode)516*4882a593Smuzhiyun int ucc_set_tdm_rxtx_clk(u32 tdm_num, enum qe_clock clock,
517*4882a593Smuzhiyun enum comm_dir mode)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun int clock_bits;
520*4882a593Smuzhiyun u32 shift;
521*4882a593Smuzhiyun struct qe_mux __iomem *qe_mux_reg;
522*4882a593Smuzhiyun __be32 __iomem *cmxs1cr;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun qe_mux_reg = &qe_immr->qmx;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun if (tdm_num > 7)
527*4882a593Smuzhiyun return -EINVAL;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /* The communications direction must be RX or TX */
530*4882a593Smuzhiyun if (mode != COMM_DIR_RX && mode != COMM_DIR_TX)
531*4882a593Smuzhiyun return -EINVAL;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun clock_bits = ucc_get_tdm_rxtx_clk(mode, tdm_num, clock);
534*4882a593Smuzhiyun if (clock_bits < 0)
535*4882a593Smuzhiyun return -EINVAL;
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun shift = ucc_get_tdm_clk_shift(mode, tdm_num);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun cmxs1cr = (tdm_num < 4) ? &qe_mux_reg->cmxsi1cr_l :
540*4882a593Smuzhiyun &qe_mux_reg->cmxsi1cr_h;
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun qe_clrsetbits_be32(cmxs1cr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,
543*4882a593Smuzhiyun clock_bits << shift);
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun return 0;
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
ucc_get_tdm_sync_source(u32 tdm_num,enum qe_clock clock,enum comm_dir mode)548*4882a593Smuzhiyun static int ucc_get_tdm_sync_source(u32 tdm_num, enum qe_clock clock,
549*4882a593Smuzhiyun enum comm_dir mode)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun int source = -EINVAL;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun if (mode == COMM_DIR_RX && clock == QE_RSYNC_PIN) {
554*4882a593Smuzhiyun source = 0;
555*4882a593Smuzhiyun return source;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun if (mode == COMM_DIR_TX && clock == QE_TSYNC_PIN) {
558*4882a593Smuzhiyun source = 0;
559*4882a593Smuzhiyun return source;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun switch (tdm_num) {
563*4882a593Smuzhiyun case 0:
564*4882a593Smuzhiyun case 1:
565*4882a593Smuzhiyun switch (clock) {
566*4882a593Smuzhiyun case QE_BRG9:
567*4882a593Smuzhiyun source = 1;
568*4882a593Smuzhiyun break;
569*4882a593Smuzhiyun case QE_BRG10:
570*4882a593Smuzhiyun source = 2;
571*4882a593Smuzhiyun break;
572*4882a593Smuzhiyun default:
573*4882a593Smuzhiyun break;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun break;
576*4882a593Smuzhiyun case 2:
577*4882a593Smuzhiyun case 3:
578*4882a593Smuzhiyun switch (clock) {
579*4882a593Smuzhiyun case QE_BRG9:
580*4882a593Smuzhiyun source = 1;
581*4882a593Smuzhiyun break;
582*4882a593Smuzhiyun case QE_BRG11:
583*4882a593Smuzhiyun source = 2;
584*4882a593Smuzhiyun break;
585*4882a593Smuzhiyun default:
586*4882a593Smuzhiyun break;
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun break;
589*4882a593Smuzhiyun case 4:
590*4882a593Smuzhiyun case 5:
591*4882a593Smuzhiyun switch (clock) {
592*4882a593Smuzhiyun case QE_BRG13:
593*4882a593Smuzhiyun source = 1;
594*4882a593Smuzhiyun break;
595*4882a593Smuzhiyun case QE_BRG14:
596*4882a593Smuzhiyun source = 2;
597*4882a593Smuzhiyun break;
598*4882a593Smuzhiyun default:
599*4882a593Smuzhiyun break;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun break;
602*4882a593Smuzhiyun case 6:
603*4882a593Smuzhiyun case 7:
604*4882a593Smuzhiyun switch (clock) {
605*4882a593Smuzhiyun case QE_BRG13:
606*4882a593Smuzhiyun source = 1;
607*4882a593Smuzhiyun break;
608*4882a593Smuzhiyun case QE_BRG15:
609*4882a593Smuzhiyun source = 2;
610*4882a593Smuzhiyun break;
611*4882a593Smuzhiyun default:
612*4882a593Smuzhiyun break;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun break;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun return source;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
ucc_get_tdm_sync_shift(enum comm_dir mode,u32 tdm_num)620*4882a593Smuzhiyun static u32 ucc_get_tdm_sync_shift(enum comm_dir mode, u32 tdm_num)
621*4882a593Smuzhiyun {
622*4882a593Smuzhiyun u32 shift;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun shift = (mode == COMM_DIR_RX) ? RX_SYNC_SHIFT_BASE : TX_SYNC_SHIFT_BASE;
625*4882a593Smuzhiyun shift -= tdm_num * 2;
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun return shift;
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun
ucc_set_tdm_rxtx_sync(u32 tdm_num,enum qe_clock clock,enum comm_dir mode)630*4882a593Smuzhiyun int ucc_set_tdm_rxtx_sync(u32 tdm_num, enum qe_clock clock,
631*4882a593Smuzhiyun enum comm_dir mode)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun int source;
634*4882a593Smuzhiyun u32 shift;
635*4882a593Smuzhiyun struct qe_mux __iomem *qe_mux_reg;
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun qe_mux_reg = &qe_immr->qmx;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun if (tdm_num >= UCC_TDM_NUM)
640*4882a593Smuzhiyun return -EINVAL;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun /* The communications direction must be RX or TX */
643*4882a593Smuzhiyun if (mode != COMM_DIR_RX && mode != COMM_DIR_TX)
644*4882a593Smuzhiyun return -EINVAL;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun source = ucc_get_tdm_sync_source(tdm_num, clock, mode);
647*4882a593Smuzhiyun if (source < 0)
648*4882a593Smuzhiyun return -EINVAL;
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun shift = ucc_get_tdm_sync_shift(mode, tdm_num);
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun qe_clrsetbits_be32(&qe_mux_reg->cmxsi1syr,
653*4882a593Smuzhiyun QE_CMXUCR_TX_CLK_SRC_MASK << shift,
654*4882a593Smuzhiyun source << shift);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun return 0;
657*4882a593Smuzhiyun }
658