Home | History | Annotate | Download | only in mpc85xx
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright 2008,2010 Freescale Semiconductor, Inc.
      4  *	Dave Liu <daveliu (at) freescale.com>
      5  */
      6 
      7 #include <config.h>
      8 #include <common.h>
      9 #include <asm/io.h>
     10 #include <asm/immap_85xx.h>
     11 #include <asm/fsl_serdes.h>
     12 
     13 /* PORDEVSR register */
     14 #define GUTS_PORDEVSR_OFFS		0xc
     15 #define GUTS_PORDEVSR_SERDES2_IO_SEL	0x38000000
     16 #define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT	27
     17 
     18 /* SerDes CR0 register */
     19 #define	FSL_SRDSCR0_OFFS	0x0
     20 #define FSL_SRDSCR0_TXEQA_MASK	0x00007000
     21 #define FSL_SRDSCR0_TXEQA_SGMII	0x00004000
     22 #define FSL_SRDSCR0_TXEQA_SATA	0x00001000
     23 #define FSL_SRDSCR0_TXEQE_MASK	0x00000700
     24 #define FSL_SRDSCR0_TXEQE_SGMII	0x00000400
     25 #define FSL_SRDSCR0_TXEQE_SATA	0x00000100
     26 
     27 /* SerDes CR1 register */
     28 #define FSL_SRDSCR1_OFFS	0x4
     29 #define FSL_SRDSCR1_LANEA_MASK	0x80200000
     30 #define FSL_SRDSCR1_LANEA_OFF	0x80200000
     31 #define FSL_SRDSCR1_LANEE_MASK	0x08020000
     32 #define FSL_SRDSCR1_LANEE_OFF	0x08020000
     33 
     34 /* SerDes CR2 register */
     35 #define FSL_SRDSCR2_OFFS	0x8
     36 #define FSL_SRDSCR2_EICA_MASK	0x00001f00
     37 #define FSL_SRDSCR2_EICA_SGMII	0x00000400
     38 #define FSL_SRDSCR2_EICA_SATA	0x00001400
     39 #define FSL_SRDSCR2_EICE_MASK	0x0000001f
     40 #define FSL_SRDSCR2_EICE_SGMII	0x00000004
     41 #define FSL_SRDSCR2_EICE_SATA	0x00000014
     42 
     43 /* SerDes CR3 register */
     44 #define FSL_SRDSCR3_OFFS	0xc
     45 #define FSL_SRDSCR3_LANEA_MASK	0x3f000700
     46 #define FSL_SRDSCR3_LANEA_SGMII	0x00000000
     47 #define FSL_SRDSCR3_LANEA_SATA	0x15000500
     48 #define FSL_SRDSCR3_LANEE_MASK	0x003f0007
     49 #define FSL_SRDSCR3_LANEE_SGMII	0x00000000
     50 #define FSL_SRDSCR3_LANEE_SATA	0x00150005
     51 
     52 #define SRDS1_MAX_LANES		8
     53 #define SRDS2_MAX_LANES		2
     54 
     55 static u32 serdes1_prtcl_map, serdes2_prtcl_map;
     56 
     57 static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
     58 	[0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
     59 	[0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
     60 	[0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
     61 	[0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3},
     62 };
     63 
     64 static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
     65 	[0x1] = {SATA1, SATA2},
     66 	[0x3] = {SATA1, NONE},
     67 	[0x4] = {SGMII_TSEC1, SGMII_TSEC3},
     68 	[0x6] = {SGMII_TSEC1, NONE},
     69 };
     70 
     71 int is_serdes_configured(enum srds_prtcl device)
     72 {
     73 	int ret;
     74 
     75 	if (!(serdes1_prtcl_map & (1 << NONE)))
     76 		fsl_serdes_init();
     77 
     78 	ret = (1 << device) & serdes1_prtcl_map;
     79 
     80 	if (ret)
     81 		return ret;
     82 
     83 	if (!(serdes2_prtcl_map & (1 << NONE)))
     84 		fsl_serdes_init();
     85 
     86 	return (1 << device) & serdes2_prtcl_map;
     87 }
     88 
     89 void fsl_serdes_init(void)
     90 {
     91 	void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
     92 	void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
     93 	u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
     94 	u32 srds1_io_sel, srds2_io_sel;
     95 	u32 tmp;
     96 	int lane;
     97 
     98 	if (serdes1_prtcl_map & (1 << NONE) &&
     99 	    serdes2_prtcl_map & (1 << NONE))
    100 		return;
    101 
    102 	srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
    103 				MPC85xx_PORDEVSR_IO_SEL_SHIFT;
    104 
    105 	/* parse the SRDS2_IO_SEL of PORDEVSR */
    106 	srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
    107 		       >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
    108 
    109 	debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel);
    110 	debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel);
    111 
    112 	switch (srds2_io_sel) {
    113 	case 1:	/* Lane A - SATA1, Lane E - SATA2 */
    114 		/* CR 0 */
    115 		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
    116 		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
    117 		tmp |= FSL_SRDSCR0_TXEQA_SATA;
    118 		tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
    119 		tmp |= FSL_SRDSCR0_TXEQE_SATA;
    120 		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
    121 		/* CR 1 */
    122 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
    123 		tmp &= ~FSL_SRDSCR1_LANEA_MASK;
    124 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
    125 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
    126 		/* CR 2 */
    127 		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
    128 		tmp &= ~FSL_SRDSCR2_EICA_MASK;
    129 		tmp |= FSL_SRDSCR2_EICA_SATA;
    130 		tmp &= ~FSL_SRDSCR2_EICE_MASK;
    131 		tmp |= FSL_SRDSCR2_EICE_SATA;
    132 		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
    133 		/* CR 3 */
    134 		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
    135 		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
    136 		tmp |= FSL_SRDSCR3_LANEA_SATA;
    137 		tmp &= ~FSL_SRDSCR3_LANEE_MASK;
    138 		tmp |= FSL_SRDSCR3_LANEE_SATA;
    139 		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
    140 		break;
    141 	case 3: /* Lane A - SATA1, Lane E - disabled */
    142 		/* CR 0 */
    143 		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
    144 		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
    145 		tmp |= FSL_SRDSCR0_TXEQA_SATA;
    146 		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
    147 		/* CR 1 */
    148 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
    149 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
    150 		tmp |= FSL_SRDSCR1_LANEE_OFF;
    151 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
    152 		/* CR 2 */
    153 		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
    154 		tmp &= ~FSL_SRDSCR2_EICA_MASK;
    155 		tmp |= FSL_SRDSCR2_EICA_SATA;
    156 		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
    157 		/* CR 3 */
    158 		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
    159 		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
    160 		tmp |= FSL_SRDSCR3_LANEA_SATA;
    161 		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
    162 		break;
    163 	case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
    164 		/* CR 0 */
    165 		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
    166 		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
    167 		tmp |= FSL_SRDSCR0_TXEQA_SGMII;
    168 		tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
    169 		tmp |= FSL_SRDSCR0_TXEQE_SGMII;
    170 		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
    171 		/* CR 1 */
    172 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
    173 		tmp &= ~FSL_SRDSCR1_LANEA_MASK;
    174 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
    175 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
    176 		/* CR 2 */
    177 		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
    178 		tmp &= ~FSL_SRDSCR2_EICA_MASK;
    179 		tmp |= FSL_SRDSCR2_EICA_SGMII;
    180 		tmp &= ~FSL_SRDSCR2_EICE_MASK;
    181 		tmp |= FSL_SRDSCR2_EICE_SGMII;
    182 		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
    183 		/* CR 3 */
    184 		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
    185 		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
    186 		tmp |= FSL_SRDSCR3_LANEA_SGMII;
    187 		tmp &= ~FSL_SRDSCR3_LANEE_MASK;
    188 		tmp |= FSL_SRDSCR3_LANEE_SGMII;
    189 		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
    190 		break;
    191 	case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
    192 		/* CR 0 */
    193 		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
    194 		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
    195 		tmp |= FSL_SRDSCR0_TXEQA_SGMII;
    196 		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
    197 		/* CR 1 */
    198 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
    199 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
    200 		tmp |= FSL_SRDSCR1_LANEE_OFF;
    201 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
    202 		/* CR 2 */
    203 		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
    204 		tmp &= ~FSL_SRDSCR2_EICA_MASK;
    205 		tmp |= FSL_SRDSCR2_EICA_SGMII;
    206 		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
    207 		/* CR 3 */
    208 		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
    209 		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
    210 		tmp |= FSL_SRDSCR3_LANEA_SGMII;
    211 		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
    212 		break;
    213 	case 7: /* Lane A - disabled, Lane E - disabled */
    214 		/* CR 1 */
    215 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
    216 		tmp &= ~FSL_SRDSCR1_LANEA_MASK;
    217 		tmp |= FSL_SRDSCR1_LANEA_OFF;
    218 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
    219 		tmp |= FSL_SRDSCR1_LANEE_OFF;
    220 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
    221 		break;
    222 	default:
    223 		break;
    224 	}
    225 
    226 	if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) {
    227 		printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
    228 		return;
    229 	}
    230 	for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
    231 		enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane];
    232 		serdes1_prtcl_map |= (1 << lane_prtcl);
    233 	}
    234 
    235 	/* Set the first bit to indicate serdes has been initialized */
    236 	serdes1_prtcl_map |= (1 << NONE);
    237 
    238 	if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) {
    239 		printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
    240 		return;
    241 	}
    242 
    243 	for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
    244 		enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane];
    245 		serdes2_prtcl_map |= (1 << lane_prtcl);
    246 	}
    247 
    248 	/* Set the first bit to indicate serdes has been initialized */
    249 	serdes2_prtcl_map |= (1 << NONE);
    250 }
    251