162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * arch/powerpc/sysdev/qe_lib/ucc.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * QE UCC API Set - UCC specific routines implementations.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Authors: 	Shlomi Gridish <gridish@freescale.com>
1062306a36Sopenharmony_ci * 		Li Yang <leoli@freescale.com>
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/errno.h>
1462306a36Sopenharmony_ci#include <linux/stddef.h>
1562306a36Sopenharmony_ci#include <linux/spinlock.h>
1662306a36Sopenharmony_ci#include <linux/export.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <asm/io.h>
1962306a36Sopenharmony_ci#include <soc/fsl/qe/immap_qe.h>
2062306a36Sopenharmony_ci#include <soc/fsl/qe/qe.h>
2162306a36Sopenharmony_ci#include <soc/fsl/qe/ucc.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define UCC_TDM_NUM 8
2462306a36Sopenharmony_ci#define RX_SYNC_SHIFT_BASE 30
2562306a36Sopenharmony_ci#define TX_SYNC_SHIFT_BASE 14
2662306a36Sopenharmony_ci#define RX_CLK_SHIFT_BASE 28
2762306a36Sopenharmony_ci#define TX_CLK_SHIFT_BASE 12
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ciint ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	unsigned long flags;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	if (ucc_num > UCC_MAX_NUM - 1)
3462306a36Sopenharmony_ci		return -EINVAL;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	spin_lock_irqsave(&cmxgcr_lock, flags);
3762306a36Sopenharmony_ci	qe_clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
3862306a36Sopenharmony_ci			   ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
3962306a36Sopenharmony_ci	spin_unlock_irqrestore(&cmxgcr_lock, flags);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	return 0;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ciEXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/* Configure the UCC to either Slow or Fast.
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * A given UCC can be figured to support either "slow" devices (e.g. UART)
4862306a36Sopenharmony_ci * or "fast" devices (e.g. Ethernet).
4962306a36Sopenharmony_ci *
5062306a36Sopenharmony_ci * 'ucc_num' is the UCC number, from 0 - 7.
5162306a36Sopenharmony_ci *
5262306a36Sopenharmony_ci * This function also sets the UCC_GUEMR_SET_RESERVED3 bit because that bit
5362306a36Sopenharmony_ci * must always be set to 1.
5462306a36Sopenharmony_ci */
5562306a36Sopenharmony_ciint ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	u8 __iomem *guemr;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	/* The GUEMR register is at the same location for both slow and fast
6062306a36Sopenharmony_ci	   devices, so we just use uccX.slow.guemr. */
6162306a36Sopenharmony_ci	switch (ucc_num) {
6262306a36Sopenharmony_ci	case 0: guemr = &qe_immr->ucc1.slow.guemr;
6362306a36Sopenharmony_ci		break;
6462306a36Sopenharmony_ci	case 1: guemr = &qe_immr->ucc2.slow.guemr;
6562306a36Sopenharmony_ci		break;
6662306a36Sopenharmony_ci	case 2: guemr = &qe_immr->ucc3.slow.guemr;
6762306a36Sopenharmony_ci		break;
6862306a36Sopenharmony_ci	case 3: guemr = &qe_immr->ucc4.slow.guemr;
6962306a36Sopenharmony_ci		break;
7062306a36Sopenharmony_ci	case 4: guemr = &qe_immr->ucc5.slow.guemr;
7162306a36Sopenharmony_ci		break;
7262306a36Sopenharmony_ci	case 5: guemr = &qe_immr->ucc6.slow.guemr;
7362306a36Sopenharmony_ci		break;
7462306a36Sopenharmony_ci	case 6: guemr = &qe_immr->ucc7.slow.guemr;
7562306a36Sopenharmony_ci		break;
7662306a36Sopenharmony_ci	case 7: guemr = &qe_immr->ucc8.slow.guemr;
7762306a36Sopenharmony_ci		break;
7862306a36Sopenharmony_ci	default:
7962306a36Sopenharmony_ci		return -EINVAL;
8062306a36Sopenharmony_ci	}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	qe_clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK,
8362306a36Sopenharmony_ci			UCC_GUEMR_SET_RESERVED3 | speed);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	return 0;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic void get_cmxucr_reg(unsigned int ucc_num, __be32 __iomem **cmxucr,
8962306a36Sopenharmony_ci	unsigned int *reg_num, unsigned int *shift)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	*reg_num = cmx + 1;
9462306a36Sopenharmony_ci	*cmxucr = &qe_immr->qmx.cmxucr[cmx];
9562306a36Sopenharmony_ci	*shift = 16 - 8 * (ucc_num & 2);
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ciint ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	__be32 __iomem *cmxucr;
10162306a36Sopenharmony_ci	unsigned int reg_num;
10262306a36Sopenharmony_ci	unsigned int shift;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	/* check if the UCC number is in range. */
10562306a36Sopenharmony_ci	if (ucc_num > UCC_MAX_NUM - 1)
10662306a36Sopenharmony_ci		return -EINVAL;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	get_cmxucr_reg(ucc_num, &cmxucr, &reg_num, &shift);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	if (set)
11162306a36Sopenharmony_ci		qe_setbits_be32(cmxucr, mask << shift);
11262306a36Sopenharmony_ci	else
11362306a36Sopenharmony_ci		qe_clrbits_be32(cmxucr, mask << shift);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	return 0;
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ciint ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
11962306a36Sopenharmony_ci	enum comm_dir mode)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	__be32 __iomem *cmxucr;
12262306a36Sopenharmony_ci	unsigned int reg_num;
12362306a36Sopenharmony_ci	unsigned int shift;
12462306a36Sopenharmony_ci	u32 clock_bits = 0;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/* check if the UCC number is in range. */
12762306a36Sopenharmony_ci	if (ucc_num > UCC_MAX_NUM - 1)
12862306a36Sopenharmony_ci		return -EINVAL;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	/* The communications direction must be RX or TX */
13162306a36Sopenharmony_ci	if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))
13262306a36Sopenharmony_ci		return -EINVAL;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	get_cmxucr_reg(ucc_num, &cmxucr, &reg_num, &shift);
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	switch (reg_num) {
13762306a36Sopenharmony_ci	case 1:
13862306a36Sopenharmony_ci		switch (clock) {
13962306a36Sopenharmony_ci		case QE_BRG1:	clock_bits = 1; break;
14062306a36Sopenharmony_ci		case QE_BRG2:	clock_bits = 2; break;
14162306a36Sopenharmony_ci		case QE_BRG7:	clock_bits = 3; break;
14262306a36Sopenharmony_ci		case QE_BRG8:	clock_bits = 4; break;
14362306a36Sopenharmony_ci		case QE_CLK9:	clock_bits = 5; break;
14462306a36Sopenharmony_ci		case QE_CLK10:	clock_bits = 6; break;
14562306a36Sopenharmony_ci		case QE_CLK11:	clock_bits = 7; break;
14662306a36Sopenharmony_ci		case QE_CLK12:	clock_bits = 8; break;
14762306a36Sopenharmony_ci		case QE_CLK15:	clock_bits = 9; break;
14862306a36Sopenharmony_ci		case QE_CLK16:	clock_bits = 10; break;
14962306a36Sopenharmony_ci		default: break;
15062306a36Sopenharmony_ci		}
15162306a36Sopenharmony_ci		break;
15262306a36Sopenharmony_ci	case 2:
15362306a36Sopenharmony_ci		switch (clock) {
15462306a36Sopenharmony_ci		case QE_BRG5:	clock_bits = 1; break;
15562306a36Sopenharmony_ci		case QE_BRG6:	clock_bits = 2; break;
15662306a36Sopenharmony_ci		case QE_BRG7:	clock_bits = 3; break;
15762306a36Sopenharmony_ci		case QE_BRG8:	clock_bits = 4; break;
15862306a36Sopenharmony_ci		case QE_CLK13:	clock_bits = 5; break;
15962306a36Sopenharmony_ci		case QE_CLK14:	clock_bits = 6; break;
16062306a36Sopenharmony_ci		case QE_CLK19:	clock_bits = 7; break;
16162306a36Sopenharmony_ci		case QE_CLK20:	clock_bits = 8; break;
16262306a36Sopenharmony_ci		case QE_CLK15:	clock_bits = 9; break;
16362306a36Sopenharmony_ci		case QE_CLK16:	clock_bits = 10; break;
16462306a36Sopenharmony_ci		default: break;
16562306a36Sopenharmony_ci		}
16662306a36Sopenharmony_ci		break;
16762306a36Sopenharmony_ci	case 3:
16862306a36Sopenharmony_ci		switch (clock) {
16962306a36Sopenharmony_ci		case QE_BRG9:	clock_bits = 1; break;
17062306a36Sopenharmony_ci		case QE_BRG10:	clock_bits = 2; break;
17162306a36Sopenharmony_ci		case QE_BRG15:	clock_bits = 3; break;
17262306a36Sopenharmony_ci		case QE_BRG16:	clock_bits = 4; break;
17362306a36Sopenharmony_ci		case QE_CLK3:	clock_bits = 5; break;
17462306a36Sopenharmony_ci		case QE_CLK4:	clock_bits = 6; break;
17562306a36Sopenharmony_ci		case QE_CLK17:	clock_bits = 7; break;
17662306a36Sopenharmony_ci		case QE_CLK18:	clock_bits = 8; break;
17762306a36Sopenharmony_ci		case QE_CLK7:	clock_bits = 9; break;
17862306a36Sopenharmony_ci		case QE_CLK8:	clock_bits = 10; break;
17962306a36Sopenharmony_ci		case QE_CLK16:	clock_bits = 11; break;
18062306a36Sopenharmony_ci		default: break;
18162306a36Sopenharmony_ci		}
18262306a36Sopenharmony_ci		break;
18362306a36Sopenharmony_ci	case 4:
18462306a36Sopenharmony_ci		switch (clock) {
18562306a36Sopenharmony_ci		case QE_BRG13:	clock_bits = 1; break;
18662306a36Sopenharmony_ci		case QE_BRG14:	clock_bits = 2; break;
18762306a36Sopenharmony_ci		case QE_BRG15:	clock_bits = 3; break;
18862306a36Sopenharmony_ci		case QE_BRG16:	clock_bits = 4; break;
18962306a36Sopenharmony_ci		case QE_CLK5:	clock_bits = 5; break;
19062306a36Sopenharmony_ci		case QE_CLK6:	clock_bits = 6; break;
19162306a36Sopenharmony_ci		case QE_CLK21:	clock_bits = 7; break;
19262306a36Sopenharmony_ci		case QE_CLK22:	clock_bits = 8; break;
19362306a36Sopenharmony_ci		case QE_CLK7:	clock_bits = 9; break;
19462306a36Sopenharmony_ci		case QE_CLK8:	clock_bits = 10; break;
19562306a36Sopenharmony_ci		case QE_CLK16:	clock_bits = 11; break;
19662306a36Sopenharmony_ci		default: break;
19762306a36Sopenharmony_ci		}
19862306a36Sopenharmony_ci		break;
19962306a36Sopenharmony_ci	default: break;
20062306a36Sopenharmony_ci	}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	/* Check for invalid combination of clock and UCC number */
20362306a36Sopenharmony_ci	if (!clock_bits)
20462306a36Sopenharmony_ci		return -ENOENT;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	if (mode == COMM_DIR_RX)
20762306a36Sopenharmony_ci		shift += 4;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	qe_clrsetbits_be32(cmxucr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,
21062306a36Sopenharmony_ci			   clock_bits << shift);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	return 0;
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cistatic int ucc_get_tdm_common_clk(u32 tdm_num, enum qe_clock clock)
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	int clock_bits = -EINVAL;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	/*
22062306a36Sopenharmony_ci	 * for TDM[0, 1, 2, 3], TX and RX use  common
22162306a36Sopenharmony_ci	 * clock source BRG3,4 and CLK1,2
22262306a36Sopenharmony_ci	 * for TDM[4, 5, 6, 7], TX and RX use  common
22362306a36Sopenharmony_ci	 * clock source BRG12,13 and CLK23,24
22462306a36Sopenharmony_ci	 */
22562306a36Sopenharmony_ci	switch (tdm_num) {
22662306a36Sopenharmony_ci	case 0:
22762306a36Sopenharmony_ci	case 1:
22862306a36Sopenharmony_ci	case 2:
22962306a36Sopenharmony_ci	case 3:
23062306a36Sopenharmony_ci		switch (clock) {
23162306a36Sopenharmony_ci		case QE_BRG3:
23262306a36Sopenharmony_ci			clock_bits = 1;
23362306a36Sopenharmony_ci			break;
23462306a36Sopenharmony_ci		case QE_BRG4:
23562306a36Sopenharmony_ci			clock_bits = 2;
23662306a36Sopenharmony_ci			break;
23762306a36Sopenharmony_ci		case QE_CLK1:
23862306a36Sopenharmony_ci			clock_bits = 4;
23962306a36Sopenharmony_ci			break;
24062306a36Sopenharmony_ci		case QE_CLK2:
24162306a36Sopenharmony_ci			clock_bits = 5;
24262306a36Sopenharmony_ci			break;
24362306a36Sopenharmony_ci		default:
24462306a36Sopenharmony_ci			break;
24562306a36Sopenharmony_ci		}
24662306a36Sopenharmony_ci		break;
24762306a36Sopenharmony_ci	case 4:
24862306a36Sopenharmony_ci	case 5:
24962306a36Sopenharmony_ci	case 6:
25062306a36Sopenharmony_ci	case 7:
25162306a36Sopenharmony_ci		switch (clock) {
25262306a36Sopenharmony_ci		case QE_BRG12:
25362306a36Sopenharmony_ci			clock_bits = 1;
25462306a36Sopenharmony_ci			break;
25562306a36Sopenharmony_ci		case QE_BRG13:
25662306a36Sopenharmony_ci			clock_bits = 2;
25762306a36Sopenharmony_ci			break;
25862306a36Sopenharmony_ci		case QE_CLK23:
25962306a36Sopenharmony_ci			clock_bits = 4;
26062306a36Sopenharmony_ci			break;
26162306a36Sopenharmony_ci		case QE_CLK24:
26262306a36Sopenharmony_ci			clock_bits = 5;
26362306a36Sopenharmony_ci			break;
26462306a36Sopenharmony_ci		default:
26562306a36Sopenharmony_ci			break;
26662306a36Sopenharmony_ci		}
26762306a36Sopenharmony_ci		break;
26862306a36Sopenharmony_ci	default:
26962306a36Sopenharmony_ci		break;
27062306a36Sopenharmony_ci	}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	return clock_bits;
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic int ucc_get_tdm_rx_clk(u32 tdm_num, enum qe_clock clock)
27662306a36Sopenharmony_ci{
27762306a36Sopenharmony_ci	int clock_bits = -EINVAL;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	switch (tdm_num) {
28062306a36Sopenharmony_ci	case 0:
28162306a36Sopenharmony_ci		switch (clock) {
28262306a36Sopenharmony_ci		case QE_CLK3:
28362306a36Sopenharmony_ci			clock_bits = 6;
28462306a36Sopenharmony_ci			break;
28562306a36Sopenharmony_ci		case QE_CLK8:
28662306a36Sopenharmony_ci			clock_bits = 7;
28762306a36Sopenharmony_ci			break;
28862306a36Sopenharmony_ci		default:
28962306a36Sopenharmony_ci			break;
29062306a36Sopenharmony_ci		}
29162306a36Sopenharmony_ci		break;
29262306a36Sopenharmony_ci	case 1:
29362306a36Sopenharmony_ci		switch (clock) {
29462306a36Sopenharmony_ci		case QE_CLK5:
29562306a36Sopenharmony_ci			clock_bits = 6;
29662306a36Sopenharmony_ci			break;
29762306a36Sopenharmony_ci		case QE_CLK10:
29862306a36Sopenharmony_ci			clock_bits = 7;
29962306a36Sopenharmony_ci			break;
30062306a36Sopenharmony_ci		default:
30162306a36Sopenharmony_ci			break;
30262306a36Sopenharmony_ci		}
30362306a36Sopenharmony_ci		break;
30462306a36Sopenharmony_ci	case 2:
30562306a36Sopenharmony_ci		switch (clock) {
30662306a36Sopenharmony_ci		case QE_CLK7:
30762306a36Sopenharmony_ci			clock_bits = 6;
30862306a36Sopenharmony_ci			break;
30962306a36Sopenharmony_ci		case QE_CLK12:
31062306a36Sopenharmony_ci			clock_bits = 7;
31162306a36Sopenharmony_ci			break;
31262306a36Sopenharmony_ci		default:
31362306a36Sopenharmony_ci			break;
31462306a36Sopenharmony_ci		}
31562306a36Sopenharmony_ci		break;
31662306a36Sopenharmony_ci	case 3:
31762306a36Sopenharmony_ci		switch (clock) {
31862306a36Sopenharmony_ci		case QE_CLK9:
31962306a36Sopenharmony_ci			clock_bits = 6;
32062306a36Sopenharmony_ci			break;
32162306a36Sopenharmony_ci		case QE_CLK14:
32262306a36Sopenharmony_ci			clock_bits = 7;
32362306a36Sopenharmony_ci			break;
32462306a36Sopenharmony_ci		default:
32562306a36Sopenharmony_ci			break;
32662306a36Sopenharmony_ci		}
32762306a36Sopenharmony_ci		break;
32862306a36Sopenharmony_ci	case 4:
32962306a36Sopenharmony_ci		switch (clock) {
33062306a36Sopenharmony_ci		case QE_CLK11:
33162306a36Sopenharmony_ci			clock_bits = 6;
33262306a36Sopenharmony_ci			break;
33362306a36Sopenharmony_ci		case QE_CLK16:
33462306a36Sopenharmony_ci			clock_bits = 7;
33562306a36Sopenharmony_ci			break;
33662306a36Sopenharmony_ci		default:
33762306a36Sopenharmony_ci			break;
33862306a36Sopenharmony_ci		}
33962306a36Sopenharmony_ci		break;
34062306a36Sopenharmony_ci	case 5:
34162306a36Sopenharmony_ci		switch (clock) {
34262306a36Sopenharmony_ci		case QE_CLK13:
34362306a36Sopenharmony_ci			clock_bits = 6;
34462306a36Sopenharmony_ci			break;
34562306a36Sopenharmony_ci		case QE_CLK18:
34662306a36Sopenharmony_ci			clock_bits = 7;
34762306a36Sopenharmony_ci			break;
34862306a36Sopenharmony_ci		default:
34962306a36Sopenharmony_ci			break;
35062306a36Sopenharmony_ci		}
35162306a36Sopenharmony_ci		break;
35262306a36Sopenharmony_ci	case 6:
35362306a36Sopenharmony_ci		switch (clock) {
35462306a36Sopenharmony_ci		case QE_CLK15:
35562306a36Sopenharmony_ci			clock_bits = 6;
35662306a36Sopenharmony_ci			break;
35762306a36Sopenharmony_ci		case QE_CLK20:
35862306a36Sopenharmony_ci			clock_bits = 7;
35962306a36Sopenharmony_ci			break;
36062306a36Sopenharmony_ci		default:
36162306a36Sopenharmony_ci			break;
36262306a36Sopenharmony_ci		}
36362306a36Sopenharmony_ci		break;
36462306a36Sopenharmony_ci	case 7:
36562306a36Sopenharmony_ci		switch (clock) {
36662306a36Sopenharmony_ci		case QE_CLK17:
36762306a36Sopenharmony_ci			clock_bits = 6;
36862306a36Sopenharmony_ci			break;
36962306a36Sopenharmony_ci		case QE_CLK22:
37062306a36Sopenharmony_ci			clock_bits = 7;
37162306a36Sopenharmony_ci			break;
37262306a36Sopenharmony_ci		default:
37362306a36Sopenharmony_ci			break;
37462306a36Sopenharmony_ci		}
37562306a36Sopenharmony_ci		break;
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	return clock_bits;
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_cistatic int ucc_get_tdm_tx_clk(u32 tdm_num, enum qe_clock clock)
38262306a36Sopenharmony_ci{
38362306a36Sopenharmony_ci	int clock_bits = -EINVAL;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	switch (tdm_num) {
38662306a36Sopenharmony_ci	case 0:
38762306a36Sopenharmony_ci		switch (clock) {
38862306a36Sopenharmony_ci		case QE_CLK4:
38962306a36Sopenharmony_ci			clock_bits = 6;
39062306a36Sopenharmony_ci			break;
39162306a36Sopenharmony_ci		case QE_CLK9:
39262306a36Sopenharmony_ci			clock_bits = 7;
39362306a36Sopenharmony_ci			break;
39462306a36Sopenharmony_ci		default:
39562306a36Sopenharmony_ci			break;
39662306a36Sopenharmony_ci		}
39762306a36Sopenharmony_ci		break;
39862306a36Sopenharmony_ci	case 1:
39962306a36Sopenharmony_ci		switch (clock) {
40062306a36Sopenharmony_ci		case QE_CLK6:
40162306a36Sopenharmony_ci			clock_bits = 6;
40262306a36Sopenharmony_ci			break;
40362306a36Sopenharmony_ci		case QE_CLK11:
40462306a36Sopenharmony_ci			clock_bits = 7;
40562306a36Sopenharmony_ci			break;
40662306a36Sopenharmony_ci		default:
40762306a36Sopenharmony_ci			break;
40862306a36Sopenharmony_ci		}
40962306a36Sopenharmony_ci		break;
41062306a36Sopenharmony_ci	case 2:
41162306a36Sopenharmony_ci		switch (clock) {
41262306a36Sopenharmony_ci		case QE_CLK8:
41362306a36Sopenharmony_ci			clock_bits = 6;
41462306a36Sopenharmony_ci			break;
41562306a36Sopenharmony_ci		case QE_CLK13:
41662306a36Sopenharmony_ci			clock_bits = 7;
41762306a36Sopenharmony_ci			break;
41862306a36Sopenharmony_ci		default:
41962306a36Sopenharmony_ci			break;
42062306a36Sopenharmony_ci		}
42162306a36Sopenharmony_ci		break;
42262306a36Sopenharmony_ci	case 3:
42362306a36Sopenharmony_ci		switch (clock) {
42462306a36Sopenharmony_ci		case QE_CLK10:
42562306a36Sopenharmony_ci			clock_bits = 6;
42662306a36Sopenharmony_ci			break;
42762306a36Sopenharmony_ci		case QE_CLK15:
42862306a36Sopenharmony_ci			clock_bits = 7;
42962306a36Sopenharmony_ci			break;
43062306a36Sopenharmony_ci		default:
43162306a36Sopenharmony_ci			break;
43262306a36Sopenharmony_ci		}
43362306a36Sopenharmony_ci		break;
43462306a36Sopenharmony_ci	case 4:
43562306a36Sopenharmony_ci		switch (clock) {
43662306a36Sopenharmony_ci		case QE_CLK12:
43762306a36Sopenharmony_ci			clock_bits = 6;
43862306a36Sopenharmony_ci			break;
43962306a36Sopenharmony_ci		case QE_CLK17:
44062306a36Sopenharmony_ci			clock_bits = 7;
44162306a36Sopenharmony_ci			break;
44262306a36Sopenharmony_ci		default:
44362306a36Sopenharmony_ci			break;
44462306a36Sopenharmony_ci		}
44562306a36Sopenharmony_ci		break;
44662306a36Sopenharmony_ci	case 5:
44762306a36Sopenharmony_ci		switch (clock) {
44862306a36Sopenharmony_ci		case QE_CLK14:
44962306a36Sopenharmony_ci			clock_bits = 6;
45062306a36Sopenharmony_ci			break;
45162306a36Sopenharmony_ci		case QE_CLK19:
45262306a36Sopenharmony_ci			clock_bits = 7;
45362306a36Sopenharmony_ci			break;
45462306a36Sopenharmony_ci		default:
45562306a36Sopenharmony_ci			break;
45662306a36Sopenharmony_ci		}
45762306a36Sopenharmony_ci		break;
45862306a36Sopenharmony_ci	case 6:
45962306a36Sopenharmony_ci		switch (clock) {
46062306a36Sopenharmony_ci		case QE_CLK16:
46162306a36Sopenharmony_ci			clock_bits = 6;
46262306a36Sopenharmony_ci			break;
46362306a36Sopenharmony_ci		case QE_CLK21:
46462306a36Sopenharmony_ci			clock_bits = 7;
46562306a36Sopenharmony_ci			break;
46662306a36Sopenharmony_ci		default:
46762306a36Sopenharmony_ci			break;
46862306a36Sopenharmony_ci		}
46962306a36Sopenharmony_ci		break;
47062306a36Sopenharmony_ci	case 7:
47162306a36Sopenharmony_ci		switch (clock) {
47262306a36Sopenharmony_ci		case QE_CLK18:
47362306a36Sopenharmony_ci			clock_bits = 6;
47462306a36Sopenharmony_ci			break;
47562306a36Sopenharmony_ci		case QE_CLK3:
47662306a36Sopenharmony_ci			clock_bits = 7;
47762306a36Sopenharmony_ci			break;
47862306a36Sopenharmony_ci		default:
47962306a36Sopenharmony_ci			break;
48062306a36Sopenharmony_ci		}
48162306a36Sopenharmony_ci		break;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return clock_bits;
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci/* tdm_num: TDM A-H port num is 0-7 */
48862306a36Sopenharmony_cistatic int ucc_get_tdm_rxtx_clk(enum comm_dir mode, u32 tdm_num,
48962306a36Sopenharmony_ci				enum qe_clock clock)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	int clock_bits;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	clock_bits = ucc_get_tdm_common_clk(tdm_num, clock);
49462306a36Sopenharmony_ci	if (clock_bits > 0)
49562306a36Sopenharmony_ci		return clock_bits;
49662306a36Sopenharmony_ci	if (mode == COMM_DIR_RX)
49762306a36Sopenharmony_ci		clock_bits = ucc_get_tdm_rx_clk(tdm_num, clock);
49862306a36Sopenharmony_ci	if (mode == COMM_DIR_TX)
49962306a36Sopenharmony_ci		clock_bits = ucc_get_tdm_tx_clk(tdm_num, clock);
50062306a36Sopenharmony_ci	return clock_bits;
50162306a36Sopenharmony_ci}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_cistatic u32 ucc_get_tdm_clk_shift(enum comm_dir mode, u32 tdm_num)
50462306a36Sopenharmony_ci{
50562306a36Sopenharmony_ci	u32 shift;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	shift = (mode == COMM_DIR_RX) ? RX_CLK_SHIFT_BASE : TX_CLK_SHIFT_BASE;
50862306a36Sopenharmony_ci	if (tdm_num < 4)
50962306a36Sopenharmony_ci		shift -= tdm_num * 4;
51062306a36Sopenharmony_ci	else
51162306a36Sopenharmony_ci		shift -= (tdm_num - 4) * 4;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	return shift;
51462306a36Sopenharmony_ci}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ciint ucc_set_tdm_rxtx_clk(u32 tdm_num, enum qe_clock clock,
51762306a36Sopenharmony_ci			 enum comm_dir mode)
51862306a36Sopenharmony_ci{
51962306a36Sopenharmony_ci	int clock_bits;
52062306a36Sopenharmony_ci	u32 shift;
52162306a36Sopenharmony_ci	struct qe_mux __iomem *qe_mux_reg;
52262306a36Sopenharmony_ci	__be32 __iomem *cmxs1cr;
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	qe_mux_reg = &qe_immr->qmx;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	if (tdm_num > 7)
52762306a36Sopenharmony_ci		return -EINVAL;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	/* The communications direction must be RX or TX */
53062306a36Sopenharmony_ci	if (mode != COMM_DIR_RX && mode != COMM_DIR_TX)
53162306a36Sopenharmony_ci		return -EINVAL;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	clock_bits = ucc_get_tdm_rxtx_clk(mode, tdm_num, clock);
53462306a36Sopenharmony_ci	if (clock_bits < 0)
53562306a36Sopenharmony_ci		return -EINVAL;
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	shift = ucc_get_tdm_clk_shift(mode, tdm_num);
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	cmxs1cr = (tdm_num < 4) ? &qe_mux_reg->cmxsi1cr_l :
54062306a36Sopenharmony_ci				  &qe_mux_reg->cmxsi1cr_h;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	qe_clrsetbits_be32(cmxs1cr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,
54362306a36Sopenharmony_ci			   clock_bits << shift);
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	return 0;
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_cistatic int ucc_get_tdm_sync_source(u32 tdm_num, enum qe_clock clock,
54962306a36Sopenharmony_ci				   enum comm_dir mode)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	int source = -EINVAL;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	if (mode == COMM_DIR_RX && clock == QE_RSYNC_PIN) {
55462306a36Sopenharmony_ci		source = 0;
55562306a36Sopenharmony_ci		return source;
55662306a36Sopenharmony_ci	}
55762306a36Sopenharmony_ci	if (mode == COMM_DIR_TX && clock == QE_TSYNC_PIN) {
55862306a36Sopenharmony_ci		source = 0;
55962306a36Sopenharmony_ci		return source;
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	switch (tdm_num) {
56362306a36Sopenharmony_ci	case 0:
56462306a36Sopenharmony_ci	case 1:
56562306a36Sopenharmony_ci		switch (clock) {
56662306a36Sopenharmony_ci		case QE_BRG9:
56762306a36Sopenharmony_ci			source = 1;
56862306a36Sopenharmony_ci			break;
56962306a36Sopenharmony_ci		case QE_BRG10:
57062306a36Sopenharmony_ci			source = 2;
57162306a36Sopenharmony_ci			break;
57262306a36Sopenharmony_ci		default:
57362306a36Sopenharmony_ci			break;
57462306a36Sopenharmony_ci		}
57562306a36Sopenharmony_ci		break;
57662306a36Sopenharmony_ci	case 2:
57762306a36Sopenharmony_ci	case 3:
57862306a36Sopenharmony_ci		switch (clock) {
57962306a36Sopenharmony_ci		case QE_BRG9:
58062306a36Sopenharmony_ci			source = 1;
58162306a36Sopenharmony_ci			break;
58262306a36Sopenharmony_ci		case QE_BRG11:
58362306a36Sopenharmony_ci			source = 2;
58462306a36Sopenharmony_ci			break;
58562306a36Sopenharmony_ci		default:
58662306a36Sopenharmony_ci			break;
58762306a36Sopenharmony_ci		}
58862306a36Sopenharmony_ci		break;
58962306a36Sopenharmony_ci	case 4:
59062306a36Sopenharmony_ci	case 5:
59162306a36Sopenharmony_ci		switch (clock) {
59262306a36Sopenharmony_ci		case QE_BRG13:
59362306a36Sopenharmony_ci			source = 1;
59462306a36Sopenharmony_ci			break;
59562306a36Sopenharmony_ci		case QE_BRG14:
59662306a36Sopenharmony_ci			source = 2;
59762306a36Sopenharmony_ci			break;
59862306a36Sopenharmony_ci		default:
59962306a36Sopenharmony_ci			break;
60062306a36Sopenharmony_ci		}
60162306a36Sopenharmony_ci		break;
60262306a36Sopenharmony_ci	case 6:
60362306a36Sopenharmony_ci	case 7:
60462306a36Sopenharmony_ci		switch (clock) {
60562306a36Sopenharmony_ci		case QE_BRG13:
60662306a36Sopenharmony_ci			source = 1;
60762306a36Sopenharmony_ci			break;
60862306a36Sopenharmony_ci		case QE_BRG15:
60962306a36Sopenharmony_ci			source = 2;
61062306a36Sopenharmony_ci			break;
61162306a36Sopenharmony_ci		default:
61262306a36Sopenharmony_ci			break;
61362306a36Sopenharmony_ci		}
61462306a36Sopenharmony_ci		break;
61562306a36Sopenharmony_ci	}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	return source;
61862306a36Sopenharmony_ci}
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_cistatic u32 ucc_get_tdm_sync_shift(enum comm_dir mode, u32 tdm_num)
62162306a36Sopenharmony_ci{
62262306a36Sopenharmony_ci	u32 shift;
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	shift = (mode == COMM_DIR_RX) ? RX_SYNC_SHIFT_BASE : TX_SYNC_SHIFT_BASE;
62562306a36Sopenharmony_ci	shift -= tdm_num * 2;
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	return shift;
62862306a36Sopenharmony_ci}
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ciint ucc_set_tdm_rxtx_sync(u32 tdm_num, enum qe_clock clock,
63162306a36Sopenharmony_ci			  enum comm_dir mode)
63262306a36Sopenharmony_ci{
63362306a36Sopenharmony_ci	int source;
63462306a36Sopenharmony_ci	u32 shift;
63562306a36Sopenharmony_ci	struct qe_mux __iomem *qe_mux_reg;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	qe_mux_reg = &qe_immr->qmx;
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	if (tdm_num >= UCC_TDM_NUM)
64062306a36Sopenharmony_ci		return -EINVAL;
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	/* The communications direction must be RX or TX */
64362306a36Sopenharmony_ci	if (mode != COMM_DIR_RX && mode != COMM_DIR_TX)
64462306a36Sopenharmony_ci		return -EINVAL;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	source = ucc_get_tdm_sync_source(tdm_num, clock, mode);
64762306a36Sopenharmony_ci	if (source < 0)
64862306a36Sopenharmony_ci		return -EINVAL;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	shift = ucc_get_tdm_sync_shift(mode, tdm_num);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	qe_clrsetbits_be32(&qe_mux_reg->cmxsi1syr,
65362306a36Sopenharmony_ci			   QE_CMXUCR_TX_CLK_SRC_MASK << shift,
65462306a36Sopenharmony_ci			   source << shift);
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	return 0;
65762306a36Sopenharmony_ci}
658