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 <log.h>
10#include <asm/io.h>
11#include <asm/immap_85xx.h>
12#include <asm/fsl_serdes.h>
13
14#define SRDS1_MAX_LANES		4
15#define SRDS2_MAX_LANES		2
16
17static u32 serdes1_prtcl_map, serdes2_prtcl_map;
18
19static const u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
20	[0x00] = {NONE, NONE, NONE, NONE},
21	[0x01] = {PCIE1, PCIE2, SGMII_TSEC2, SGMII_TSEC3},
22	[0x02] = {PCIE1, SGMII_TSEC1, SGMII_TSEC2, SGMII_TSEC3},
23	[0x03] = {NONE, SGMII_TSEC1, SGMII_TSEC2, SGMII_TSEC3},
24};
25
26static const u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
27	[0x00] = {NONE, NONE},
28	[0x01] = {SATA1, SATA2},
29	[0x02] = {SATA1, SATA2},
30	[0x03] = {PCIE1, PCIE2},
31};
32
33
34int is_serdes_configured(enum srds_prtcl device)
35{
36	int ret;
37
38	if (!(serdes1_prtcl_map & (1 << NONE)))
39		fsl_serdes_init();
40
41	ret = (1 << device) & serdes1_prtcl_map;
42
43	if (ret)
44		return ret;
45
46	if (!(serdes2_prtcl_map & (1 << NONE)))
47		fsl_serdes_init();
48
49	return (1 << device) & serdes2_prtcl_map;
50}
51
52void fsl_serdes_init(void)
53{
54	ccsr_gur_t *gur = (void *)CFG_SYS_MPC85xx_GUTS_ADDR;
55	u32 pordevsr = in_be32(&gur->pordevsr);
56	u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
57				MPC85xx_PORDEVSR_IO_SEL_SHIFT;
58	int lane;
59
60	if (serdes1_prtcl_map & (1 << NONE) &&
61	    serdes2_prtcl_map & (1 << NONE))
62		return;
63
64	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
65
66	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
67		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
68		return;
69	}
70	for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
71		enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
72		serdes1_prtcl_map |= (1 << lane_prtcl);
73	}
74
75	/* Set the first bit to indicate serdes has been initialized */
76	serdes1_prtcl_map |= (1 << NONE);
77
78	if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
79		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
80		return;
81	}
82
83	for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
84		enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds_cfg][lane];
85		serdes2_prtcl_map |= (1 << lane_prtcl);
86	}
87
88	/* Set the first bit to indicate serdes has been initialized */
89	serdes2_prtcl_map |= (1 << NONE);
90}
91