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