p4080/serdes: Implement the XAUI workaround for SERDES9 erratum
Signed-off-by: Emil Medve <Emilian.Medve@Freescale.com> Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
This commit is contained in:
		
							parent
							
								
									3d28c5c8ed
								
							
						
					
					
						commit
						df8af0b4a6
					
				|  | @ -44,6 +44,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | ||||||
| #if defined(CONFIG_SYS_P4080_ERRATUM_SERDES8) | #if defined(CONFIG_SYS_P4080_ERRATUM_SERDES8) | ||||||
| 	puts("Work-around for Erratum SERDES8 enabled\n"); | 	puts("Work-around for Erratum SERDES8 enabled\n"); | ||||||
| #endif | #endif | ||||||
|  | #if defined(CONFIG_SYS_P4080_ERRATUM_SERDES9) | ||||||
|  | 	puts("Work-around for Erratum SERDES9 enabled\n"); | ||||||
|  | #endif | ||||||
| #if defined(CONFIG_SYS_P4080_ERRATUM_CPU22) | #if defined(CONFIG_SYS_P4080_ERRATUM_CPU22) | ||||||
| 	puts("Work-around for Erratum CPU22 enabled\n"); | 	puts("Work-around for Erratum CPU22 enabled\n"); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -168,6 +168,90 @@ int serdes_get_first_lane(enum srds_prtcl device) | ||||||
| 	return __serdes_get_first_lane(prtcl, device); | 	return __serdes_get_first_lane(prtcl, device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 | ||||||
|  | /*
 | ||||||
|  |  * Returns the SERDES bank (1, 2, or 3) that a given device is on for a given | ||||||
|  |  * SERDES protocol. | ||||||
|  |  * | ||||||
|  |  * Returns a negative error code if the given device is not supported for the | ||||||
|  |  * given SERDES protocol. | ||||||
|  |  */ | ||||||
|  | static int serdes_get_bank_by_device(uint32_t prtcl, enum srds_prtcl device) | ||||||
|  | { | ||||||
|  | 	int lane; | ||||||
|  | 
 | ||||||
|  | 	lane = __serdes_get_first_lane(prtcl, device); | ||||||
|  | 	if (unlikely(lane < 0)) | ||||||
|  | 		return lane; | ||||||
|  | 
 | ||||||
|  | 	return serdes_get_bank_by_lane(lane); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static uint32_t __serdes_get_lane_count(uint32_t prtcl, enum srds_prtcl device, | ||||||
|  | 					int first) | ||||||
|  | { | ||||||
|  | 	int lane; | ||||||
|  | 
 | ||||||
|  | 	for (lane = first; lane < SRDS_MAX_LANES; lane++) { | ||||||
|  | 		if (serdes_get_prtcl(prtcl, lane) != device) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return lane - first; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void __serdes_reset_rx(serdes_corenet_t *regs, | ||||||
|  | 			      uint32_t prtcl, | ||||||
|  | 			      enum srds_prtcl device) | ||||||
|  | { | ||||||
|  | 	int lane, idx, first, last; | ||||||
|  | 
 | ||||||
|  | 	lane = __serdes_get_first_lane(prtcl, device); | ||||||
|  | 	if (unlikely(lane < 0)) | ||||||
|  | 		return; | ||||||
|  | 	first = serdes_get_lane_idx(lane); | ||||||
|  | 	last = first + __serdes_get_lane_count(prtcl, device, lane); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Set BnGCRy0[RRST] = 0 for each lane in the each bank that is | ||||||
|  | 	 * selected as XAUI to place the lane into reset. | ||||||
|  | 	*/ | ||||||
|  | 	for (idx = first; idx < last; idx++) | ||||||
|  | 		clrbits_be32(®s->lane[idx].gcr0, SRDS_GCR0_RRST); | ||||||
|  | 
 | ||||||
|  | 	/* Wait at least 250 ns */ | ||||||
|  | 	udelay(1); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Set BnGCRy0[RRST] = 1 for each lane in the each bank that is | ||||||
|  | 	 * selected as XAUI to bring the lane out of reset. | ||||||
|  | 	 */ | ||||||
|  | 	for (idx = first; idx < last; idx++) | ||||||
|  | 		setbits_be32(®s->lane[idx].gcr0, SRDS_GCR0_RRST); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void serdes_reset_rx(enum srds_prtcl device) | ||||||
|  | { | ||||||
|  | 	u32 prtcl; | ||||||
|  | 	const ccsr_gur_t *gur; | ||||||
|  | 	serdes_corenet_t *regs; | ||||||
|  | 
 | ||||||
|  | 	if (unlikely(device == NONE)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	gur = (typeof(gur))CONFIG_SYS_MPC85xx_GUTS_ADDR; | ||||||
|  | 
 | ||||||
|  | 	/* Is serdes enabled at all? */ | ||||||
|  | 	if (unlikely((in_be32(&gur->rcwsr[5]) & 0x2000) == 0)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	regs = (typeof(regs))CONFIG_SYS_FSL_CORENET_SERDES_ADDR; | ||||||
|  | 	prtcl = (in_be32(&gur->rcwsr[4]) & FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26; | ||||||
|  | 
 | ||||||
|  | 	__serdes_reset_rx(regs, prtcl, device); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifndef CONFIG_SYS_DCSRBAR_PHYS | #ifndef CONFIG_SYS_DCSRBAR_PHYS | ||||||
| #define CONFIG_SYS_DCSRBAR_PHYS	0x80000000 /* Must be 1GB-aligned for rev1.0 */ | #define CONFIG_SYS_DCSRBAR_PHYS	0x80000000 /* Must be 1GB-aligned for rev1.0 */ | ||||||
| #define CONFIG_SYS_DCSRBAR	0x80000000 | #define CONFIG_SYS_DCSRBAR	0x80000000 | ||||||
|  | @ -317,6 +401,9 @@ void fsl_serdes_init(void) | ||||||
| 	char srds_lpd_opt[16]; | 	char srds_lpd_opt[16]; | ||||||
| 	const char *srds_lpd_arg; | 	const char *srds_lpd_arg; | ||||||
| 	size_t arglen; | 	size_t arglen; | ||||||
|  | #endif | ||||||
|  | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 | ||||||
|  | 	enum srds_prtcl device; | ||||||
| #endif | #endif | ||||||
| 	char buffer[HWCONFIG_BUFFER_SIZE]; | 	char buffer[HWCONFIG_BUFFER_SIZE]; | ||||||
| 	char *buf = NULL; | 	char *buf = NULL; | ||||||
|  | @ -452,6 +539,17 @@ void fsl_serdes_init(void) | ||||||
| 			break; | 			break; | ||||||
| 		case XAUI_FM1: | 		case XAUI_FM1: | ||||||
| 		case XAUI_FM2: | 		case XAUI_FM2: | ||||||
|  | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 | ||||||
|  | 			/*
 | ||||||
|  | 			 * Set BnTTLCRy0[FLT_SEL] = 000011 and set | ||||||
|  | 			 * BnTTLCRy0[17] = 1 for each of the SerDes lanes | ||||||
|  | 			 * selected as XAUI on each bank before XAUI is | ||||||
|  | 			 * initialized. | ||||||
|  | 			 */ | ||||||
|  | 			clrsetbits_be32(&srds_regs->lane[idx].ttlcr0, | ||||||
|  | 					SRDS_TTLCR0_FLT_SEL_MASK, | ||||||
|  | 					0x03000000 | SRDS_TTLCR0_PM_DIS); | ||||||
|  | #endif | ||||||
| 			if (lane_prtcl == XAUI_FM1) | 			if (lane_prtcl == XAUI_FM1) | ||||||
| 				serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1	| | 				serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1	| | ||||||
| 						    FSL_CORENET_DEVDISR2_10GEC1; | 						    FSL_CORENET_DEVDISR2_10GEC1; | ||||||
|  | @ -470,6 +568,8 @@ void fsl_serdes_init(void) | ||||||
| 
 | 
 | ||||||
| #ifdef DEBUG | #ifdef DEBUG | ||||||
| 	puts("\n"); | 	puts("\n"); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	for (idx = 0; idx < SRDS_MAX_BANK; idx++) { | 	for (idx = 0; idx < SRDS_MAX_BANK; idx++) { | ||||||
|  | @ -527,4 +627,11 @@ void fsl_serdes_init(void) | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 | ||||||
|  | 	for (device = XAUI_FM1; device <= XAUI_FM2; device++) { | ||||||
|  | 		if (is_serdes_configured(device)) | ||||||
|  | 			__serdes_reset_rx(srds_regs, cfg, device); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -304,6 +304,7 @@ | ||||||
| #define CONFIG_SYS_FSL_ERRATUM_ESDHC136 | #define CONFIG_SYS_FSL_ERRATUM_ESDHC136 | ||||||
| #define CONFIG_SYS_P4080_ERRATUM_CPU22 | #define CONFIG_SYS_P4080_ERRATUM_CPU22 | ||||||
| #define CONFIG_SYS_P4080_ERRATUM_SERDES8 | #define CONFIG_SYS_P4080_ERRATUM_SERDES8 | ||||||
|  | #define CONFIG_SYS_P4080_ERRATUM_SERDES9 | ||||||
| 
 | 
 | ||||||
| /* P5010 is single core version of P5020 */ | /* P5010 is single core version of P5020 */ | ||||||
| #elif defined(CONFIG_PPC_P5010) | #elif defined(CONFIG_PPC_P5010) | ||||||
|  |  | ||||||
|  | @ -55,6 +55,9 @@ void fsl_serdes_init(void); | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_FSL_CORENET | #ifdef CONFIG_FSL_CORENET | ||||||
| int serdes_get_first_lane(enum srds_prtcl device); | int serdes_get_first_lane(enum srds_prtcl device); | ||||||
|  | #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 | ||||||
|  | void serdes_reset_rx(enum srds_prtcl device); | ||||||
|  | #endif | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #endif /* __FSL_SERDES_H */ | #endif /* __FSL_SERDES_H */ | ||||||
|  |  | ||||||
|  | @ -2137,6 +2137,8 @@ typedef struct serdes_corenet { | ||||||
| #define SRDS_TECR0_TEQ_TYPE_2LVL	0x10000000 | #define SRDS_TECR0_TEQ_TYPE_2LVL	0x10000000 | ||||||
| 		u32	res3; | 		u32	res3; | ||||||
| 		u32	ttlcr0;	/* Transition Tracking Loop Ctrl 0 */ | 		u32	ttlcr0;	/* Transition Tracking Loop Ctrl 0 */ | ||||||
|  | #define SRDS_TTLCR0_FLT_SEL_MASK	0x3f000000 | ||||||
|  | #define SRDS_TTLCR0_PM_DIS		0x00004000 | ||||||
| 		u32	res4[7]; | 		u32	res4[7]; | ||||||
| 	} lane[24]; | 	} lane[24]; | ||||||
| 	u32 res6[384]; | 	u32 res6[384]; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue