diff options
| -rw-r--r-- | arch/powerpc/cpu/mpc85xx/cmd_errata.c | 8 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/config_mpc85xx.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/immap_85xx.h | 19 | ||||
| -rw-r--r-- | board/freescale/b4860qds/b4860qds.c | 193 | 
4 files changed, 220 insertions, 2 deletions
| diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c index 769389905..d0a1c518b 100644 --- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c +++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c @@ -229,6 +229,14 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	if (IS_SVR_REV(svr, 1, 0))  		puts("Work-around for Erratum A005871 enabled\n");  #endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A006475 +	if (SVR_MAJ(get_svr()) == 1) +		puts("Work-around for Erratum A006475 enabled\n"); +#endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A006384 +	if (SVR_MAJ(get_svr()) == 1) +		puts("Work-around for Erratum A006384 enabled\n"); +#endif  #ifdef CONFIG_SYS_FSL_ERRATUM_A004849  	/* This work-around is implemented in PBI, so just check for it */  	check_erratum_a4849(svr); diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h index 0ec1417a4..2f47b3fbd 100644 --- a/arch/powerpc/include/asm/config_mpc85xx.h +++ b/arch/powerpc/include/asm/config_mpc85xx.h @@ -662,6 +662,8 @@  #define CONFIG_SYS_FSL_ERRATUM_A005871  #define CONFIG_SYS_FSL_ERRATUM_A006379  #define CONFIG_SYS_FSL_ERRATUM_A006593 +#define CONFIG_SYS_FSL_ERRATUM_A006475 +#define CONFIG_SYS_FSL_ERRATUM_A006384  #define CONFIG_SYS_CCSRBAR_DEFAULT	0xfe000000  #ifdef CONFIG_PPC_B4860 diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h index e0efc7eba..edd7888c4 100644 --- a/arch/powerpc/include/asm/immap_85xx.h +++ b/arch/powerpc/include/asm/immap_85xx.h @@ -2495,6 +2495,7 @@ typedef struct serdes_corenet {  #define SRDS_RSTCTL_SDEN	0x00000020  #define SRDS_RSTCTL_SDRST_B	0x00000040  #define SRDS_RSTCTL_PLLRST_B	0x00000080 +#define SRDS_RSTCTL_RSTERR_SHIFT  29  		u32	pllcr0; /* PLL Control Register 0 */  #define SRDS_PLLCR0_POFF		0x80000000  #define SRDS_PLLCR0_RFCK_SEL_MASK	0x70000000 @@ -2504,6 +2505,7 @@ typedef struct serdes_corenet {  #define SRDS_PLLCR0_RFCK_SEL_150	0x30000000  #define SRDS_PLLCR0_RFCK_SEL_161_13	0x40000000  #define SRDS_PLLCR0_RFCK_SEL_122_88	0x50000000 +#define SRDS_PLLCR0_DCBIAS_OUT_EN      0x02000000  #define SRDS_PLLCR0_FRATE_SEL_MASK	0x000f0000  #define SRDS_PLLCR0_FRATE_SEL_5		0x00000000  #define SRDS_PLLCR0_FRATE_SEL_3_75	0x00050000 @@ -2511,9 +2513,22 @@ typedef struct serdes_corenet {  #define SRDS_PLLCR0_FRATE_SEL_4		0x00070000  #define SRDS_PLLCR0_FRATE_SEL_3_12	0x00090000  #define SRDS_PLLCR0_FRATE_SEL_3		0x000a0000 +#define SRDS_PLLCR0_DCBIAS_OVRD		0x000000F0 +#define SRDS_PLLCR0_DCBIAS_OVRD_SHIFT	4  		u32	pllcr1; /* PLL Control Register 1 */ -#define SRDS_PLLCR1_PLL_BWSEL	0x08000000 -		u32	res_0c;	/* 0x00c */ +#define SRDS_PLLCR1_BCAP_EN		0x20000000 +#define SRDS_PLLCR1_BCAP_OVD		0x10000000 +#define SRDS_PLLCR1_PLL_FCAP		0x001F8000 +#define SRDS_PLLCR1_PLL_FCAP_SHIFT	15 +#define SRDS_PLLCR1_PLL_BWSEL		0x08000000 +#define SRDS_PLLCR1_BYP_CAL		0x02000000 +		u32	pllsr2;	/* At 0x00c, PLL Status Register 2 */ +#define SRDS_PLLSR2_BCAP_EN		0x00800000 +#define SRDS_PLLSR2_BCAP_EN_SHIFT	23 +#define SRDS_PLLSR2_FCAP		0x003F0000 +#define SRDS_PLLSR2_FCAP_SHIFT		16 +#define SRDS_PLLSR2_DCBIAS		0x000F0000 +#define SRDS_PLLSR2_DCBIAS_SHIFT	16  		u32	pllcr3;  		u32	pllcr4;  		u8	res_18[0x20-0x18]; diff --git a/board/freescale/b4860qds/b4860qds.c b/board/freescale/b4860qds/b4860qds.c index 24a709e25..d9c88a074 100644 --- a/board/freescale/b4860qds/b4860qds.c +++ b/board/freescale/b4860qds/b4860qds.c @@ -288,6 +288,182 @@ int configure_vsc3316_3308(void)  	return 0;  } +static int calibrate_pll(serdes_corenet_t *srds_regs, int pll_num) +{ +	u32 rst_err; + +	/* Steps For SerDes PLLs reset and reconfiguration +	 * or PLL power-up procedure +	 */ +	debug("CALIBRATE PLL:%d\n", pll_num); +	clrbits_be32(&srds_regs->bank[pll_num].rstctl, +			SRDS_RSTCTL_SDRST_B); +	udelay(10); +	clrbits_be32(&srds_regs->bank[pll_num].rstctl, +		(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B)); +	udelay(10); +	setbits_be32(&srds_regs->bank[pll_num].rstctl, +			SRDS_RSTCTL_RST); +	setbits_be32(&srds_regs->bank[pll_num].rstctl, +		(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B +		| SRDS_RSTCTL_SDRST_B)); + +	udelay(20); + +	/* Check whether PLL has been locked or not */ +	rst_err = in_be32(&srds_regs->bank[pll_num].rstctl) & +				SRDS_RSTCTL_RSTERR; +	rst_err >>= SRDS_RSTCTL_RSTERR_SHIFT; +	debug("RST_ERR value for PLL %d is: 0x%x:\n", pll_num, rst_err); +	if (rst_err) +		return rst_err; + +	return rst_err; +} + +static int check_pll_locks(serdes_corenet_t *srds_regs, int pll_num) +{ +	int ret = 0; +	u32 fcap, dcbias, bcap, pllcr1, pllcr0; + +	if (calibrate_pll(srds_regs, pll_num)) { +		/* STEP 1 */ +		/* Read fcap, dcbias and bcap value */ +		clrbits_be32(&srds_regs->bank[pll_num].pllcr0, +				SRDS_PLLCR0_DCBIAS_OUT_EN); +		fcap = in_be32(&srds_regs->bank[pll_num].pllsr2) & +					SRDS_PLLSR2_FCAP; +		fcap >>= SRDS_PLLSR2_FCAP_SHIFT; +		bcap = in_be32(&srds_regs->bank[pll_num].pllsr2) & +					SRDS_PLLSR2_BCAP_EN; +		bcap >>= SRDS_PLLSR2_BCAP_EN_SHIFT; +		setbits_be32(&srds_regs->bank[pll_num].pllcr0, +				SRDS_PLLCR0_DCBIAS_OUT_EN); +		dcbias = in_be32(&srds_regs->bank[pll_num].pllsr2) & +					SRDS_PLLSR2_DCBIAS; +		dcbias >>= SRDS_PLLSR2_DCBIAS_SHIFT; +		debug("values of bcap:%x, fcap:%x and dcbias:%x\n", +					bcap, fcap, dcbias); +		if (fcap == 0 && bcap == 1) { +			/* Step 3 */ +			clrbits_be32(&srds_regs->bank[pll_num].rstctl, +				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B +				 | SRDS_RSTCTL_SDRST_B)); +			clrbits_be32(&srds_regs->bank[pll_num].pllcr1, +					SRDS_PLLCR1_BCAP_EN); +			setbits_be32(&srds_regs->bank[pll_num].pllcr1, +					SRDS_PLLCR1_BCAP_OVD); +			if (calibrate_pll(srds_regs, pll_num)) { +				/*save the fcap, dcbias and bcap values*/ +				clrbits_be32(&srds_regs->bank[pll_num].pllcr0, +						SRDS_PLLCR0_DCBIAS_OUT_EN); +				fcap = in_be32(&srds_regs->bank[pll_num].pllsr2) +					& SRDS_PLLSR2_FCAP; +				fcap >>= SRDS_PLLSR2_FCAP_SHIFT; +				bcap = in_be32(&srds_regs->bank[pll_num].pllsr2) +					& SRDS_PLLSR2_BCAP_EN; +				bcap >>= SRDS_PLLSR2_BCAP_EN_SHIFT; +				setbits_be32(&srds_regs->bank[pll_num].pllcr0, +						SRDS_PLLCR0_DCBIAS_OUT_EN); +				dcbias = in_be32 +					(&srds_regs->bank[pll_num].pllsr2) & +							SRDS_PLLSR2_DCBIAS; +				dcbias >>= SRDS_PLLSR2_DCBIAS_SHIFT; + +				/* Step 4*/ +				clrbits_be32(&srds_regs->bank[pll_num].rstctl, +				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B +				 | SRDS_RSTCTL_SDRST_B)); +				setbits_be32(&srds_regs->bank[pll_num].pllcr1, +						SRDS_PLLCR1_BYP_CAL); +				clrbits_be32(&srds_regs->bank[pll_num].pllcr1, +						SRDS_PLLCR1_BCAP_EN); +				setbits_be32(&srds_regs->bank[pll_num].pllcr1, +						SRDS_PLLCR1_BCAP_OVD); +				/* change the fcap and dcbias to the saved +				 * values from Step 3 */ +				clrbits_be32(&srds_regs->bank[pll_num].pllcr1, +							SRDS_PLLCR1_PLL_FCAP); +				pllcr1 = (in_be32 +					(&srds_regs->bank[pll_num].pllcr1)| +					(fcap << SRDS_PLLCR1_PLL_FCAP_SHIFT)); +				out_be32(&srds_regs->bank[pll_num].pllcr1, +							pllcr1); +				clrbits_be32(&srds_regs->bank[pll_num].pllcr0, +						SRDS_PLLCR0_DCBIAS_OVRD); +				pllcr0 = (in_be32 +				(&srds_regs->bank[pll_num].pllcr0)| +				(dcbias << SRDS_PLLCR0_DCBIAS_OVRD_SHIFT)); +				out_be32(&srds_regs->bank[pll_num].pllcr0, +							pllcr0); +				ret = calibrate_pll(srds_regs, pll_num); +				if (ret) +					return ret; +			} else { +				goto out; +			} +		} else { /* Step 5 */ +			clrbits_be32(&srds_regs->bank[pll_num].rstctl, +				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B +				 | SRDS_RSTCTL_SDRST_B)); +			udelay(10); +			/* Change the fcap, dcbias, and bcap to the +			 * values from Step 1 */ +			setbits_be32(&srds_regs->bank[pll_num].pllcr1, +					SRDS_PLLCR1_BYP_CAL); +			clrbits_be32(&srds_regs->bank[pll_num].pllcr1, +						SRDS_PLLCR1_PLL_FCAP); +			pllcr1 = (in_be32(&srds_regs->bank[pll_num].pllcr1)| +				(fcap << SRDS_PLLCR1_PLL_FCAP_SHIFT)); +			out_be32(&srds_regs->bank[pll_num].pllcr1, +						pllcr1); +			clrbits_be32(&srds_regs->bank[pll_num].pllcr0, +						SRDS_PLLCR0_DCBIAS_OVRD); +			pllcr0 = (in_be32(&srds_regs->bank[pll_num].pllcr0)| +				(dcbias << SRDS_PLLCR0_DCBIAS_OVRD_SHIFT)); +			out_be32(&srds_regs->bank[pll_num].pllcr0, +						pllcr0); +			clrbits_be32(&srds_regs->bank[pll_num].pllcr1, +					SRDS_PLLCR1_BCAP_EN); +			setbits_be32(&srds_regs->bank[pll_num].pllcr1, +					SRDS_PLLCR1_BCAP_OVD); +			ret = calibrate_pll(srds_regs, pll_num); +			if (ret) +				return ret; +		} +	} +out: +	return 0; +} + +static int check_serdes_pll_locks(void) +{ +	serdes_corenet_t *srds1_regs = +		(void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; +	serdes_corenet_t *srds2_regs = +		(void *)CONFIG_SYS_FSL_CORENET_SERDES2_ADDR; +	int i, ret1, ret2; + +	debug("\nSerDes1 Lock check\n"); +	for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) { +		ret1 = check_pll_locks(srds1_regs, i); +		if (ret1) { +			printf("SerDes1, PLL:%d didnt lock\n", i); +			return ret1; +		} +	} +	debug("\nSerDes2 Lock check\n"); +	for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) { +		ret2 = check_pll_locks(srds2_regs, i); +		if (ret2) { +			printf("SerDes2, PLL:%d didnt lock\n", i); +			return ret2; +		} +	} + +	return 0; +} +  int config_serdes1_refclks(void)  {  	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); @@ -478,6 +654,8 @@ int config_serdes2_refclks(void)  			setbits_be32(&srds2_regs->bank[i].rstctl,  				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B  				| SRDS_RSTCTL_SDRST_B)); + +			udelay(10);  		}  		break;  	default: @@ -544,6 +722,21 @@ int board_early_init_r(void)  	else  		printf("SerDes2 Refclk reconfiguring failed.\n"); +#if defined(CONFIG_SYS_FSL_ERRATUM_A006384) || \ +			defined(CONFIG_SYS_FSL_ERRATUM_A006475) +	/* Rechecking the SerDes locks after all SerDes configurations +	 * are done, As SerDes PLLs may not lock reliably at 5 G VCO +	 * and at cold temperatures. +	 * Following sequence ensure the proper locking of SerDes PLLs. +	 */ +	if (SVR_MAJ(get_svr()) == 1) { +		if (check_serdes_pll_locks()) +			printf("SerDes plls still not locked properly.\n"); +		else +			printf("SerDes plls have been locked well.\n"); +	} +#endif +  	/* Configure VSC3316 and VSC3308 crossbar switches */  	if (configure_vsc3316_3308())  		printf("VSC:failed to configure VSC3316/3308.\n"); |