brintos

brintos / linux-shallow public Read only

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