2 * Copyright 2008,2010 Freescale Semiconductor, Inc.
3 * Dave Liu <daveliu@freescale.com>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 #include <asm/immap_85xx.h>
28 #include <asm/fsl_serdes.h>
30 /* PORDEVSR register */
31 #define GUTS_PORDEVSR_OFFS 0xc
32 #define GUTS_PORDEVSR_SERDES2_IO_SEL 0x38000000
33 #define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT 27
35 /* SerDes CR0 register */
36 #define FSL_SRDSCR0_OFFS 0x0
37 #define FSL_SRDSCR0_TXEQA_MASK 0x00007000
38 #define FSL_SRDSCR0_TXEQA_SGMII 0x00004000
39 #define FSL_SRDSCR0_TXEQA_SATA 0x00001000
40 #define FSL_SRDSCR0_TXEQE_MASK 0x00000700
41 #define FSL_SRDSCR0_TXEQE_SGMII 0x00000400
42 #define FSL_SRDSCR0_TXEQE_SATA 0x00000100
44 /* SerDes CR1 register */
45 #define FSL_SRDSCR1_OFFS 0x4
46 #define FSL_SRDSCR1_LANEA_MASK 0x80200000
47 #define FSL_SRDSCR1_LANEA_OFF 0x80200000
48 #define FSL_SRDSCR1_LANEE_MASK 0x08020000
49 #define FSL_SRDSCR1_LANEE_OFF 0x08020000
51 /* SerDes CR2 register */
52 #define FSL_SRDSCR2_OFFS 0x8
53 #define FSL_SRDSCR2_EICA_MASK 0x00001f00
54 #define FSL_SRDSCR2_EICA_SGMII 0x00000400
55 #define FSL_SRDSCR2_EICA_SATA 0x00001400
56 #define FSL_SRDSCR2_EICE_MASK 0x0000001f
57 #define FSL_SRDSCR2_EICE_SGMII 0x00000004
58 #define FSL_SRDSCR2_EICE_SATA 0x00000014
60 /* SerDes CR3 register */
61 #define FSL_SRDSCR3_OFFS 0xc
62 #define FSL_SRDSCR3_LANEA_MASK 0x3f000700
63 #define FSL_SRDSCR3_LANEA_SGMII 0x00000000
64 #define FSL_SRDSCR3_LANEA_SATA 0x15000500
65 #define FSL_SRDSCR3_LANEE_MASK 0x003f0007
66 #define FSL_SRDSCR3_LANEE_SGMII 0x00000000
67 #define FSL_SRDSCR3_LANEE_SATA 0x00150005
69 #define SRDS1_MAX_LANES 8
70 #define SRDS2_MAX_LANES 2
72 static u32 serdes1_prtcl_map
, serdes2_prtcl_map
;
74 static u8 serdes1_cfg_tbl
[][SRDS1_MAX_LANES
] = {
75 [0x2] = {PCIE1
, PCIE1
, PCIE1
, PCIE1
, NONE
, NONE
, NONE
, NONE
},
76 [0x3] = {PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE1
},
77 [0x5] = {PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE2
, PCIE2
, PCIE2
, PCIE2
},
78 [0x7] = {PCIE1
, PCIE1
, PCIE1
, PCIE1
, PCIE2
, PCIE2
, PCIE3
, PCIE3
},
81 static u8 serdes2_cfg_tbl
[][SRDS2_MAX_LANES
] = {
82 [0x1] = {SATA1
, SATA2
},
83 [0x3] = {SATA1
, NONE
},
84 [0x4] = {SGMII_TSEC1
, SGMII_TSEC3
},
85 [0x6] = {SGMII_TSEC1
, NONE
},
88 int is_serdes_configured(enum srds_prtcl device
)
90 int ret
= (1 << device
) & serdes1_prtcl_map
;
95 return (1 << device
) & serdes2_prtcl_map
;
98 void fsl_serdes_init(void)
100 void *guts
= (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR
);
101 void *sd
= (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR
;
102 u32 pordevsr
= in_be32(guts
+ GUTS_PORDEVSR_OFFS
);
103 u32 srds1_io_sel
, srds2_io_sel
;
107 srds1_io_sel
= (pordevsr
& MPC85xx_PORDEVSR_IO_SEL
) >>
108 MPC85xx_PORDEVSR_IO_SEL_SHIFT
;
110 /* parse the SRDS2_IO_SEL of PORDEVSR */
111 srds2_io_sel
= (pordevsr
& GUTS_PORDEVSR_SERDES2_IO_SEL
)
112 >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT
;
114 debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel
);
115 debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel
);
117 switch (srds2_io_sel
) {
118 case 1: /* Lane A - SATA1, Lane E - SATA2 */
120 tmp
= in_be32(sd
+ FSL_SRDSCR0_OFFS
);
121 tmp
&= ~FSL_SRDSCR0_TXEQA_MASK
;
122 tmp
|= FSL_SRDSCR0_TXEQA_SATA
;
123 tmp
&= ~FSL_SRDSCR0_TXEQE_MASK
;
124 tmp
|= FSL_SRDSCR0_TXEQE_SATA
;
125 out_be32(sd
+ FSL_SRDSCR0_OFFS
, tmp
);
127 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
128 tmp
&= ~FSL_SRDSCR1_LANEA_MASK
;
129 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
130 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
132 tmp
= in_be32(sd
+ FSL_SRDSCR2_OFFS
);
133 tmp
&= ~FSL_SRDSCR2_EICA_MASK
;
134 tmp
|= FSL_SRDSCR2_EICA_SATA
;
135 tmp
&= ~FSL_SRDSCR2_EICE_MASK
;
136 tmp
|= FSL_SRDSCR2_EICE_SATA
;
137 out_be32(sd
+ FSL_SRDSCR2_OFFS
, tmp
);
139 tmp
= in_be32(sd
+ FSL_SRDSCR3_OFFS
);
140 tmp
&= ~FSL_SRDSCR3_LANEA_MASK
;
141 tmp
|= FSL_SRDSCR3_LANEA_SATA
;
142 tmp
&= ~FSL_SRDSCR3_LANEE_MASK
;
143 tmp
|= FSL_SRDSCR3_LANEE_SATA
;
144 out_be32(sd
+ FSL_SRDSCR3_OFFS
, tmp
);
146 case 3: /* Lane A - SATA1, Lane E - disabled */
148 tmp
= in_be32(sd
+ FSL_SRDSCR0_OFFS
);
149 tmp
&= ~FSL_SRDSCR0_TXEQA_MASK
;
150 tmp
|= FSL_SRDSCR0_TXEQA_SATA
;
151 out_be32(sd
+ FSL_SRDSCR0_OFFS
, tmp
);
153 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
154 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
155 tmp
|= FSL_SRDSCR1_LANEE_OFF
;
156 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
158 tmp
= in_be32(sd
+ FSL_SRDSCR2_OFFS
);
159 tmp
&= ~FSL_SRDSCR2_EICA_MASK
;
160 tmp
|= FSL_SRDSCR2_EICA_SATA
;
161 out_be32(sd
+ FSL_SRDSCR2_OFFS
, tmp
);
163 tmp
= in_be32(sd
+ FSL_SRDSCR3_OFFS
);
164 tmp
&= ~FSL_SRDSCR3_LANEA_MASK
;
165 tmp
|= FSL_SRDSCR3_LANEA_SATA
;
166 out_be32(sd
+ FSL_SRDSCR3_OFFS
, tmp
);
168 case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
170 tmp
= in_be32(sd
+ FSL_SRDSCR0_OFFS
);
171 tmp
&= ~FSL_SRDSCR0_TXEQA_MASK
;
172 tmp
|= FSL_SRDSCR0_TXEQA_SGMII
;
173 tmp
&= ~FSL_SRDSCR0_TXEQE_MASK
;
174 tmp
|= FSL_SRDSCR0_TXEQE_SGMII
;
175 out_be32(sd
+ FSL_SRDSCR0_OFFS
, tmp
);
177 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
178 tmp
&= ~FSL_SRDSCR1_LANEA_MASK
;
179 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
180 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
182 tmp
= in_be32(sd
+ FSL_SRDSCR2_OFFS
);
183 tmp
&= ~FSL_SRDSCR2_EICA_MASK
;
184 tmp
|= FSL_SRDSCR2_EICA_SGMII
;
185 tmp
&= ~FSL_SRDSCR2_EICE_MASK
;
186 tmp
|= FSL_SRDSCR2_EICE_SGMII
;
187 out_be32(sd
+ FSL_SRDSCR2_OFFS
, tmp
);
189 tmp
= in_be32(sd
+ FSL_SRDSCR3_OFFS
);
190 tmp
&= ~FSL_SRDSCR3_LANEA_MASK
;
191 tmp
|= FSL_SRDSCR3_LANEA_SGMII
;
192 tmp
&= ~FSL_SRDSCR3_LANEE_MASK
;
193 tmp
|= FSL_SRDSCR3_LANEE_SGMII
;
194 out_be32(sd
+ FSL_SRDSCR3_OFFS
, tmp
);
196 case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
198 tmp
= in_be32(sd
+ FSL_SRDSCR0_OFFS
);
199 tmp
&= ~FSL_SRDSCR0_TXEQA_MASK
;
200 tmp
|= FSL_SRDSCR0_TXEQA_SGMII
;
201 out_be32(sd
+ FSL_SRDSCR0_OFFS
, tmp
);
203 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
204 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
205 tmp
|= FSL_SRDSCR1_LANEE_OFF
;
206 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
208 tmp
= in_be32(sd
+ FSL_SRDSCR2_OFFS
);
209 tmp
&= ~FSL_SRDSCR2_EICA_MASK
;
210 tmp
|= FSL_SRDSCR2_EICA_SGMII
;
211 out_be32(sd
+ FSL_SRDSCR2_OFFS
, tmp
);
213 tmp
= in_be32(sd
+ FSL_SRDSCR3_OFFS
);
214 tmp
&= ~FSL_SRDSCR3_LANEA_MASK
;
215 tmp
|= FSL_SRDSCR3_LANEA_SGMII
;
216 out_be32(sd
+ FSL_SRDSCR3_OFFS
, tmp
);
218 case 7: /* Lane A - disabled, Lane E - disabled */
220 tmp
= in_be32(sd
+ FSL_SRDSCR1_OFFS
);
221 tmp
&= ~FSL_SRDSCR1_LANEA_MASK
;
222 tmp
|= FSL_SRDSCR1_LANEA_OFF
;
223 tmp
&= ~FSL_SRDSCR1_LANEE_MASK
;
224 tmp
|= FSL_SRDSCR1_LANEE_OFF
;
225 out_be32(sd
+ FSL_SRDSCR1_OFFS
, tmp
);
231 if (srds1_io_sel
>= ARRAY_SIZE(serdes1_cfg_tbl
)) {
232 printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel
);
235 for (lane
= 0; lane
< SRDS1_MAX_LANES
; lane
++) {
236 enum srds_prtcl lane_prtcl
= serdes1_cfg_tbl
[srds1_io_sel
][lane
];
237 serdes1_prtcl_map
|= (1 << lane_prtcl
);
240 if (srds2_io_sel
>= ARRAY_SIZE(serdes2_cfg_tbl
)) {
241 printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel
);
245 for (lane
= 0; lane
< SRDS2_MAX_LANES
; lane
++) {
246 enum srds_prtcl lane_prtcl
= serdes2_cfg_tbl
[srds2_io_sel
][lane
];
247 serdes2_prtcl_map
|= (1 << lane_prtcl
);