Home | History | Annotate | Download | only in ls102xa
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright 2014 Freescale Semiconductor, Inc.
      4  */
      5 
      6 #include <common.h>
      7 #include <asm/arch/fsl_serdes.h>
      8 #include <asm/arch/immap_ls102xa.h>
      9 #include <linux/errno.h>
     10 #include <asm/io.h>
     11 #include "fsl_ls1_serdes.h"
     12 
     13 #ifdef CONFIG_SYS_FSL_SRDS_1
     14 static u64 serdes1_prtcl_map;
     15 #endif
     16 #ifdef CONFIG_SYS_FSL_SRDS_2
     17 static u64 serdes2_prtcl_map;
     18 #endif
     19 
     20 int is_serdes_configured(enum srds_prtcl device)
     21 {
     22 	u64 ret = 0;
     23 
     24 #ifdef CONFIG_SYS_FSL_SRDS_1
     25 	if (!(serdes1_prtcl_map & (1ULL << NONE)))
     26 		fsl_serdes_init();
     27 
     28 	ret |= (1ULL << device) & serdes1_prtcl_map;
     29 #endif
     30 #ifdef CONFIG_SYS_FSL_SRDS_2
     31 	if (!(serdes2_prtcl_map & (1ULL << NONE)))
     32 		fsl_serdes_init();
     33 
     34 	ret |= (1ULL << device) & serdes2_prtcl_map;
     35 #endif
     36 
     37 	return !!ret;
     38 }
     39 
     40 int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
     41 {
     42 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
     43 	u32 cfg = in_be32(&gur->rcwsr[4]);
     44 	int i;
     45 
     46 	switch (sd) {
     47 #ifdef CONFIG_SYS_FSL_SRDS_1
     48 	case FSL_SRDS_1:
     49 		cfg &= RCWSR4_SRDS1_PRTCL_MASK;
     50 		cfg >>= RCWSR4_SRDS1_PRTCL_SHIFT;
     51 		break;
     52 #endif
     53 #ifdef CONFIG_SYS_FSL_SRDS_2
     54 	case FSL_SRDS_2:
     55 		cfg &= RCWSR4_SRDS2_PRTCL_MASK;
     56 		cfg >>= RCWSR4_SRDS2_PRTCL_SHIFT;
     57 		break;
     58 #endif
     59 	default:
     60 		printf("invalid SerDes%d\n", sd);
     61 		break;
     62 	}
     63 	/* Is serdes enabled at all? */
     64 	if (unlikely(cfg == 0))
     65 		return -ENODEV;
     66 
     67 	for (i = 0; i < SRDS_MAX_LANES; i++) {
     68 		if (serdes_get_prtcl(sd, cfg, i) == device)
     69 			return i;
     70 	}
     71 
     72 	return -ENODEV;
     73 }
     74 
     75 u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift)
     76 {
     77 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
     78 	u64 serdes_prtcl_map = 0;
     79 	u32 cfg;
     80 	int lane;
     81 
     82 	cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask;
     83 	cfg >>= sd_prctl_shift;
     84 	printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
     85 
     86 	if (!is_serdes_prtcl_valid(sd, cfg))
     87 		printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
     88 
     89 	for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
     90 		enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
     91 
     92 		serdes_prtcl_map |= (1ULL << lane_prtcl);
     93 	}
     94 
     95 	/* Set the first bit to indicate serdes has been initialized */
     96 	serdes_prtcl_map |= (1ULL << NONE);
     97 
     98 	return serdes_prtcl_map;
     99 }
    100 
    101 void fsl_serdes_init(void)
    102 {
    103 #ifdef CONFIG_SYS_FSL_SRDS_1
    104 	if (!(serdes1_prtcl_map & (1ULL << NONE)))
    105 		serdes1_prtcl_map = serdes_init(FSL_SRDS_1,
    106 					CONFIG_SYS_FSL_SERDES_ADDR,
    107 					RCWSR4_SRDS1_PRTCL_MASK,
    108 					RCWSR4_SRDS1_PRTCL_SHIFT);
    109 #endif
    110 #ifdef CONFIG_SYS_FSL_SRDS_2
    111 	if (!(serdes2_prtcl_map & (1ULL << NONE)))
    112 		serdes2_prtcl_map = serdes_init(FSL_SRDS_2,
    113 					CONFIG_SYS_FSL_SERDES_ADDR +
    114 					FSL_SRDS_2 * 0x1000,
    115 					RCWSR4_SRDS2_PRTCL_MASK,
    116 					RCWSR4_SRDS2_PRTCL_SHIFT);
    117 #endif
    118 }
    119 
    120 const char *serdes_clock_to_string(u32 clock)
    121 {
    122 	switch (clock) {
    123 	case SRDS_PLLCR0_RFCK_SEL_100:
    124 		return "100";
    125 	case SRDS_PLLCR0_RFCK_SEL_125:
    126 		return "125";
    127 	default:
    128 		return "100";
    129 	}
    130 }
    131