xref: /OK3568_Linux_fs/kernel/drivers/soc/fsl/qe/ucc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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, &reg_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, &reg_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