18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/powerpc/sysdev/qe_lib/ucc.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * QE UCC API Set - UCC specific routines implementations. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Authors: Shlomi Gridish <gridish@freescale.com> 108c2ecf20Sopenharmony_ci * Li Yang <leoli@freescale.com> 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/errno.h> 148c2ecf20Sopenharmony_ci#include <linux/stddef.h> 158c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 168c2ecf20Sopenharmony_ci#include <linux/export.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <asm/io.h> 198c2ecf20Sopenharmony_ci#include <soc/fsl/qe/immap_qe.h> 208c2ecf20Sopenharmony_ci#include <soc/fsl/qe/qe.h> 218c2ecf20Sopenharmony_ci#include <soc/fsl/qe/ucc.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define UCC_TDM_NUM 8 248c2ecf20Sopenharmony_ci#define RX_SYNC_SHIFT_BASE 30 258c2ecf20Sopenharmony_ci#define TX_SYNC_SHIFT_BASE 14 268c2ecf20Sopenharmony_ci#define RX_CLK_SHIFT_BASE 28 278c2ecf20Sopenharmony_ci#define TX_CLK_SHIFT_BASE 12 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ciint ucc_set_qe_mux_mii_mng(unsigned int ucc_num) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci unsigned long flags; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci if (ucc_num > UCC_MAX_NUM - 1) 348c2ecf20Sopenharmony_ci return -EINVAL; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci spin_lock_irqsave(&cmxgcr_lock, flags); 378c2ecf20Sopenharmony_ci qe_clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG, 388c2ecf20Sopenharmony_ci ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT); 398c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&cmxgcr_lock, flags); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci return 0; 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ucc_set_qe_mux_mii_mng); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* Configure the UCC to either Slow or Fast. 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * A given UCC can be figured to support either "slow" devices (e.g. UART) 488c2ecf20Sopenharmony_ci * or "fast" devices (e.g. Ethernet). 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * 'ucc_num' is the UCC number, from 0 - 7. 518c2ecf20Sopenharmony_ci * 528c2ecf20Sopenharmony_ci * This function also sets the UCC_GUEMR_SET_RESERVED3 bit because that bit 538c2ecf20Sopenharmony_ci * must always be set to 1. 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ciint ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci u8 __iomem *guemr; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* The GUEMR register is at the same location for both slow and fast 608c2ecf20Sopenharmony_ci devices, so we just use uccX.slow.guemr. */ 618c2ecf20Sopenharmony_ci switch (ucc_num) { 628c2ecf20Sopenharmony_ci case 0: guemr = &qe_immr->ucc1.slow.guemr; 638c2ecf20Sopenharmony_ci break; 648c2ecf20Sopenharmony_ci case 1: guemr = &qe_immr->ucc2.slow.guemr; 658c2ecf20Sopenharmony_ci break; 668c2ecf20Sopenharmony_ci case 2: guemr = &qe_immr->ucc3.slow.guemr; 678c2ecf20Sopenharmony_ci break; 688c2ecf20Sopenharmony_ci case 3: guemr = &qe_immr->ucc4.slow.guemr; 698c2ecf20Sopenharmony_ci break; 708c2ecf20Sopenharmony_ci case 4: guemr = &qe_immr->ucc5.slow.guemr; 718c2ecf20Sopenharmony_ci break; 728c2ecf20Sopenharmony_ci case 5: guemr = &qe_immr->ucc6.slow.guemr; 738c2ecf20Sopenharmony_ci break; 748c2ecf20Sopenharmony_ci case 6: guemr = &qe_immr->ucc7.slow.guemr; 758c2ecf20Sopenharmony_ci break; 768c2ecf20Sopenharmony_ci case 7: guemr = &qe_immr->ucc8.slow.guemr; 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci default: 798c2ecf20Sopenharmony_ci return -EINVAL; 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci qe_clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK, 838c2ecf20Sopenharmony_ci UCC_GUEMR_SET_RESERVED3 | speed); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci return 0; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic void get_cmxucr_reg(unsigned int ucc_num, __be32 __iomem **cmxucr, 898c2ecf20Sopenharmony_ci unsigned int *reg_num, unsigned int *shift) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci *reg_num = cmx + 1; 948c2ecf20Sopenharmony_ci *cmxucr = &qe_immr->qmx.cmxucr[cmx]; 958c2ecf20Sopenharmony_ci *shift = 16 - 8 * (ucc_num & 2); 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ciint ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci __be32 __iomem *cmxucr; 1018c2ecf20Sopenharmony_ci unsigned int reg_num; 1028c2ecf20Sopenharmony_ci unsigned int shift; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* check if the UCC number is in range. */ 1058c2ecf20Sopenharmony_ci if (ucc_num > UCC_MAX_NUM - 1) 1068c2ecf20Sopenharmony_ci return -EINVAL; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (set) 1118c2ecf20Sopenharmony_ci qe_setbits_be32(cmxucr, mask << shift); 1128c2ecf20Sopenharmony_ci else 1138c2ecf20Sopenharmony_ci qe_clrbits_be32(cmxucr, mask << shift); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci return 0; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ciint ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock, 1198c2ecf20Sopenharmony_ci enum comm_dir mode) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci __be32 __iomem *cmxucr; 1228c2ecf20Sopenharmony_ci unsigned int reg_num; 1238c2ecf20Sopenharmony_ci unsigned int shift; 1248c2ecf20Sopenharmony_ci u32 clock_bits = 0; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* check if the UCC number is in range. */ 1278c2ecf20Sopenharmony_ci if (ucc_num > UCC_MAX_NUM - 1) 1288c2ecf20Sopenharmony_ci return -EINVAL; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* The communications direction must be RX or TX */ 1318c2ecf20Sopenharmony_ci if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX))) 1328c2ecf20Sopenharmony_ci return -EINVAL; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci switch (reg_num) { 1378c2ecf20Sopenharmony_ci case 1: 1388c2ecf20Sopenharmony_ci switch (clock) { 1398c2ecf20Sopenharmony_ci case QE_BRG1: clock_bits = 1; break; 1408c2ecf20Sopenharmony_ci case QE_BRG2: clock_bits = 2; break; 1418c2ecf20Sopenharmony_ci case QE_BRG7: clock_bits = 3; break; 1428c2ecf20Sopenharmony_ci case QE_BRG8: clock_bits = 4; break; 1438c2ecf20Sopenharmony_ci case QE_CLK9: clock_bits = 5; break; 1448c2ecf20Sopenharmony_ci case QE_CLK10: clock_bits = 6; break; 1458c2ecf20Sopenharmony_ci case QE_CLK11: clock_bits = 7; break; 1468c2ecf20Sopenharmony_ci case QE_CLK12: clock_bits = 8; break; 1478c2ecf20Sopenharmony_ci case QE_CLK15: clock_bits = 9; break; 1488c2ecf20Sopenharmony_ci case QE_CLK16: clock_bits = 10; break; 1498c2ecf20Sopenharmony_ci default: break; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci break; 1528c2ecf20Sopenharmony_ci case 2: 1538c2ecf20Sopenharmony_ci switch (clock) { 1548c2ecf20Sopenharmony_ci case QE_BRG5: clock_bits = 1; break; 1558c2ecf20Sopenharmony_ci case QE_BRG6: clock_bits = 2; break; 1568c2ecf20Sopenharmony_ci case QE_BRG7: clock_bits = 3; break; 1578c2ecf20Sopenharmony_ci case QE_BRG8: clock_bits = 4; break; 1588c2ecf20Sopenharmony_ci case QE_CLK13: clock_bits = 5; break; 1598c2ecf20Sopenharmony_ci case QE_CLK14: clock_bits = 6; break; 1608c2ecf20Sopenharmony_ci case QE_CLK19: clock_bits = 7; break; 1618c2ecf20Sopenharmony_ci case QE_CLK20: clock_bits = 8; break; 1628c2ecf20Sopenharmony_ci case QE_CLK15: clock_bits = 9; break; 1638c2ecf20Sopenharmony_ci case QE_CLK16: clock_bits = 10; break; 1648c2ecf20Sopenharmony_ci default: break; 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci break; 1678c2ecf20Sopenharmony_ci case 3: 1688c2ecf20Sopenharmony_ci switch (clock) { 1698c2ecf20Sopenharmony_ci case QE_BRG9: clock_bits = 1; break; 1708c2ecf20Sopenharmony_ci case QE_BRG10: clock_bits = 2; break; 1718c2ecf20Sopenharmony_ci case QE_BRG15: clock_bits = 3; break; 1728c2ecf20Sopenharmony_ci case QE_BRG16: clock_bits = 4; break; 1738c2ecf20Sopenharmony_ci case QE_CLK3: clock_bits = 5; break; 1748c2ecf20Sopenharmony_ci case QE_CLK4: clock_bits = 6; break; 1758c2ecf20Sopenharmony_ci case QE_CLK17: clock_bits = 7; break; 1768c2ecf20Sopenharmony_ci case QE_CLK18: clock_bits = 8; break; 1778c2ecf20Sopenharmony_ci case QE_CLK7: clock_bits = 9; break; 1788c2ecf20Sopenharmony_ci case QE_CLK8: clock_bits = 10; break; 1798c2ecf20Sopenharmony_ci case QE_CLK16: clock_bits = 11; break; 1808c2ecf20Sopenharmony_ci default: break; 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci case 4: 1848c2ecf20Sopenharmony_ci switch (clock) { 1858c2ecf20Sopenharmony_ci case QE_BRG13: clock_bits = 1; break; 1868c2ecf20Sopenharmony_ci case QE_BRG14: clock_bits = 2; break; 1878c2ecf20Sopenharmony_ci case QE_BRG15: clock_bits = 3; break; 1888c2ecf20Sopenharmony_ci case QE_BRG16: clock_bits = 4; break; 1898c2ecf20Sopenharmony_ci case QE_CLK5: clock_bits = 5; break; 1908c2ecf20Sopenharmony_ci case QE_CLK6: clock_bits = 6; break; 1918c2ecf20Sopenharmony_ci case QE_CLK21: clock_bits = 7; break; 1928c2ecf20Sopenharmony_ci case QE_CLK22: clock_bits = 8; break; 1938c2ecf20Sopenharmony_ci case QE_CLK7: clock_bits = 9; break; 1948c2ecf20Sopenharmony_ci case QE_CLK8: clock_bits = 10; break; 1958c2ecf20Sopenharmony_ci case QE_CLK16: clock_bits = 11; break; 1968c2ecf20Sopenharmony_ci default: break; 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci break; 1998c2ecf20Sopenharmony_ci default: break; 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* Check for invalid combination of clock and UCC number */ 2038c2ecf20Sopenharmony_ci if (!clock_bits) 2048c2ecf20Sopenharmony_ci return -ENOENT; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (mode == COMM_DIR_RX) 2078c2ecf20Sopenharmony_ci shift += 4; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci qe_clrsetbits_be32(cmxucr, QE_CMXUCR_TX_CLK_SRC_MASK << shift, 2108c2ecf20Sopenharmony_ci clock_bits << shift); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci return 0; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int ucc_get_tdm_common_clk(u32 tdm_num, enum qe_clock clock) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci int clock_bits = -EINVAL; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* 2208c2ecf20Sopenharmony_ci * for TDM[0, 1, 2, 3], TX and RX use common 2218c2ecf20Sopenharmony_ci * clock source BRG3,4 and CLK1,2 2228c2ecf20Sopenharmony_ci * for TDM[4, 5, 6, 7], TX and RX use common 2238c2ecf20Sopenharmony_ci * clock source BRG12,13 and CLK23,24 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_ci switch (tdm_num) { 2268c2ecf20Sopenharmony_ci case 0: 2278c2ecf20Sopenharmony_ci case 1: 2288c2ecf20Sopenharmony_ci case 2: 2298c2ecf20Sopenharmony_ci case 3: 2308c2ecf20Sopenharmony_ci switch (clock) { 2318c2ecf20Sopenharmony_ci case QE_BRG3: 2328c2ecf20Sopenharmony_ci clock_bits = 1; 2338c2ecf20Sopenharmony_ci break; 2348c2ecf20Sopenharmony_ci case QE_BRG4: 2358c2ecf20Sopenharmony_ci clock_bits = 2; 2368c2ecf20Sopenharmony_ci break; 2378c2ecf20Sopenharmony_ci case QE_CLK1: 2388c2ecf20Sopenharmony_ci clock_bits = 4; 2398c2ecf20Sopenharmony_ci break; 2408c2ecf20Sopenharmony_ci case QE_CLK2: 2418c2ecf20Sopenharmony_ci clock_bits = 5; 2428c2ecf20Sopenharmony_ci break; 2438c2ecf20Sopenharmony_ci default: 2448c2ecf20Sopenharmony_ci break; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci break; 2478c2ecf20Sopenharmony_ci case 4: 2488c2ecf20Sopenharmony_ci case 5: 2498c2ecf20Sopenharmony_ci case 6: 2508c2ecf20Sopenharmony_ci case 7: 2518c2ecf20Sopenharmony_ci switch (clock) { 2528c2ecf20Sopenharmony_ci case QE_BRG12: 2538c2ecf20Sopenharmony_ci clock_bits = 1; 2548c2ecf20Sopenharmony_ci break; 2558c2ecf20Sopenharmony_ci case QE_BRG13: 2568c2ecf20Sopenharmony_ci clock_bits = 2; 2578c2ecf20Sopenharmony_ci break; 2588c2ecf20Sopenharmony_ci case QE_CLK23: 2598c2ecf20Sopenharmony_ci clock_bits = 4; 2608c2ecf20Sopenharmony_ci break; 2618c2ecf20Sopenharmony_ci case QE_CLK24: 2628c2ecf20Sopenharmony_ci clock_bits = 5; 2638c2ecf20Sopenharmony_ci break; 2648c2ecf20Sopenharmony_ci default: 2658c2ecf20Sopenharmony_ci break; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci break; 2688c2ecf20Sopenharmony_ci default: 2698c2ecf20Sopenharmony_ci break; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci return clock_bits; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic int ucc_get_tdm_rx_clk(u32 tdm_num, enum qe_clock clock) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci int clock_bits = -EINVAL; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci switch (tdm_num) { 2808c2ecf20Sopenharmony_ci case 0: 2818c2ecf20Sopenharmony_ci switch (clock) { 2828c2ecf20Sopenharmony_ci case QE_CLK3: 2838c2ecf20Sopenharmony_ci clock_bits = 6; 2848c2ecf20Sopenharmony_ci break; 2858c2ecf20Sopenharmony_ci case QE_CLK8: 2868c2ecf20Sopenharmony_ci clock_bits = 7; 2878c2ecf20Sopenharmony_ci break; 2888c2ecf20Sopenharmony_ci default: 2898c2ecf20Sopenharmony_ci break; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci break; 2928c2ecf20Sopenharmony_ci case 1: 2938c2ecf20Sopenharmony_ci switch (clock) { 2948c2ecf20Sopenharmony_ci case QE_CLK5: 2958c2ecf20Sopenharmony_ci clock_bits = 6; 2968c2ecf20Sopenharmony_ci break; 2978c2ecf20Sopenharmony_ci case QE_CLK10: 2988c2ecf20Sopenharmony_ci clock_bits = 7; 2998c2ecf20Sopenharmony_ci break; 3008c2ecf20Sopenharmony_ci default: 3018c2ecf20Sopenharmony_ci break; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci break; 3048c2ecf20Sopenharmony_ci case 2: 3058c2ecf20Sopenharmony_ci switch (clock) { 3068c2ecf20Sopenharmony_ci case QE_CLK7: 3078c2ecf20Sopenharmony_ci clock_bits = 6; 3088c2ecf20Sopenharmony_ci break; 3098c2ecf20Sopenharmony_ci case QE_CLK12: 3108c2ecf20Sopenharmony_ci clock_bits = 7; 3118c2ecf20Sopenharmony_ci break; 3128c2ecf20Sopenharmony_ci default: 3138c2ecf20Sopenharmony_ci break; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci break; 3168c2ecf20Sopenharmony_ci case 3: 3178c2ecf20Sopenharmony_ci switch (clock) { 3188c2ecf20Sopenharmony_ci case QE_CLK9: 3198c2ecf20Sopenharmony_ci clock_bits = 6; 3208c2ecf20Sopenharmony_ci break; 3218c2ecf20Sopenharmony_ci case QE_CLK14: 3228c2ecf20Sopenharmony_ci clock_bits = 7; 3238c2ecf20Sopenharmony_ci break; 3248c2ecf20Sopenharmony_ci default: 3258c2ecf20Sopenharmony_ci break; 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci break; 3288c2ecf20Sopenharmony_ci case 4: 3298c2ecf20Sopenharmony_ci switch (clock) { 3308c2ecf20Sopenharmony_ci case QE_CLK11: 3318c2ecf20Sopenharmony_ci clock_bits = 6; 3328c2ecf20Sopenharmony_ci break; 3338c2ecf20Sopenharmony_ci case QE_CLK16: 3348c2ecf20Sopenharmony_ci clock_bits = 7; 3358c2ecf20Sopenharmony_ci break; 3368c2ecf20Sopenharmony_ci default: 3378c2ecf20Sopenharmony_ci break; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci break; 3408c2ecf20Sopenharmony_ci case 5: 3418c2ecf20Sopenharmony_ci switch (clock) { 3428c2ecf20Sopenharmony_ci case QE_CLK13: 3438c2ecf20Sopenharmony_ci clock_bits = 6; 3448c2ecf20Sopenharmony_ci break; 3458c2ecf20Sopenharmony_ci case QE_CLK18: 3468c2ecf20Sopenharmony_ci clock_bits = 7; 3478c2ecf20Sopenharmony_ci break; 3488c2ecf20Sopenharmony_ci default: 3498c2ecf20Sopenharmony_ci break; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci break; 3528c2ecf20Sopenharmony_ci case 6: 3538c2ecf20Sopenharmony_ci switch (clock) { 3548c2ecf20Sopenharmony_ci case QE_CLK15: 3558c2ecf20Sopenharmony_ci clock_bits = 6; 3568c2ecf20Sopenharmony_ci break; 3578c2ecf20Sopenharmony_ci case QE_CLK20: 3588c2ecf20Sopenharmony_ci clock_bits = 7; 3598c2ecf20Sopenharmony_ci break; 3608c2ecf20Sopenharmony_ci default: 3618c2ecf20Sopenharmony_ci break; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci break; 3648c2ecf20Sopenharmony_ci case 7: 3658c2ecf20Sopenharmony_ci switch (clock) { 3668c2ecf20Sopenharmony_ci case QE_CLK17: 3678c2ecf20Sopenharmony_ci clock_bits = 6; 3688c2ecf20Sopenharmony_ci break; 3698c2ecf20Sopenharmony_ci case QE_CLK22: 3708c2ecf20Sopenharmony_ci clock_bits = 7; 3718c2ecf20Sopenharmony_ci break; 3728c2ecf20Sopenharmony_ci default: 3738c2ecf20Sopenharmony_ci break; 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci break; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci return clock_bits; 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_cistatic int ucc_get_tdm_tx_clk(u32 tdm_num, enum qe_clock clock) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci int clock_bits = -EINVAL; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci switch (tdm_num) { 3868c2ecf20Sopenharmony_ci case 0: 3878c2ecf20Sopenharmony_ci switch (clock) { 3888c2ecf20Sopenharmony_ci case QE_CLK4: 3898c2ecf20Sopenharmony_ci clock_bits = 6; 3908c2ecf20Sopenharmony_ci break; 3918c2ecf20Sopenharmony_ci case QE_CLK9: 3928c2ecf20Sopenharmony_ci clock_bits = 7; 3938c2ecf20Sopenharmony_ci break; 3948c2ecf20Sopenharmony_ci default: 3958c2ecf20Sopenharmony_ci break; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci break; 3988c2ecf20Sopenharmony_ci case 1: 3998c2ecf20Sopenharmony_ci switch (clock) { 4008c2ecf20Sopenharmony_ci case QE_CLK6: 4018c2ecf20Sopenharmony_ci clock_bits = 6; 4028c2ecf20Sopenharmony_ci break; 4038c2ecf20Sopenharmony_ci case QE_CLK11: 4048c2ecf20Sopenharmony_ci clock_bits = 7; 4058c2ecf20Sopenharmony_ci break; 4068c2ecf20Sopenharmony_ci default: 4078c2ecf20Sopenharmony_ci break; 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci break; 4108c2ecf20Sopenharmony_ci case 2: 4118c2ecf20Sopenharmony_ci switch (clock) { 4128c2ecf20Sopenharmony_ci case QE_CLK8: 4138c2ecf20Sopenharmony_ci clock_bits = 6; 4148c2ecf20Sopenharmony_ci break; 4158c2ecf20Sopenharmony_ci case QE_CLK13: 4168c2ecf20Sopenharmony_ci clock_bits = 7; 4178c2ecf20Sopenharmony_ci break; 4188c2ecf20Sopenharmony_ci default: 4198c2ecf20Sopenharmony_ci break; 4208c2ecf20Sopenharmony_ci } 4218c2ecf20Sopenharmony_ci break; 4228c2ecf20Sopenharmony_ci case 3: 4238c2ecf20Sopenharmony_ci switch (clock) { 4248c2ecf20Sopenharmony_ci case QE_CLK10: 4258c2ecf20Sopenharmony_ci clock_bits = 6; 4268c2ecf20Sopenharmony_ci break; 4278c2ecf20Sopenharmony_ci case QE_CLK15: 4288c2ecf20Sopenharmony_ci clock_bits = 7; 4298c2ecf20Sopenharmony_ci break; 4308c2ecf20Sopenharmony_ci default: 4318c2ecf20Sopenharmony_ci break; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci break; 4348c2ecf20Sopenharmony_ci case 4: 4358c2ecf20Sopenharmony_ci switch (clock) { 4368c2ecf20Sopenharmony_ci case QE_CLK12: 4378c2ecf20Sopenharmony_ci clock_bits = 6; 4388c2ecf20Sopenharmony_ci break; 4398c2ecf20Sopenharmony_ci case QE_CLK17: 4408c2ecf20Sopenharmony_ci clock_bits = 7; 4418c2ecf20Sopenharmony_ci break; 4428c2ecf20Sopenharmony_ci default: 4438c2ecf20Sopenharmony_ci break; 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci break; 4468c2ecf20Sopenharmony_ci case 5: 4478c2ecf20Sopenharmony_ci switch (clock) { 4488c2ecf20Sopenharmony_ci case QE_CLK14: 4498c2ecf20Sopenharmony_ci clock_bits = 6; 4508c2ecf20Sopenharmony_ci break; 4518c2ecf20Sopenharmony_ci case QE_CLK19: 4528c2ecf20Sopenharmony_ci clock_bits = 7; 4538c2ecf20Sopenharmony_ci break; 4548c2ecf20Sopenharmony_ci default: 4558c2ecf20Sopenharmony_ci break; 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci break; 4588c2ecf20Sopenharmony_ci case 6: 4598c2ecf20Sopenharmony_ci switch (clock) { 4608c2ecf20Sopenharmony_ci case QE_CLK16: 4618c2ecf20Sopenharmony_ci clock_bits = 6; 4628c2ecf20Sopenharmony_ci break; 4638c2ecf20Sopenharmony_ci case QE_CLK21: 4648c2ecf20Sopenharmony_ci clock_bits = 7; 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci default: 4678c2ecf20Sopenharmony_ci break; 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci break; 4708c2ecf20Sopenharmony_ci case 7: 4718c2ecf20Sopenharmony_ci switch (clock) { 4728c2ecf20Sopenharmony_ci case QE_CLK18: 4738c2ecf20Sopenharmony_ci clock_bits = 6; 4748c2ecf20Sopenharmony_ci break; 4758c2ecf20Sopenharmony_ci case QE_CLK3: 4768c2ecf20Sopenharmony_ci clock_bits = 7; 4778c2ecf20Sopenharmony_ci break; 4788c2ecf20Sopenharmony_ci default: 4798c2ecf20Sopenharmony_ci break; 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci break; 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci return clock_bits; 4858c2ecf20Sopenharmony_ci} 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci/* tdm_num: TDM A-H port num is 0-7 */ 4888c2ecf20Sopenharmony_cistatic int ucc_get_tdm_rxtx_clk(enum comm_dir mode, u32 tdm_num, 4898c2ecf20Sopenharmony_ci enum qe_clock clock) 4908c2ecf20Sopenharmony_ci{ 4918c2ecf20Sopenharmony_ci int clock_bits; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci clock_bits = ucc_get_tdm_common_clk(tdm_num, clock); 4948c2ecf20Sopenharmony_ci if (clock_bits > 0) 4958c2ecf20Sopenharmony_ci return clock_bits; 4968c2ecf20Sopenharmony_ci if (mode == COMM_DIR_RX) 4978c2ecf20Sopenharmony_ci clock_bits = ucc_get_tdm_rx_clk(tdm_num, clock); 4988c2ecf20Sopenharmony_ci if (mode == COMM_DIR_TX) 4998c2ecf20Sopenharmony_ci clock_bits = ucc_get_tdm_tx_clk(tdm_num, clock); 5008c2ecf20Sopenharmony_ci return clock_bits; 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistatic u32 ucc_get_tdm_clk_shift(enum comm_dir mode, u32 tdm_num) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci u32 shift; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci shift = (mode == COMM_DIR_RX) ? RX_CLK_SHIFT_BASE : TX_CLK_SHIFT_BASE; 5088c2ecf20Sopenharmony_ci if (tdm_num < 4) 5098c2ecf20Sopenharmony_ci shift -= tdm_num * 4; 5108c2ecf20Sopenharmony_ci else 5118c2ecf20Sopenharmony_ci shift -= (tdm_num - 4) * 4; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci return shift; 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ciint ucc_set_tdm_rxtx_clk(u32 tdm_num, enum qe_clock clock, 5178c2ecf20Sopenharmony_ci enum comm_dir mode) 5188c2ecf20Sopenharmony_ci{ 5198c2ecf20Sopenharmony_ci int clock_bits; 5208c2ecf20Sopenharmony_ci u32 shift; 5218c2ecf20Sopenharmony_ci struct qe_mux __iomem *qe_mux_reg; 5228c2ecf20Sopenharmony_ci __be32 __iomem *cmxs1cr; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci qe_mux_reg = &qe_immr->qmx; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci if (tdm_num > 7) 5278c2ecf20Sopenharmony_ci return -EINVAL; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci /* The communications direction must be RX or TX */ 5308c2ecf20Sopenharmony_ci if (mode != COMM_DIR_RX && mode != COMM_DIR_TX) 5318c2ecf20Sopenharmony_ci return -EINVAL; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci clock_bits = ucc_get_tdm_rxtx_clk(mode, tdm_num, clock); 5348c2ecf20Sopenharmony_ci if (clock_bits < 0) 5358c2ecf20Sopenharmony_ci return -EINVAL; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci shift = ucc_get_tdm_clk_shift(mode, tdm_num); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci cmxs1cr = (tdm_num < 4) ? &qe_mux_reg->cmxsi1cr_l : 5408c2ecf20Sopenharmony_ci &qe_mux_reg->cmxsi1cr_h; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci qe_clrsetbits_be32(cmxs1cr, QE_CMXUCR_TX_CLK_SRC_MASK << shift, 5438c2ecf20Sopenharmony_ci clock_bits << shift); 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci return 0; 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic int ucc_get_tdm_sync_source(u32 tdm_num, enum qe_clock clock, 5498c2ecf20Sopenharmony_ci enum comm_dir mode) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci int source = -EINVAL; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci if (mode == COMM_DIR_RX && clock == QE_RSYNC_PIN) { 5548c2ecf20Sopenharmony_ci source = 0; 5558c2ecf20Sopenharmony_ci return source; 5568c2ecf20Sopenharmony_ci } 5578c2ecf20Sopenharmony_ci if (mode == COMM_DIR_TX && clock == QE_TSYNC_PIN) { 5588c2ecf20Sopenharmony_ci source = 0; 5598c2ecf20Sopenharmony_ci return source; 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci switch (tdm_num) { 5638c2ecf20Sopenharmony_ci case 0: 5648c2ecf20Sopenharmony_ci case 1: 5658c2ecf20Sopenharmony_ci switch (clock) { 5668c2ecf20Sopenharmony_ci case QE_BRG9: 5678c2ecf20Sopenharmony_ci source = 1; 5688c2ecf20Sopenharmony_ci break; 5698c2ecf20Sopenharmony_ci case QE_BRG10: 5708c2ecf20Sopenharmony_ci source = 2; 5718c2ecf20Sopenharmony_ci break; 5728c2ecf20Sopenharmony_ci default: 5738c2ecf20Sopenharmony_ci break; 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci break; 5768c2ecf20Sopenharmony_ci case 2: 5778c2ecf20Sopenharmony_ci case 3: 5788c2ecf20Sopenharmony_ci switch (clock) { 5798c2ecf20Sopenharmony_ci case QE_BRG9: 5808c2ecf20Sopenharmony_ci source = 1; 5818c2ecf20Sopenharmony_ci break; 5828c2ecf20Sopenharmony_ci case QE_BRG11: 5838c2ecf20Sopenharmony_ci source = 2; 5848c2ecf20Sopenharmony_ci break; 5858c2ecf20Sopenharmony_ci default: 5868c2ecf20Sopenharmony_ci break; 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci break; 5898c2ecf20Sopenharmony_ci case 4: 5908c2ecf20Sopenharmony_ci case 5: 5918c2ecf20Sopenharmony_ci switch (clock) { 5928c2ecf20Sopenharmony_ci case QE_BRG13: 5938c2ecf20Sopenharmony_ci source = 1; 5948c2ecf20Sopenharmony_ci break; 5958c2ecf20Sopenharmony_ci case QE_BRG14: 5968c2ecf20Sopenharmony_ci source = 2; 5978c2ecf20Sopenharmony_ci break; 5988c2ecf20Sopenharmony_ci default: 5998c2ecf20Sopenharmony_ci break; 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci break; 6028c2ecf20Sopenharmony_ci case 6: 6038c2ecf20Sopenharmony_ci case 7: 6048c2ecf20Sopenharmony_ci switch (clock) { 6058c2ecf20Sopenharmony_ci case QE_BRG13: 6068c2ecf20Sopenharmony_ci source = 1; 6078c2ecf20Sopenharmony_ci break; 6088c2ecf20Sopenharmony_ci case QE_BRG15: 6098c2ecf20Sopenharmony_ci source = 2; 6108c2ecf20Sopenharmony_ci break; 6118c2ecf20Sopenharmony_ci default: 6128c2ecf20Sopenharmony_ci break; 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci break; 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci return source; 6188c2ecf20Sopenharmony_ci} 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_cistatic u32 ucc_get_tdm_sync_shift(enum comm_dir mode, u32 tdm_num) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci u32 shift; 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci shift = (mode == COMM_DIR_RX) ? RX_SYNC_SHIFT_BASE : TX_SYNC_SHIFT_BASE; 6258c2ecf20Sopenharmony_ci shift -= tdm_num * 2; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci return shift; 6288c2ecf20Sopenharmony_ci} 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ciint ucc_set_tdm_rxtx_sync(u32 tdm_num, enum qe_clock clock, 6318c2ecf20Sopenharmony_ci enum comm_dir mode) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci int source; 6348c2ecf20Sopenharmony_ci u32 shift; 6358c2ecf20Sopenharmony_ci struct qe_mux __iomem *qe_mux_reg; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci qe_mux_reg = &qe_immr->qmx; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci if (tdm_num >= UCC_TDM_NUM) 6408c2ecf20Sopenharmony_ci return -EINVAL; 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci /* The communications direction must be RX or TX */ 6438c2ecf20Sopenharmony_ci if (mode != COMM_DIR_RX && mode != COMM_DIR_TX) 6448c2ecf20Sopenharmony_ci return -EINVAL; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci source = ucc_get_tdm_sync_source(tdm_num, clock, mode); 6478c2ecf20Sopenharmony_ci if (source < 0) 6488c2ecf20Sopenharmony_ci return -EINVAL; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci shift = ucc_get_tdm_sync_shift(mode, tdm_num); 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci qe_clrsetbits_be32(&qe_mux_reg->cmxsi1syr, 6538c2ecf20Sopenharmony_ci QE_CMXUCR_TX_CLK_SRC_MASK << shift, 6548c2ecf20Sopenharmony_ci source << shift); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci return 0; 6578c2ecf20Sopenharmony_ci} 658