]>
Commit | Line | Data |
---|---|---|
ef50d6c0 | 1 | /* |
6ab4011b | 2 | * Copyright 2008,2010 Freescale Semiconductor, Inc. |
ef50d6c0 KG |
3 | * Dave Liu <daveliu@freescale.com> |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
ef50d6c0 KG |
6 | */ |
7 | ||
8 | #include <config.h> | |
9 | #include <common.h> | |
10 | #include <asm/io.h> | |
11 | #include <asm/immap_85xx.h> | |
6ab4011b | 12 | #include <asm/fsl_serdes.h> |
ef50d6c0 KG |
13 | |
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 | |
18 | ||
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 | |
27 | ||
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 | |
34 | ||
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 | |
43 | ||
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 | |
52 | ||
6ab4011b KG |
53 | #define SRDS1_MAX_LANES 8 |
54 | #define SRDS2_MAX_LANES 2 | |
55 | ||
af025065 KG |
56 | static u32 serdes1_prtcl_map, serdes2_prtcl_map; |
57 | ||
6ab4011b KG |
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}, | |
63 | }; | |
64 | ||
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}, | |
70 | }; | |
71 | ||
72 | int is_serdes_configured(enum srds_prtcl device) | |
73 | { | |
71fe2225 HZ |
74 | int ret; |
75 | ||
76 | if (!(serdes1_prtcl_map & (1 << NONE))) | |
77 | fsl_serdes_init(); | |
78 | ||
79 | ret = (1 << device) & serdes1_prtcl_map; | |
6ab4011b | 80 | |
af025065 KG |
81 | if (ret) |
82 | return ret; | |
6ab4011b | 83 | |
71fe2225 HZ |
84 | if (!(serdes2_prtcl_map & (1 << NONE))) |
85 | fsl_serdes_init(); | |
86 | ||
af025065 | 87 | return (1 << device) & serdes2_prtcl_map; |
6ab4011b KG |
88 | } |
89 | ||
ef50d6c0 KG |
90 | void fsl_serdes_init(void) |
91 | { | |
6d0f6bcf JCPV |
92 | void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); |
93 | void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR; | |
ef50d6c0 | 94 | u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS); |
af025065 | 95 | u32 srds1_io_sel, srds2_io_sel; |
ef50d6c0 | 96 | u32 tmp; |
af025065 KG |
97 | int lane; |
98 | ||
71fe2225 HZ |
99 | if (serdes1_prtcl_map & (1 << NONE) && |
100 | serdes2_prtcl_map & (1 << NONE)) | |
101 | return; | |
102 | ||
af025065 KG |
103 | srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >> |
104 | MPC85xx_PORDEVSR_IO_SEL_SHIFT; | |
ef50d6c0 KG |
105 | |
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; | |
109 | ||
af025065 KG |
110 | debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel); |
111 | debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel); | |
112 | ||
ef50d6c0 KG |
113 | switch (srds2_io_sel) { |
114 | case 1: /* Lane A - SATA1, Lane E - SATA2 */ | |
115 | /* CR 0 */ | |
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); | |
122 | /* CR 1 */ | |
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); | |
127 | /* CR 2 */ | |
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); | |
134 | /* CR 3 */ | |
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); | |
141 | break; | |
142 | case 3: /* Lane A - SATA1, Lane E - disabled */ | |
143 | /* CR 0 */ | |
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); | |
148 | /* CR 1 */ | |
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); | |
153 | /* CR 2 */ | |
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); | |
158 | /* CR 3 */ | |
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); | |
163 | break; | |
164 | case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */ | |
165 | /* CR 0 */ | |
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); | |
172 | /* CR 1 */ | |
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); | |
177 | /* CR 2 */ | |
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); | |
184 | /* CR 3 */ | |
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); | |
191 | break; | |
192 | case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */ | |
193 | /* CR 0 */ | |
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); | |
198 | /* CR 1 */ | |
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); | |
203 | /* CR 2 */ | |
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); | |
208 | /* CR 3 */ | |
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); | |
213 | break; | |
214 | case 7: /* Lane A - disabled, Lane E - disabled */ | |
215 | /* CR 1 */ | |
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); | |
222 | break; | |
223 | default: | |
224 | break; | |
225 | } | |
af025065 | 226 | |
e51e47d3 | 227 | if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) { |
af025065 KG |
228 | printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel); |
229 | return; | |
230 | } | |
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); | |
234 | } | |
235 | ||
71fe2225 HZ |
236 | /* Set the first bit to indicate serdes has been initialized */ |
237 | serdes1_prtcl_map |= (1 << NONE); | |
238 | ||
e51e47d3 | 239 | if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) { |
af025065 KG |
240 | printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel); |
241 | return; | |
242 | } | |
243 | ||
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); | |
247 | } | |
71fe2225 HZ |
248 | |
249 | /* Set the first bit to indicate serdes has been initialized */ | |
250 | serdes2_prtcl_map |= (1 << NONE); | |
ef50d6c0 | 251 | } |