xref: /openbmc/u-boot/arch/powerpc/cpu/mpc85xx/p1010_serdes.c (revision eba6589f7e019d8ccb331a84a789b0c4d74f51f6)
1  // SPDX-License-Identifier: GPL-2.0+
2  /*
3   * Copyright 2011 Freescale Semiconductor, Inc.
4   * Author: Prabhakar Kushwaha <prabhakar@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  #define SRDS1_MAX_LANES		4
14  #define SRDS2_MAX_LANES		2
15  
16  static u32 serdes1_prtcl_map, serdes2_prtcl_map;
17  
18  static const u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
19  	[0x00] = {NONE, NONE, NONE, NONE},
20  	[0x01] = {PCIE1, PCIE2, SGMII_TSEC2, SGMII_TSEC3},
21  	[0x02] = {PCIE1, SGMII_TSEC1, SGMII_TSEC2, SGMII_TSEC3},
22  	[0x03] = {NONE, SGMII_TSEC1, SGMII_TSEC2, SGMII_TSEC3},
23  };
24  
25  static const u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
26  	[0x00] = {NONE, NONE},
27  	[0x01] = {SATA1, SATA2},
28  	[0x02] = {SATA1, SATA2},
29  	[0x03] = {PCIE1, PCIE2},
30  };
31  
32  
33  int is_serdes_configured(enum srds_prtcl device)
34  {
35  	int ret;
36  
37  	if (!(serdes1_prtcl_map & (1 << NONE)))
38  		fsl_serdes_init();
39  
40  	ret = (1 << device) & serdes1_prtcl_map;
41  
42  	if (ret)
43  		return ret;
44  
45  	if (!(serdes2_prtcl_map & (1 << NONE)))
46  		fsl_serdes_init();
47  
48  	return (1 << device) & serdes2_prtcl_map;
49  }
50  
51  void fsl_serdes_init(void)
52  {
53  	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
54  	u32 pordevsr = in_be32(&gur->pordevsr);
55  	u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
56  				MPC85xx_PORDEVSR_IO_SEL_SHIFT;
57  	int lane;
58  
59  	if (serdes1_prtcl_map & (1 << NONE) &&
60  	    serdes2_prtcl_map & (1 << NONE))
61  		return;
62  
63  	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
64  
65  	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
66  		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
67  		return;
68  	}
69  	for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
70  		enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
71  		serdes1_prtcl_map |= (1 << lane_prtcl);
72  	}
73  
74  	/* Set the first bit to indicate serdes has been initialized */
75  	serdes1_prtcl_map |= (1 << NONE);
76  
77  	if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
78  		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
79  		return;
80  	}
81  
82  	for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
83  		enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds_cfg][lane];
84  		serdes2_prtcl_map |= (1 << lane_prtcl);
85  	}
86  
87  	/* Set the first bit to indicate serdes has been initialized */
88  	serdes2_prtcl_map |= (1 << NONE);
89  }
90