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