]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0 |
edb47025 SR |
2 | /* |
3 | * Copyright (C) Marvell International Ltd. and its affiliates | |
edb47025 SR |
4 | */ |
5 | ||
6 | #include <common.h> | |
edb47025 SR |
7 | #include <spl.h> |
8 | #include <asm/io.h> | |
9 | #include <asm/arch/cpu.h> | |
10 | #include <asm/arch/soc.h> | |
c05ed00a | 11 | #include <linux/delay.h> |
edb47025 SR |
12 | |
13 | #include "high_speed_env_spec.h" | |
edb47025 SR |
14 | #include "sys_env_lib.h" |
15 | #include "ctrl_pex.h" | |
16 | ||
17 | #if defined(CONFIG_ARMADA_38X) | |
18 | #elif defined(CONFIG_ARMADA_39X) | |
19 | #else | |
20 | #error "No device is defined" | |
21 | #endif | |
22 | ||
edb47025 SR |
23 | |
24 | /* | |
25 | * serdes_seq_db - holds all serdes sequences, their size and the | |
26 | * relevant index in the data array initialized in serdes_seq_init | |
27 | */ | |
28 | struct cfg_seq serdes_seq_db[SERDES_LAST_SEQ]; | |
29 | ||
d374e90b | 30 | #define SERDES_VERSION "2.0" |
edb47025 SR |
31 | #define ENDED_OK "High speed PHY - Ended Successfully\n" |
32 | ||
33 | #define LINK_WAIT_CNTR 100 | |
34 | #define LINK_WAIT_SLEEP 100 | |
35 | ||
36 | #define MAX_UNIT_NUMB 4 | |
37 | #define TOPOLOGY_TEST_OK 0 | |
38 | #define WRONG_NUMBER_OF_UNITS 1 | |
39 | #define SERDES_ALREADY_IN_USE 2 | |
40 | #define UNIT_NUMBER_VIOLATION 3 | |
41 | ||
42 | /* | |
43 | * serdes_lane_in_use_count contains the exact amount of serdes lanes | |
44 | * needed per type | |
45 | */ | |
46 | u8 serdes_lane_in_use_count[MAX_UNITS_ID][MAX_UNIT_NUMB] = { | |
47 | /* 0 1 2 3 */ | |
48 | { 1, 1, 1, 1 }, /* PEX */ | |
49 | { 1, 1, 1, 1 }, /* ETH_GIG */ | |
50 | { 1, 1, 0, 0 }, /* USB3H */ | |
51 | { 1, 1, 1, 0 }, /* USB3D */ | |
52 | { 1, 1, 1, 1 }, /* SATA */ | |
53 | { 1, 0, 0, 0 }, /* QSGMII */ | |
54 | { 4, 0, 0, 0 }, /* XAUI */ | |
55 | { 2, 0, 0, 0 } /* RXAUI */ | |
56 | }; | |
57 | ||
58 | /* | |
59 | * serdes_unit_count count unit number. | |
60 | * (i.e a single XAUI is counted as 1 unit) | |
61 | */ | |
62 | u8 serdes_unit_count[MAX_UNITS_ID] = { 0 }; | |
63 | ||
64 | /* Selector mapping for A380-A0 and A390-Z1 */ | |
65 | u8 selectors_serdes_rev2_map[LAST_SERDES_TYPE][MAX_SERDES_LANES] = { | |
66 | /* 0 1 2 3 4 5 6 */ | |
67 | { 0x1, 0x1, NA, NA, NA, NA, NA }, /* PEX0 */ | |
68 | { NA, NA, 0x1, NA, 0x1, NA, 0x1 }, /* PEX1 */ | |
69 | { NA, NA, NA, NA, 0x7, 0x1, NA }, /* PEX2 */ | |
70 | { NA, NA, NA, 0x1, NA, NA, NA }, /* PEX3 */ | |
71 | { 0x2, 0x3, NA, NA, NA, NA, NA }, /* SATA0 */ | |
72 | { NA, NA, 0x3, NA, NA, NA, NA }, /* SATA1 */ | |
73 | { NA, NA, NA, NA, 0x6, 0x2, NA }, /* SATA2 */ | |
74 | { NA, NA, NA, 0x3, NA, NA, NA }, /* SATA3 */ | |
75 | { 0x3, 0x4, NA, NA, NA, NA, NA }, /* SGMII0 */ | |
76 | { NA, 0x5, 0x4, NA, 0x3, NA, NA }, /* SGMII1 */ | |
77 | { NA, NA, NA, 0x4, NA, 0x3, NA }, /* SGMII2 */ | |
78 | { NA, 0x7, NA, NA, NA, NA, NA }, /* QSGMII */ | |
79 | { NA, 0x6, NA, NA, 0x4, NA, NA }, /* USB3_HOST0 */ | |
80 | { NA, NA, NA, 0x5, NA, 0x4, NA }, /* USB3_HOST1 */ | |
81 | { NA, NA, NA, 0x6, 0x5, 0x5, NA }, /* USB3_DEVICE */ | |
82 | #ifdef CONFIG_ARMADA_39X | |
83 | { NA, NA, 0x5, NA, 0x8, NA, 0x2 }, /* SGMII3 */ | |
84 | { NA, NA, NA, 0x8, 0x9, 0x8, 0x4 }, /* XAUI */ | |
85 | { NA, NA, NA, NA, NA, 0x8, 0x4 }, /* RXAUI */ | |
86 | #endif | |
87 | { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, NA } /* DEFAULT_SERDES */ | |
88 | }; | |
89 | ||
90 | /* Selector mapping for PEX by 4 confiuration */ | |
91 | u8 common_phys_selectors_pex_by4_lanes[] = { 0x1, 0x2, 0x2, 0x2 }; | |
92 | ||
93 | static const char *const serdes_type_to_string[] = { | |
94 | "PCIe0", | |
95 | "PCIe1", | |
96 | "PCIe2", | |
97 | "PCIe3", | |
98 | "SATA0", | |
99 | "SATA1", | |
100 | "SATA2", | |
101 | "SATA3", | |
102 | "SGMII0", | |
103 | "SGMII1", | |
104 | "SGMII2", | |
105 | "QSGMII", | |
106 | "USB3 HOST0", | |
107 | "USB3 HOST1", | |
108 | "USB3 DEVICE", | |
109 | "SGMII3", | |
110 | "XAUI", | |
111 | "RXAUI", | |
112 | "DEFAULT SERDES", | |
113 | "LAST_SERDES_TYPE" | |
114 | }; | |
115 | ||
116 | struct serdes_unit_data { | |
117 | u8 serdes_unit_id; | |
118 | u8 serdes_unit_num; | |
119 | }; | |
120 | ||
121 | static struct serdes_unit_data serdes_type_to_unit_info[] = { | |
122 | {PEX_UNIT_ID, 0,}, | |
123 | {PEX_UNIT_ID, 1,}, | |
124 | {PEX_UNIT_ID, 2,}, | |
125 | {PEX_UNIT_ID, 3,}, | |
126 | {SATA_UNIT_ID, 0,}, | |
127 | {SATA_UNIT_ID, 1,}, | |
128 | {SATA_UNIT_ID, 2,}, | |
129 | {SATA_UNIT_ID, 3,}, | |
130 | {ETH_GIG_UNIT_ID, 0,}, | |
131 | {ETH_GIG_UNIT_ID, 1,}, | |
132 | {ETH_GIG_UNIT_ID, 2,}, | |
133 | {QSGMII_UNIT_ID, 0,}, | |
134 | {USB3H_UNIT_ID, 0,}, | |
135 | {USB3H_UNIT_ID, 1,}, | |
136 | {USB3D_UNIT_ID, 0,}, | |
137 | {ETH_GIG_UNIT_ID, 3,}, | |
138 | {XAUI_UNIT_ID, 0,}, | |
139 | {RXAUI_UNIT_ID, 0,}, | |
140 | }; | |
141 | ||
142 | /* Sequences DB */ | |
143 | ||
144 | /* | |
145 | * SATA and SGMII | |
146 | */ | |
147 | ||
148 | struct op_params sata_port0_power_up_params[] = { | |
149 | /* | |
150 | * unit_base_reg, unit_offset, mask, SATA data, wait_time, | |
151 | * num_of_loops | |
152 | */ | |
153 | /* Access to reg 0x48(OOB param 1) */ | |
154 | {SATA_VENDOR_PORT_0_REG_ADDR, 0x38000, 0xffffffff, {0x48,}, 0, 0}, | |
155 | /* OOB Com_wake and Com_reset spacing upper limit data */ | |
156 | {SATA_VENDOR_PORT_0_REG_DATA, 0x38000, 0xf03f, {0x6018,}, 0, 0}, | |
157 | /* Access to reg 0xa(PHY Control) */ | |
158 | {SATA_VENDOR_PORT_0_REG_ADDR, 0x38000, 0xffffffff, {0xa,}, 0, 0}, | |
159 | /* Rx clk and Tx clk select non-inverted mode */ | |
160 | {SATA_VENDOR_PORT_0_REG_DATA, 0x38000, 0x3000, {0x0,}, 0, 0}, | |
161 | /* Power Down Sata addr */ | |
162 | {SATA_CTRL_REG_IND_ADDR, 0x38000, 0xffffffff, {0x0,}, 0, 0}, | |
163 | /* Power Down Sata Port 0 */ | |
164 | {SATA_CTRL_REG_IND_DATA, 0x38000, 0xffff00ff, {0xc40040,}, 0, 0}, | |
165 | }; | |
166 | ||
167 | struct op_params sata_port1_power_up_params[] = { | |
168 | /* | |
169 | * unit_base_reg, unit_offset, mask, SATA data, wait_time, | |
170 | * num_of_loops | |
171 | */ | |
172 | /* Access to reg 0x48(OOB param 1) */ | |
173 | {SATA_VENDOR_PORT_1_REG_ADDR, 0x38000, 0xffffffff, {0x48,}, 0, 0}, | |
174 | /* OOB Com_wake and Com_reset spacing upper limit data */ | |
175 | {SATA_VENDOR_PORT_1_REG_DATA, 0x38000, 0xf03f, {0x6018,}, 0, 0}, | |
176 | /* Access to reg 0xa(PHY Control) */ | |
177 | {SATA_VENDOR_PORT_1_REG_ADDR, 0x38000, 0xffffffff, {0xa,}, 0, 0}, | |
178 | /* Rx clk and Tx clk select non-inverted mode */ | |
179 | {SATA_VENDOR_PORT_1_REG_DATA, 0x38000, 0x3000, {0x0,}, 0, 0}, | |
180 | /* Power Down Sata addr */ | |
181 | {SATA_CTRL_REG_IND_ADDR, 0x38000, 0xffffffff, {0x0,}, 0, 0}, | |
182 | /* Power Down Sata Port 1 */ | |
183 | {SATA_CTRL_REG_IND_DATA, 0x38000, 0xffffff00, {0xc44000,}, 0, 0}, | |
184 | }; | |
185 | ||
186 | /* SATA and SGMII - power up seq */ | |
187 | struct op_params sata_and_sgmii_power_up_params[] = { | |
188 | /* | |
189 | * unit_base_reg, unit_offset, mask, SATA data, SGMII data, | |
190 | * wait_time, num_of_loops | |
191 | */ | |
192 | /* Power Up */ | |
193 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x90006, {0x80002, 0x80002}, | |
194 | 0, 0}, | |
195 | /* Unreset */ | |
196 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x7800, {0x6000, 0x6000}, 0, 0}, | |
197 | /* Phy Selector */ | |
198 | {POWER_AND_PLL_CTRL_REG, 0x800, 0x0e0, {0x0, 0x80}, 0, 0}, | |
199 | /* Ref clock source select */ | |
200 | {MISC_REG, 0x800, 0x440, {0x440, 0x400}, 0, 0} | |
201 | }; | |
202 | ||
203 | /* SATA and SGMII - speed config seq */ | |
204 | struct op_params sata_and_sgmii_speed_config_params[] = { | |
205 | /* | |
206 | * unit_base_reg, unit_offset, mask, SATA data, | |
207 | * SGMII (1.25G), SGMII (3.125G), wait_time, num_of_loops | |
208 | */ | |
209 | /* Baud Rate */ | |
210 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x3fc00000, | |
211 | {0x8800000, 0x19800000, 0x22000000}, 0, 0}, | |
212 | /* Select Baud Rate for SATA only */ | |
213 | {INTERFACE_REG, 0x800, 0xc00, {0x800, NO_DATA, NO_DATA}, 0, 0}, | |
214 | /* Phy Gen RX and TX */ | |
215 | {ISOLATE_REG, 0x800, 0xff, {NO_DATA, 0x66, 0x66}, 0, 0}, | |
216 | /* Bus Width */ | |
217 | {LOOPBACK_REG, 0x800, 0xe, {0x4, 0x2, 0x2}, 0, 0} | |
218 | }; | |
219 | ||
220 | /* SATA and SGMII - TX config seq */ | |
221 | struct op_params sata_and_sgmii_tx_config_params1[] = { | |
222 | /* | |
223 | * unitunit_base_reg, unit_offset, mask, SATA data, SGMII data, | |
224 | * wait_time, num_of_loops | |
225 | */ | |
226 | {GLUE_REG, 0x800, 0x1800, {NO_DATA, 0x800}, 0, 0}, | |
227 | /* Sft Reset pulse */ | |
228 | {RESET_DFE_REG, 0x800, 0x401, {0x401, 0x401}, 0, 0}, | |
229 | /* Sft Reset pulse */ | |
230 | {RESET_DFE_REG, 0x800, 0x401, {0x0, 0x0}, 0, 0}, | |
231 | /* Power up PLL, RX and TX */ | |
232 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0xf0000, {0x70000, 0x70000}, | |
233 | 0, 0} | |
234 | }; | |
235 | ||
236 | struct op_params sata_port0_tx_config_params[] = { | |
237 | /* | |
238 | * unit_base_reg, unit_offset, mask, SATA data, wait_time, | |
239 | * num_of_loops | |
240 | */ | |
241 | /* Power Down Sata addr */ | |
242 | {SATA_CTRL_REG_IND_ADDR, 0x38000, 0xffffffff, {0x0}, 0, 0}, | |
243 | /* Power Down Sata Port 0 */ | |
244 | {SATA_CTRL_REG_IND_DATA, 0x38000, 0xffff00ff, {0xc40000}, 0, 0}, | |
245 | /* Regret bit addr */ | |
246 | {SATA_CTRL_REG_IND_ADDR, 0x38000, 0xffffffff, {0x4}, 0, 0}, | |
247 | /* Regret bit data */ | |
248 | {SATA_CTRL_REG_IND_DATA, 0x38000, 0xffffffff, {0x80}, 0, 0} | |
249 | }; | |
250 | ||
251 | struct op_params sata_port1_tx_config_params[] = { | |
252 | /* | |
253 | * unit_base_reg, unit_offset, mask, SATA data, wait_time, | |
254 | * num_of_loops | |
255 | */ | |
256 | /* Power Down Sata addr */ | |
257 | {SATA_CTRL_REG_IND_ADDR, 0x38000, 0xffffffff, {0x0}, 0, 0}, | |
258 | /* Power Down Sata Port 1 */ | |
259 | {SATA_CTRL_REG_IND_DATA, 0x38000, 0xffffff00, {0xc40000}, 0, 0}, | |
260 | /* Regret bit addr */ | |
261 | {SATA_CTRL_REG_IND_ADDR, 0x38000, 0xffffffff, {0x4}, 0, 0}, | |
262 | /* Regret bit data */ | |
263 | {SATA_CTRL_REG_IND_DATA, 0x38000, 0xffffffff, {0x80}, 0, 0} | |
264 | }; | |
265 | ||
266 | struct op_params sata_and_sgmii_tx_config_serdes_rev1_params2[] = { | |
267 | /* | |
268 | * unit_base_reg, unit_offset, mask, SATA data, SGMII data, | |
269 | * wait_time, num_of_loops | |
270 | */ | |
271 | /* Wait for PHY power up sequence to finish */ | |
272 | {COMMON_PHY_STATUS1_REG, 0x28, 0xc, {0xc, 0xc}, 10, 1000}, | |
273 | /* Wait for PHY power up sequence to finish */ | |
274 | {COMMON_PHY_STATUS1_REG, 0x28, 0x1, {0x1, 0x1}, 1, 1000} | |
275 | }; | |
276 | ||
277 | struct op_params sata_and_sgmii_tx_config_serdes_rev2_params2[] = { | |
278 | /* | |
279 | * unit_base_reg, unit_offset, mask, SATA data, SGMII data, | |
280 | * wait_time, num_of_loops | |
281 | */ | |
282 | /* Wait for PHY power up sequence to finish */ | |
283 | {COMMON_PHY_STATUS1_REG, 0x28, 0xc, {0xc, 0xc}, 10, 1000}, | |
284 | /* Assert Rx Init for SGMII */ | |
285 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x40000000, {NA, 0x40000000}, | |
286 | 0, 0}, | |
287 | /* Assert Rx Init for SATA */ | |
288 | {ISOLATE_REG, 0x800, 0x400, {0x400, NA}, 0, 0}, | |
289 | /* Wait for PHY power up sequence to finish */ | |
290 | {COMMON_PHY_STATUS1_REG, 0x28, 0x1, {0x1, 0x1}, 1, 1000}, | |
291 | /* De-assert Rx Init for SGMII */ | |
292 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x40000000, {NA, 0x0}, 0, 0}, | |
293 | /* De-assert Rx Init for SATA */ | |
294 | {ISOLATE_REG, 0x800, 0x400, {0x0, NA}, 0, 0}, | |
295 | /* os_ph_offset_force (align 90) */ | |
296 | {RX_REG3, 0x800, 0xff, {0xde, NO_DATA}, 0, 0}, | |
297 | /* Set os_ph_valid */ | |
298 | {RX_REG3, 0x800, 0x100, {0x100, NO_DATA}, 0, 0}, | |
299 | /* Unset os_ph_valid */ | |
300 | {RX_REG3, 0x800, 0x100, {0x0, NO_DATA}, 0, 0}, | |
301 | }; | |
302 | ||
303 | struct op_params sata_electrical_config_serdes_rev1_params[] = { | |
304 | /* | |
305 | * unit_base_reg, unit_offset, mask, SATA data, wait_time, | |
306 | * num_of_loops | |
307 | */ | |
308 | /* enable SSC and DFE update enable */ | |
309 | {COMMON_PHY_CONFIGURATION4_REG, 0x28, 0x400008, {0x400000,}, 0, 0}, | |
310 | /* tximpcal_th and rximpcal_th */ | |
311 | {VTHIMPCAL_CTRL_REG, 0x800, 0xff00, {0x4000,}, 0, 0}, | |
312 | /* SQ_THRESH and FFE Setting */ | |
313 | {SQUELCH_FFE_SETTING_REG, 0x800, 0xfff, {0x6cf,}, 0, 0}, | |
314 | /* G1_TX SLEW, EMPH1 and AMP */ | |
315 | {G1_SETTINGS_0_REG, 0x800, 0xffff, {0x8a32,}, 0, 0}, | |
316 | /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
317 | {G1_SETTINGS_1_REG, 0x800, 0x3ff, {0x3c9,}, 0, 0}, | |
318 | /* G2_TX SLEW, EMPH1 and AMP */ | |
319 | {G2_SETTINGS_0_REG, 0x800, 0xffff, {0x8b5c,}, 0, 0}, | |
320 | /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
321 | {G2_SETTINGS_1_REG, 0x800, 0x3ff, {0x3d2,}, 0, 0}, | |
322 | /* G3_TX SLEW, EMPH1 and AMP */ | |
323 | {G3_SETTINGS_0_REG, 0x800, 0xffff, {0xe6e,}, 0, 0}, | |
324 | /* G3_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
325 | {G3_SETTINGS_1_REG, 0x800, 0x3ff, {0x3d2,}, 0, 0}, | |
326 | /* Cal rxclkalign90 ext enable and Cal os ph ext */ | |
327 | {CAL_REG6, 0x800, 0xff00, {0xdd00,}, 0, 0}, | |
328 | /* Dtl Clamping disable and Dtl clamping Sel(6000ppm) */ | |
329 | {RX_REG2, 0x800, 0xf0, {0x70,}, 0, 0}, | |
330 | }; | |
331 | ||
332 | struct op_params sata_electrical_config_serdes_rev2_params[] = { | |
333 | /* | |
334 | * unit_base_reg, unit_offset, mask, SATA data, wait_time, | |
335 | * num_of_loops | |
336 | */ | |
337 | /* SQ_THRESH and FFE Setting */ | |
338 | {SQUELCH_FFE_SETTING_REG, 0x800, 0xf00, {0x600}, 0, 0}, | |
339 | /* enable SSC and DFE update enable */ | |
340 | {COMMON_PHY_CONFIGURATION4_REG, 0x28, 0x400008, {0x400000}, 0, 0}, | |
341 | /* G1_TX SLEW, EMPH1 and AMP */ | |
342 | {G1_SETTINGS_0_REG, 0x800, 0xffff, {0x8a32}, 0, 0}, | |
343 | /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
344 | {G1_SETTINGS_1_REG, 0x800, 0x3ff, {0x3c9}, 0, 0}, | |
345 | /* G2_TX SLEW, EMPH1 and AMP */ | |
346 | {G2_SETTINGS_0_REG, 0x800, 0xffff, {0x8b5c}, 0, 0}, | |
347 | /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
348 | {G2_SETTINGS_1_REG, 0x800, 0x3ff, {0x3d2}, 0, 0}, | |
349 | /* G3_TX SLEW, EMPH1 and AMP */ | |
350 | {G3_SETTINGS_0_REG, 0x800, 0xffff, {0xe6e}, 0, 0}, | |
351 | /* | |
352 | * G3_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI & DFE_En Gen3, | |
353 | * DC wander calibration dis | |
354 | */ | |
355 | {G3_SETTINGS_1_REG, 0x800, 0x47ff, {0x7d2}, 0, 0}, | |
356 | /* Bit[12]=0x0 idle_sync_en */ | |
357 | {PCIE_REG0, 0x800, 0x1000, {0x0}, 0, 0}, | |
358 | /* Dtl Clamping disable and Dtl clamping Sel(6000ppm) */ | |
359 | {RX_REG2, 0x800, 0xf0, {0x70,}, 0, 0}, | |
360 | /* tximpcal_th and rximpcal_th */ | |
361 | {VTHIMPCAL_CTRL_REG, 0x800, 0xff00, {0x3000}, 0, 0}, | |
362 | /* DFE_STEP_FINE_FX[3:0] =0xa */ | |
363 | {DFE_REG0, 0x800, 0xa00f, {0x800a}, 0, 0}, | |
364 | /* DFE_EN and Dis Update control from pin disable */ | |
365 | {DFE_REG3, 0x800, 0xc000, {0x0}, 0, 0}, | |
366 | /* FFE Force FFE_REs and cap settings for Gen1 */ | |
367 | {G1_SETTINGS_3_REG, 0x800, 0xff, {0xcf}, 0, 0}, | |
368 | /* FFE Force FFE_REs and cap settings for Gen2 */ | |
369 | {G2_SETTINGS_3_REG, 0x800, 0xff, {0xbf}, 0, 0}, | |
370 | /* FE Force FFE_REs=4 and cap settings for Gen3n */ | |
371 | {G3_SETTINGS_3_REG, 0x800, 0xff, {0xcf}, 0, 0}, | |
372 | /* Set DFE Gen 3 Resolution to 3 */ | |
373 | {G3_SETTINGS_4_REG, 0x800, 0x300, {0x300}, 0, 0}, | |
374 | }; | |
375 | ||
376 | struct op_params sgmii_electrical_config_serdes_rev1_params[] = { | |
377 | /* | |
378 | * unit_base_reg, unit_offset, mask, SGMII (1.25G), SGMII (3.125G), | |
379 | * wait_time, num_of_loops | |
380 | */ | |
381 | /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
382 | {G1_SETTINGS_1_REG, 0x800, 0x3ff, {0x3c9, 0x3c9}, 0, 0}, | |
383 | /* SQ_THRESH and FFE Setting */ | |
384 | {SQUELCH_FFE_SETTING_REG, 0x800, 0xfff, {0x8f, 0xbf}, 0, 0}, | |
385 | /* tximpcal_th and rximpcal_th */ | |
386 | {VTHIMPCAL_CTRL_REG, 0x800, 0xff00, {0x4000, 0x4000}, 0, 0}, | |
387 | }; | |
388 | ||
389 | struct op_params sgmii_electrical_config_serdes_rev2_params[] = { | |
390 | /* | |
391 | * unit_base_reg, unit_offset, mask, SGMII (1.25G), SGMII (3.125G), | |
392 | * wait_time, num_of_loops | |
393 | */ | |
394 | /* Set Slew_rate, Emph and Amp */ | |
395 | {G1_SETTINGS_0_REG, 0x800, 0xffff, {0x8fa, 0x8fa}, 0, 0}, | |
396 | /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
397 | {G1_SETTINGS_1_REG, 0x800, 0x3ff, {0x3c9, 0x3c9}, 0, 0}, | |
398 | /* DTL_FLOOP_EN */ | |
399 | {RX_REG2, 0x800, 0x4, {0x0, 0x0}, 0, 0}, | |
400 | /* G1 FFE Setting Force, RES and CAP */ | |
401 | {G1_SETTINGS_3_REG, 0x800, 0xff, {0x8f, 0xbf}, 0, 0}, | |
402 | /* tximpcal_th and rximpcal_th */ | |
403 | {VTHIMPCAL_CTRL_REG, 0x800, 0xff00, {0x3000, 0x3000}, 0, 0}, | |
404 | }; | |
405 | ||
406 | /* | |
407 | * PEX and USB3 | |
408 | */ | |
409 | ||
410 | /* PEX and USB3 - power up seq for Serdes Rev 1.2 */ | |
411 | struct op_params pex_and_usb3_power_up_serdes_rev1_params[] = { | |
412 | /* | |
413 | * unit_base_reg, unit_offset, mask, PEX data, USB3 data, | |
414 | * wait_time, num_of_loops | |
415 | */ | |
416 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x3fc7f806, | |
417 | {0x4471804, 0x4479804}, 0, 0}, | |
418 | {COMMON_PHY_CONFIGURATION2_REG, 0x28, 0x5c, {0x58, 0x58}, 0, 0}, | |
419 | {COMMON_PHY_CONFIGURATION4_REG, 0x28, 0x3, {0x1, 0x1}, 0, 0}, | |
420 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x7800, {0x6000, 0xe000}, 0, 0}, | |
421 | {GLOBAL_CLK_CTRL, 0x800, 0xd, {0x5, 0x1}, 0, 0}, | |
422 | /* Ref clock source select */ | |
423 | {MISC_REG, 0x800, 0x4c0, {0x80, 0x4c0}, 0, 0} | |
424 | }; | |
425 | ||
426 | /* PEX and USB3 - power up seq for Serdes Rev 2.1 */ | |
427 | struct op_params pex_and_usb3_power_up_serdes_rev2_params[] = { | |
428 | /* | |
429 | * unit_base_reg, unit_offset, mask, PEX data, USB3 data, | |
430 | * wait_time, num_of_loops | |
431 | */ | |
432 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x3fc7f806, | |
433 | {0x4471804, 0x4479804}, 0, 0}, | |
434 | {COMMON_PHY_CONFIGURATION2_REG, 0x28, 0x5c, {0x58, 0x58}, 0, 0}, | |
435 | {COMMON_PHY_CONFIGURATION4_REG, 0x28, 0x3, {0x1, 0x1}, 0, 0}, | |
436 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x7800, {0x6000, 0xe000}, 0, 0}, | |
437 | {GLOBAL_CLK_CTRL, 0x800, 0xd, {0x5, 0x1}, 0, 0}, | |
438 | {GLOBAL_MISC_CTRL, 0x800, 0xc0, {0x0, NO_DATA}, 0, 0}, | |
439 | /* Ref clock source select */ | |
440 | {MISC_REG, 0x800, 0x4c0, {0x80, 0x4c0}, 0, 0} | |
441 | }; | |
442 | ||
443 | /* PEX and USB3 - speed config seq */ | |
444 | struct op_params pex_and_usb3_speed_config_params[] = { | |
445 | /* | |
446 | * unit_base_reg, unit_offset, mask, PEX data, USB3 data, | |
447 | * wait_time, num_of_loops | |
448 | */ | |
449 | /* Maximal PHY Generation Setting */ | |
450 | {INTERFACE_REG, 0x800, 0xc00, {0x400, 0x400, 0x400, 0x400, 0x400}, | |
451 | 0, 0}, | |
452 | }; | |
453 | ||
454 | struct op_params usb3_electrical_config_serdes_rev1_params[] = { | |
455 | /* Spread Spectrum Clock Enable */ | |
456 | {LANE_CFG4_REG, 0x800, 0x80, {0x80}, 0, 0}, | |
457 | /* G2_TX_SSC_AMP[6:0]=4.5k_p_pM and TX emphasis mode=m_v */ | |
458 | {G2_SETTINGS_2_REG, 0x800, 0xfe40, {0x4440}, 0, 0}, | |
459 | /* tximpcal_th and rximpcal_th */ | |
460 | {VTHIMPCAL_CTRL_REG, 0x800, 0xff00, {0x4000}, 0, 0}, | |
461 | /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
462 | {G2_SETTINGS_1_REG, 0x800, 0x3ff, {0x3d2}, 0, 0}, | |
463 | /* FFE Setting Force, RES and CAP */ | |
464 | {SQUELCH_FFE_SETTING_REG, 0x800, 0xff, {0xef}, 0, 0}, | |
465 | /* Dtl Clamping disable and Dtl-clamping-Sel(6000ppm) */ | |
466 | {RX_REG2, 0x800, 0xf0, {0x70}, 0, 0}, | |
467 | /* cal_rxclkalign90_ext_en and cal_os_ph_ext */ | |
468 | {CAL_REG6, 0x800, 0xff00, {0xd500}, 0, 0}, | |
469 | /* vco_cal_vth_sel */ | |
470 | {REF_REG0, 0x800, 0x38, {0x20}, 0, 0}, | |
471 | }; | |
472 | ||
473 | struct op_params usb3_electrical_config_serdes_rev2_params[] = { | |
474 | /* Spread Spectrum Clock Enable */ | |
475 | {LANE_CFG4_REG, 0x800, 0x80, {0x80}, 0, 0}, | |
476 | /* G2_TX_SSC_AMP[6:0]=4.5k_p_pM and TX emphasis mode=m_v */ | |
477 | {G2_SETTINGS_2_REG, 0x800, 0xfe40, {0x4440}, 0, 0}, | |
478 | /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
479 | {G2_SETTINGS_1_REG, 0x800, 0x3ff, {0x3d2}, 0, 0}, | |
480 | /* Dtl Clamping disable and Dtl-clamping-Sel(6000ppm) */ | |
481 | {RX_REG2, 0x800, 0xf0, {0x70}, 0, 0}, | |
482 | /* vco_cal_vth_sel */ | |
483 | {REF_REG0, 0x800, 0x38, {0x20}, 0, 0}, | |
484 | /* Spread Spectrum Clock Enable */ | |
485 | {LANE_CFG5_REG, 0x800, 0x4, {0x4}, 0, 0}, | |
486 | }; | |
487 | ||
488 | /* PEX and USB3 - TX config seq */ | |
489 | ||
490 | /* | |
491 | * For PEXx1: the pex_and_usb3_tx_config_params1/2/3 configurations should run | |
492 | * one by one on the lane. | |
493 | * For PEXx4: the pex_and_usb3_tx_config_params1/2/3 configurations should run | |
494 | * by setting each sequence for all 4 lanes. | |
495 | */ | |
496 | struct op_params pex_and_usb3_tx_config_params1[] = { | |
497 | /* | |
498 | * unit_base_reg, unit_offset, mask, PEX data, USB3 data, | |
499 | * wait_time, num_of_loops | |
500 | */ | |
501 | {GLOBAL_CLK_CTRL, 0x800, 0x1, {0x0, 0x0}, 0, 0}, | |
502 | /* 10ms delay */ | |
503 | {0x0, 0x0, 0x0, {0x0, 0x0}, 10, 0}, | |
504 | /* os_ph_offset_force (align 90) */ | |
505 | {RX_REG3, 0x800, 0xff, {0xdc, NO_DATA}, 0, 0}, | |
506 | /* Set os_ph_valid */ | |
507 | {RX_REG3, 0x800, 0x100, {0x100, NO_DATA}, 0, 0}, | |
508 | /* Unset os_ph_valid */ | |
509 | {RX_REG3, 0x800, 0x100, {0x0, NO_DATA}, 0, 0}, | |
510 | }; | |
511 | ||
512 | struct op_params pex_and_usb3_tx_config_params2[] = { | |
513 | /* | |
514 | * unit_base_reg, unit_offset, mask, PEX data, USB3 data, | |
515 | * wait_time, num_of_loops | |
516 | */ | |
517 | /* Sft Reset pulse */ | |
518 | {RESET_DFE_REG, 0x800, 0x401, {0x401, 0x401}, 0, 0}, | |
519 | }; | |
520 | ||
521 | struct op_params pex_and_usb3_tx_config_params3[] = { | |
522 | /* | |
523 | * unit_base_reg, unit_offset, mask, PEX data, USB3 data, | |
524 | * wait_time, num_of_loops | |
525 | */ | |
526 | /* Sft Reset pulse */ | |
527 | {RESET_DFE_REG, 0x800, 0x401, {0x0, 0x0}, 0, 0}, | |
528 | /* 10ms delay */ | |
529 | {0x0, 0x0, 0x0, {0x0, 0x0}, 10, 0} | |
530 | }; | |
531 | ||
532 | /* PEX by 4 config seq */ | |
533 | struct op_params pex_by4_config_params[] = { | |
534 | /* unit_base_reg, unit_offset, mask, data, wait_time, num_of_loops */ | |
535 | {GLOBAL_CLK_SRC_HI, 0x800, 0x7, {0x5, 0x0, 0x0, 0x2}, 0, 0}, | |
536 | /* Lane Alignement enable */ | |
537 | {LANE_ALIGN_REG0, 0x800, 0x1000, {0x0, 0x0, 0x0, 0x0}, 0, 0}, | |
538 | /* Max PLL phy config */ | |
539 | {CALIBRATION_CTRL_REG, 0x800, 0x1000, {0x1000, 0x1000, 0x1000, 0x1000}, | |
540 | 0, 0}, | |
541 | /* Max PLL pipe config */ | |
542 | {LANE_CFG1_REG, 0x800, 0x600, {0x600, 0x600, 0x600, 0x600}, 0, 0}, | |
543 | }; | |
544 | ||
545 | /* USB3 device donfig seq */ | |
546 | struct op_params usb3_device_config_params[] = { | |
547 | /* unit_base_reg, unit_offset, mask, data, wait_time, num_of_loops */ | |
548 | {LANE_CFG4_REG, 0x800, 0x200, {0x200}, 0, 0} | |
549 | }; | |
550 | ||
551 | /* PEX - electrical configuration seq Rev 1.2 */ | |
552 | struct op_params pex_electrical_config_serdes_rev1_params[] = { | |
553 | /* | |
554 | * unit_base_reg, unit_offset, mask, PEX data, wait_time, | |
555 | * num_of_loops | |
556 | */ | |
557 | /* G1_TX_SLEW_CTRL_EN and G1_TX_SLEW_RATE */ | |
558 | {G1_SETTINGS_0_REG, 0x800, 0xf000, {0xb000}, 0, 0}, | |
559 | /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
560 | {G1_SETTINGS_1_REG, 0x800, 0x3ff, {0x3c9}, 0, 0}, | |
561 | /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
562 | {G2_SETTINGS_1_REG, 0x800, 0x3ff, {0x3c9}, 0, 0}, | |
563 | /* CFG_DFE_EN_SEL */ | |
564 | {LANE_CFG4_REG, 0x800, 0x8, {0x8}, 0, 0}, | |
565 | /* FFE Setting Force, RES and CAP */ | |
566 | {SQUELCH_FFE_SETTING_REG, 0x800, 0xff, {0xaf}, 0, 0}, | |
567 | /* tximpcal_th and rximpcal_th */ | |
568 | {VTHIMPCAL_CTRL_REG, 0x800, 0xff00, {0x3000}, 0, 0}, | |
569 | /* cal_rxclkalign90_ext_en and cal_os_ph_ext */ | |
570 | {CAL_REG6, 0x800, 0xff00, {0xdc00}, 0, 0}, | |
571 | }; | |
572 | ||
573 | /* PEX - electrical configuration seq Rev 2.1 */ | |
574 | struct op_params pex_electrical_config_serdes_rev2_params[] = { | |
575 | /* | |
576 | * unit_base_reg, unit_offset, mask, PEX data, wait_time, | |
577 | * num_of_loops | |
578 | */ | |
579 | /* G1_TX_SLEW_CTRL_EN and G1_TX_SLEW_RATE */ | |
580 | {G1_SETTINGS_0_REG, 0x800, 0xf000, {0xb000}, 0, 0}, | |
581 | /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
582 | {G1_SETTINGS_1_REG, 0x800, 0x3ff, {0x3c9}, 0, 0}, | |
583 | /* G1 FFE Setting Force, RES and CAP */ | |
584 | {G1_SETTINGS_3_REG, 0x800, 0xff, {0xcf}, 0, 0}, | |
585 | /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ | |
586 | {G2_SETTINGS_1_REG, 0x800, 0x3ff, {0x3c9}, 0, 0}, | |
587 | /* G2 FFE Setting Force, RES and CAP */ | |
588 | {G2_SETTINGS_3_REG, 0x800, 0xff, {0xaf}, 0, 0}, | |
589 | /* G2 DFE resolution value */ | |
590 | {G2_SETTINGS_4_REG, 0x800, 0x300, {0x300}, 0, 0}, | |
591 | /* DFE resolution force */ | |
592 | {DFE_REG0, 0x800, 0x8000, {0x8000}, 0, 0}, | |
593 | /* Tx amplitude for Tx Margin 0 */ | |
594 | {PCIE_REG1, 0x800, 0xf80, {0xd00}, 0, 0}, | |
595 | /* Tx_Emph value for -3.5d_b and -6d_b */ | |
596 | {PCIE_REG3, 0x800, 0xff00, {0xaf00}, 0, 0}, | |
597 | /* CFG_DFE_EN_SEL */ | |
598 | {LANE_CFG4_REG, 0x800, 0x8, {0x8}, 0, 0}, | |
599 | /* tximpcal_th and rximpcal_th */ | |
600 | {VTHIMPCAL_CTRL_REG, 0x800, 0xff00, {0x3000}, 0, 0}, | |
28be54dc RK |
601 | /* Force receiver detected */ |
602 | {LANE_CFG0_REG, 0x800, 0x8000, {0x8000}, 0, 0}, | |
edb47025 SR |
603 | }; |
604 | ||
605 | /* PEX - configuration seq for REF_CLOCK_25MHz */ | |
606 | struct op_params pex_config_ref_clock25_m_hz[] = { | |
607 | /* | |
608 | * unit_base_reg, unit_offset, mask, PEX data, wait_time, | |
609 | * num_of_loops | |
610 | */ | |
611 | /* Bits[4:0]=0x2 - REF_FREF_SEL */ | |
612 | {POWER_AND_PLL_CTRL_REG, 0x800, 0x1f, {0x2}, 0, 0}, | |
613 | /* Bit[10]=0x1 - REFCLK_SEL */ | |
614 | {MISC_REG, 0x800, 0x400, {0x400}, 0, 0}, | |
615 | /* Bits[7:0]=0x7 - CFG_PM_RXDLOZ_WAIT */ | |
616 | {GLOBAL_PM_CTRL, 0x800, 0xff, {0x7}, 0, 0}, | |
617 | }; | |
618 | ||
619 | /* PEX - configuration seq for REF_CLOCK_40MHz */ | |
620 | struct op_params pex_config_ref_clock40_m_hz[] = { | |
621 | /* | |
622 | * unit_base_reg, unit_offset, mask, PEX data, wait_time, | |
623 | * num_of_loops | |
624 | */ | |
625 | /* Bits[4:0]=0x3 - REF_FREF_SEL */ | |
626 | {POWER_AND_PLL_CTRL_REG, 0x800, 0x1f, {0x3}, 0, 0}, | |
627 | /* Bits[10]=0x1 - REFCLK_SEL */ | |
628 | {MISC_REG, 0x800, 0x400, {0x400}, 0, 0}, | |
629 | /* Bits[7:0]=0xc - CFG_PM_RXDLOZ_WAIT */ | |
630 | {GLOBAL_PM_CTRL, 0x800, 0xff, {0xc}, 0, 0}, | |
631 | }; | |
632 | ||
633 | /* PEX - configuration seq for REF_CLOCK_100MHz */ | |
634 | struct op_params pex_config_ref_clock100_m_hz[] = { | |
635 | /* | |
636 | * unit_base_reg, unit_offset, mask, PEX data, wait_time, | |
637 | * num_of_loops | |
638 | */ | |
639 | /* Bits[4:0]=0x0 - REF_FREF_SEL */ | |
640 | {POWER_AND_PLL_CTRL_REG, 0x800, 0x1f, {0x0}, 0, 0}, | |
641 | /* Bit[10]=0x0 - REFCLK_SEL */ | |
642 | {MISC_REG, 0x800, 0x400, {0x0}, 0, 0}, | |
643 | /* Bits[7:0]=0x1e - CFG_PM_RXDLOZ_WAIT */ | |
644 | {GLOBAL_PM_CTRL, 0x800, 0xff, {0x1e}, 0, 0}, | |
645 | }; | |
646 | ||
647 | /* | |
648 | * USB2 | |
649 | */ | |
650 | ||
651 | struct op_params usb2_power_up_params[] = { | |
652 | /* | |
653 | * unit_base_reg, unit_offset, mask, USB2 data, wait_time, | |
654 | * num_of_loops | |
655 | */ | |
656 | /* Init phy 0 */ | |
657 | {0x18440, 0x0 /*NA*/, 0xffffffff, {0x62}, 0, 0}, | |
658 | /* Init phy 1 */ | |
659 | {0x18444, 0x0 /*NA*/, 0xffffffff, {0x62}, 0, 0}, | |
660 | /* Init phy 2 */ | |
661 | {0x18448, 0x0 /*NA*/, 0xffffffff, {0x62}, 0, 0}, | |
662 | /* Phy offset 0x0 - PLL_CONTROL0 */ | |
663 | {0xc0000, 0x0 /*NA*/, 0xffffffff, {0x40605205}, 0, 0}, | |
664 | {0xc001c, 0x0 /*NA*/, 0xffffffff, {0x39f16ce}, 0, 0}, | |
665 | {0xc201c, 0x0 /*NA*/, 0xffffffff, {0x39f16ce}, 0, 0}, | |
666 | {0xc401c, 0x0 /*NA*/, 0xffffffff, {0x39f16ce}, 0, 0}, | |
667 | /* Phy offset 0x1 - PLL_CONTROL1 */ | |
668 | {0xc0004, 0x0 /*NA*/, 0x1, {0x1}, 0, 0}, | |
669 | /* Phy0 register 3 - TX Channel control 0 */ | |
670 | {0xc000c, 0x0 /*NA*/, 0x1000000, {0x1000000}, 0, 0}, | |
671 | /* Phy0 register 3 - TX Channel control 0 */ | |
672 | {0xc200c, 0x0 /*NA*/, 0x1000000, {0x1000000}, 0, 0}, | |
673 | /* Phy0 register 3 - TX Channel control 0 */ | |
674 | {0xc400c, 0x0 /*NA*/, 0x1000000, {0x1000000}, 0, 0}, | |
675 | /* check PLLCAL_DONE is set and IMPCAL_DONE is set */ | |
676 | {0xc0008, 0x0 /*NA*/, 0x80800000, {0x80800000}, 1, 1000}, | |
677 | /* check REG_SQCAL_DONE is set */ | |
678 | {0xc0018, 0x0 /*NA*/, 0x80000000, {0x80000000}, 1, 1000}, | |
679 | /* check PLL_READY is set */ | |
680 | {0xc0000, 0x0 /*NA*/, 0x80000000, {0x80000000}, 1, 1000} | |
681 | }; | |
682 | ||
683 | /* | |
684 | * QSGMII | |
685 | */ | |
686 | ||
687 | /* QSGMII - power up seq */ | |
688 | struct op_params qsgmii_port_power_up_params[] = { | |
689 | /* | |
690 | * unit_base_reg, unit_offset, mask, QSGMII data, wait_time, | |
691 | * num_of_loops | |
692 | */ | |
693 | /* Connect the QSGMII to Gigabit Ethernet units */ | |
694 | {QSGMII_CONTROL_REG1, 0x0, 0x40000000, {0x40000000}, 0, 0}, | |
695 | /* Power Up */ | |
696 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0xf0006, {0x80002}, 0, 0}, | |
697 | /* Unreset */ | |
698 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x7800, {0x6000}, 0, 0}, | |
699 | /* Phy Selector */ | |
700 | {POWER_AND_PLL_CTRL_REG, 0x800, 0xff, {0xfc81}, 0, 0}, | |
701 | /* Ref clock source select */ | |
702 | {MISC_REG, 0x800, 0x4c0, {0x480}, 0, 0} | |
703 | }; | |
704 | ||
705 | /* QSGMII - speed config seq */ | |
706 | struct op_params qsgmii_port_speed_config_params[] = { | |
707 | /* | |
708 | * unit_base_reg, unit_offset, mask, QSGMII data, wait_time, | |
709 | * num_of_loops | |
710 | */ | |
711 | /* Baud Rate */ | |
712 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x3fc00000, {0xcc00000}, 0, 0}, | |
713 | /* Phy Gen RX and TX */ | |
714 | {ISOLATE_REG, 0x800, 0xff, {0x33}, 0, 0}, | |
715 | /* Bus Width */ | |
716 | {LOOPBACK_REG, 0x800, 0xe, {0x2}, 0, 0} | |
717 | }; | |
718 | ||
719 | /* QSGMII - Select electrical param seq */ | |
720 | struct op_params qsgmii_port_electrical_config_params[] = { | |
721 | /* | |
722 | * unit_base_reg, unit_offset, mask, QSGMII data, wait_time, | |
723 | * num_of_loops | |
724 | */ | |
725 | /* Slew rate and emphasis */ | |
726 | {G1_SETTINGS_0_REG, 0x800, 0x8000, {0x0}, 0, 0} | |
727 | }; | |
728 | ||
729 | /* QSGMII - TX config seq */ | |
730 | struct op_params qsgmii_port_tx_config_params1[] = { | |
731 | /* | |
732 | * unit_base_reg, unit_offset, mask, QSGMII data, wait_time, | |
733 | * num_of_loops | |
734 | */ | |
735 | {GLUE_REG, 0x800, 0x1800, {0x800}, 0, 0}, | |
736 | /* Sft Reset pulse */ | |
737 | {RESET_DFE_REG, 0x800, 0x401, {0x401}, 0, 0}, | |
738 | /* Sft Reset pulse */ | |
739 | {RESET_DFE_REG, 0x800, 0x401, {0x0}, 0, 0}, | |
740 | /* Lane align */ | |
741 | {LANE_ALIGN_REG0, 0x800, 0x1000, {0x1000}, 0, 0}, | |
742 | /* Power up PLL, RX and TX */ | |
743 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x70000, {0x70000}, 0, 0}, | |
744 | /* Tx driver output idle */ | |
745 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x80000, {0x80000}, 0, 0} | |
746 | }; | |
747 | ||
748 | struct op_params qsgmii_port_tx_config_params2[] = { | |
749 | /* | |
750 | * unit_base_reg, unit_offset, mask, QSGMII data, wait_time, | |
751 | * num_of_loops | |
752 | */ | |
753 | /* Wait for PHY power up sequence to finish */ | |
754 | {COMMON_PHY_STATUS1_REG, 0x28, 0xc, {0xc}, 10, 1000}, | |
755 | /* Assert Rx Init and Tx driver output valid */ | |
756 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x40080000, {0x40000000}, 0, 0}, | |
757 | /* Wait for PHY power up sequence to finish */ | |
758 | {COMMON_PHY_STATUS1_REG, 0x28, 0x1, {0x1}, 1, 1000}, | |
759 | /* De-assert Rx Init */ | |
760 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x40000000, {0x0}, 0, 0} | |
761 | }; | |
762 | ||
763 | /* SERDES_POWER_DOWN */ | |
764 | struct op_params serdes_power_down_params[] = { | |
765 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, (0xf << 11), {(0x3 << 11)}, | |
766 | 0, 0}, | |
767 | {COMMON_PHY_CONFIGURATION1_REG, 0x28, (0x7 << 16), {0}, 0, 0} | |
768 | }; | |
769 | ||
770 | /* | |
771 | * hws_ctrl_serdes_rev_get | |
772 | * | |
773 | * DESCRIPTION: Get the Serdes revision number | |
774 | * | |
775 | * INPUT: config_field - Field description enum | |
776 | * | |
777 | * OUTPUT: None | |
778 | * | |
779 | * RETURN: | |
780 | * 8bit Serdes revision number | |
781 | */ | |
782 | u8 hws_ctrl_serdes_rev_get(void) | |
783 | { | |
784 | #ifdef CONFIG_ARMADA_38X | |
785 | /* for A38x-Z1 */ | |
786 | if (sys_env_device_rev_get() == MV_88F68XX_Z1_ID) | |
787 | return MV_SERDES_REV_1_2; | |
788 | #endif | |
789 | ||
790 | /* for A39x-Z1, A38x-A0 */ | |
791 | return MV_SERDES_REV_2_1; | |
792 | } | |
793 | ||
794 | u32 hws_serdes_topology_verify(enum serdes_type serdes_type, u32 serdes_id, | |
795 | enum serdes_mode serdes_mode) | |
796 | { | |
797 | u32 test_result = 0; | |
798 | u8 serd_max_num, unit_numb; | |
799 | enum unit_id unit_id; | |
800 | ||
801 | if (serdes_type > RXAUI) { | |
802 | printf("%s: Warning: Wrong serdes type %s serdes#%d\n", | |
803 | __func__, serdes_type_to_string[serdes_type], serdes_id); | |
804 | return MV_FAIL; | |
805 | } | |
806 | ||
807 | unit_id = serdes_type_to_unit_info[serdes_type].serdes_unit_id; | |
808 | unit_numb = serdes_type_to_unit_info[serdes_type].serdes_unit_num; | |
809 | serd_max_num = sys_env_unit_max_num_get(unit_id); | |
810 | ||
811 | /* if didn't exceed amount of required Serdes lanes for current type */ | |
812 | if (serdes_lane_in_use_count[unit_id][unit_numb] != 0) { | |
813 | /* update amount of required Serdes lanes for current type */ | |
814 | serdes_lane_in_use_count[unit_id][unit_numb]--; | |
815 | ||
816 | /* | |
817 | * If reached the exact amount of required Serdes lanes for | |
818 | * current type | |
819 | */ | |
820 | if (serdes_lane_in_use_count[unit_id][unit_numb] == 0) { | |
821 | if (((serdes_type <= PEX3)) && | |
822 | ((serdes_mode == PEX_END_POINT_X4) || | |
823 | (serdes_mode == PEX_ROOT_COMPLEX_X4))) { | |
824 | /* PCiex4 uses 2 SerDes */ | |
825 | serdes_unit_count[PEX_UNIT_ID] += 2; | |
826 | } else { | |
827 | serdes_unit_count[unit_id]++; | |
828 | } | |
829 | ||
830 | /* test SoC unit count limitation */ | |
831 | if (serdes_unit_count[unit_id] > serd_max_num) { | |
832 | test_result = WRONG_NUMBER_OF_UNITS; | |
833 | } else if (unit_numb >= serd_max_num) { | |
834 | /* test SoC unit number limitation */ | |
835 | test_result = UNIT_NUMBER_VIOLATION; | |
836 | } | |
837 | } | |
838 | } else { | |
839 | test_result = SERDES_ALREADY_IN_USE; | |
014a357b CP |
840 | } |
841 | ||
842 | if (test_result == SERDES_ALREADY_IN_USE) { | |
843 | printf("%s: Error: serdes lane %d is configured to type %s: type already in use\n", | |
844 | __func__, serdes_id, | |
845 | serdes_type_to_string[serdes_type]); | |
846 | return MV_FAIL; | |
847 | } else if (test_result == WRONG_NUMBER_OF_UNITS) { | |
848 | printf("%s: Warning: serdes lane %d is set to type %s.\n", | |
849 | __func__, serdes_id, | |
850 | serdes_type_to_string[serdes_type]); | |
851 | printf("%s: Maximum supported lanes are already set to this type (limit = %d)\n", | |
852 | __func__, serd_max_num); | |
853 | return MV_FAIL; | |
854 | } else if (test_result == UNIT_NUMBER_VIOLATION) { | |
855 | printf("%s: Warning: serdes lane %d type is %s: current device support only %d units of this type.\n", | |
856 | __func__, serdes_id, | |
857 | serdes_type_to_string[serdes_type], | |
858 | serd_max_num); | |
859 | return MV_FAIL; | |
edb47025 SR |
860 | } |
861 | ||
862 | return MV_OK; | |
863 | } | |
864 | ||
865 | void hws_serdes_xaui_topology_verify(void) | |
866 | { | |
867 | /* | |
868 | * If XAUI is in use - serdes_lane_in_use_count has to be = 0; | |
869 | * if it is not in use hast be = 4 | |
870 | */ | |
871 | if ((serdes_lane_in_use_count[XAUI_UNIT_ID][0] != 0) && | |
872 | (serdes_lane_in_use_count[XAUI_UNIT_ID][0] != 4)) { | |
873 | printf("%s: Warning: wrong number of lanes is set to XAUI - %d\n", | |
874 | __func__, serdes_lane_in_use_count[XAUI_UNIT_ID][0]); | |
875 | printf("%s: XAUI has to be defined on 4 lanes\n", __func__); | |
876 | } | |
877 | ||
878 | /* | |
879 | * If RXAUI is in use - serdes_lane_in_use_count has to be = 0; | |
880 | * if it is not in use hast be = 2 | |
881 | */ | |
882 | if ((serdes_lane_in_use_count[RXAUI_UNIT_ID][0] != 0) && | |
883 | (serdes_lane_in_use_count[RXAUI_UNIT_ID][0] != 2)) { | |
884 | printf("%s: Warning: wrong number of lanes is set to RXAUI - %d\n", | |
885 | __func__, serdes_lane_in_use_count[RXAUI_UNIT_ID][0]); | |
886 | printf("%s: RXAUI has to be defined on 2 lanes\n", __func__); | |
887 | } | |
888 | } | |
889 | ||
890 | int hws_serdes_seq_db_init(void) | |
891 | { | |
892 | u8 serdes_rev = hws_ctrl_serdes_rev_get(); | |
893 | ||
894 | DEBUG_INIT_FULL_S("\n### serdes_seq38x_init ###\n"); | |
895 | ||
896 | if (serdes_rev == MV_SERDES_REV_NA) { | |
897 | printf("hws_serdes_seq_db_init: serdes revision number is not supported\n"); | |
898 | return MV_NOT_SUPPORTED; | |
899 | } | |
900 | ||
901 | /* SATA_PORT_0_ONLY_POWER_UP_SEQ sequence init */ | |
902 | serdes_seq_db[SATA_PORT_0_ONLY_POWER_UP_SEQ].op_params_ptr = | |
903 | sata_port0_power_up_params; | |
904 | serdes_seq_db[SATA_PORT_0_ONLY_POWER_UP_SEQ].cfg_seq_size = | |
905 | sizeof(sata_port0_power_up_params) / sizeof(struct op_params); | |
906 | serdes_seq_db[SATA_PORT_0_ONLY_POWER_UP_SEQ].data_arr_idx = SATA; | |
907 | ||
908 | /* SATA_PORT_1_ONLY_POWER_UP_SEQ sequence init */ | |
909 | serdes_seq_db[SATA_PORT_1_ONLY_POWER_UP_SEQ].op_params_ptr = | |
910 | sata_port1_power_up_params; | |
911 | serdes_seq_db[SATA_PORT_1_ONLY_POWER_UP_SEQ].cfg_seq_size = | |
912 | sizeof(sata_port1_power_up_params) / sizeof(struct op_params); | |
913 | serdes_seq_db[SATA_PORT_1_ONLY_POWER_UP_SEQ].data_arr_idx = SATA; | |
914 | ||
915 | /* SATA_POWER_UP_SEQ sequence init */ | |
916 | serdes_seq_db[SATA_POWER_UP_SEQ].op_params_ptr = | |
917 | sata_and_sgmii_power_up_params; | |
918 | serdes_seq_db[SATA_POWER_UP_SEQ].cfg_seq_size = | |
919 | sizeof(sata_and_sgmii_power_up_params) / sizeof(struct op_params); | |
920 | serdes_seq_db[SATA_POWER_UP_SEQ].data_arr_idx = SATA; | |
921 | ||
922 | /* SATA_1_5_SPEED_CONFIG_SEQ sequence init */ | |
923 | serdes_seq_db[SATA_1_5_SPEED_CONFIG_SEQ].op_params_ptr = | |
924 | sata_and_sgmii_speed_config_params; | |
925 | serdes_seq_db[SATA_1_5_SPEED_CONFIG_SEQ].cfg_seq_size = | |
926 | sizeof(sata_and_sgmii_speed_config_params) / | |
927 | sizeof(struct op_params); | |
928 | serdes_seq_db[SATA_1_5_SPEED_CONFIG_SEQ].data_arr_idx = SATA; | |
929 | ||
930 | /* SATA_3_SPEED_CONFIG_SEQ sequence init */ | |
931 | serdes_seq_db[SATA_3_SPEED_CONFIG_SEQ].op_params_ptr = | |
932 | sata_and_sgmii_speed_config_params; | |
933 | serdes_seq_db[SATA_3_SPEED_CONFIG_SEQ].cfg_seq_size = | |
934 | sizeof(sata_and_sgmii_speed_config_params) / | |
935 | sizeof(struct op_params); | |
936 | serdes_seq_db[SATA_3_SPEED_CONFIG_SEQ].data_arr_idx = SATA; | |
937 | ||
938 | /* SATA_6_SPEED_CONFIG_SEQ sequence init */ | |
939 | serdes_seq_db[SATA_6_SPEED_CONFIG_SEQ].op_params_ptr = | |
940 | sata_and_sgmii_speed_config_params; | |
941 | serdes_seq_db[SATA_6_SPEED_CONFIG_SEQ].cfg_seq_size = | |
942 | sizeof(sata_and_sgmii_speed_config_params) / | |
943 | sizeof(struct op_params); | |
944 | serdes_seq_db[SATA_6_SPEED_CONFIG_SEQ].data_arr_idx = SATA; | |
945 | ||
946 | /* SATA_ELECTRICAL_CONFIG_SEQ seq sequence init */ | |
947 | if (serdes_rev == MV_SERDES_REV_1_2) { | |
948 | serdes_seq_db[SATA_ELECTRICAL_CONFIG_SEQ].op_params_ptr = | |
949 | sata_electrical_config_serdes_rev1_params; | |
950 | serdes_seq_db[SATA_ELECTRICAL_CONFIG_SEQ].cfg_seq_size = | |
951 | sizeof(sata_electrical_config_serdes_rev1_params) / | |
952 | sizeof(struct op_params); | |
953 | } else { | |
954 | serdes_seq_db[SATA_ELECTRICAL_CONFIG_SEQ].op_params_ptr = | |
955 | sata_electrical_config_serdes_rev2_params; | |
956 | serdes_seq_db[SATA_ELECTRICAL_CONFIG_SEQ].cfg_seq_size = | |
957 | sizeof(sata_electrical_config_serdes_rev2_params) / | |
958 | sizeof(struct op_params); | |
959 | } | |
960 | serdes_seq_db[SATA_ELECTRICAL_CONFIG_SEQ].data_arr_idx = SATA; | |
961 | ||
962 | /* SATA_TX_CONFIG_SEQ sequence init */ | |
963 | serdes_seq_db[SATA_TX_CONFIG_SEQ1].op_params_ptr = | |
964 | sata_and_sgmii_tx_config_params1; | |
965 | serdes_seq_db[SATA_TX_CONFIG_SEQ1].cfg_seq_size = | |
966 | sizeof(sata_and_sgmii_tx_config_params1) / sizeof(struct op_params); | |
967 | serdes_seq_db[SATA_TX_CONFIG_SEQ1].data_arr_idx = SATA; | |
968 | ||
969 | /* SATA_PORT_0_ONLY_TX_CONFIG_SEQ sequence init */ | |
970 | serdes_seq_db[SATA_PORT_0_ONLY_TX_CONFIG_SEQ].op_params_ptr = | |
971 | sata_port0_tx_config_params; | |
972 | serdes_seq_db[SATA_PORT_0_ONLY_TX_CONFIG_SEQ].cfg_seq_size = | |
973 | sizeof(sata_port0_tx_config_params) / sizeof(struct op_params); | |
974 | serdes_seq_db[SATA_PORT_0_ONLY_TX_CONFIG_SEQ].data_arr_idx = SATA; | |
975 | ||
976 | /* SATA_PORT_1_ONLY_TX_CONFIG_SEQ sequence init */ | |
977 | serdes_seq_db[SATA_PORT_1_ONLY_TX_CONFIG_SEQ].op_params_ptr = | |
978 | sata_port1_tx_config_params; | |
979 | serdes_seq_db[SATA_PORT_1_ONLY_TX_CONFIG_SEQ].cfg_seq_size = | |
980 | sizeof(sata_port1_tx_config_params) / sizeof(struct op_params); | |
981 | serdes_seq_db[SATA_PORT_1_ONLY_TX_CONFIG_SEQ].data_arr_idx = SATA; | |
982 | ||
983 | /* SATA_TX_CONFIG_SEQ2 sequence init */ | |
984 | if (serdes_rev == MV_SERDES_REV_1_2) { | |
985 | serdes_seq_db[SATA_TX_CONFIG_SEQ2].op_params_ptr = | |
986 | sata_and_sgmii_tx_config_serdes_rev1_params2; | |
987 | serdes_seq_db[SATA_TX_CONFIG_SEQ2].cfg_seq_size = | |
988 | sizeof(sata_and_sgmii_tx_config_serdes_rev1_params2) / | |
989 | sizeof(struct op_params); | |
990 | } else { | |
991 | serdes_seq_db[SATA_TX_CONFIG_SEQ2].op_params_ptr = | |
992 | sata_and_sgmii_tx_config_serdes_rev2_params2; | |
993 | serdes_seq_db[SATA_TX_CONFIG_SEQ2].cfg_seq_size = | |
994 | sizeof(sata_and_sgmii_tx_config_serdes_rev2_params2) / | |
995 | sizeof(struct op_params); | |
996 | } | |
997 | serdes_seq_db[SATA_TX_CONFIG_SEQ2].data_arr_idx = SATA; | |
998 | ||
999 | /* SGMII_POWER_UP_SEQ sequence init */ | |
1000 | serdes_seq_db[SGMII_POWER_UP_SEQ].op_params_ptr = | |
1001 | sata_and_sgmii_power_up_params; | |
1002 | serdes_seq_db[SGMII_POWER_UP_SEQ].cfg_seq_size = | |
1003 | sizeof(sata_and_sgmii_power_up_params) / sizeof(struct op_params); | |
1004 | serdes_seq_db[SGMII_POWER_UP_SEQ].data_arr_idx = SGMII; | |
1005 | ||
1006 | /* SGMII_1_25_SPEED_CONFIG_SEQ sequence init */ | |
1007 | serdes_seq_db[SGMII_1_25_SPEED_CONFIG_SEQ].op_params_ptr = | |
1008 | sata_and_sgmii_speed_config_params; | |
1009 | serdes_seq_db[SGMII_1_25_SPEED_CONFIG_SEQ].cfg_seq_size = | |
1010 | sizeof(sata_and_sgmii_speed_config_params) / | |
1011 | sizeof(struct op_params); | |
1012 | serdes_seq_db[SGMII_1_25_SPEED_CONFIG_SEQ].data_arr_idx = SGMII; | |
1013 | ||
1014 | /* SGMII_3_125_SPEED_CONFIG_SEQ sequence init */ | |
1015 | serdes_seq_db[SGMII_3_125_SPEED_CONFIG_SEQ].op_params_ptr = | |
1016 | sata_and_sgmii_speed_config_params; | |
1017 | serdes_seq_db[SGMII_3_125_SPEED_CONFIG_SEQ].cfg_seq_size = | |
1018 | sizeof(sata_and_sgmii_speed_config_params) / | |
1019 | sizeof(struct op_params); | |
1020 | serdes_seq_db[SGMII_3_125_SPEED_CONFIG_SEQ].data_arr_idx = SGMII_3_125; | |
1021 | ||
1022 | /* SGMII_ELECTRICAL_CONFIG_SEQ seq sequence init */ | |
1023 | if (serdes_rev == MV_SERDES_REV_1_2) { | |
1024 | serdes_seq_db[SGMII_ELECTRICAL_CONFIG_SEQ].op_params_ptr = | |
1025 | sgmii_electrical_config_serdes_rev1_params; | |
1026 | serdes_seq_db[SGMII_ELECTRICAL_CONFIG_SEQ].cfg_seq_size = | |
1027 | sizeof(sgmii_electrical_config_serdes_rev1_params) / | |
1028 | sizeof(struct op_params); | |
1029 | } else { | |
1030 | serdes_seq_db[SGMII_ELECTRICAL_CONFIG_SEQ].op_params_ptr = | |
1031 | sgmii_electrical_config_serdes_rev2_params; | |
1032 | serdes_seq_db[SGMII_ELECTRICAL_CONFIG_SEQ].cfg_seq_size = | |
1033 | sizeof(sgmii_electrical_config_serdes_rev2_params) / | |
1034 | sizeof(struct op_params); | |
1035 | } | |
1036 | serdes_seq_db[SGMII_ELECTRICAL_CONFIG_SEQ].data_arr_idx = SGMII; | |
1037 | ||
1038 | /* SGMII_TX_CONFIG_SEQ sequence init */ | |
1039 | serdes_seq_db[SGMII_TX_CONFIG_SEQ1].op_params_ptr = | |
1040 | sata_and_sgmii_tx_config_params1; | |
1041 | serdes_seq_db[SGMII_TX_CONFIG_SEQ1].cfg_seq_size = | |
1042 | sizeof(sata_and_sgmii_tx_config_params1) / sizeof(struct op_params); | |
1043 | serdes_seq_db[SGMII_TX_CONFIG_SEQ1].data_arr_idx = SGMII; | |
1044 | ||
1045 | /* SGMII_TX_CONFIG_SEQ sequence init */ | |
1046 | if (serdes_rev == MV_SERDES_REV_1_2) { | |
1047 | serdes_seq_db[SGMII_TX_CONFIG_SEQ2].op_params_ptr = | |
1048 | sata_and_sgmii_tx_config_serdes_rev1_params2; | |
1049 | serdes_seq_db[SGMII_TX_CONFIG_SEQ2].cfg_seq_size = | |
1050 | sizeof(sata_and_sgmii_tx_config_serdes_rev1_params2) / | |
1051 | sizeof(struct op_params); | |
1052 | } else { | |
1053 | serdes_seq_db[SGMII_TX_CONFIG_SEQ2].op_params_ptr = | |
1054 | sata_and_sgmii_tx_config_serdes_rev2_params2; | |
1055 | serdes_seq_db[SGMII_TX_CONFIG_SEQ2].cfg_seq_size = | |
1056 | sizeof(sata_and_sgmii_tx_config_serdes_rev2_params2) / | |
1057 | sizeof(struct op_params); | |
1058 | } | |
1059 | serdes_seq_db[SGMII_TX_CONFIG_SEQ2].data_arr_idx = SGMII; | |
1060 | ||
1061 | /* PEX_POWER_UP_SEQ sequence init */ | |
1062 | if (serdes_rev == MV_SERDES_REV_1_2) { | |
1063 | serdes_seq_db[PEX_POWER_UP_SEQ].op_params_ptr = | |
1064 | pex_and_usb3_power_up_serdes_rev1_params; | |
1065 | serdes_seq_db[PEX_POWER_UP_SEQ].cfg_seq_size = | |
1066 | sizeof(pex_and_usb3_power_up_serdes_rev1_params) / | |
1067 | sizeof(struct op_params); | |
1068 | } else { | |
1069 | serdes_seq_db[PEX_POWER_UP_SEQ].op_params_ptr = | |
1070 | pex_and_usb3_power_up_serdes_rev2_params; | |
1071 | serdes_seq_db[PEX_POWER_UP_SEQ].cfg_seq_size = | |
1072 | sizeof(pex_and_usb3_power_up_serdes_rev2_params) / | |
1073 | sizeof(struct op_params); | |
1074 | } | |
1075 | serdes_seq_db[PEX_POWER_UP_SEQ].data_arr_idx = PEX; | |
1076 | ||
1077 | /* PEX_2_5_SPEED_CONFIG_SEQ sequence init */ | |
1078 | serdes_seq_db[PEX_2_5_SPEED_CONFIG_SEQ].op_params_ptr = | |
1079 | pex_and_usb3_speed_config_params; | |
1080 | serdes_seq_db[PEX_2_5_SPEED_CONFIG_SEQ].cfg_seq_size = | |
1081 | sizeof(pex_and_usb3_speed_config_params) / sizeof(struct op_params); | |
1082 | serdes_seq_db[PEX_2_5_SPEED_CONFIG_SEQ].data_arr_idx = | |
1083 | PEXSERDES_SPEED_2_5_GBPS; | |
1084 | ||
1085 | /* PEX_5_SPEED_CONFIG_SEQ sequence init */ | |
1086 | serdes_seq_db[PEX_5_SPEED_CONFIG_SEQ].op_params_ptr = | |
1087 | pex_and_usb3_speed_config_params; | |
1088 | serdes_seq_db[PEX_5_SPEED_CONFIG_SEQ].cfg_seq_size = | |
1089 | sizeof(pex_and_usb3_speed_config_params) / sizeof(struct op_params); | |
1090 | serdes_seq_db[PEX_5_SPEED_CONFIG_SEQ].data_arr_idx = | |
1091 | PEXSERDES_SPEED_5_GBPS; | |
1092 | ||
1093 | /* PEX_ELECTRICAL_CONFIG_SEQ seq sequence init */ | |
1094 | if (serdes_rev == MV_SERDES_REV_1_2) { | |
1095 | serdes_seq_db[PEX_ELECTRICAL_CONFIG_SEQ].op_params_ptr = | |
1096 | pex_electrical_config_serdes_rev1_params; | |
1097 | serdes_seq_db[PEX_ELECTRICAL_CONFIG_SEQ].cfg_seq_size = | |
1098 | sizeof(pex_electrical_config_serdes_rev1_params) / | |
1099 | sizeof(struct op_params); | |
1100 | } else { | |
1101 | serdes_seq_db[PEX_ELECTRICAL_CONFIG_SEQ].op_params_ptr = | |
1102 | pex_electrical_config_serdes_rev2_params; | |
1103 | serdes_seq_db[PEX_ELECTRICAL_CONFIG_SEQ].cfg_seq_size = | |
1104 | sizeof(pex_electrical_config_serdes_rev2_params) / | |
1105 | sizeof(struct op_params); | |
1106 | } | |
1107 | serdes_seq_db[PEX_ELECTRICAL_CONFIG_SEQ].data_arr_idx = PEX; | |
1108 | ||
1109 | /* PEX_TX_CONFIG_SEQ1 sequence init */ | |
1110 | serdes_seq_db[PEX_TX_CONFIG_SEQ1].op_params_ptr = | |
1111 | pex_and_usb3_tx_config_params1; | |
1112 | serdes_seq_db[PEX_TX_CONFIG_SEQ1].cfg_seq_size = | |
1113 | sizeof(pex_and_usb3_tx_config_params1) / sizeof(struct op_params); | |
1114 | serdes_seq_db[PEX_TX_CONFIG_SEQ1].data_arr_idx = PEX; | |
1115 | ||
1116 | /* PEX_TX_CONFIG_SEQ2 sequence init */ | |
1117 | serdes_seq_db[PEX_TX_CONFIG_SEQ2].op_params_ptr = | |
1118 | pex_and_usb3_tx_config_params2; | |
1119 | serdes_seq_db[PEX_TX_CONFIG_SEQ2].cfg_seq_size = | |
1120 | sizeof(pex_and_usb3_tx_config_params2) / sizeof(struct op_params); | |
1121 | serdes_seq_db[PEX_TX_CONFIG_SEQ2].data_arr_idx = PEX; | |
1122 | ||
1123 | /* PEX_TX_CONFIG_SEQ3 sequence init */ | |
1124 | serdes_seq_db[PEX_TX_CONFIG_SEQ3].op_params_ptr = | |
1125 | pex_and_usb3_tx_config_params3; | |
1126 | serdes_seq_db[PEX_TX_CONFIG_SEQ3].cfg_seq_size = | |
1127 | sizeof(pex_and_usb3_tx_config_params3) / sizeof(struct op_params); | |
1128 | serdes_seq_db[PEX_TX_CONFIG_SEQ3].data_arr_idx = PEX; | |
1129 | ||
1130 | /* PEX_BY_4_CONFIG_SEQ sequence init */ | |
1131 | serdes_seq_db[PEX_BY_4_CONFIG_SEQ].op_params_ptr = | |
1132 | pex_by4_config_params; | |
1133 | serdes_seq_db[PEX_BY_4_CONFIG_SEQ].cfg_seq_size = | |
1134 | sizeof(pex_by4_config_params) / sizeof(struct op_params); | |
1135 | serdes_seq_db[PEX_BY_4_CONFIG_SEQ].data_arr_idx = PEX; | |
1136 | ||
1137 | /* PEX_CONFIG_REF_CLOCK_25MHZ_SEQ sequence init */ | |
1138 | serdes_seq_db[PEX_CONFIG_REF_CLOCK_25MHZ_SEQ].op_params_ptr = | |
1139 | pex_config_ref_clock25_m_hz; | |
1140 | serdes_seq_db[PEX_CONFIG_REF_CLOCK_25MHZ_SEQ].cfg_seq_size = | |
1141 | sizeof(pex_config_ref_clock25_m_hz) / sizeof(struct op_params); | |
1142 | serdes_seq_db[PEX_CONFIG_REF_CLOCK_25MHZ_SEQ].data_arr_idx = PEX; | |
1143 | ||
1144 | /* PEX_ELECTRICAL_CONFIG_REF_CLOCK_40MHZ_SEQ sequence init */ | |
1145 | serdes_seq_db[PEX_CONFIG_REF_CLOCK_40MHZ_SEQ].op_params_ptr = | |
1146 | pex_config_ref_clock40_m_hz; | |
1147 | serdes_seq_db[PEX_CONFIG_REF_CLOCK_40MHZ_SEQ].cfg_seq_size = | |
1148 | sizeof(pex_config_ref_clock40_m_hz) / sizeof(struct op_params); | |
1149 | serdes_seq_db[PEX_CONFIG_REF_CLOCK_40MHZ_SEQ].data_arr_idx = PEX; | |
1150 | ||
1151 | /* PEX_CONFIG_REF_CLOCK_100MHZ_SEQ sequence init */ | |
1152 | serdes_seq_db[PEX_CONFIG_REF_CLOCK_100MHZ_SEQ].op_params_ptr = | |
1153 | pex_config_ref_clock100_m_hz; | |
1154 | serdes_seq_db[PEX_CONFIG_REF_CLOCK_100MHZ_SEQ].cfg_seq_size = | |
1155 | sizeof(pex_config_ref_clock100_m_hz) / sizeof(struct op_params); | |
1156 | serdes_seq_db[PEX_CONFIG_REF_CLOCK_100MHZ_SEQ].data_arr_idx = PEX; | |
1157 | ||
1158 | /* USB3_POWER_UP_SEQ sequence init */ | |
1159 | if (serdes_rev == MV_SERDES_REV_1_2) { | |
1160 | serdes_seq_db[USB3_POWER_UP_SEQ].op_params_ptr = | |
1161 | pex_and_usb3_power_up_serdes_rev1_params; | |
1162 | serdes_seq_db[USB3_POWER_UP_SEQ].cfg_seq_size = | |
1163 | sizeof(pex_and_usb3_power_up_serdes_rev1_params) / | |
1164 | sizeof(struct op_params); | |
1165 | } else { | |
1166 | serdes_seq_db[USB3_POWER_UP_SEQ].op_params_ptr = | |
1167 | pex_and_usb3_power_up_serdes_rev2_params; | |
1168 | serdes_seq_db[USB3_POWER_UP_SEQ].cfg_seq_size = | |
1169 | sizeof(pex_and_usb3_power_up_serdes_rev2_params) / | |
1170 | sizeof(struct op_params); | |
1171 | } | |
1172 | serdes_seq_db[USB3_POWER_UP_SEQ].data_arr_idx = USB3; | |
1173 | ||
1174 | /* USB3_HOST_SPEED_CONFIG_SEQ sequence init */ | |
1175 | serdes_seq_db[USB3_HOST_SPEED_CONFIG_SEQ].op_params_ptr = | |
1176 | pex_and_usb3_speed_config_params; | |
1177 | serdes_seq_db[USB3_HOST_SPEED_CONFIG_SEQ].cfg_seq_size = | |
1178 | sizeof(pex_and_usb3_speed_config_params) / sizeof(struct op_params); | |
1179 | serdes_seq_db[USB3_HOST_SPEED_CONFIG_SEQ].data_arr_idx = | |
1180 | USB3SERDES_SPEED_5_GBPS_HOST; | |
1181 | ||
1182 | /* USB3_DEVICE_SPEED_CONFIG_SEQ sequence init */ | |
1183 | serdes_seq_db[USB3_DEVICE_SPEED_CONFIG_SEQ].op_params_ptr = | |
1184 | pex_and_usb3_speed_config_params; | |
1185 | serdes_seq_db[USB3_DEVICE_SPEED_CONFIG_SEQ].cfg_seq_size = | |
1186 | sizeof(pex_and_usb3_speed_config_params) / sizeof(struct op_params); | |
1187 | serdes_seq_db[USB3_DEVICE_SPEED_CONFIG_SEQ].data_arr_idx = | |
1188 | USB3SERDES_SPEED_5_GBPS_DEVICE; | |
1189 | ||
1190 | /* USB3_ELECTRICAL_CONFIG_SEQ seq sequence init */ | |
1191 | if (serdes_rev == MV_SERDES_REV_1_2) { | |
1192 | serdes_seq_db[USB3_ELECTRICAL_CONFIG_SEQ].op_params_ptr = | |
1193 | usb3_electrical_config_serdes_rev1_params; | |
1194 | serdes_seq_db[USB3_ELECTRICAL_CONFIG_SEQ].cfg_seq_size = | |
1195 | sizeof(usb3_electrical_config_serdes_rev1_params) / | |
1196 | sizeof(struct op_params); | |
1197 | } else { | |
1198 | serdes_seq_db[USB3_ELECTRICAL_CONFIG_SEQ].op_params_ptr = | |
1199 | usb3_electrical_config_serdes_rev2_params; | |
1200 | serdes_seq_db[USB3_ELECTRICAL_CONFIG_SEQ].cfg_seq_size = | |
1201 | sizeof(usb3_electrical_config_serdes_rev2_params) / | |
1202 | sizeof(struct op_params); | |
1203 | } | |
1204 | serdes_seq_db[USB3_ELECTRICAL_CONFIG_SEQ].data_arr_idx = USB3; | |
1205 | ||
1206 | /* USB3_TX_CONFIG_SEQ sequence init */ | |
1207 | serdes_seq_db[USB3_TX_CONFIG_SEQ1].op_params_ptr = | |
1208 | pex_and_usb3_tx_config_params1; | |
1209 | serdes_seq_db[USB3_TX_CONFIG_SEQ1].cfg_seq_size = | |
1210 | sizeof(pex_and_usb3_tx_config_params1) / sizeof(struct op_params); | |
1211 | serdes_seq_db[USB3_TX_CONFIG_SEQ1].data_arr_idx = USB3; | |
1212 | ||
1213 | /* USB3_TX_CONFIG_SEQ sequence init */ | |
1214 | serdes_seq_db[USB3_TX_CONFIG_SEQ2].op_params_ptr = | |
1215 | pex_and_usb3_tx_config_params2; | |
1216 | serdes_seq_db[USB3_TX_CONFIG_SEQ2].cfg_seq_size = | |
1217 | sizeof(pex_and_usb3_tx_config_params2) / sizeof(struct op_params); | |
1218 | serdes_seq_db[USB3_TX_CONFIG_SEQ2].data_arr_idx = USB3; | |
1219 | ||
1220 | /* USB3_TX_CONFIG_SEQ sequence init */ | |
1221 | serdes_seq_db[USB3_TX_CONFIG_SEQ3].op_params_ptr = | |
1222 | pex_and_usb3_tx_config_params3; | |
1223 | serdes_seq_db[USB3_TX_CONFIG_SEQ3].cfg_seq_size = | |
1224 | sizeof(pex_and_usb3_tx_config_params3) / sizeof(struct op_params); | |
1225 | serdes_seq_db[USB3_TX_CONFIG_SEQ3].data_arr_idx = USB3; | |
1226 | ||
1227 | /* USB2_POWER_UP_SEQ sequence init */ | |
1228 | serdes_seq_db[USB2_POWER_UP_SEQ].op_params_ptr = usb2_power_up_params; | |
1229 | serdes_seq_db[USB2_POWER_UP_SEQ].cfg_seq_size = | |
1230 | sizeof(usb2_power_up_params) / sizeof(struct op_params); | |
1231 | serdes_seq_db[USB2_POWER_UP_SEQ].data_arr_idx = 0; | |
1232 | ||
1233 | /* USB3_DEVICE_CONFIG_SEQ sequence init */ | |
1234 | serdes_seq_db[USB3_DEVICE_CONFIG_SEQ].op_params_ptr = | |
1235 | usb3_device_config_params; | |
1236 | serdes_seq_db[USB3_DEVICE_CONFIG_SEQ].cfg_seq_size = | |
1237 | sizeof(usb3_device_config_params) / sizeof(struct op_params); | |
1238 | serdes_seq_db[USB3_DEVICE_CONFIG_SEQ].data_arr_idx = 0; /* Not relevant */ | |
1239 | ||
1240 | /* SERDES_POWER_DOWN_SEQ sequence init */ | |
1241 | serdes_seq_db[SERDES_POWER_DOWN_SEQ].op_params_ptr = | |
1242 | serdes_power_down_params; | |
1243 | serdes_seq_db[SERDES_POWER_DOWN_SEQ].cfg_seq_size = | |
1244 | sizeof(serdes_power_down_params) / | |
1245 | sizeof(struct op_params); | |
1246 | serdes_seq_db[SERDES_POWER_DOWN_SEQ].data_arr_idx = FIRST_CELL; | |
1247 | ||
1248 | if (serdes_rev == MV_SERDES_REV_2_1) { | |
1249 | /* QSGMII_POWER_UP_SEQ sequence init */ | |
1250 | serdes_seq_db[QSGMII_POWER_UP_SEQ].op_params_ptr = | |
1251 | qsgmii_port_power_up_params; | |
1252 | serdes_seq_db[QSGMII_POWER_UP_SEQ].cfg_seq_size = | |
1253 | sizeof(qsgmii_port_power_up_params) / | |
1254 | sizeof(struct op_params); | |
1255 | serdes_seq_db[QSGMII_POWER_UP_SEQ].data_arr_idx = | |
1256 | QSGMII_SEQ_IDX; | |
1257 | ||
1258 | /* QSGMII_5_SPEED_CONFIG_SEQ sequence init */ | |
1259 | serdes_seq_db[QSGMII_5_SPEED_CONFIG_SEQ].op_params_ptr = | |
1260 | qsgmii_port_speed_config_params; | |
1261 | serdes_seq_db[QSGMII_5_SPEED_CONFIG_SEQ].cfg_seq_size = | |
1262 | sizeof(qsgmii_port_speed_config_params) / | |
1263 | sizeof(struct op_params); | |
1264 | serdes_seq_db[QSGMII_5_SPEED_CONFIG_SEQ].data_arr_idx = | |
1265 | QSGMII_SEQ_IDX; | |
1266 | ||
1267 | /* QSGMII_ELECTRICAL_CONFIG_SEQ seq sequence init */ | |
1268 | serdes_seq_db[QSGMII_ELECTRICAL_CONFIG_SEQ].op_params_ptr = | |
1269 | qsgmii_port_electrical_config_params; | |
1270 | serdes_seq_db[QSGMII_ELECTRICAL_CONFIG_SEQ].cfg_seq_size = | |
1271 | sizeof(qsgmii_port_electrical_config_params) / | |
1272 | sizeof(struct op_params); | |
1273 | serdes_seq_db[QSGMII_ELECTRICAL_CONFIG_SEQ].data_arr_idx = | |
1274 | QSGMII_SEQ_IDX; | |
1275 | ||
1276 | /* QSGMII_TX_CONFIG_SEQ sequence init */ | |
1277 | serdes_seq_db[QSGMII_TX_CONFIG_SEQ1].op_params_ptr = | |
1278 | qsgmii_port_tx_config_params1; | |
1279 | serdes_seq_db[QSGMII_TX_CONFIG_SEQ1].cfg_seq_size = | |
1280 | sizeof(qsgmii_port_tx_config_params1) / | |
1281 | sizeof(struct op_params); | |
1282 | serdes_seq_db[QSGMII_TX_CONFIG_SEQ1].data_arr_idx = | |
1283 | QSGMII_SEQ_IDX; | |
1284 | ||
1285 | /* QSGMII_TX_CONFIG_SEQ sequence init */ | |
1286 | serdes_seq_db[QSGMII_TX_CONFIG_SEQ2].op_params_ptr = | |
1287 | qsgmii_port_tx_config_params2; | |
1288 | serdes_seq_db[QSGMII_TX_CONFIG_SEQ2].cfg_seq_size = | |
1289 | sizeof(qsgmii_port_tx_config_params2) / | |
1290 | sizeof(struct op_params); | |
1291 | serdes_seq_db[QSGMII_TX_CONFIG_SEQ2].data_arr_idx = | |
1292 | QSGMII_SEQ_IDX; | |
1293 | } | |
1294 | ||
1295 | return MV_OK; | |
1296 | } | |
1297 | ||
1298 | enum serdes_seq serdes_type_and_speed_to_speed_seq(enum serdes_type serdes_type, | |
1299 | enum serdes_speed baud_rate) | |
1300 | { | |
1301 | enum serdes_seq seq_id = SERDES_LAST_SEQ; | |
1302 | ||
1303 | DEBUG_INIT_FULL_S("\n### serdes_type_and_speed_to_speed_seq ###\n"); | |
1304 | switch (serdes_type) { | |
1305 | case PEX0: | |
1306 | case PEX1: | |
1307 | case PEX2: | |
1308 | case PEX3: | |
1309 | if (baud_rate == SERDES_SPEED_2_5_GBPS) | |
1310 | seq_id = PEX_2_5_SPEED_CONFIG_SEQ; | |
1311 | else if (baud_rate == SERDES_SPEED_5_GBPS) | |
1312 | seq_id = PEX_5_SPEED_CONFIG_SEQ; | |
1313 | break; | |
1314 | case USB3_HOST0: | |
1315 | case USB3_HOST1: | |
1316 | if (baud_rate == SERDES_SPEED_5_GBPS) | |
1317 | seq_id = USB3_HOST_SPEED_CONFIG_SEQ; | |
1318 | break; | |
1319 | case USB3_DEVICE: | |
1320 | if (baud_rate == SERDES_SPEED_5_GBPS) | |
1321 | seq_id = USB3_DEVICE_SPEED_CONFIG_SEQ; | |
1322 | break; | |
1323 | case SATA0: | |
1324 | case SATA1: | |
1325 | case SATA2: | |
1326 | case SATA3: | |
1327 | if (baud_rate == SERDES_SPEED_1_5_GBPS) | |
1328 | seq_id = SATA_1_5_SPEED_CONFIG_SEQ; | |
1329 | else if (baud_rate == SERDES_SPEED_3_GBPS) | |
1330 | seq_id = SATA_3_SPEED_CONFIG_SEQ; | |
1331 | else if (baud_rate == SERDES_SPEED_6_GBPS) | |
1332 | seq_id = SATA_6_SPEED_CONFIG_SEQ; | |
1333 | break; | |
1334 | case SGMII0: | |
1335 | case SGMII1: | |
1336 | case SGMII2: | |
1337 | #ifdef CONFIG_ARMADA_39X | |
1338 | case SGMII3: | |
1339 | #endif | |
1340 | if (baud_rate == SERDES_SPEED_1_25_GBPS) | |
1341 | seq_id = SGMII_1_25_SPEED_CONFIG_SEQ; | |
1342 | else if (baud_rate == SERDES_SPEED_3_125_GBPS) | |
1343 | seq_id = SGMII_3_125_SPEED_CONFIG_SEQ; | |
1344 | break; | |
1345 | case QSGMII: | |
1346 | seq_id = QSGMII_5_SPEED_CONFIG_SEQ; | |
1347 | break; | |
1348 | #ifdef CONFIG_ARMADA_39X | |
1349 | case XAUI: | |
1350 | seq_id = XAUI_3_125_SPEED_CONFIG_SEQ; | |
1351 | break; | |
1352 | case RXAUI: | |
1353 | seq_id = RXAUI_6_25_SPEED_CONFIG_SEQ; | |
1354 | break; | |
1355 | #endif | |
1356 | default: | |
1357 | return SERDES_LAST_SEQ; | |
1358 | } | |
1359 | ||
1360 | return seq_id; | |
1361 | } | |
1362 | ||
490753ac KS |
1363 | static void print_topology_details(const struct serdes_map *serdes_map, |
1364 | u8 count) | |
edb47025 SR |
1365 | { |
1366 | u32 lane_num; | |
1367 | ||
1368 | DEBUG_INIT_S("board SerDes lanes topology details:\n"); | |
1369 | ||
4f7991ee | 1370 | DEBUG_INIT_S(" | Lane # | Speed | Type |\n"); |
edb47025 | 1371 | DEBUG_INIT_S(" --------------------------------\n"); |
490753ac KS |
1372 | for (lane_num = 0; lane_num < count; lane_num++) { |
1373 | if (serdes_map[lane_num].serdes_type == DEFAULT_SERDES) | |
edb47025 SR |
1374 | continue; |
1375 | DEBUG_INIT_S(" | "); | |
1376 | DEBUG_INIT_D(hws_get_physical_serdes_num(lane_num), 1); | |
4f7991ee | 1377 | DEBUG_INIT_S(" | "); |
490753ac | 1378 | DEBUG_INIT_D(serdes_map[lane_num].serdes_speed, 2); |
4f7991ee | 1379 | DEBUG_INIT_S(" | "); |
edb47025 | 1380 | DEBUG_INIT_S((char *) |
490753ac | 1381 | serdes_type_to_string[serdes_map[lane_num]. |
edb47025 SR |
1382 | serdes_type]); |
1383 | DEBUG_INIT_S("\t|\n"); | |
1384 | } | |
1385 | DEBUG_INIT_S(" --------------------------------\n"); | |
1386 | } | |
1387 | ||
1388 | int hws_pre_serdes_init_config(void) | |
1389 | { | |
1390 | u32 data; | |
1391 | ||
1392 | /* | |
1393 | * Configure Core PLL | |
1394 | */ | |
1395 | /* | |
1396 | * set PLL parameters | |
1397 | * bits[2:0] =0x3 (Core-PLL Kdiv) | |
1398 | * bits[20:12]=0x9f (Core-PLL Ndiv) | |
1399 | * bits[24:21]=0x7(Core-PLL VCO Band) | |
1400 | * bits[28:25]=0x1(Core-PLL Rlf) | |
1401 | * bits[31:29]=0x2(Core-PLL charge-pump adjust) | |
1402 | */ | |
1403 | reg_write(CORE_PLL_PARAMETERS_REG, 0x42e9f003); | |
1404 | ||
1405 | /* Enable PLL Configuration */ | |
1406 | data = reg_read(CORE_PLL_CONFIG_REG); | |
1407 | data = SET_BIT(data, 9); | |
1408 | reg_write(CORE_PLL_CONFIG_REG, data); | |
1409 | ||
1410 | return MV_OK; | |
1411 | } | |
1412 | ||
1413 | int serdes_phy_config(void) | |
1414 | { | |
490753ac KS |
1415 | struct serdes_map *serdes_map; |
1416 | u8 serdes_count; | |
1417 | ||
edb47025 SR |
1418 | DEBUG_INIT_FULL_S("\n### ctrl_high_speed_serdes_phy_config ###\n"); |
1419 | ||
1420 | DEBUG_INIT_S("High speed PHY - Version: "); | |
d374e90b | 1421 | DEBUG_INIT_S(SERDES_VERSION); |
edb47025 SR |
1422 | DEBUG_INIT_S("\n"); |
1423 | ||
1424 | /* Init serdes sequences DB */ | |
1425 | if (hws_serdes_seq_init() != MV_OK) { | |
1426 | printf("hws_ctrl_high_speed_serdes_phy_config: Error: Serdes initialization fail\n"); | |
1427 | return MV_FAIL; | |
1428 | } | |
1429 | ||
edb47025 SR |
1430 | /* Board topology load */ |
1431 | DEBUG_INIT_FULL_S | |
1432 | ("ctrl_high_speed_serdes_phy_config: Loading board topology..\n"); | |
490753ac KS |
1433 | CHECK_STATUS(hws_board_topology_load(&serdes_map, &serdes_count)); |
1434 | if (serdes_count > hws_serdes_get_max_lane()) { | |
1435 | printf("Error: too many serdes lanes specified by board\n"); | |
1436 | return MV_FAIL; | |
1437 | } | |
edb47025 SR |
1438 | |
1439 | /* print topology */ | |
490753ac | 1440 | print_topology_details(serdes_map, serdes_count); |
edb47025 SR |
1441 | CHECK_STATUS(hws_pre_serdes_init_config()); |
1442 | ||
1443 | /* Power-Up sequence */ | |
1444 | DEBUG_INIT_FULL_S | |
1445 | ("ctrl_high_speed_serdes_phy_config: Starting serdes power up sequence\n"); | |
1446 | ||
490753ac | 1447 | CHECK_STATUS(hws_power_up_serdes_lanes(serdes_map, serdes_count)); |
edb47025 SR |
1448 | |
1449 | DEBUG_INIT_FULL_S | |
1450 | ("\n### ctrl_high_speed_serdes_phy_config ended successfully ###\n"); | |
1451 | ||
1452 | DEBUG_INIT_S(ENDED_OK); | |
1453 | ||
1454 | return MV_OK; | |
1455 | } | |
1456 | ||
1457 | int serdes_polarity_config(u32 serdes_num, int is_rx) | |
1458 | { | |
1459 | u32 data; | |
1460 | u32 reg_addr; | |
1461 | u8 bit_off = (is_rx) ? 11 : 10; | |
1462 | ||
1463 | reg_addr = SERDES_REGS_LANE_BASE_OFFSET(serdes_num) + SYNC_PATTERN_REG; | |
1464 | data = reg_read(reg_addr); | |
1465 | data = SET_BIT(data, bit_off); | |
1466 | reg_write(reg_addr, data); | |
1467 | ||
1468 | return MV_OK; | |
1469 | } | |
1470 | ||
490753ac | 1471 | int hws_power_up_serdes_lanes(struct serdes_map *serdes_map, u8 count) |
edb47025 SR |
1472 | { |
1473 | u32 serdes_id, serdes_lane_num; | |
1474 | enum ref_clock ref_clock; | |
1475 | enum serdes_type serdes_type; | |
1476 | enum serdes_speed serdes_speed; | |
1477 | enum serdes_mode serdes_mode; | |
1478 | int serdes_rx_polarity_swap; | |
1479 | int serdes_tx_polarity_swap; | |
1480 | int is_pex_enabled = 0; | |
1481 | ||
1482 | /* | |
1483 | * is_pex_enabled: | |
1484 | * Flag which indicates that one of the Serdes is of PEX. | |
1485 | * In this case, PEX unit will be initialized after Serdes power-up | |
1486 | */ | |
1487 | ||
1488 | DEBUG_INIT_FULL_S("\n### hws_power_up_serdes_lanes ###\n"); | |
1489 | ||
1490 | /* COMMON PHYS SELECTORS register configuration */ | |
1491 | DEBUG_INIT_FULL_S | |
1492 | ("hws_power_up_serdes_lanes: Updating COMMON PHYS SELECTORS reg\n"); | |
490753ac | 1493 | CHECK_STATUS(hws_update_serdes_phy_selectors(serdes_map, count)); |
edb47025 SR |
1494 | |
1495 | /* per Serdes Power Up */ | |
490753ac | 1496 | for (serdes_id = 0; serdes_id < count; serdes_id++) { |
edb47025 SR |
1497 | DEBUG_INIT_FULL_S |
1498 | ("calling serdes_power_up_ctrl: serdes lane number "); | |
1499 | DEBUG_INIT_FULL_D_10(serdes_lane_num, 1); | |
1500 | DEBUG_INIT_FULL_S("\n"); | |
1501 | ||
1502 | serdes_lane_num = hws_get_physical_serdes_num(serdes_id); | |
490753ac KS |
1503 | serdes_type = serdes_map[serdes_id].serdes_type; |
1504 | serdes_speed = serdes_map[serdes_id].serdes_speed; | |
1505 | serdes_mode = serdes_map[serdes_id].serdes_mode; | |
1506 | serdes_rx_polarity_swap = serdes_map[serdes_id].swap_rx; | |
1507 | serdes_tx_polarity_swap = serdes_map[serdes_id].swap_tx; | |
edb47025 SR |
1508 | |
1509 | /* serdes lane is not in use */ | |
1510 | if (serdes_type == DEFAULT_SERDES) | |
1511 | continue; | |
1512 | else if (serdes_type <= PEX3) /* PEX type */ | |
1513 | is_pex_enabled = 1; | |
1514 | ||
1515 | ref_clock = hws_serdes_get_ref_clock_val(serdes_type); | |
1516 | if (ref_clock == REF_CLOCK_UNSUPPORTED) { | |
1517 | DEBUG_INIT_S | |
1518 | ("hws_power_up_serdes_lanes: unsupported ref clock\n"); | |
1519 | return MV_NOT_SUPPORTED; | |
1520 | } | |
1521 | CHECK_STATUS(serdes_power_up_ctrl(serdes_lane_num, | |
1522 | 1, | |
1523 | serdes_type, | |
1524 | serdes_speed, | |
1525 | serdes_mode, ref_clock)); | |
1526 | ||
1527 | /* RX Polarity config */ | |
1528 | if (serdes_rx_polarity_swap) | |
1529 | CHECK_STATUS(serdes_polarity_config | |
1530 | (serdes_lane_num, 1)); | |
1531 | ||
1532 | /* TX Polarity config */ | |
1533 | if (serdes_tx_polarity_swap) | |
1534 | CHECK_STATUS(serdes_polarity_config | |
1535 | (serdes_lane_num, 0)); | |
1536 | } | |
1537 | ||
1538 | if (is_pex_enabled) { | |
1539 | /* Set PEX_TX_CONFIG_SEQ sequence for PEXx4 mode. | |
1540 | After finish the Power_up sequence for all lanes, | |
1541 | the lanes should be released from reset state. */ | |
490753ac | 1542 | CHECK_STATUS(hws_pex_tx_config_seq(serdes_map, count)); |
edb47025 SR |
1543 | |
1544 | /* PEX configuration */ | |
490753ac | 1545 | CHECK_STATUS(hws_pex_config(serdes_map, count)); |
edb47025 SR |
1546 | } |
1547 | ||
1548 | /* USB2 configuration */ | |
1549 | DEBUG_INIT_FULL_S("hws_power_up_serdes_lanes: init USB2 Phys\n"); | |
1550 | CHECK_STATUS(mv_seq_exec(0 /* not relevant */ , USB2_POWER_UP_SEQ)); | |
1551 | ||
1552 | DEBUG_INIT_FULL_S | |
1553 | ("### hws_power_up_serdes_lanes ended successfully ###\n"); | |
1554 | ||
1555 | return MV_OK; | |
1556 | } | |
1557 | ||
1558 | int ctrl_high_speed_serdes_phy_config(void) | |
1559 | { | |
1560 | return hws_ctrl_high_speed_serdes_phy_config(); | |
1561 | } | |
1562 | ||
1563 | static int serdes_pex_usb3_pipe_delay_w_a(u32 serdes_num, u8 serdes_type) | |
1564 | { | |
1565 | u32 reg_data; | |
1566 | ||
1567 | /* WA for A380 Z1 relevant for lanes 3,4,5 only */ | |
1568 | if (serdes_num >= 3) { | |
1569 | reg_data = reg_read(GENERAL_PURPOSE_RESERVED0_REG); | |
1570 | /* set delay on pipe - | |
1571 | * When lane 3 is connected to a MAC of Pex -> set bit 7 to 1. | |
1572 | * When lane 3 is connected to a MAC of USB3 -> set bit 7 to 0. | |
1573 | * When lane 4 is connected to a MAC of Pex -> set bit 8 to 1. | |
1574 | * When lane 4 is connected to a MAC of USB3 -> set bit 8 to 0. | |
1575 | * When lane 5 is connected to a MAC of Pex -> set bit 8 to 1. | |
1576 | * When lane 5 is connected to a MAC of USB3 -> set bit 8 to 0. | |
1577 | */ | |
1578 | if (serdes_type == PEX) | |
1579 | reg_data |= 1 << (7 + (serdes_num - 3)); | |
1580 | if (serdes_type == USB3) { | |
1581 | /* USB3 */ | |
1582 | reg_data &= ~(1 << (7 + (serdes_num - 3))); | |
1583 | } | |
1584 | reg_write(GENERAL_PURPOSE_RESERVED0_REG, reg_data); | |
1585 | } | |
1586 | ||
1587 | return MV_OK; | |
1588 | } | |
1589 | ||
1590 | /* | |
1591 | * hws_serdes_pex_ref_clock_satr_get - | |
1592 | * | |
1593 | * DESCRIPTION: Get the reference clock value from DEVICE_SAMPLE_AT_RESET1_REG | |
1594 | * and check: | |
1595 | * bit[2] for PEX#0, bit[3] for PEX#1, bit[30] for PEX#2, bit[31] | |
1596 | * for PEX#3. | |
1597 | * If bit=0 --> REF_CLOCK_100MHz | |
1598 | * If bit=1 && DEVICE_SAMPLE_AT_RESET2_REG bit[0]=0 | |
1599 | * --> REF_CLOCK_25MHz | |
1600 | * If bit=1 && DEVICE_SAMPLE_AT_RESET2_REG bit[0]=1 | |
1601 | * --> REF_CLOCK_40MHz | |
1602 | * | |
1603 | * INPUT: serdes_type - Type of Serdes | |
1604 | * | |
1605 | * OUTPUT: pex_satr - Return the REF_CLOCK value: | |
1606 | * REF_CLOCK_25MHz, REF_CLOCK_40MHz or REF_CLOCK_100MHz | |
1607 | * | |
1608 | * RETURNS: MV_OK - for success | |
1609 | * MV_BAD_PARAM - for fail | |
1610 | */ | |
1611 | int hws_serdes_pex_ref_clock_satr_get(enum serdes_type serdes_type, u32 *pex_satr) | |
1612 | { | |
1613 | u32 data, reg_satr1; | |
1614 | ||
1615 | reg_satr1 = reg_read(DEVICE_SAMPLE_AT_RESET1_REG); | |
1616 | ||
1617 | switch (serdes_type) { | |
1618 | case PEX0: | |
1619 | data = REF_CLK_SELECTOR_VAL_PEX0(reg_satr1); | |
1620 | break; | |
1621 | case PEX1: | |
1622 | data = REF_CLK_SELECTOR_VAL_PEX1(reg_satr1); | |
1623 | break; | |
1624 | case PEX2: | |
1625 | data = REF_CLK_SELECTOR_VAL_PEX2(reg_satr1); | |
1626 | break; | |
1627 | case PEX3: | |
1628 | data = REF_CLK_SELECTOR_VAL_PEX3(reg_satr1); | |
1629 | break; | |
1630 | default: | |
1631 | printf("%s: Error: SerDes type %d is not supported\n", | |
1632 | __func__, serdes_type); | |
1633 | return MV_BAD_PARAM; | |
1634 | } | |
1635 | ||
1636 | *pex_satr = data; | |
1637 | ||
1638 | return MV_OK; | |
1639 | } | |
1640 | ||
1641 | u32 hws_serdes_get_ref_clock_val(enum serdes_type serdes_type) | |
1642 | { | |
1643 | u32 pex_satr; | |
1644 | enum ref_clock ref_clock; | |
1645 | ||
1646 | DEBUG_INIT_FULL_S("\n### hws_serdes_get_ref_clock_val ###\n"); | |
1647 | ||
1648 | if (serdes_type >= LAST_SERDES_TYPE) | |
1649 | return REF_CLOCK_UNSUPPORTED; | |
1650 | ||
1651 | /* read ref clock from S@R */ | |
1652 | ref_clock = hws_serdes_silicon_ref_clock_get(); | |
1653 | ||
1654 | if (serdes_type > PEX3) { | |
1655 | /* for all Serdes types but PCIe */ | |
1656 | return ref_clock; | |
1657 | } | |
1658 | ||
1659 | /* for PCIe, need also to check PCIe S@R */ | |
1660 | CHECK_STATUS(hws_serdes_pex_ref_clock_satr_get | |
1661 | (serdes_type, &pex_satr)); | |
1662 | ||
1663 | if (pex_satr == 0) { | |
1664 | return REF_CLOCK_100MHZ; | |
1665 | } else if (pex_satr == 1) { | |
1666 | /* value of 1 means we can use ref clock from SoC (as other Serdes types) */ | |
1667 | return ref_clock; | |
1668 | } else { | |
1669 | printf | |
1670 | ("%s: Error: REF_CLK_SELECTOR_VAL for SerDes type %d is wrong\n", | |
1671 | __func__, serdes_type); | |
1672 | return REF_CLOCK_UNSUPPORTED; | |
1673 | } | |
1674 | } | |
1675 | ||
1676 | int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up, | |
1677 | enum serdes_type serdes_type, | |
1678 | enum serdes_speed baud_rate, | |
1679 | enum serdes_mode serdes_mode, enum ref_clock ref_clock) | |
1680 | { | |
1681 | u32 sata_idx, pex_idx, sata_port; | |
1682 | enum serdes_seq speed_seq_id; | |
1683 | u32 reg_data; | |
1684 | int is_pex_by1; | |
1685 | ||
1686 | DEBUG_INIT_FULL_S("\n### serdes_power_up_ctrl ###\n"); | |
1687 | ||
1688 | if (serdes_power_up == 1) { /* Serdes power up */ | |
1689 | DEBUG_INIT_FULL_S | |
1690 | ("serdes_power_up_ctrl: executing power up.. "); | |
1691 | DEBUG_INIT_FULL_C("serdes num = ", serdes_num, 2); | |
1692 | DEBUG_INIT_FULL_C("serdes type = ", serdes_type, 2); | |
1693 | ||
1694 | DEBUG_INIT_FULL_S("Going access 1"); | |
1695 | ||
1696 | /* Getting the Speed Select sequence id */ | |
1697 | speed_seq_id = | |
1698 | serdes_type_and_speed_to_speed_seq(serdes_type, | |
1699 | baud_rate); | |
1700 | if (speed_seq_id == SERDES_LAST_SEQ) { | |
1701 | printf | |
1702 | ("serdes_power_up_ctrl: serdes type %d and speed %d are not supported together\n", | |
1703 | serdes_type, baud_rate); | |
1704 | ||
1705 | return MV_BAD_PARAM; | |
1706 | } | |
1707 | ||
1708 | /* Executing power up, ref clock set, speed config and TX config */ | |
1709 | switch (serdes_type) { | |
1710 | case PEX0: | |
1711 | case PEX1: | |
1712 | case PEX2: | |
1713 | case PEX3: | |
1714 | if (hws_ctrl_serdes_rev_get() == MV_SERDES_REV_1_2) { | |
1715 | CHECK_STATUS(serdes_pex_usb3_pipe_delay_w_a | |
1716 | (serdes_num, PEX)); | |
1717 | } | |
1718 | ||
1719 | is_pex_by1 = (serdes_mode == PEX_ROOT_COMPLEX_X1) || | |
1720 | (serdes_mode == PEX_END_POINT_X1); | |
1721 | pex_idx = serdes_type - PEX0; | |
1722 | ||
1723 | if ((is_pex_by1 == 1) || (serdes_type == PEX0)) { | |
1724 | /* For PEX by 4, init only the PEX 0 */ | |
1725 | reg_data = reg_read(SOC_CONTROL_REG1); | |
1726 | if (is_pex_by1 == 1) | |
1727 | reg_data |= 0x4000; | |
1728 | else | |
1729 | reg_data &= ~0x4000; | |
1730 | reg_write(SOC_CONTROL_REG1, reg_data); | |
1731 | ||
1732 | reg_data = | |
1733 | reg_read(((PEX_IF_REGS_BASE(pex_idx)) + | |
1734 | 0x6c)); | |
1735 | reg_data &= ~0x3f0; | |
1736 | if (is_pex_by1 == 1) | |
1737 | reg_data |= 0x10; | |
1738 | else | |
1739 | reg_data |= 0x40; | |
1740 | reg_write(((PEX_IF_REGS_BASE(pex_idx)) + 0x6c), | |
1741 | reg_data); | |
1742 | ||
1743 | reg_data = | |
1744 | reg_read(((PEX_IF_REGS_BASE(pex_idx)) + | |
1745 | 0x6c)); | |
1746 | reg_data &= ~0xf; | |
1747 | reg_data |= 0x2; | |
1748 | reg_write(((PEX_IF_REGS_BASE(pex_idx)) + 0x6c), | |
1749 | reg_data); | |
1750 | ||
1751 | reg_data = | |
1752 | reg_read(((PEX_IF_REGS_BASE(pex_idx)) + | |
1753 | 0x70)); | |
1754 | reg_data &= ~0x40; | |
1755 | reg_data |= 0x40; | |
1756 | reg_write(((PEX_IF_REGS_BASE(pex_idx)) + 0x70), | |
1757 | reg_data); | |
1758 | } | |
1759 | ||
1760 | CHECK_STATUS(mv_seq_exec(serdes_num, PEX_POWER_UP_SEQ)); | |
1761 | if (is_pex_by1 == 0) { | |
1762 | /* | |
1763 | * for PEX by 4 - use the PEX index as the | |
1764 | * seq array index | |
1765 | */ | |
1766 | serdes_seq_db[PEX_BY_4_CONFIG_SEQ]. | |
1767 | data_arr_idx = pex_idx; | |
1768 | CHECK_STATUS(mv_seq_exec | |
1769 | (serdes_num, PEX_BY_4_CONFIG_SEQ)); | |
1770 | } | |
1771 | ||
1772 | CHECK_STATUS(hws_ref_clock_set | |
1773 | (serdes_num, serdes_type, ref_clock)); | |
1774 | CHECK_STATUS(mv_seq_exec(serdes_num, speed_seq_id)); | |
1775 | CHECK_STATUS(mv_seq_exec | |
1776 | (serdes_num, PEX_ELECTRICAL_CONFIG_SEQ)); | |
1777 | ||
1778 | if (is_pex_by1 == 1) { | |
1779 | CHECK_STATUS(mv_seq_exec | |
1780 | (serdes_num, PEX_TX_CONFIG_SEQ2)); | |
1781 | CHECK_STATUS(mv_seq_exec | |
1782 | (serdes_num, PEX_TX_CONFIG_SEQ3)); | |
1783 | CHECK_STATUS(mv_seq_exec | |
1784 | (serdes_num, PEX_TX_CONFIG_SEQ1)); | |
1785 | } | |
1786 | udelay(20); | |
1787 | ||
1788 | break; | |
1789 | case USB3_HOST0: | |
1790 | case USB3_HOST1: | |
1791 | case USB3_DEVICE: | |
1792 | if (hws_ctrl_serdes_rev_get() == MV_SERDES_REV_1_2) { | |
1793 | CHECK_STATUS(serdes_pex_usb3_pipe_delay_w_a | |
1794 | (serdes_num, USB3)); | |
1795 | } | |
1796 | CHECK_STATUS(mv_seq_exec | |
1797 | (serdes_num, USB3_POWER_UP_SEQ)); | |
1798 | CHECK_STATUS(hws_ref_clock_set | |
1799 | (serdes_num, serdes_type, ref_clock)); | |
1800 | CHECK_STATUS(mv_seq_exec(serdes_num, speed_seq_id)); | |
1801 | if (serdes_type == USB3_DEVICE) { | |
1802 | CHECK_STATUS(mv_seq_exec | |
1803 | (serdes_num, | |
1804 | USB3_DEVICE_CONFIG_SEQ)); | |
1805 | } | |
1806 | CHECK_STATUS(mv_seq_exec | |
1807 | (serdes_num, USB3_ELECTRICAL_CONFIG_SEQ)); | |
1808 | CHECK_STATUS(mv_seq_exec | |
1809 | (serdes_num, USB3_TX_CONFIG_SEQ1)); | |
1810 | CHECK_STATUS(mv_seq_exec | |
1811 | (serdes_num, USB3_TX_CONFIG_SEQ2)); | |
1812 | CHECK_STATUS(mv_seq_exec | |
1813 | (serdes_num, USB3_TX_CONFIG_SEQ3)); | |
1814 | ||
1815 | udelay(10000); | |
1816 | break; | |
1817 | case SATA0: | |
1818 | case SATA1: | |
1819 | case SATA2: | |
1820 | case SATA3: | |
1821 | sata_idx = ((serdes_type == SATA0) || | |
1822 | (serdes_type == SATA1)) ? 0 : 1; | |
1823 | sata_port = ((serdes_type == SATA0) || | |
1824 | (serdes_type == SATA2)) ? 0 : 1; | |
1825 | ||
1826 | CHECK_STATUS(mv_seq_exec | |
1827 | (sata_idx, (sata_port == 0) ? | |
1828 | SATA_PORT_0_ONLY_POWER_UP_SEQ : | |
1829 | SATA_PORT_1_ONLY_POWER_UP_SEQ)); | |
1830 | CHECK_STATUS(mv_seq_exec | |
1831 | (serdes_num, SATA_POWER_UP_SEQ)); | |
1832 | CHECK_STATUS(hws_ref_clock_set | |
1833 | (serdes_num, serdes_type, ref_clock)); | |
1834 | CHECK_STATUS(mv_seq_exec(serdes_num, speed_seq_id)); | |
1835 | CHECK_STATUS(mv_seq_exec | |
1836 | (serdes_num, SATA_ELECTRICAL_CONFIG_SEQ)); | |
1837 | CHECK_STATUS(mv_seq_exec | |
1838 | (serdes_num, SATA_TX_CONFIG_SEQ1)); | |
1839 | CHECK_STATUS(mv_seq_exec | |
1840 | (sata_idx, (sata_port == 0) ? | |
1841 | SATA_PORT_0_ONLY_TX_CONFIG_SEQ : | |
1842 | SATA_PORT_1_ONLY_TX_CONFIG_SEQ)); | |
1843 | CHECK_STATUS(mv_seq_exec | |
1844 | (serdes_num, SATA_TX_CONFIG_SEQ2)); | |
1845 | ||
1846 | udelay(10000); | |
1847 | break; | |
1848 | case SGMII0: | |
1849 | case SGMII1: | |
1850 | case SGMII2: | |
1851 | CHECK_STATUS(mv_seq_exec | |
1852 | (serdes_num, SGMII_POWER_UP_SEQ)); | |
1853 | CHECK_STATUS(hws_ref_clock_set | |
1854 | (serdes_num, serdes_type, ref_clock)); | |
1855 | CHECK_STATUS(mv_seq_exec(serdes_num, speed_seq_id)); | |
1856 | CHECK_STATUS(mv_seq_exec | |
1857 | (serdes_num, SGMII_ELECTRICAL_CONFIG_SEQ)); | |
1858 | CHECK_STATUS(mv_seq_exec | |
1859 | (serdes_num, SGMII_TX_CONFIG_SEQ1)); | |
1860 | CHECK_STATUS(mv_seq_exec | |
1861 | (serdes_num, SGMII_TX_CONFIG_SEQ2)); | |
1862 | ||
1863 | /* GBE configuration */ | |
1864 | reg_data = reg_read(GBE_CONFIGURATION_REG); | |
1865 | /* write the SGMII index */ | |
1866 | reg_data |= 0x1 << (serdes_type - SGMII0); | |
1867 | reg_write(GBE_CONFIGURATION_REG, reg_data); | |
1868 | ||
1869 | break; | |
1870 | case QSGMII: | |
1871 | if (hws_ctrl_serdes_rev_get() < MV_SERDES_REV_2_1) | |
1872 | return MV_NOT_SUPPORTED; | |
1873 | ||
1874 | CHECK_STATUS(mv_seq_exec | |
1875 | (serdes_num, QSGMII_POWER_UP_SEQ)); | |
1876 | CHECK_STATUS(hws_ref_clock_set | |
1877 | (serdes_num, serdes_type, ref_clock)); | |
1878 | CHECK_STATUS(mv_seq_exec(serdes_num, speed_seq_id)); | |
1879 | CHECK_STATUS(mv_seq_exec | |
1880 | (serdes_num, | |
1881 | QSGMII_ELECTRICAL_CONFIG_SEQ)); | |
1882 | CHECK_STATUS(mv_seq_exec | |
1883 | (serdes_num, QSGMII_TX_CONFIG_SEQ1)); | |
1884 | CHECK_STATUS(mv_seq_exec | |
1885 | (serdes_num, QSGMII_TX_CONFIG_SEQ2)); | |
1886 | break; | |
1887 | case SGMII3: | |
1888 | case XAUI: | |
1889 | case RXAUI: | |
1890 | CHECK_STATUS(serdes_power_up_ctrl_ext | |
1891 | (serdes_num, serdes_power_up, serdes_type, | |
1892 | baud_rate, serdes_mode, ref_clock)); | |
1893 | break; | |
1894 | default: | |
1895 | DEBUG_INIT_S | |
1896 | ("serdes_power_up_ctrl: bad serdes_type parameter\n"); | |
1897 | return MV_BAD_PARAM; | |
1898 | } | |
1899 | } else { /* Serdes power down */ | |
1900 | DEBUG_INIT_FULL_S("serdes_power_up: executing power down.. "); | |
1901 | DEBUG_INIT_FULL_C("serdes num = ", serdes_num, 1); | |
1902 | ||
1903 | CHECK_STATUS(mv_seq_exec(serdes_num, SERDES_POWER_DOWN_SEQ)); | |
1904 | } | |
1905 | ||
1906 | DEBUG_INIT_FULL_C( | |
1907 | "serdes_power_up_ctrl ended successfully for serdes ", | |
1908 | serdes_num, 2); | |
1909 | ||
1910 | return MV_OK; | |
1911 | } | |
1912 | ||
490753ac | 1913 | int hws_update_serdes_phy_selectors(struct serdes_map *serdes_map, u8 count) |
edb47025 SR |
1914 | { |
1915 | u32 lane_data, idx, serdes_lane_hw_num, reg_data = 0; | |
1916 | enum serdes_type serdes_type; | |
1917 | enum serdes_mode serdes_mode; | |
1918 | u8 select_bit_off; | |
1919 | int is_pex_x4 = 0; | |
1920 | int updated_topology_print = 0; | |
1921 | ||
1922 | DEBUG_INIT_FULL_S("\n### hws_update_serdes_phy_selectors ###\n"); | |
1923 | DEBUG_INIT_FULL_S | |
1924 | ("Updating the COMMON PHYS SELECTORS register with the serdes types\n"); | |
1925 | ||
1926 | if (hws_ctrl_serdes_rev_get() == MV_SERDES_REV_1_2) | |
1927 | select_bit_off = 3; | |
1928 | else | |
1929 | select_bit_off = 4; | |
1930 | ||
1931 | /* | |
1932 | * Updating bits 0-17 in the COMMON PHYS SELECTORS register | |
1933 | * according to the serdes types | |
1934 | */ | |
490753ac KS |
1935 | for (idx = 0; idx < count; idx++) { |
1936 | serdes_type = serdes_map[idx].serdes_type; | |
1937 | serdes_mode = serdes_map[idx].serdes_mode; | |
edb47025 SR |
1938 | serdes_lane_hw_num = hws_get_physical_serdes_num(idx); |
1939 | ||
1940 | lane_data = | |
1941 | hws_serdes_get_phy_selector_val(serdes_lane_hw_num, | |
1942 | serdes_type); | |
1943 | ||
1944 | if (serdes_type == DEFAULT_SERDES) | |
1945 | continue; | |
1946 | ||
1947 | if (hws_serdes_topology_verify | |
1948 | (serdes_type, idx, serdes_mode) != MV_OK) { | |
490753ac | 1949 | serdes_map[idx].serdes_type = |
edb47025 SR |
1950 | DEFAULT_SERDES; |
1951 | printf("%s: SerDes lane #%d is disabled\n", __func__, | |
1952 | serdes_lane_hw_num); | |
1953 | updated_topology_print = 1; | |
1954 | continue; | |
1955 | } | |
1956 | ||
1957 | /* | |
1958 | * Checking if the board topology configuration includes | |
1959 | * PEXx4 - for the next step | |
1960 | */ | |
1961 | if ((serdes_mode == PEX_END_POINT_X4) || | |
1962 | (serdes_mode == PEX_ROOT_COMPLEX_X4)) { | |
1963 | /* update lane data to the 3 next SERDES lanes */ | |
1964 | lane_data = | |
1965 | common_phys_selectors_pex_by4_lanes | |
1966 | [serdes_lane_hw_num]; | |
1967 | if (serdes_type == PEX0) | |
1968 | is_pex_x4 = 1; | |
1969 | } | |
1970 | ||
1971 | if (lane_data == NA) { | |
1972 | printf | |
1973 | ("%s: Warning: SerDes lane #%d and type %d are not supported together\n", | |
1974 | __func__, serdes_lane_hw_num, serdes_mode); | |
490753ac | 1975 | serdes_map[idx].serdes_type = DEFAULT_SERDES; |
edb47025 SR |
1976 | printf("%s: SerDes lane #%d is disabled\n", __func__, |
1977 | serdes_lane_hw_num); | |
1978 | continue; | |
1979 | } | |
1980 | ||
1981 | /* | |
1982 | * Updating the data that will be written to | |
1983 | * COMMON_PHYS_SELECTORS_REG | |
1984 | */ | |
1985 | reg_data |= (lane_data << | |
1986 | (select_bit_off * serdes_lane_hw_num)); | |
1987 | } | |
1988 | ||
1989 | /* | |
1990 | * Check that number of used lanes for XAUI and RXAUI | |
1991 | * (if used) is right | |
1992 | */ | |
1993 | hws_serdes_xaui_topology_verify(); | |
1994 | ||
1995 | /* Print topology */ | |
1996 | if (updated_topology_print) | |
490753ac | 1997 | print_topology_details(serdes_map, count); |
edb47025 SR |
1998 | |
1999 | /* | |
2000 | * Updating the PEXx4 Enable bit in the COMMON PHYS SELECTORS | |
2001 | * register for PEXx4 mode | |
2002 | */ | |
2003 | reg_data |= (is_pex_x4 == 1) ? (0x1 << PEX_X4_ENABLE_OFFS) : 0; | |
2004 | ||
2005 | /* Updating the COMMON PHYS SELECTORS register */ | |
2006 | reg_write(COMMON_PHYS_SELECTORS_REG, reg_data); | |
2007 | ||
2008 | return MV_OK; | |
2009 | } | |
2010 | ||
2011 | int hws_ref_clock_set(u32 serdes_num, enum serdes_type serdes_type, | |
2012 | enum ref_clock ref_clock) | |
2013 | { | |
2014 | u32 data1 = 0, data2 = 0, data3 = 0, reg_data; | |
2015 | ||
2016 | DEBUG_INIT_FULL_S("\n### hws_ref_clock_set ###\n"); | |
2017 | ||
2018 | if (hws_is_serdes_active(serdes_num) != 1) { | |
2019 | printf("%s: SerDes lane #%d is not Active\n", __func__, | |
2020 | serdes_num); | |
2021 | return MV_BAD_PARAM; | |
2022 | } | |
2023 | ||
2024 | switch (serdes_type) { | |
2025 | case PEX0: | |
2026 | case PEX1: | |
2027 | case PEX2: | |
2028 | case PEX3: | |
2029 | switch (ref_clock) { | |
2030 | case REF_CLOCK_25MHZ: | |
2031 | CHECK_STATUS(mv_seq_exec | |
2032 | (serdes_num, | |
2033 | PEX_CONFIG_REF_CLOCK_25MHZ_SEQ)); | |
2034 | return MV_OK; | |
2035 | case REF_CLOCK_100MHZ: | |
2036 | CHECK_STATUS(mv_seq_exec | |
2037 | (serdes_num, | |
2038 | PEX_CONFIG_REF_CLOCK_100MHZ_SEQ)); | |
2039 | return MV_OK; | |
2040 | #ifdef CONFIG_ARMADA_39X | |
2041 | case REF_CLOCK_40MHZ: | |
2042 | CHECK_STATUS(mv_seq_exec | |
2043 | (serdes_num, | |
2044 | PEX_CONFIG_REF_CLOCK_40MHZ_SEQ)); | |
2045 | return MV_OK; | |
2046 | #endif | |
2047 | default: | |
2048 | printf | |
2049 | ("%s: Error: ref_clock %d for SerDes lane #%d, type %d is not supported\n", | |
2050 | __func__, ref_clock, serdes_num, serdes_type); | |
2051 | return MV_BAD_PARAM; | |
2052 | } | |
2053 | case USB3_HOST0: | |
2054 | case USB3_HOST1: | |
2055 | case USB3_DEVICE: | |
2056 | if (ref_clock == REF_CLOCK_25MHZ) { | |
2057 | data1 = POWER_AND_PLL_CTRL_REG_25MHZ_VAL_2; | |
2058 | data2 = GLOBAL_PM_CTRL_REG_25MHZ_VAL; | |
2059 | data3 = LANE_CFG4_REG_25MHZ_VAL; | |
2060 | } else if (ref_clock == REF_CLOCK_40MHZ) { | |
2061 | data1 = POWER_AND_PLL_CTRL_REG_40MHZ_VAL; | |
2062 | data2 = GLOBAL_PM_CTRL_REG_40MHZ_VAL; | |
2063 | data3 = LANE_CFG4_REG_40MHZ_VAL; | |
2064 | } else { | |
2065 | printf | |
2066 | ("hws_ref_clock_set: ref clock is not valid for serdes type %d\n", | |
2067 | serdes_type); | |
2068 | return MV_BAD_PARAM; | |
2069 | } | |
2070 | break; | |
2071 | case SATA0: | |
2072 | case SATA1: | |
2073 | case SATA2: | |
2074 | case SATA3: | |
2075 | case SGMII0: | |
2076 | case SGMII1: | |
2077 | case SGMII2: | |
2078 | case QSGMII: | |
2079 | if (ref_clock == REF_CLOCK_25MHZ) { | |
2080 | data1 = POWER_AND_PLL_CTRL_REG_25MHZ_VAL_1; | |
2081 | } else if (ref_clock == REF_CLOCK_40MHZ) { | |
2082 | data1 = POWER_AND_PLL_CTRL_REG_40MHZ_VAL; | |
2083 | } else { | |
2084 | printf | |
2085 | ("hws_ref_clock_set: ref clock is not valid for serdes type %d\n", | |
2086 | serdes_type); | |
2087 | return MV_BAD_PARAM; | |
2088 | } | |
2089 | break; | |
2090 | #ifdef CONFIG_ARMADA_39X | |
2091 | case SGMII3: | |
2092 | case XAUI: | |
2093 | case RXAUI: | |
2094 | if (ref_clock == REF_CLOCK_25MHZ) { | |
2095 | data1 = POWER_AND_PLL_CTRL_REG_25MHZ_VAL_1; | |
2096 | } else if (ref_clock == REF_CLOCK_40MHZ) { | |
2097 | data1 = POWER_AND_PLL_CTRL_REG_40MHZ_VAL; | |
2098 | } else { | |
2099 | printf | |
2100 | ("hws_ref_clock_set: ref clock is not valid for serdes type %d\n", | |
2101 | serdes_type); | |
2102 | return MV_BAD_PARAM; | |
2103 | } | |
2104 | break; | |
2105 | #endif | |
2106 | default: | |
2107 | DEBUG_INIT_S("hws_ref_clock_set: not supported serdes type\n"); | |
2108 | return MV_BAD_PARAM; | |
2109 | } | |
2110 | ||
2111 | /* | |
2112 | * Write the ref_clock to relevant SELECT_REF_CLOCK_REG bits and | |
2113 | * offset | |
2114 | */ | |
2115 | reg_data = reg_read(POWER_AND_PLL_CTRL_REG + | |
2116 | SERDES_REGS_LANE_BASE_OFFSET(serdes_num)); | |
2117 | reg_data &= POWER_AND_PLL_CTRL_REG_MASK; | |
2118 | reg_data |= data1; | |
2119 | reg_write(POWER_AND_PLL_CTRL_REG + | |
2120 | SERDES_REGS_LANE_BASE_OFFSET(serdes_num), reg_data); | |
2121 | ||
2122 | if ((serdes_type == USB3_HOST0) || (serdes_type == USB3_HOST1) || | |
2123 | (serdes_type == USB3_DEVICE)) { | |
2124 | reg_data = reg_read(GLOBAL_PM_CTRL + | |
2125 | SERDES_REGS_LANE_BASE_OFFSET(serdes_num)); | |
2126 | reg_data &= GLOBAL_PM_CTRL_REG_MASK; | |
2127 | reg_data |= data2; | |
2128 | reg_write(GLOBAL_PM_CTRL + | |
2129 | SERDES_REGS_LANE_BASE_OFFSET(serdes_num), reg_data); | |
2130 | ||
2131 | reg_data = reg_read(LANE_CFG4_REG + | |
2132 | SERDES_REGS_LANE_BASE_OFFSET(serdes_num)); | |
2133 | reg_data &= LANE_CFG4_REG_MASK; | |
2134 | reg_data |= data3; | |
2135 | reg_write(LANE_CFG4_REG + | |
2136 | SERDES_REGS_LANE_BASE_OFFSET(serdes_num), reg_data); | |
2137 | } | |
2138 | ||
2139 | return MV_OK; | |
2140 | } | |
2141 | ||
2142 | /* | |
2143 | * hws_pex_tx_config_seq - | |
2144 | * | |
2145 | * DESCRIPTION: Set PEX_TX_CONFIG_SEQ sequence init for PEXx4 mode | |
2146 | * INPUT: serdes_map - The board topology map | |
2147 | * OUTPUT: None | |
2148 | * RETURNS: MV_OK - for success | |
2149 | * MV_BAD_PARAM - for fail | |
2150 | */ | |
490753ac | 2151 | int hws_pex_tx_config_seq(const struct serdes_map *serdes_map, u8 count) |
edb47025 SR |
2152 | { |
2153 | enum serdes_mode serdes_mode; | |
2154 | u32 serdes_lane_id, serdes_lane_hw_num; | |
2155 | ||
2156 | DEBUG_INIT_FULL_S("\n### hws_pex_tx_config_seq ###\n"); | |
2157 | ||
2158 | /* | |
2159 | * For PEXx4: the pex_and_usb3_tx_config_params1/2/3 | |
2160 | * configurations should run by setting each sequence for | |
2161 | * all 4 lanes. | |
2162 | */ | |
2163 | ||
2164 | /* relese pipe soft reset for all lanes */ | |
490753ac | 2165 | for (serdes_lane_id = 0; serdes_lane_id < count; serdes_lane_id++) { |
edb47025 SR |
2166 | serdes_mode = serdes_map[serdes_lane_id].serdes_mode; |
2167 | serdes_lane_hw_num = | |
2168 | hws_get_physical_serdes_num(serdes_lane_id); | |
2169 | ||
2170 | if ((serdes_mode == PEX_ROOT_COMPLEX_X4) || | |
2171 | (serdes_mode == PEX_END_POINT_X4)) { | |
2172 | CHECK_STATUS(mv_seq_exec | |
2173 | (serdes_lane_hw_num, PEX_TX_CONFIG_SEQ1)); | |
2174 | } | |
2175 | } | |
2176 | ||
2177 | /* set phy soft reset for all lanes */ | |
490753ac | 2178 | for (serdes_lane_id = 0; serdes_lane_id < count; serdes_lane_id++) { |
edb47025 SR |
2179 | serdes_mode = serdes_map[serdes_lane_id].serdes_mode; |
2180 | serdes_lane_hw_num = | |
2181 | hws_get_physical_serdes_num(serdes_lane_id); | |
2182 | if ((serdes_mode == PEX_ROOT_COMPLEX_X4) || | |
2183 | (serdes_mode == PEX_END_POINT_X4)) { | |
2184 | CHECK_STATUS(mv_seq_exec | |
2185 | (serdes_lane_hw_num, PEX_TX_CONFIG_SEQ2)); | |
2186 | } | |
2187 | } | |
2188 | ||
2189 | /* set phy soft reset for all lanes */ | |
490753ac | 2190 | for (serdes_lane_id = 0; serdes_lane_id < count; serdes_lane_id++) { |
edb47025 SR |
2191 | serdes_mode = serdes_map[serdes_lane_id].serdes_mode; |
2192 | serdes_lane_hw_num = | |
2193 | hws_get_physical_serdes_num(serdes_lane_id); | |
2194 | if ((serdes_mode == PEX_ROOT_COMPLEX_X4) || | |
2195 | (serdes_mode == PEX_END_POINT_X4)) { | |
2196 | CHECK_STATUS(mv_seq_exec | |
2197 | (serdes_lane_hw_num, PEX_TX_CONFIG_SEQ3)); | |
2198 | } | |
2199 | } | |
2200 | ||
2201 | return MV_OK; | |
2202 | } |