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, ®_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, ®_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