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