18281c58fSMingkai Hu /*
28281c58fSMingkai Hu  * Copyright 2015 Freescale Semiconductor, Inc.
38281c58fSMingkai Hu  *
48281c58fSMingkai Hu  * SPDX-License-Identifier:	GPL-2.0+
58281c58fSMingkai Hu  */
68281c58fSMingkai Hu 
78281c58fSMingkai Hu #include <common.h>
88281c58fSMingkai Hu #include <asm/io.h>
98281c58fSMingkai Hu #include <asm/errno.h>
108281c58fSMingkai Hu #include <asm/arch/fsl_serdes.h>
118281c58fSMingkai Hu #include <asm/arch/soc.h>
128281c58fSMingkai Hu 
138281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
148281c58fSMingkai Hu static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
158281c58fSMingkai Hu #endif
168281c58fSMingkai Hu 
178281c58fSMingkai Hu int is_serdes_configured(enum srds_prtcl device)
188281c58fSMingkai Hu {
198281c58fSMingkai Hu 	int ret = 0;
208281c58fSMingkai Hu 
218281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
228281c58fSMingkai Hu 	ret |= serdes1_prtcl_map[device];
238281c58fSMingkai Hu #endif
248281c58fSMingkai Hu 
258281c58fSMingkai Hu 	return !!ret;
268281c58fSMingkai Hu }
278281c58fSMingkai Hu 
288281c58fSMingkai Hu int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
298281c58fSMingkai Hu {
308281c58fSMingkai Hu 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
318281c58fSMingkai Hu 	u32 cfg = gur_in32(&gur->rcwsr[4]);
328281c58fSMingkai Hu 	int i;
338281c58fSMingkai Hu 
348281c58fSMingkai Hu 	switch (sd) {
358281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
368281c58fSMingkai Hu 	case FSL_SRDS_1:
378281c58fSMingkai Hu 		cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
388281c58fSMingkai Hu 		cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
398281c58fSMingkai Hu 		break;
408281c58fSMingkai Hu #endif
418281c58fSMingkai Hu 	default:
428281c58fSMingkai Hu 		printf("invalid SerDes%d\n", sd);
438281c58fSMingkai Hu 		break;
448281c58fSMingkai Hu 	}
458281c58fSMingkai Hu 
468281c58fSMingkai Hu 	/* Is serdes enabled at all? */
478281c58fSMingkai Hu 	if (unlikely(cfg == 0))
488281c58fSMingkai Hu 		return -ENODEV;
498281c58fSMingkai Hu 
508281c58fSMingkai Hu 	for (i = 0; i < SRDS_MAX_LANES; i++) {
518281c58fSMingkai Hu 		if (serdes_get_prtcl(sd, cfg, i) == device)
528281c58fSMingkai Hu 			return i;
538281c58fSMingkai Hu 	}
548281c58fSMingkai Hu 
558281c58fSMingkai Hu 	return -ENODEV;
568281c58fSMingkai Hu }
578281c58fSMingkai Hu 
588281c58fSMingkai Hu int get_serdes_protocol(void)
598281c58fSMingkai Hu {
608281c58fSMingkai Hu 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
618281c58fSMingkai Hu 	u32 cfg = gur_in32(&gur->rcwsr[4]) &
628281c58fSMingkai Hu 			  FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
638281c58fSMingkai Hu 	cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
648281c58fSMingkai Hu 
658281c58fSMingkai Hu 	return cfg;
668281c58fSMingkai Hu }
678281c58fSMingkai Hu 
688281c58fSMingkai Hu const char *serdes_clock_to_string(u32 clock)
698281c58fSMingkai Hu {
708281c58fSMingkai Hu 	switch (clock) {
718281c58fSMingkai Hu 	case SRDS_PLLCR0_RFCK_SEL_100:
728281c58fSMingkai Hu 		return "100";
738281c58fSMingkai Hu 	case SRDS_PLLCR0_RFCK_SEL_125:
748281c58fSMingkai Hu 		return "125";
758281c58fSMingkai Hu 	case SRDS_PLLCR0_RFCK_SEL_156_25:
768281c58fSMingkai Hu 		return "156.25";
778281c58fSMingkai Hu 	default:
788281c58fSMingkai Hu 		return "100";
798281c58fSMingkai Hu 	}
808281c58fSMingkai Hu }
818281c58fSMingkai Hu 
828281c58fSMingkai Hu void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
838281c58fSMingkai Hu 		 u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
848281c58fSMingkai Hu {
858281c58fSMingkai Hu 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
868281c58fSMingkai Hu 	u32 cfg;
878281c58fSMingkai Hu 	int lane;
888281c58fSMingkai Hu 
89*1a338921STom Rini 	memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
908281c58fSMingkai Hu 
918281c58fSMingkai Hu 	cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask;
928281c58fSMingkai Hu 	cfg >>= sd_prctl_shift;
938281c58fSMingkai Hu 	printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
948281c58fSMingkai Hu 
958281c58fSMingkai Hu 	if (!is_serdes_prtcl_valid(sd, cfg))
968281c58fSMingkai Hu 		printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
978281c58fSMingkai Hu 
988281c58fSMingkai Hu 	for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
998281c58fSMingkai Hu 		enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
1008281c58fSMingkai Hu 
1018281c58fSMingkai Hu 		if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
1028281c58fSMingkai Hu 			debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
1038281c58fSMingkai Hu 		else
1048281c58fSMingkai Hu 			serdes_prtcl_map[lane_prtcl] = 1;
1058281c58fSMingkai Hu 	}
1068281c58fSMingkai Hu }
1078281c58fSMingkai Hu 
1088281c58fSMingkai Hu void fsl_serdes_init(void)
1098281c58fSMingkai Hu {
1108281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
1118281c58fSMingkai Hu 	serdes_init(FSL_SRDS_1,
1128281c58fSMingkai Hu 		    CONFIG_SYS_FSL_SERDES_ADDR,
1138281c58fSMingkai Hu 		    FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK,
1148281c58fSMingkai Hu 		    FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT,
1158281c58fSMingkai Hu 		    serdes1_prtcl_map);
1168281c58fSMingkai Hu #endif
1178281c58fSMingkai Hu }
118