2 * Copyright 2008,2010 Freescale Semiconductor, Inc.
3 * Dave Liu <daveliu@freescale.com>
5 * SPDX-License-Identifier: GPL-2.0+
11 #include <asm/immap_85xx.h>
12 #include <asm/fsl_serdes.h>
14 /* PORDEVSR register */
15 #define GUTS_PORDEVSR_OFFS 0xc
16 #define GUTS_PORDEVSR_SERDES2_IO_SEL 0x38000000
17 #define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT 27
19 /* SerDes CR0 register */
20 #define FSL_SRDSCR0_OFFS 0x0
21 #define FSL_SRDSCR0_TXEQA_MASK 0x00007000
22 #define FSL_SRDSCR0_TXEQA_SGMII 0x00004000
23 #define FSL_SRDSCR0_TXEQA_SATA 0x00001000
24 #define FSL_SRDSCR0_TXEQE_MASK 0x00000700
25 #define FSL_SRDSCR0_TXEQE_SGMII 0x00000400
26 #define FSL_SRDSCR0_TXEQE_SATA 0x00000100
28 /* SerDes CR1 register */
29 #define FSL_SRDSCR1_OFFS 0x4
30 #define FSL_SRDSCR1_LANEA_MASK 0x80200000
31 #define FSL_SRDSCR1_LANEA_OFF 0x80200000
32 #define FSL_SRDSCR1_LANEE_MASK 0x08020000
33 #define FSL_SRDSCR1_LANEE_OFF 0x08020000
35 /* SerDes CR2 register */
36 #define FSL_SRDSCR2_OFFS 0x8
37 #define FSL_SRDSCR2_EICA_MASK 0x00001f00
38 #define FSL_SRDSCR2_EICA_SGMII 0x00000400
39 #define FSL_SRDSCR2_EICA_SATA 0x00001400
40 #define FSL_SRDSCR2_EICE_MASK 0x0000001f
41 #define FSL_SRDSCR2_EICE_SGMII 0x00000004
42 #define FSL_SRDSCR2_EICE_SATA 0x00000014
44 /* SerDes CR3 register */
45 #define FSL_SRDSCR3_OFFS 0xc
46 #define FSL_SRDSCR3_LANEA_MASK 0x3f000700
47 #define FSL_SRDSCR3_LANEA_SGMII 0x00000000
48 #define FSL_SRDSCR3_LANEA_SATA 0x15000500
49 #define FSL_SRDSCR3_LANEE_MASK 0x003f0007
50 #define FSL_SRDSCR3_LANEE_SGMII 0x00000000
51 #define FSL_SRDSCR3_LANEE_SATA 0x00150005
53 #define SRDS1_MAX_LANES 8
54 #define SRDS2_MAX_LANES 2
56 static u32 serdes1_prtcl_map
, serdes2_prtcl_map
;
58 static u8 serdes1_cfg_tbl
[][SRDS1_MAX_LANES
] = {
59 [0x2] = {PCIE1
, PCIE1
, PCIE1
, PCIE1
, NONE
, NONE
, NONE
, NONE
},
60 [0x3] = {PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE1
},
61 [0x5] = {PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE2
, PCIE2
, PCIE2
, PCIE2
},
62 [0x7] = {PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE2
, PCIE2
, PCIE3
, PCIE3
},
65 static u8 serdes2_cfg_tbl
[][SRDS2_MAX_LANES
] = {
66 [0x1] = {SATA1
, SATA2
},
67 [0x3] = {SATA1
, NONE
},
68 [0x4] = {SGMII_TSEC1
, SGMII_TSEC3
},
69 [0x6] = {SGMII_TSEC1
, NONE
},
72 int is_serdes_configured(enum srds_prtcl device
)
76 if (!(serdes1_prtcl_map
& (1 << NONE
)))
79 ret
= (1 << device
) & serdes1_prtcl_map
;
84 if (!(serdes2_prtcl_map
& (1 << NONE
)))
87 return (1 << device
) & serdes2_prtcl_map
;
90 void fsl_serdes_init(void)
92 void *guts
= (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR
);
93 void *sd
= (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR
;
94 u32 pordevsr
= in_be32(guts
+ GUTS_PORDEVSR_OFFS
);
95 u32 srds1_io_sel
, srds2_io_sel
;
99 if (serdes1_prtcl_map
& (1 << NONE
) &&
100 serdes2_prtcl_map
& (1 << NONE
))
103 srds1_io_sel
= (pordevsr
& MPC85xx_PORDEVSR_IO_SEL
) >>
104 MPC85xx_PORDEVSR_IO_SEL_SHIFT
;
106 /* parse the SRDS2_IO_SEL of PORDEVSR */
107 srds2_io_sel
= (pordevsr
& GUTS_PORDEVSR_SERDES2_IO_SEL
)
108 >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT
;
110 debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel
);
111 debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel
);
113 switch (srds2_io_sel
) {
114 case 1: /* Lane A - SATA1, Lane E - SATA2 */
116 tmp
= in_be32(sd
+ FSL_SRDSCR0_OFFS
);
117 tmp
&= ~FSL_SRDSCR0_TXEQA_MASK
;
118 tmp
|= FSL_SRDSCR0_TXEQA_SATA
;
119 tmp
&= ~FSL_SRDSCR0_TXEQE_MASK
;
120 tmp
|= FSL_SRDSCR0_TXEQE_SATA
;
121 out_be32(sd
+ FSL_SRDSCR0_OFFS
, tmp
);
123 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
124 tmp
&= ~FSL_SRDSCR1_LANEA_MASK
;
125 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
126 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
128 tmp
= in_be32(sd
+ FSL_SRDSCR2_OFFS
);
129 tmp
&= ~FSL_SRDSCR2_EICA_MASK
;
130 tmp
|= FSL_SRDSCR2_EICA_SATA
;
131 tmp
&= ~FSL_SRDSCR2_EICE_MASK
;
132 tmp
|= FSL_SRDSCR2_EICE_SATA
;
133 out_be32(sd
+ FSL_SRDSCR2_OFFS
, tmp
);
135 tmp
= in_be32(sd
+ FSL_SRDSCR3_OFFS
);
136 tmp
&= ~FSL_SRDSCR3_LANEA_MASK
;
137 tmp
|= FSL_SRDSCR3_LANEA_SATA
;
138 tmp
&= ~FSL_SRDSCR3_LANEE_MASK
;
139 tmp
|= FSL_SRDSCR3_LANEE_SATA
;
140 out_be32(sd
+ FSL_SRDSCR3_OFFS
, tmp
);
142 case 3: /* Lane A - SATA1, Lane E - disabled */
144 tmp
= in_be32(sd
+ FSL_SRDSCR0_OFFS
);
145 tmp
&= ~FSL_SRDSCR0_TXEQA_MASK
;
146 tmp
|= FSL_SRDSCR0_TXEQA_SATA
;
147 out_be32(sd
+ FSL_SRDSCR0_OFFS
, tmp
);
149 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
150 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
151 tmp
|= FSL_SRDSCR1_LANEE_OFF
;
152 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
154 tmp
= in_be32(sd
+ FSL_SRDSCR2_OFFS
);
155 tmp
&= ~FSL_SRDSCR2_EICA_MASK
;
156 tmp
|= FSL_SRDSCR2_EICA_SATA
;
157 out_be32(sd
+ FSL_SRDSCR2_OFFS
, tmp
);
159 tmp
= in_be32(sd
+ FSL_SRDSCR3_OFFS
);
160 tmp
&= ~FSL_SRDSCR3_LANEA_MASK
;
161 tmp
|= FSL_SRDSCR3_LANEA_SATA
;
162 out_be32(sd
+ FSL_SRDSCR3_OFFS
, tmp
);
164 case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
166 tmp
= in_be32(sd
+ FSL_SRDSCR0_OFFS
);
167 tmp
&= ~FSL_SRDSCR0_TXEQA_MASK
;
168 tmp
|= FSL_SRDSCR0_TXEQA_SGMII
;
169 tmp
&= ~FSL_SRDSCR0_TXEQE_MASK
;
170 tmp
|= FSL_SRDSCR0_TXEQE_SGMII
;
171 out_be32(sd
+ FSL_SRDSCR0_OFFS
, tmp
);
173 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
174 tmp
&= ~FSL_SRDSCR1_LANEA_MASK
;
175 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
176 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
178 tmp
= in_be32(sd
+ FSL_SRDSCR2_OFFS
);
179 tmp
&= ~FSL_SRDSCR2_EICA_MASK
;
180 tmp
|= FSL_SRDSCR2_EICA_SGMII
;
181 tmp
&= ~FSL_SRDSCR2_EICE_MASK
;
182 tmp
|= FSL_SRDSCR2_EICE_SGMII
;
183 out_be32(sd
+ FSL_SRDSCR2_OFFS
, tmp
);
185 tmp
= in_be32(sd
+ FSL_SRDSCR3_OFFS
);
186 tmp
&= ~FSL_SRDSCR3_LANEA_MASK
;
187 tmp
|= FSL_SRDSCR3_LANEA_SGMII
;
188 tmp
&= ~FSL_SRDSCR3_LANEE_MASK
;
189 tmp
|= FSL_SRDSCR3_LANEE_SGMII
;
190 out_be32(sd
+ FSL_SRDSCR3_OFFS
, tmp
);
192 case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
194 tmp
= in_be32(sd
+ FSL_SRDSCR0_OFFS
);
195 tmp
&= ~FSL_SRDSCR0_TXEQA_MASK
;
196 tmp
|= FSL_SRDSCR0_TXEQA_SGMII
;
197 out_be32(sd
+ FSL_SRDSCR0_OFFS
, tmp
);
199 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
200 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
201 tmp
|= FSL_SRDSCR1_LANEE_OFF
;
202 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
204 tmp
= in_be32(sd
+ FSL_SRDSCR2_OFFS
);
205 tmp
&= ~FSL_SRDSCR2_EICA_MASK
;
206 tmp
|= FSL_SRDSCR2_EICA_SGMII
;
207 out_be32(sd
+ FSL_SRDSCR2_OFFS
, tmp
);
209 tmp
= in_be32(sd
+ FSL_SRDSCR3_OFFS
);
210 tmp
&= ~FSL_SRDSCR3_LANEA_MASK
;
211 tmp
|= FSL_SRDSCR3_LANEA_SGMII
;
212 out_be32(sd
+ FSL_SRDSCR3_OFFS
, tmp
);
214 case 7: /* Lane A - disabled, Lane E - disabled */
216 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
217 tmp
&= ~FSL_SRDSCR1_LANEA_MASK
;
218 tmp
|= FSL_SRDSCR1_LANEA_OFF
;
219 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
220 tmp
|= FSL_SRDSCR1_LANEE_OFF
;
221 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
227 if (srds1_io_sel
>= ARRAY_SIZE(serdes1_cfg_tbl
)) {
228 printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel
);
231 for (lane
= 0; lane
< SRDS1_MAX_LANES
; lane
++) {
232 enum srds_prtcl lane_prtcl
= serdes1_cfg_tbl
[srds1_io_sel
][lane
];
233 serdes1_prtcl_map
|= (1 << lane_prtcl
);
236 /* Set the first bit to indicate serdes has been initialized */
237 serdes1_prtcl_map
|= (1 << NONE
);
239 if (srds2_io_sel
>= ARRAY_SIZE(serdes2_cfg_tbl
)) {
240 printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel
);
244 for (lane
= 0; lane
< SRDS2_MAX_LANES
; lane
++) {
245 enum srds_prtcl lane_prtcl
= serdes2_cfg_tbl
[srds2_io_sel
][lane
];
246 serdes2_prtcl_map
|= (1 << lane_prtcl
);
249 /* Set the first bit to indicate serdes has been initialized */
250 serdes2_prtcl_map
|= (1 << NONE
);