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