1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* Microchip Sparx5 Switch SerDes driver |
3 | * |
4 | * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries. |
5 | * |
6 | * The Sparx5 Chip Register Model can be browsed at this location: |
7 | * https://github.com/microchip-ung/sparx-5_reginfo |
8 | * and the datasheet is available here: |
9 | * https://ww1.microchip.com/downloads/en/DeviceDoc/SparX-5_Family_L2L3_Enterprise_10G_Ethernet_Switches_Datasheet_00003822B.pdf |
10 | */ |
11 | #include <linux/printk.h> |
12 | #include <linux/module.h> |
13 | #include <linux/device.h> |
14 | #include <linux/netdevice.h> |
15 | #include <linux/platform_device.h> |
16 | #include <linux/of.h> |
17 | #include <linux/io.h> |
18 | #include <linux/clk.h> |
19 | #include <linux/phy.h> |
20 | #include <linux/phy/phy.h> |
21 | |
22 | #include "sparx5_serdes.h" |
23 | |
24 | #define SPX5_CMU_MAX 14 |
25 | |
26 | #define SPX5_SERDES_10G_START 13 |
27 | #define SPX5_SERDES_25G_START 25 |
28 | #define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START |
29 | |
30 | /* Optimal power settings from GUC */ |
31 | #define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c |
32 | |
33 | enum sparx5_10g28cmu_mode { |
34 | SPX5_SD10G28_CMU_MAIN = 0, |
35 | SPX5_SD10G28_CMU_AUX1 = 1, |
36 | SPX5_SD10G28_CMU_AUX2 = 3, |
37 | SPX5_SD10G28_CMU_NONE = 4, |
38 | SPX5_SD10G28_CMU_MAX, |
39 | }; |
40 | |
41 | enum sparx5_sd25g28_mode_preset_type { |
42 | SPX5_SD25G28_MODE_PRESET_25000, |
43 | SPX5_SD25G28_MODE_PRESET_10000, |
44 | SPX5_SD25G28_MODE_PRESET_5000, |
45 | SPX5_SD25G28_MODE_PRESET_SD_2G5, |
46 | SPX5_SD25G28_MODE_PRESET_1000BASEX, |
47 | }; |
48 | |
49 | enum sparx5_sd10g28_mode_preset_type { |
50 | SPX5_SD10G28_MODE_PRESET_10000, |
51 | SPX5_SD10G28_MODE_PRESET_SFI_5000_6G, |
52 | SPX5_SD10G28_MODE_PRESET_SFI_5000_10G, |
53 | SPX5_SD10G28_MODE_PRESET_QSGMII, |
54 | SPX5_SD10G28_MODE_PRESET_SD_2G5, |
55 | SPX5_SD10G28_MODE_PRESET_1000BASEX, |
56 | }; |
57 | |
58 | struct sparx5_serdes_io_resource { |
59 | enum sparx5_serdes_target id; |
60 | phys_addr_t offset; |
61 | }; |
62 | |
63 | struct sparx5_sd25g28_mode_preset { |
64 | u8 bitwidth; |
65 | u8 tx_pre_div; |
66 | u8 fifo_ck_div; |
67 | u8 pre_divsel; |
68 | u8 vco_div_mode; |
69 | u8 sel_div; |
70 | u8 ck_bitwidth; |
71 | u8 subrate; |
72 | u8 com_txcal_en; |
73 | u8 com_tx_reserve_msb; |
74 | u8 com_tx_reserve_lsb; |
75 | u8 cfg_itx_ipcml_base; |
76 | u8 tx_reserve_lsb; |
77 | u8 tx_reserve_msb; |
78 | u8 bw; |
79 | u8 rxterm; |
80 | u8 dfe_tap; |
81 | u8 dfe_enable; |
82 | bool txmargin; |
83 | u8 cfg_ctle_rstn; |
84 | u8 r_dfe_rstn; |
85 | u8 cfg_pi_bw_3_0; |
86 | u8 tx_tap_dly; |
87 | u8 tx_tap_adv; |
88 | }; |
89 | |
90 | struct sparx5_sd25g28_media_preset { |
91 | u8 cfg_eq_c_force_3_0; |
92 | u8 cfg_vga_ctrl_byp_4_0; |
93 | u8 cfg_eq_r_force_3_0; |
94 | u8 cfg_en_adv; |
95 | u8 cfg_en_main; |
96 | u8 cfg_en_dly; |
97 | u8 cfg_tap_adv_3_0; |
98 | u8 cfg_tap_main; |
99 | u8 cfg_tap_dly_4_0; |
100 | u8 cfg_alos_thr_2_0; |
101 | }; |
102 | |
103 | struct sparx5_sd25g28_args { |
104 | u8 if_width; /* UDL if-width: 10/16/20/32/64 */ |
105 | bool skip_cmu_cfg:1; /* Enable/disable CMU cfg */ |
106 | enum sparx5_10g28cmu_mode cmu_sel; /* Device/Mode serdes uses */ |
107 | bool no_pwrcycle:1; /* Omit initial power-cycle */ |
108 | bool txinvert:1; /* Enable inversion of output data */ |
109 | bool rxinvert:1; /* Enable inversion of input data */ |
110 | u16 txswing; /* Set output level */ |
111 | u8 rate; /* Rate of network interface */ |
112 | u8 pi_bw_gen1; |
113 | u8 duty_cycle; /* Set output level to half/full */ |
114 | bool mute:1; /* Mute Output Buffer */ |
115 | bool reg_rst:1; |
116 | u8 com_pll_reserve; |
117 | }; |
118 | |
119 | struct sparx5_sd25g28_params { |
120 | u8 reg_rst; |
121 | u8 cfg_jc_byp; |
122 | u8 cfg_common_reserve_7_0; |
123 | u8 r_reg_manual; |
124 | u8 r_d_width_ctrl_from_hwt; |
125 | u8 r_d_width_ctrl_2_0; |
126 | u8 r_txfifo_ck_div_pmad_2_0; |
127 | u8 r_rxfifo_ck_div_pmad_2_0; |
128 | u8 cfg_pll_lol_set; |
129 | u8 cfg_vco_div_mode_1_0; |
130 | u8 cfg_pre_divsel_1_0; |
131 | u8 cfg_sel_div_3_0; |
132 | u8 cfg_vco_start_code_3_0; |
133 | u8 cfg_pma_tx_ck_bitwidth_2_0; |
134 | u8 cfg_tx_prediv_1_0; |
135 | u8 cfg_rxdiv_sel_2_0; |
136 | u8 cfg_tx_subrate_2_0; |
137 | u8 cfg_rx_subrate_2_0; |
138 | u8 r_multi_lane_mode; |
139 | u8 cfg_cdrck_en; |
140 | u8 cfg_dfeck_en; |
141 | u8 cfg_dfe_pd; |
142 | u8 cfg_dfedmx_pd; |
143 | u8 cfg_dfetap_en_5_1; |
144 | u8 cfg_dmux_pd; |
145 | u8 cfg_dmux_clk_pd; |
146 | u8 cfg_erramp_pd; |
147 | u8 cfg_pi_dfe_en; |
148 | u8 cfg_pi_en; |
149 | u8 cfg_pd_ctle; |
150 | u8 cfg_summer_en; |
151 | u8 cfg_pmad_ck_pd; |
152 | u8 cfg_pd_clk; |
153 | u8 cfg_pd_cml; |
154 | u8 cfg_pd_driver; |
155 | u8 cfg_rx_reg_pu; |
156 | u8 cfg_pd_rms_det; |
157 | u8 cfg_dcdr_pd; |
158 | u8 cfg_ecdr_pd; |
159 | u8 cfg_pd_sq; |
160 | u8 cfg_itx_ipdriver_base_2_0; |
161 | u8 cfg_tap_dly_4_0; |
162 | u8 cfg_tap_main; |
163 | u8 cfg_en_main; |
164 | u8 cfg_tap_adv_3_0; |
165 | u8 cfg_en_adv; |
166 | u8 cfg_en_dly; |
167 | u8 cfg_iscan_en; |
168 | u8 l1_pcs_en_fast_iscan; |
169 | u8 l0_cfg_bw_1_0; |
170 | u8 l0_cfg_txcal_en; |
171 | u8 cfg_en_dummy; |
172 | u8 cfg_pll_reserve_3_0; |
173 | u8 l0_cfg_tx_reserve_15_8; |
174 | u8 l0_cfg_tx_reserve_7_0; |
175 | u8 cfg_tx_reserve_15_8; |
176 | u8 cfg_tx_reserve_7_0; |
177 | u8 cfg_bw_1_0; |
178 | u8 cfg_txcal_man_en; |
179 | u8 cfg_phase_man_4_0; |
180 | u8 cfg_quad_man_1_0; |
181 | u8 cfg_txcal_shift_code_5_0; |
182 | u8 cfg_txcal_valid_sel_3_0; |
183 | u8 cfg_txcal_en; |
184 | u8 cfg_cdr_kf_2_0; |
185 | u8 cfg_cdr_m_7_0; |
186 | u8 cfg_pi_bw_3_0; |
187 | u8 cfg_pi_steps_1_0; |
188 | u8 cfg_dis_2ndorder; |
189 | u8 cfg_ctle_rstn; |
190 | u8 r_dfe_rstn; |
191 | u8 cfg_alos_thr_2_0; |
192 | u8 cfg_itx_ipcml_base_1_0; |
193 | u8 cfg_rx_reserve_7_0; |
194 | u8 cfg_rx_reserve_15_8; |
195 | u8 cfg_rxterm_2_0; |
196 | u8 cfg_fom_selm; |
197 | u8 cfg_rx_sp_ctle_1_0; |
198 | u8 cfg_isel_ctle_1_0; |
199 | u8 cfg_vga_ctrl_byp_4_0; |
200 | u8 cfg_vga_byp; |
201 | u8 cfg_agc_adpt_byp; |
202 | u8 cfg_eqr_byp; |
203 | u8 cfg_eqr_force_3_0; |
204 | u8 cfg_eqc_force_3_0; |
205 | u8 cfg_sum_setcm_en; |
206 | u8 cfg_init_pos_iscan_6_0; |
207 | u8 cfg_init_pos_ipi_6_0; |
208 | u8 cfg_dfedig_m_2_0; |
209 | u8 cfg_en_dfedig; |
210 | u8 cfg_pi_DFE_en; |
211 | u8 cfg_tx2rx_lp_en; |
212 | u8 cfg_txlb_en; |
213 | u8 cfg_rx2tx_lp_en; |
214 | u8 cfg_rxlb_en; |
215 | u8 r_tx_pol_inv; |
216 | u8 r_rx_pol_inv; |
217 | }; |
218 | |
219 | struct sparx5_sd10g28_media_preset { |
220 | u8 cfg_en_adv; |
221 | u8 cfg_en_main; |
222 | u8 cfg_en_dly; |
223 | u8 cfg_tap_adv_3_0; |
224 | u8 cfg_tap_main; |
225 | u8 cfg_tap_dly_4_0; |
226 | u8 cfg_vga_ctrl_3_0; |
227 | u8 cfg_vga_cp_2_0; |
228 | u8 cfg_eq_res_3_0; |
229 | u8 cfg_eq_r_byp; |
230 | u8 cfg_eq_c_force_3_0; |
231 | u8 cfg_alos_thr_3_0; |
232 | }; |
233 | |
234 | struct sparx5_sd10g28_mode_preset { |
235 | u8 bwidth; /* interface width: 10/16/20/32/64 */ |
236 | enum sparx5_10g28cmu_mode cmu_sel; /* Device/Mode serdes uses */ |
237 | u8 rate; /* Rate of network interface */ |
238 | u8 dfe_tap; |
239 | u8 dfe_enable; |
240 | u8 pi_bw_gen1; |
241 | u8 duty_cycle; /* Set output level to half/full */ |
242 | }; |
243 | |
244 | struct sparx5_sd10g28_args { |
245 | bool skip_cmu_cfg:1; /* Enable/disable CMU cfg */ |
246 | bool no_pwrcycle:1; /* Omit initial power-cycle */ |
247 | bool txinvert:1; /* Enable inversion of output data */ |
248 | bool rxinvert:1; /* Enable inversion of input data */ |
249 | bool txmargin:1; /* Set output level to half/full */ |
250 | u16 txswing; /* Set output level */ |
251 | bool mute:1; /* Mute Output Buffer */ |
252 | bool is_6g:1; |
253 | bool reg_rst:1; |
254 | }; |
255 | |
256 | struct sparx5_sd10g28_params { |
257 | u8 cmu_sel; |
258 | u8 is_6g; |
259 | u8 skip_cmu_cfg; |
260 | u8 cfg_lane_reserve_7_0; |
261 | u8 cfg_ssc_rtl_clk_sel; |
262 | u8 cfg_lane_reserve_15_8; |
263 | u8 cfg_txrate_1_0; |
264 | u8 cfg_rxrate_1_0; |
265 | u8 r_d_width_ctrl_2_0; |
266 | u8 cfg_pma_tx_ck_bitwidth_2_0; |
267 | u8 cfg_rxdiv_sel_2_0; |
268 | u8 r_pcs2pma_phymode_4_0; |
269 | u8 cfg_lane_id_2_0; |
270 | u8 cfg_cdrck_en; |
271 | u8 cfg_dfeck_en; |
272 | u8 cfg_dfe_pd; |
273 | u8 cfg_dfetap_en_5_1; |
274 | u8 cfg_erramp_pd; |
275 | u8 cfg_pi_DFE_en; |
276 | u8 cfg_pi_en; |
277 | u8 cfg_pd_ctle; |
278 | u8 cfg_summer_en; |
279 | u8 cfg_pd_rx_cktree; |
280 | u8 cfg_pd_clk; |
281 | u8 cfg_pd_cml; |
282 | u8 cfg_pd_driver; |
283 | u8 cfg_rx_reg_pu; |
284 | u8 cfg_d_cdr_pd; |
285 | u8 cfg_pd_sq; |
286 | u8 cfg_rxdet_en; |
287 | u8 cfg_rxdet_str; |
288 | u8 r_multi_lane_mode; |
289 | u8 cfg_en_adv; |
290 | u8 cfg_en_main; |
291 | u8 cfg_en_dly; |
292 | u8 cfg_tap_adv_3_0; |
293 | u8 cfg_tap_main; |
294 | u8 cfg_tap_dly_4_0; |
295 | u8 cfg_vga_ctrl_3_0; |
296 | u8 cfg_vga_cp_2_0; |
297 | u8 cfg_eq_res_3_0; |
298 | u8 cfg_eq_r_byp; |
299 | u8 cfg_eq_c_force_3_0; |
300 | u8 cfg_en_dfedig; |
301 | u8 cfg_sum_setcm_en; |
302 | u8 cfg_en_preemph; |
303 | u8 cfg_itx_ippreemp_base_1_0; |
304 | u8 cfg_itx_ipdriver_base_2_0; |
305 | u8 cfg_ibias_tune_reserve_5_0; |
306 | u8 cfg_txswing_half; |
307 | u8 cfg_dis_2nd_order; |
308 | u8 cfg_rx_ssc_lh; |
309 | u8 cfg_pi_floop_steps_1_0; |
310 | u8 cfg_pi_ext_dac_23_16; |
311 | u8 cfg_pi_ext_dac_15_8; |
312 | u8 cfg_iscan_ext_dac_7_0; |
313 | u8 cfg_cdr_kf_gen1_2_0; |
314 | u8 cfg_cdr_kf_gen2_2_0; |
315 | u8 cfg_cdr_kf_gen3_2_0; |
316 | u8 cfg_cdr_kf_gen4_2_0; |
317 | u8 r_cdr_m_gen1_7_0; |
318 | u8 cfg_pi_bw_gen1_3_0; |
319 | u8 cfg_pi_bw_gen2; |
320 | u8 cfg_pi_bw_gen3; |
321 | u8 cfg_pi_bw_gen4; |
322 | u8 cfg_pi_ext_dac_7_0; |
323 | u8 cfg_pi_steps; |
324 | u8 cfg_mp_max_3_0; |
325 | u8 cfg_rstn_dfedig; |
326 | u8 cfg_alos_thr_3_0; |
327 | u8 cfg_predrv_slewrate_1_0; |
328 | u8 cfg_itx_ipcml_base_1_0; |
329 | u8 cfg_ip_pre_base_1_0; |
330 | u8 r_cdr_m_gen2_7_0; |
331 | u8 r_cdr_m_gen3_7_0; |
332 | u8 r_cdr_m_gen4_7_0; |
333 | u8 r_en_auto_cdr_rstn; |
334 | u8 cfg_oscal_afe; |
335 | u8 cfg_pd_osdac_afe; |
336 | u8 cfg_resetb_oscal_afe[2]; |
337 | u8 cfg_center_spreading; |
338 | u8 cfg_m_cnt_maxval_4_0; |
339 | u8 cfg_ncnt_maxval_7_0; |
340 | u8 cfg_ncnt_maxval_10_8; |
341 | u8 cfg_ssc_en; |
342 | u8 cfg_tx2rx_lp_en; |
343 | u8 cfg_txlb_en; |
344 | u8 cfg_rx2tx_lp_en; |
345 | u8 cfg_rxlb_en; |
346 | u8 r_tx_pol_inv; |
347 | u8 r_rx_pol_inv; |
348 | u8 fx_100; |
349 | }; |
350 | |
351 | static struct sparx5_sd25g28_media_preset media_presets_25g[] = { |
352 | { /* ETH_MEDIA_DEFAULT */ |
353 | .cfg_en_adv = 0, |
354 | .cfg_en_main = 1, |
355 | .cfg_en_dly = 0, |
356 | .cfg_tap_adv_3_0 = 0, |
357 | .cfg_tap_main = 1, |
358 | .cfg_tap_dly_4_0 = 0, |
359 | .cfg_eq_c_force_3_0 = 0xf, |
360 | .cfg_vga_ctrl_byp_4_0 = 4, |
361 | .cfg_eq_r_force_3_0 = 12, |
362 | .cfg_alos_thr_2_0 = 7, |
363 | }, |
364 | { /* ETH_MEDIA_SR */ |
365 | .cfg_en_adv = 1, |
366 | .cfg_en_main = 1, |
367 | .cfg_en_dly = 1, |
368 | .cfg_tap_adv_3_0 = 0, |
369 | .cfg_tap_main = 1, |
370 | .cfg_tap_dly_4_0 = 0x10, |
371 | .cfg_eq_c_force_3_0 = 0xf, |
372 | .cfg_vga_ctrl_byp_4_0 = 8, |
373 | .cfg_eq_r_force_3_0 = 4, |
374 | .cfg_alos_thr_2_0 = 0, |
375 | }, |
376 | { /* ETH_MEDIA_DAC */ |
377 | .cfg_en_adv = 0, |
378 | .cfg_en_main = 1, |
379 | .cfg_en_dly = 0, |
380 | .cfg_tap_adv_3_0 = 0, |
381 | .cfg_tap_main = 1, |
382 | .cfg_tap_dly_4_0 = 0, |
383 | .cfg_eq_c_force_3_0 = 0xf, |
384 | .cfg_vga_ctrl_byp_4_0 = 8, |
385 | .cfg_eq_r_force_3_0 = 0xc, |
386 | .cfg_alos_thr_2_0 = 0, |
387 | }, |
388 | }; |
389 | |
390 | static struct sparx5_sd25g28_mode_preset mode_presets_25g[] = { |
391 | { /* SPX5_SD25G28_MODE_PRESET_25000 */ |
392 | .bitwidth = 40, |
393 | .tx_pre_div = 0, |
394 | .fifo_ck_div = 0, |
395 | .pre_divsel = 1, |
396 | .vco_div_mode = 0, |
397 | .sel_div = 15, |
398 | .ck_bitwidth = 3, |
399 | .subrate = 0, |
400 | .com_txcal_en = 0, |
401 | .com_tx_reserve_msb = (0x26 << 1), |
402 | .com_tx_reserve_lsb = 0xf0, |
403 | .cfg_itx_ipcml_base = 0, |
404 | .tx_reserve_msb = 0xcc, |
405 | .tx_reserve_lsb = 0xfe, |
406 | .bw = 3, |
407 | .rxterm = 0, |
408 | .dfe_enable = 1, |
409 | .dfe_tap = 0x1f, |
410 | .txmargin = 1, |
411 | .cfg_ctle_rstn = 1, |
412 | .r_dfe_rstn = 1, |
413 | .cfg_pi_bw_3_0 = 0, |
414 | .tx_tap_dly = 8, |
415 | .tx_tap_adv = 0xc, |
416 | }, |
417 | { /* SPX5_SD25G28_MODE_PRESET_10000 */ |
418 | .bitwidth = 64, |
419 | .tx_pre_div = 0, |
420 | .fifo_ck_div = 2, |
421 | .pre_divsel = 0, |
422 | .vco_div_mode = 1, |
423 | .sel_div = 9, |
424 | .ck_bitwidth = 0, |
425 | .subrate = 0, |
426 | .com_txcal_en = 1, |
427 | .com_tx_reserve_msb = (0x20 << 1), |
428 | .com_tx_reserve_lsb = 0x40, |
429 | .cfg_itx_ipcml_base = 0, |
430 | .tx_reserve_msb = 0x4c, |
431 | .tx_reserve_lsb = 0x44, |
432 | .bw = 3, |
433 | .cfg_pi_bw_3_0 = 0, |
434 | .rxterm = 3, |
435 | .dfe_enable = 1, |
436 | .dfe_tap = 0x1f, |
437 | .txmargin = 0, |
438 | .cfg_ctle_rstn = 1, |
439 | .r_dfe_rstn = 1, |
440 | .tx_tap_dly = 0, |
441 | .tx_tap_adv = 0, |
442 | }, |
443 | { /* SPX5_SD25G28_MODE_PRESET_5000 */ |
444 | .bitwidth = 64, |
445 | .tx_pre_div = 0, |
446 | .fifo_ck_div = 2, |
447 | .pre_divsel = 0, |
448 | .vco_div_mode = 2, |
449 | .sel_div = 9, |
450 | .ck_bitwidth = 0, |
451 | .subrate = 0, |
452 | .com_txcal_en = 1, |
453 | .com_tx_reserve_msb = (0x20 << 1), |
454 | .com_tx_reserve_lsb = 0, |
455 | .cfg_itx_ipcml_base = 0, |
456 | .tx_reserve_msb = 0xe, |
457 | .tx_reserve_lsb = 0x80, |
458 | .bw = 0, |
459 | .rxterm = 0, |
460 | .cfg_pi_bw_3_0 = 6, |
461 | .dfe_enable = 0, |
462 | .dfe_tap = 0, |
463 | .tx_tap_dly = 0, |
464 | .tx_tap_adv = 0, |
465 | }, |
466 | { /* SPX5_SD25G28_MODE_PRESET_SD_2G5 */ |
467 | .bitwidth = 10, |
468 | .tx_pre_div = 0, |
469 | .fifo_ck_div = 0, |
470 | .pre_divsel = 0, |
471 | .vco_div_mode = 1, |
472 | .sel_div = 6, |
473 | .ck_bitwidth = 3, |
474 | .subrate = 2, |
475 | .com_txcal_en = 1, |
476 | .com_tx_reserve_msb = (0x26 << 1), |
477 | .com_tx_reserve_lsb = (0xf << 4), |
478 | .cfg_itx_ipcml_base = 2, |
479 | .tx_reserve_msb = 0x8, |
480 | .tx_reserve_lsb = 0x8a, |
481 | .bw = 0, |
482 | .cfg_pi_bw_3_0 = 0, |
483 | .rxterm = (1 << 2), |
484 | .dfe_enable = 0, |
485 | .dfe_tap = 0, |
486 | .tx_tap_dly = 0, |
487 | .tx_tap_adv = 0, |
488 | }, |
489 | { /* SPX5_SD25G28_MODE_PRESET_1000BASEX */ |
490 | .bitwidth = 10, |
491 | .tx_pre_div = 0, |
492 | .fifo_ck_div = 1, |
493 | .pre_divsel = 0, |
494 | .vco_div_mode = 1, |
495 | .sel_div = 8, |
496 | .ck_bitwidth = 3, |
497 | .subrate = 3, |
498 | .com_txcal_en = 1, |
499 | .com_tx_reserve_msb = (0x26 << 1), |
500 | .com_tx_reserve_lsb = 0xf0, |
501 | .cfg_itx_ipcml_base = 0, |
502 | .tx_reserve_msb = 0x8, |
503 | .tx_reserve_lsb = 0xce, |
504 | .bw = 0, |
505 | .rxterm = 0, |
506 | .cfg_pi_bw_3_0 = 0, |
507 | .dfe_enable = 0, |
508 | .dfe_tap = 0, |
509 | .tx_tap_dly = 0, |
510 | .tx_tap_adv = 0, |
511 | }, |
512 | }; |
513 | |
514 | static struct sparx5_sd10g28_media_preset media_presets_10g[] = { |
515 | { /* ETH_MEDIA_DEFAULT */ |
516 | .cfg_en_adv = 0, |
517 | .cfg_en_main = 1, |
518 | .cfg_en_dly = 0, |
519 | .cfg_tap_adv_3_0 = 0, |
520 | .cfg_tap_main = 1, |
521 | .cfg_tap_dly_4_0 = 0, |
522 | .cfg_vga_ctrl_3_0 = 5, |
523 | .cfg_vga_cp_2_0 = 0, |
524 | .cfg_eq_res_3_0 = 0xa, |
525 | .cfg_eq_r_byp = 1, |
526 | .cfg_eq_c_force_3_0 = 0x8, |
527 | .cfg_alos_thr_3_0 = 0x3, |
528 | }, |
529 | { /* ETH_MEDIA_SR */ |
530 | .cfg_en_adv = 1, |
531 | .cfg_en_main = 1, |
532 | .cfg_en_dly = 1, |
533 | .cfg_tap_adv_3_0 = 0, |
534 | .cfg_tap_main = 1, |
535 | .cfg_tap_dly_4_0 = 0xc, |
536 | .cfg_vga_ctrl_3_0 = 0xa, |
537 | .cfg_vga_cp_2_0 = 0x4, |
538 | .cfg_eq_res_3_0 = 0xa, |
539 | .cfg_eq_r_byp = 1, |
540 | .cfg_eq_c_force_3_0 = 0xF, |
541 | .cfg_alos_thr_3_0 = 0x3, |
542 | }, |
543 | { /* ETH_MEDIA_DAC */ |
544 | .cfg_en_adv = 1, |
545 | .cfg_en_main = 1, |
546 | .cfg_en_dly = 1, |
547 | .cfg_tap_adv_3_0 = 12, |
548 | .cfg_tap_main = 1, |
549 | .cfg_tap_dly_4_0 = 8, |
550 | .cfg_vga_ctrl_3_0 = 0xa, |
551 | .cfg_vga_cp_2_0 = 4, |
552 | .cfg_eq_res_3_0 = 0xa, |
553 | .cfg_eq_r_byp = 1, |
554 | .cfg_eq_c_force_3_0 = 0xf, |
555 | .cfg_alos_thr_3_0 = 0x0, |
556 | } |
557 | }; |
558 | |
559 | static struct sparx5_sd10g28_mode_preset mode_presets_10g[] = { |
560 | { /* SPX5_SD10G28_MODE_PRESET_10000 */ |
561 | .bwidth = 64, |
562 | .cmu_sel = SPX5_SD10G28_CMU_MAIN, |
563 | .rate = 0x0, |
564 | .dfe_enable = 1, |
565 | .dfe_tap = 0x1f, |
566 | .pi_bw_gen1 = 0x0, |
567 | .duty_cycle = 0x2, |
568 | }, |
569 | { /* SPX5_SD10G28_MODE_PRESET_SFI_5000_6G */ |
570 | .bwidth = 16, |
571 | .cmu_sel = SPX5_SD10G28_CMU_MAIN, |
572 | .rate = 0x1, |
573 | .dfe_enable = 0, |
574 | .dfe_tap = 0, |
575 | .pi_bw_gen1 = 0x5, |
576 | .duty_cycle = 0x0, |
577 | }, |
578 | { /* SPX5_SD10G28_MODE_PRESET_SFI_5000_10G */ |
579 | .bwidth = 64, |
580 | .cmu_sel = SPX5_SD10G28_CMU_MAIN, |
581 | .rate = 0x1, |
582 | .dfe_enable = 0, |
583 | .dfe_tap = 0, |
584 | .pi_bw_gen1 = 0x5, |
585 | .duty_cycle = 0x0, |
586 | }, |
587 | { /* SPX5_SD10G28_MODE_PRESET_QSGMII */ |
588 | .bwidth = 20, |
589 | .cmu_sel = SPX5_SD10G28_CMU_AUX1, |
590 | .rate = 0x1, |
591 | .dfe_enable = 0, |
592 | .dfe_tap = 0, |
593 | .pi_bw_gen1 = 0x5, |
594 | .duty_cycle = 0x0, |
595 | }, |
596 | { /* SPX5_SD10G28_MODE_PRESET_SD_2G5 */ |
597 | .bwidth = 10, |
598 | .cmu_sel = SPX5_SD10G28_CMU_AUX2, |
599 | .rate = 0x2, |
600 | .dfe_enable = 0, |
601 | .dfe_tap = 0, |
602 | .pi_bw_gen1 = 0x7, |
603 | .duty_cycle = 0x0, |
604 | }, |
605 | { /* SPX5_SD10G28_MODE_PRESET_1000BASEX */ |
606 | .bwidth = 10, |
607 | .cmu_sel = SPX5_SD10G28_CMU_AUX1, |
608 | .rate = 0x3, |
609 | .dfe_enable = 0, |
610 | .dfe_tap = 0, |
611 | .pi_bw_gen1 = 0x7, |
612 | .duty_cycle = 0x0, |
613 | }, |
614 | }; |
615 | |
616 | /* map from SD25G28 interface width to configuration value */ |
617 | static u8 sd25g28_get_iw_setting(struct device *dev, const u8 interface_width) |
618 | { |
619 | switch (interface_width) { |
620 | case 10: return 0; |
621 | case 16: return 1; |
622 | case 32: return 3; |
623 | case 40: return 4; |
624 | case 64: return 5; |
625 | default: |
626 | dev_err(dev, "%s: Illegal value %d for interface width\n" , |
627 | __func__, interface_width); |
628 | } |
629 | return 0; |
630 | } |
631 | |
632 | /* map from SD10G28 interface width to configuration value */ |
633 | static u8 sd10g28_get_iw_setting(struct device *dev, const u8 interface_width) |
634 | { |
635 | switch (interface_width) { |
636 | case 10: return 0; |
637 | case 16: return 1; |
638 | case 20: return 2; |
639 | case 32: return 3; |
640 | case 40: return 4; |
641 | case 64: return 7; |
642 | default: |
643 | dev_err(dev, "%s: Illegal value %d for interface width\n" , __func__, |
644 | interface_width); |
645 | return 0; |
646 | } |
647 | } |
648 | |
649 | static int sparx5_sd10g25_get_mode_preset(struct sparx5_serdes_macro *macro, |
650 | struct sparx5_sd25g28_mode_preset *mode) |
651 | { |
652 | switch (macro->serdesmode) { |
653 | case SPX5_SD_MODE_SFI: |
654 | if (macro->speed == SPEED_25000) |
655 | *mode = mode_presets_25g[SPX5_SD25G28_MODE_PRESET_25000]; |
656 | else if (macro->speed == SPEED_10000) |
657 | *mode = mode_presets_25g[SPX5_SD25G28_MODE_PRESET_10000]; |
658 | else if (macro->speed == SPEED_5000) |
659 | *mode = mode_presets_25g[SPX5_SD25G28_MODE_PRESET_5000]; |
660 | break; |
661 | case SPX5_SD_MODE_2G5: |
662 | *mode = mode_presets_25g[SPX5_SD25G28_MODE_PRESET_SD_2G5]; |
663 | break; |
664 | case SPX5_SD_MODE_1000BASEX: |
665 | *mode = mode_presets_25g[SPX5_SD25G28_MODE_PRESET_1000BASEX]; |
666 | break; |
667 | case SPX5_SD_MODE_100FX: |
668 | /* Not supported */ |
669 | return -EINVAL; |
670 | default: |
671 | *mode = mode_presets_25g[SPX5_SD25G28_MODE_PRESET_25000]; |
672 | break; |
673 | } |
674 | return 0; |
675 | } |
676 | |
677 | static int sparx5_sd10g28_get_mode_preset(struct sparx5_serdes_macro *macro, |
678 | struct sparx5_sd10g28_mode_preset *mode, |
679 | struct sparx5_sd10g28_args *args) |
680 | { |
681 | switch (macro->serdesmode) { |
682 | case SPX5_SD_MODE_SFI: |
683 | if (macro->speed == SPEED_10000) { |
684 | *mode = mode_presets_10g[SPX5_SD10G28_MODE_PRESET_10000]; |
685 | } else if (macro->speed == SPEED_5000) { |
686 | if (args->is_6g) |
687 | *mode = mode_presets_10g[SPX5_SD10G28_MODE_PRESET_SFI_5000_6G]; |
688 | else |
689 | *mode = mode_presets_10g[SPX5_SD10G28_MODE_PRESET_SFI_5000_10G]; |
690 | } else { |
691 | dev_err(macro->priv->dev, "%s: Illegal speed: %02u, sidx: %02u, mode (%u)" , |
692 | __func__, macro->speed, macro->sidx, |
693 | macro->serdesmode); |
694 | return -EINVAL; |
695 | } |
696 | break; |
697 | case SPX5_SD_MODE_QSGMII: |
698 | *mode = mode_presets_10g[SPX5_SD10G28_MODE_PRESET_QSGMII]; |
699 | break; |
700 | case SPX5_SD_MODE_2G5: |
701 | *mode = mode_presets_10g[SPX5_SD10G28_MODE_PRESET_SD_2G5]; |
702 | break; |
703 | case SPX5_SD_MODE_100FX: |
704 | case SPX5_SD_MODE_1000BASEX: |
705 | *mode = mode_presets_10g[SPX5_SD10G28_MODE_PRESET_1000BASEX]; |
706 | break; |
707 | default: |
708 | *mode = mode_presets_10g[SPX5_SD10G28_MODE_PRESET_10000]; |
709 | break; |
710 | } |
711 | return 0; |
712 | } |
713 | |
714 | static void sparx5_sd25g28_get_params(struct sparx5_serdes_macro *macro, |
715 | struct sparx5_sd25g28_media_preset *media, |
716 | struct sparx5_sd25g28_mode_preset *mode, |
717 | struct sparx5_sd25g28_args *args, |
718 | struct sparx5_sd25g28_params *params) |
719 | { |
720 | u8 iw = sd25g28_get_iw_setting(dev: macro->priv->dev, interface_width: mode->bitwidth); |
721 | struct sparx5_sd25g28_params init = { |
722 | .r_d_width_ctrl_2_0 = iw, |
723 | .r_txfifo_ck_div_pmad_2_0 = mode->fifo_ck_div, |
724 | .r_rxfifo_ck_div_pmad_2_0 = mode->fifo_ck_div, |
725 | .cfg_vco_div_mode_1_0 = mode->vco_div_mode, |
726 | .cfg_pre_divsel_1_0 = mode->pre_divsel, |
727 | .cfg_sel_div_3_0 = mode->sel_div, |
728 | .cfg_vco_start_code_3_0 = 0, |
729 | .cfg_pma_tx_ck_bitwidth_2_0 = mode->ck_bitwidth, |
730 | .cfg_tx_prediv_1_0 = mode->tx_pre_div, |
731 | .cfg_rxdiv_sel_2_0 = mode->ck_bitwidth, |
732 | .cfg_tx_subrate_2_0 = mode->subrate, |
733 | .cfg_rx_subrate_2_0 = mode->subrate, |
734 | .r_multi_lane_mode = 0, |
735 | .cfg_cdrck_en = 1, |
736 | .cfg_dfeck_en = mode->dfe_enable, |
737 | .cfg_dfe_pd = mode->dfe_enable == 1 ? 0 : 1, |
738 | .cfg_dfedmx_pd = 1, |
739 | .cfg_dfetap_en_5_1 = mode->dfe_tap, |
740 | .cfg_dmux_pd = 0, |
741 | .cfg_dmux_clk_pd = 1, |
742 | .cfg_erramp_pd = mode->dfe_enable == 1 ? 0 : 1, |
743 | .cfg_pi_DFE_en = mode->dfe_enable, |
744 | .cfg_pi_en = 1, |
745 | .cfg_pd_ctle = 0, |
746 | .cfg_summer_en = 1, |
747 | .cfg_pmad_ck_pd = 0, |
748 | .cfg_pd_clk = 0, |
749 | .cfg_pd_cml = 0, |
750 | .cfg_pd_driver = 0, |
751 | .cfg_rx_reg_pu = 1, |
752 | .cfg_pd_rms_det = 1, |
753 | .cfg_dcdr_pd = 0, |
754 | .cfg_ecdr_pd = 1, |
755 | .cfg_pd_sq = 1, |
756 | .cfg_itx_ipdriver_base_2_0 = mode->txmargin, |
757 | .cfg_tap_dly_4_0 = media->cfg_tap_dly_4_0, |
758 | .cfg_tap_main = media->cfg_tap_main, |
759 | .cfg_en_main = media->cfg_en_main, |
760 | .cfg_tap_adv_3_0 = media->cfg_tap_adv_3_0, |
761 | .cfg_en_adv = media->cfg_en_adv, |
762 | .cfg_en_dly = media->cfg_en_dly, |
763 | .cfg_iscan_en = 0, |
764 | .l1_pcs_en_fast_iscan = 0, |
765 | .l0_cfg_bw_1_0 = 0, |
766 | .cfg_en_dummy = 0, |
767 | .cfg_pll_reserve_3_0 = args->com_pll_reserve, |
768 | .l0_cfg_txcal_en = mode->com_txcal_en, |
769 | .l0_cfg_tx_reserve_15_8 = mode->com_tx_reserve_msb, |
770 | .l0_cfg_tx_reserve_7_0 = mode->com_tx_reserve_lsb, |
771 | .cfg_tx_reserve_15_8 = mode->tx_reserve_msb, |
772 | .cfg_tx_reserve_7_0 = mode->tx_reserve_lsb, |
773 | .cfg_bw_1_0 = mode->bw, |
774 | .cfg_txcal_man_en = 1, |
775 | .cfg_phase_man_4_0 = 0, |
776 | .cfg_quad_man_1_0 = 0, |
777 | .cfg_txcal_shift_code_5_0 = 2, |
778 | .cfg_txcal_valid_sel_3_0 = 4, |
779 | .cfg_txcal_en = 0, |
780 | .cfg_cdr_kf_2_0 = 1, |
781 | .cfg_cdr_m_7_0 = 6, |
782 | .cfg_pi_bw_3_0 = mode->cfg_pi_bw_3_0, |
783 | .cfg_pi_steps_1_0 = 0, |
784 | .cfg_dis_2ndorder = 1, |
785 | .cfg_ctle_rstn = mode->cfg_ctle_rstn, |
786 | .r_dfe_rstn = mode->r_dfe_rstn, |
787 | .cfg_alos_thr_2_0 = media->cfg_alos_thr_2_0, |
788 | .cfg_itx_ipcml_base_1_0 = mode->cfg_itx_ipcml_base, |
789 | .cfg_rx_reserve_7_0 = 0xbf, |
790 | .cfg_rx_reserve_15_8 = 0x61, |
791 | .cfg_rxterm_2_0 = mode->rxterm, |
792 | .cfg_fom_selm = 0, |
793 | .cfg_rx_sp_ctle_1_0 = 0, |
794 | .cfg_isel_ctle_1_0 = 0, |
795 | .cfg_vga_ctrl_byp_4_0 = media->cfg_vga_ctrl_byp_4_0, |
796 | .cfg_vga_byp = 1, |
797 | .cfg_agc_adpt_byp = 1, |
798 | .cfg_eqr_byp = 1, |
799 | .cfg_eqr_force_3_0 = media->cfg_eq_r_force_3_0, |
800 | .cfg_eqc_force_3_0 = media->cfg_eq_c_force_3_0, |
801 | .cfg_sum_setcm_en = 1, |
802 | .cfg_pi_dfe_en = 1, |
803 | .cfg_init_pos_iscan_6_0 = 6, |
804 | .cfg_init_pos_ipi_6_0 = 9, |
805 | .cfg_dfedig_m_2_0 = 6, |
806 | .cfg_en_dfedig = mode->dfe_enable, |
807 | .r_d_width_ctrl_from_hwt = 0, |
808 | .r_reg_manual = 1, |
809 | .reg_rst = args->reg_rst, |
810 | .cfg_jc_byp = 1, |
811 | .cfg_common_reserve_7_0 = 1, |
812 | .cfg_pll_lol_set = 1, |
813 | .cfg_tx2rx_lp_en = 0, |
814 | .cfg_txlb_en = 0, |
815 | .cfg_rx2tx_lp_en = 0, |
816 | .cfg_rxlb_en = 0, |
817 | .r_tx_pol_inv = args->txinvert, |
818 | .r_rx_pol_inv = args->rxinvert, |
819 | }; |
820 | |
821 | *params = init; |
822 | } |
823 | |
824 | static void sparx5_sd10g28_get_params(struct sparx5_serdes_macro *macro, |
825 | struct sparx5_sd10g28_media_preset *media, |
826 | struct sparx5_sd10g28_mode_preset *mode, |
827 | struct sparx5_sd10g28_args *args, |
828 | struct sparx5_sd10g28_params *params) |
829 | { |
830 | u8 iw = sd10g28_get_iw_setting(dev: macro->priv->dev, interface_width: mode->bwidth); |
831 | struct sparx5_sd10g28_params init = { |
832 | .skip_cmu_cfg = args->skip_cmu_cfg, |
833 | .is_6g = args->is_6g, |
834 | .cmu_sel = mode->cmu_sel, |
835 | .cfg_lane_reserve_7_0 = (mode->cmu_sel % 2) << 6, |
836 | .cfg_ssc_rtl_clk_sel = (mode->cmu_sel / 2), |
837 | .cfg_lane_reserve_15_8 = mode->duty_cycle, |
838 | .cfg_txrate_1_0 = mode->rate, |
839 | .cfg_rxrate_1_0 = mode->rate, |
840 | .fx_100 = macro->serdesmode == SPX5_SD_MODE_100FX, |
841 | .r_d_width_ctrl_2_0 = iw, |
842 | .cfg_pma_tx_ck_bitwidth_2_0 = iw, |
843 | .cfg_rxdiv_sel_2_0 = iw, |
844 | .r_pcs2pma_phymode_4_0 = 0, |
845 | .cfg_lane_id_2_0 = 0, |
846 | .cfg_cdrck_en = 1, |
847 | .cfg_dfeck_en = mode->dfe_enable, |
848 | .cfg_dfe_pd = (mode->dfe_enable == 1) ? 0 : 1, |
849 | .cfg_dfetap_en_5_1 = mode->dfe_tap, |
850 | .cfg_erramp_pd = (mode->dfe_enable == 1) ? 0 : 1, |
851 | .cfg_pi_DFE_en = mode->dfe_enable, |
852 | .cfg_pi_en = 1, |
853 | .cfg_pd_ctle = 0, |
854 | .cfg_summer_en = 1, |
855 | .cfg_pd_rx_cktree = 0, |
856 | .cfg_pd_clk = 0, |
857 | .cfg_pd_cml = 0, |
858 | .cfg_pd_driver = 0, |
859 | .cfg_rx_reg_pu = 1, |
860 | .cfg_d_cdr_pd = 0, |
861 | .cfg_pd_sq = mode->dfe_enable, |
862 | .cfg_rxdet_en = 0, |
863 | .cfg_rxdet_str = 0, |
864 | .r_multi_lane_mode = 0, |
865 | .cfg_en_adv = media->cfg_en_adv, |
866 | .cfg_en_main = 1, |
867 | .cfg_en_dly = media->cfg_en_dly, |
868 | .cfg_tap_adv_3_0 = media->cfg_tap_adv_3_0, |
869 | .cfg_tap_main = media->cfg_tap_main, |
870 | .cfg_tap_dly_4_0 = media->cfg_tap_dly_4_0, |
871 | .cfg_vga_ctrl_3_0 = media->cfg_vga_ctrl_3_0, |
872 | .cfg_vga_cp_2_0 = media->cfg_vga_cp_2_0, |
873 | .cfg_eq_res_3_0 = media->cfg_eq_res_3_0, |
874 | .cfg_eq_r_byp = media->cfg_eq_r_byp, |
875 | .cfg_eq_c_force_3_0 = media->cfg_eq_c_force_3_0, |
876 | .cfg_en_dfedig = mode->dfe_enable, |
877 | .cfg_sum_setcm_en = 1, |
878 | .cfg_en_preemph = 0, |
879 | .cfg_itx_ippreemp_base_1_0 = 0, |
880 | .cfg_itx_ipdriver_base_2_0 = (args->txswing >> 6), |
881 | .cfg_ibias_tune_reserve_5_0 = (args->txswing & 63), |
882 | .cfg_txswing_half = (args->txmargin), |
883 | .cfg_dis_2nd_order = 0x1, |
884 | .cfg_rx_ssc_lh = 0x0, |
885 | .cfg_pi_floop_steps_1_0 = 0x0, |
886 | .cfg_pi_ext_dac_23_16 = (1 << 5), |
887 | .cfg_pi_ext_dac_15_8 = (0 << 6), |
888 | .cfg_iscan_ext_dac_7_0 = (1 << 7) + 9, |
889 | .cfg_cdr_kf_gen1_2_0 = 1, |
890 | .cfg_cdr_kf_gen2_2_0 = 1, |
891 | .cfg_cdr_kf_gen3_2_0 = 1, |
892 | .cfg_cdr_kf_gen4_2_0 = 1, |
893 | .r_cdr_m_gen1_7_0 = 4, |
894 | .cfg_pi_bw_gen1_3_0 = mode->pi_bw_gen1, |
895 | .cfg_pi_bw_gen2 = mode->pi_bw_gen1, |
896 | .cfg_pi_bw_gen3 = mode->pi_bw_gen1, |
897 | .cfg_pi_bw_gen4 = mode->pi_bw_gen1, |
898 | .cfg_pi_ext_dac_7_0 = 3, |
899 | .cfg_pi_steps = 0, |
900 | .cfg_mp_max_3_0 = 1, |
901 | .cfg_rstn_dfedig = mode->dfe_enable, |
902 | .cfg_alos_thr_3_0 = media->cfg_alos_thr_3_0, |
903 | .cfg_predrv_slewrate_1_0 = 3, |
904 | .cfg_itx_ipcml_base_1_0 = 0, |
905 | .cfg_ip_pre_base_1_0 = 0, |
906 | .r_cdr_m_gen2_7_0 = 2, |
907 | .r_cdr_m_gen3_7_0 = 2, |
908 | .r_cdr_m_gen4_7_0 = 2, |
909 | .r_en_auto_cdr_rstn = 0, |
910 | .cfg_oscal_afe = 1, |
911 | .cfg_pd_osdac_afe = 0, |
912 | .cfg_resetb_oscal_afe[0] = 0, |
913 | .cfg_resetb_oscal_afe[1] = 1, |
914 | .cfg_center_spreading = 0, |
915 | .cfg_m_cnt_maxval_4_0 = 15, |
916 | .cfg_ncnt_maxval_7_0 = 32, |
917 | .cfg_ncnt_maxval_10_8 = 6, |
918 | .cfg_ssc_en = 1, |
919 | .cfg_tx2rx_lp_en = 0, |
920 | .cfg_txlb_en = 0, |
921 | .cfg_rx2tx_lp_en = 0, |
922 | .cfg_rxlb_en = 0, |
923 | .r_tx_pol_inv = args->txinvert, |
924 | .r_rx_pol_inv = args->rxinvert, |
925 | }; |
926 | |
927 | *params = init; |
928 | } |
929 | |
930 | static int sparx5_cmu_apply_cfg(struct sparx5_serdes_private *priv, |
931 | u32 cmu_idx, |
932 | void __iomem *cmu_tgt, |
933 | void __iomem *cmu_cfg_tgt, |
934 | u32 spd10g) |
935 | { |
936 | void __iomem **regs = priv->regs; |
937 | struct device *dev = priv->dev; |
938 | int value; |
939 | |
940 | cmu_tgt = sdx5_inst_get(priv, id: TARGET_SD_CMU, tinst: cmu_idx); |
941 | cmu_cfg_tgt = sdx5_inst_get(priv, id: TARGET_SD_CMU_CFG, tinst: cmu_idx); |
942 | |
943 | if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || |
944 | cmu_idx == 10 || cmu_idx == 13) { |
945 | spd10g = 0; |
946 | } |
947 | |
948 | sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(1), |
949 | SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, |
950 | iomem: cmu_cfg_tgt, |
951 | SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); |
952 | |
953 | sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), |
954 | SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, |
955 | iomem: cmu_cfg_tgt, |
956 | SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); |
957 | |
958 | sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(1), |
959 | SD_CMU_CFG_SD_CMU_CFG_CMU_RST, |
960 | iomem: cmu_cfg_tgt, |
961 | SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); |
962 | |
963 | sdx5_inst_rmw(SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT_SET(0x1) | |
964 | SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT_SET(0x1) | |
965 | SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT_SET(0x1) | |
966 | SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT_SET(0x1) | |
967 | SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(0x0), |
968 | SD_CMU_CMU_45_R_DWIDTHCTRL_FROM_HWT | |
969 | SD_CMU_CMU_45_R_REFCK_SSC_EN_FROM_HWT | |
970 | SD_CMU_CMU_45_R_LINK_BUF_EN_FROM_HWT | |
971 | SD_CMU_CMU_45_R_BIAS_EN_FROM_HWT | |
972 | SD_CMU_CMU_45_R_EN_RATECHG_CTRL, |
973 | iomem: cmu_tgt, |
974 | SD_CMU_CMU_45(cmu_idx)); |
975 | |
976 | sdx5_inst_rmw(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(0), |
977 | SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, |
978 | iomem: cmu_tgt, |
979 | SD_CMU_CMU_47(cmu_idx)); |
980 | |
981 | sdx5_inst_rmw(SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(0), |
982 | SD_CMU_CMU_1B_CFG_RESERVE_7_0, |
983 | iomem: cmu_tgt, |
984 | SD_CMU_CMU_1B(cmu_idx)); |
985 | |
986 | sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_JC_BYP_SET(0x1), |
987 | SD_CMU_CMU_0D_CFG_JC_BYP, |
988 | iomem: cmu_tgt, |
989 | SD_CMU_CMU_0D(cmu_idx)); |
990 | |
991 | sdx5_inst_rmw(SD_CMU_CMU_1F_CFG_VTUNE_SEL_SET(1), |
992 | SD_CMU_CMU_1F_CFG_VTUNE_SEL, |
993 | iomem: cmu_tgt, |
994 | SD_CMU_CMU_1F(cmu_idx)); |
995 | |
996 | sdx5_inst_rmw(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_SET(3), |
997 | SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, |
998 | iomem: cmu_tgt, |
999 | SD_CMU_CMU_00(cmu_idx)); |
1000 | |
1001 | sdx5_inst_rmw(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_SET(3), |
1002 | SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, |
1003 | iomem: cmu_tgt, |
1004 | SD_CMU_CMU_05(cmu_idx)); |
1005 | |
1006 | sdx5_inst_rmw(SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(1), |
1007 | SD_CMU_CMU_30_R_PLL_DLOL_EN, |
1008 | iomem: cmu_tgt, |
1009 | SD_CMU_CMU_30(cmu_idx)); |
1010 | |
1011 | sdx5_inst_rmw(SD_CMU_CMU_09_CFG_SW_10G_SET(spd10g), |
1012 | SD_CMU_CMU_09_CFG_SW_10G, |
1013 | iomem: cmu_tgt, |
1014 | SD_CMU_CMU_09(cmu_idx)); |
1015 | |
1016 | sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(0), |
1017 | SD_CMU_CFG_SD_CMU_CFG_CMU_RST, |
1018 | iomem: cmu_cfg_tgt, |
1019 | SD_CMU_CFG_SD_CMU_CFG(cmu_idx)); |
1020 | |
1021 | msleep(msecs: 20); |
1022 | |
1023 | sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(0), |
1024 | SD_CMU_CMU_44_R_PLL_RSTN, |
1025 | iomem: cmu_tgt, |
1026 | SD_CMU_CMU_44(cmu_idx)); |
1027 | |
1028 | sdx5_inst_rmw(SD_CMU_CMU_44_R_PLL_RSTN_SET(1), |
1029 | SD_CMU_CMU_44_R_PLL_RSTN, |
1030 | iomem: cmu_tgt, |
1031 | SD_CMU_CMU_44(cmu_idx)); |
1032 | |
1033 | msleep(msecs: 20); |
1034 | |
1035 | value = readl(addr: sdx5_addr(base: regs, SD_CMU_CMU_E0(cmu_idx))); |
1036 | value = SD_CMU_CMU_E0_PLL_LOL_UDL_GET(value); |
1037 | |
1038 | if (value) { |
1039 | dev_err(dev, "CMU PLL Loss of Lock: 0x%x\n" , value); |
1040 | return -EINVAL; |
1041 | } |
1042 | sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD_SET(0), |
1043 | SD_CMU_CMU_0D_CFG_PMA_TX_CK_PD, |
1044 | iomem: cmu_tgt, |
1045 | SD_CMU_CMU_0D(cmu_idx)); |
1046 | return 0; |
1047 | } |
1048 | |
1049 | static int sparx5_cmu_cfg(struct sparx5_serdes_private *priv, u32 cmu_idx) |
1050 | { |
1051 | void __iomem *cmu_tgt, *cmu_cfg_tgt; |
1052 | u32 spd10g = 1; |
1053 | |
1054 | if (cmu_idx == 1 || cmu_idx == 4 || cmu_idx == 7 || |
1055 | cmu_idx == 10 || cmu_idx == 13) { |
1056 | spd10g = 0; |
1057 | } |
1058 | |
1059 | cmu_tgt = sdx5_inst_get(priv, id: TARGET_SD_CMU, tinst: cmu_idx); |
1060 | cmu_cfg_tgt = sdx5_inst_get(priv, id: TARGET_SD_CMU_CFG, tinst: cmu_idx); |
1061 | |
1062 | return sparx5_cmu_apply_cfg(priv, cmu_idx, cmu_tgt, cmu_cfg_tgt, spd10g); |
1063 | } |
1064 | |
1065 | /* Map of 6G/10G serdes mode and index to CMU index. */ |
1066 | static const int |
1067 | sparx5_serdes_cmu_map[SPX5_SD10G28_CMU_MAX][SPX5_SERDES_6G10G_CNT] = { |
1068 | [SPX5_SD10G28_CMU_MAIN] = { 2, 2, 2, 2, 2, |
1069 | 2, 2, 2, 5, 5, |
1070 | 5, 5, 5, 5, 5, |
1071 | 5, 8, 11, 11, 11, |
1072 | 11, 11, 11, 11, 11 }, |
1073 | [SPX5_SD10G28_CMU_AUX1] = { 0, 0, 3, 3, 3, |
1074 | 3, 3, 3, 3, 3, |
1075 | 6, 6, 6, 6, 6, |
1076 | 6, 6, 9, 9, 12, |
1077 | 12, 12, 12, 12, 12 }, |
1078 | [SPX5_SD10G28_CMU_AUX2] = { 1, 1, 1, 1, 4, |
1079 | 4, 4, 4, 4, 4, |
1080 | 4, 4, 7, 7, 7, |
1081 | 7, 7, 10, 10, 10, |
1082 | 10, 13, 13, 13, 13 }, |
1083 | [SPX5_SD10G28_CMU_NONE] = { 1, 1, 1, 1, 4, |
1084 | 4, 4, 4, 4, 4, |
1085 | 4, 4, 7, 7, 7, |
1086 | 7, 7, 10, 10, 10, |
1087 | 10, 13, 13, 13, 13 }, |
1088 | }; |
1089 | |
1090 | /* Get the index of the CMU which provides the clock for the specified serdes |
1091 | * mode and index. |
1092 | */ |
1093 | static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index) |
1094 | { |
1095 | return sparx5_serdes_cmu_map[mode][sd_index]; |
1096 | } |
1097 | |
1098 | static void sparx5_serdes_cmu_power_off(struct sparx5_serdes_private *priv) |
1099 | { |
1100 | void __iomem *cmu_inst, *cmu_cfg_inst; |
1101 | int i; |
1102 | |
1103 | /* Power down each CMU */ |
1104 | for (i = 0; i < SPX5_CMU_MAX; i++) { |
1105 | cmu_inst = sdx5_inst_get(priv, id: TARGET_SD_CMU, tinst: i); |
1106 | cmu_cfg_inst = sdx5_inst_get(priv, id: TARGET_SD_CMU_CFG, tinst: i); |
1107 | |
1108 | sdx5_inst_rmw(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_SET(0), |
1109 | SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, iomem: cmu_cfg_inst, |
1110 | SD_CMU_CFG_SD_CMU_CFG(0)); |
1111 | |
1112 | sdx5_inst_rmw(SD_CMU_CMU_05_CFG_REFCK_TERM_EN_SET(0), |
1113 | SD_CMU_CMU_05_CFG_REFCK_TERM_EN, iomem: cmu_inst, |
1114 | SD_CMU_CMU_05(0)); |
1115 | |
1116 | sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_DN_SET(0), |
1117 | SD_CMU_CMU_09_CFG_EN_TX_CK_DN, iomem: cmu_inst, |
1118 | SD_CMU_CMU_09(0)); |
1119 | |
1120 | sdx5_inst_rmw(SD_CMU_CMU_06_CFG_VCO_PD_SET(1), |
1121 | SD_CMU_CMU_06_CFG_VCO_PD, iomem: cmu_inst, |
1122 | SD_CMU_CMU_06(0)); |
1123 | |
1124 | sdx5_inst_rmw(SD_CMU_CMU_09_CFG_EN_TX_CK_UP_SET(0), |
1125 | SD_CMU_CMU_09_CFG_EN_TX_CK_UP, iomem: cmu_inst, |
1126 | SD_CMU_CMU_09(0)); |
1127 | |
1128 | sdx5_inst_rmw(SD_CMU_CMU_08_CFG_CK_TREE_PD_SET(1), |
1129 | SD_CMU_CMU_08_CFG_CK_TREE_PD, iomem: cmu_inst, |
1130 | SD_CMU_CMU_08(0)); |
1131 | |
1132 | sdx5_inst_rmw(SD_CMU_CMU_0D_CFG_REFCK_PD_SET(1) | |
1133 | SD_CMU_CMU_0D_CFG_PD_DIV64_SET(1) | |
1134 | SD_CMU_CMU_0D_CFG_PD_DIV66_SET(1), |
1135 | SD_CMU_CMU_0D_CFG_REFCK_PD | |
1136 | SD_CMU_CMU_0D_CFG_PD_DIV64 | |
1137 | SD_CMU_CMU_0D_CFG_PD_DIV66, iomem: cmu_inst, |
1138 | SD_CMU_CMU_0D(0)); |
1139 | |
1140 | sdx5_inst_rmw(SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD_SET(1), |
1141 | SD_CMU_CMU_06_CFG_CTRL_LOGIC_PD, iomem: cmu_inst, |
1142 | SD_CMU_CMU_06(0)); |
1143 | } |
1144 | } |
1145 | |
1146 | static void sparx5_sd25g28_reset(void __iomem *regs[], |
1147 | struct sparx5_sd25g28_params *params, |
1148 | u32 sd_index) |
1149 | { |
1150 | if (params->reg_rst == 1) { |
1151 | sdx5_rmw_addr(SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST_SET(1), |
1152 | SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST, |
1153 | addr: sdx5_addr(base: regs, SD_LANE_25G_SD_LANE_CFG(sd_index))); |
1154 | |
1155 | usleep_range(min: 1000, max: 2000); |
1156 | |
1157 | sdx5_rmw_addr(SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST_SET(0), |
1158 | SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST, |
1159 | addr: sdx5_addr(base: regs, SD_LANE_25G_SD_LANE_CFG(sd_index))); |
1160 | } |
1161 | } |
1162 | |
1163 | static int sparx5_sd25g28_apply_params(struct sparx5_serdes_macro *macro, |
1164 | struct sparx5_sd25g28_params *params) |
1165 | { |
1166 | struct sparx5_serdes_private *priv = macro->priv; |
1167 | void __iomem **regs = priv->regs; |
1168 | struct device *dev = priv->dev; |
1169 | u32 sd_index = macro->stpidx; |
1170 | u32 value; |
1171 | |
1172 | sdx5_rmw(SD_LANE_25G_SD_LANE_CFG_MACRO_RST_SET(1), |
1173 | SD_LANE_25G_SD_LANE_CFG_MACRO_RST, |
1174 | priv, |
1175 | SD_LANE_25G_SD_LANE_CFG(sd_index)); |
1176 | |
1177 | sdx5_rmw(SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_SET(0xFF), |
1178 | SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX, |
1179 | priv, |
1180 | SD25G_LANE_CMU_FF(sd_index)); |
1181 | |
1182 | sdx5_rmw(SD25G_LANE_CMU_1A_R_DWIDTHCTRL_FROM_HWT_SET |
1183 | (params->r_d_width_ctrl_from_hwt) | |
1184 | SD25G_LANE_CMU_1A_R_REG_MANUAL_SET(params->r_reg_manual), |
1185 | SD25G_LANE_CMU_1A_R_DWIDTHCTRL_FROM_HWT | |
1186 | SD25G_LANE_CMU_1A_R_REG_MANUAL, |
1187 | priv, |
1188 | SD25G_LANE_CMU_1A(sd_index)); |
1189 | |
1190 | sdx5_rmw(SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0_SET |
1191 | (params->cfg_common_reserve_7_0), |
1192 | SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0, |
1193 | priv, |
1194 | SD25G_LANE_CMU_31(sd_index)); |
1195 | |
1196 | sdx5_rmw(SD25G_LANE_CMU_09_CFG_EN_DUMMY_SET(params->cfg_en_dummy), |
1197 | SD25G_LANE_CMU_09_CFG_EN_DUMMY, |
1198 | priv, |
1199 | SD25G_LANE_CMU_09(sd_index)); |
1200 | |
1201 | sdx5_rmw(SD25G_LANE_CMU_13_CFG_PLL_RESERVE_3_0_SET |
1202 | (params->cfg_pll_reserve_3_0), |
1203 | SD25G_LANE_CMU_13_CFG_PLL_RESERVE_3_0, |
1204 | priv, |
1205 | SD25G_LANE_CMU_13(sd_index)); |
1206 | |
1207 | sdx5_rmw(SD25G_LANE_CMU_40_L0_CFG_TXCAL_EN_SET(params->l0_cfg_txcal_en), |
1208 | SD25G_LANE_CMU_40_L0_CFG_TXCAL_EN, |
1209 | priv, |
1210 | SD25G_LANE_CMU_40(sd_index)); |
1211 | |
1212 | sdx5_rmw(SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8_SET |
1213 | (params->l0_cfg_tx_reserve_15_8), |
1214 | SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8, |
1215 | priv, |
1216 | SD25G_LANE_CMU_46(sd_index)); |
1217 | |
1218 | sdx5_rmw(SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0_SET |
1219 | (params->l0_cfg_tx_reserve_7_0), |
1220 | SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0, |
1221 | priv, |
1222 | SD25G_LANE_CMU_45(sd_index)); |
1223 | |
1224 | sdx5_rmw(SD25G_LANE_CMU_0B_CFG_VCO_CAL_RESETN_SET(0), |
1225 | SD25G_LANE_CMU_0B_CFG_VCO_CAL_RESETN, |
1226 | priv, |
1227 | SD25G_LANE_CMU_0B(sd_index)); |
1228 | |
1229 | sdx5_rmw(SD25G_LANE_CMU_0B_CFG_VCO_CAL_RESETN_SET(1), |
1230 | SD25G_LANE_CMU_0B_CFG_VCO_CAL_RESETN, |
1231 | priv, |
1232 | SD25G_LANE_CMU_0B(sd_index)); |
1233 | |
1234 | sdx5_rmw(SD25G_LANE_CMU_19_R_CK_RESETB_SET(0), |
1235 | SD25G_LANE_CMU_19_R_CK_RESETB, |
1236 | priv, |
1237 | SD25G_LANE_CMU_19(sd_index)); |
1238 | |
1239 | sdx5_rmw(SD25G_LANE_CMU_19_R_CK_RESETB_SET(1), |
1240 | SD25G_LANE_CMU_19_R_CK_RESETB, |
1241 | priv, |
1242 | SD25G_LANE_CMU_19(sd_index)); |
1243 | |
1244 | sdx5_rmw(SD25G_LANE_CMU_18_R_PLL_RSTN_SET(0), |
1245 | SD25G_LANE_CMU_18_R_PLL_RSTN, |
1246 | priv, |
1247 | SD25G_LANE_CMU_18(sd_index)); |
1248 | |
1249 | sdx5_rmw(SD25G_LANE_CMU_18_R_PLL_RSTN_SET(1), |
1250 | SD25G_LANE_CMU_18_R_PLL_RSTN, |
1251 | priv, |
1252 | SD25G_LANE_CMU_18(sd_index)); |
1253 | |
1254 | sdx5_rmw(SD25G_LANE_CMU_1A_R_DWIDTHCTRL_2_0_SET(params->r_d_width_ctrl_2_0), |
1255 | SD25G_LANE_CMU_1A_R_DWIDTHCTRL_2_0, |
1256 | priv, |
1257 | SD25G_LANE_CMU_1A(sd_index)); |
1258 | |
1259 | sdx5_rmw(SD25G_LANE_CMU_30_R_TXFIFO_CK_DIV_PMAD_2_0_SET |
1260 | (params->r_txfifo_ck_div_pmad_2_0) | |
1261 | SD25G_LANE_CMU_30_R_RXFIFO_CK_DIV_PMAD_2_0_SET |
1262 | (params->r_rxfifo_ck_div_pmad_2_0), |
1263 | SD25G_LANE_CMU_30_R_TXFIFO_CK_DIV_PMAD_2_0 | |
1264 | SD25G_LANE_CMU_30_R_RXFIFO_CK_DIV_PMAD_2_0, |
1265 | priv, |
1266 | SD25G_LANE_CMU_30(sd_index)); |
1267 | |
1268 | sdx5_rmw(SD25G_LANE_CMU_0C_CFG_PLL_LOL_SET_SET(params->cfg_pll_lol_set) | |
1269 | SD25G_LANE_CMU_0C_CFG_VCO_DIV_MODE_1_0_SET |
1270 | (params->cfg_vco_div_mode_1_0), |
1271 | SD25G_LANE_CMU_0C_CFG_PLL_LOL_SET | |
1272 | SD25G_LANE_CMU_0C_CFG_VCO_DIV_MODE_1_0, |
1273 | priv, |
1274 | SD25G_LANE_CMU_0C(sd_index)); |
1275 | |
1276 | sdx5_rmw(SD25G_LANE_CMU_0D_CFG_PRE_DIVSEL_1_0_SET |
1277 | (params->cfg_pre_divsel_1_0), |
1278 | SD25G_LANE_CMU_0D_CFG_PRE_DIVSEL_1_0, |
1279 | priv, |
1280 | SD25G_LANE_CMU_0D(sd_index)); |
1281 | |
1282 | sdx5_rmw(SD25G_LANE_CMU_0E_CFG_SEL_DIV_3_0_SET(params->cfg_sel_div_3_0), |
1283 | SD25G_LANE_CMU_0E_CFG_SEL_DIV_3_0, |
1284 | priv, |
1285 | SD25G_LANE_CMU_0E(sd_index)); |
1286 | |
1287 | sdx5_rmw(SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_SET(0x00), |
1288 | SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX, |
1289 | priv, |
1290 | SD25G_LANE_CMU_FF(sd_index)); |
1291 | |
1292 | sdx5_rmw(SD25G_LANE_LANE_0C_LN_CFG_PMA_TX_CK_BITWIDTH_2_0_SET |
1293 | (params->cfg_pma_tx_ck_bitwidth_2_0), |
1294 | SD25G_LANE_LANE_0C_LN_CFG_PMA_TX_CK_BITWIDTH_2_0, |
1295 | priv, |
1296 | SD25G_LANE_LANE_0C(sd_index)); |
1297 | |
1298 | sdx5_rmw(SD25G_LANE_LANE_01_LN_CFG_TX_PREDIV_1_0_SET |
1299 | (params->cfg_tx_prediv_1_0), |
1300 | SD25G_LANE_LANE_01_LN_CFG_TX_PREDIV_1_0, |
1301 | priv, |
1302 | SD25G_LANE_LANE_01(sd_index)); |
1303 | |
1304 | sdx5_rmw(SD25G_LANE_LANE_18_LN_CFG_RXDIV_SEL_2_0_SET |
1305 | (params->cfg_rxdiv_sel_2_0), |
1306 | SD25G_LANE_LANE_18_LN_CFG_RXDIV_SEL_2_0, |
1307 | priv, |
1308 | SD25G_LANE_LANE_18(sd_index)); |
1309 | |
1310 | sdx5_rmw(SD25G_LANE_LANE_2C_LN_CFG_TX_SUBRATE_2_0_SET |
1311 | (params->cfg_tx_subrate_2_0), |
1312 | SD25G_LANE_LANE_2C_LN_CFG_TX_SUBRATE_2_0, |
1313 | priv, |
1314 | SD25G_LANE_LANE_2C(sd_index)); |
1315 | |
1316 | sdx5_rmw(SD25G_LANE_LANE_28_LN_CFG_RX_SUBRATE_2_0_SET |
1317 | (params->cfg_rx_subrate_2_0), |
1318 | SD25G_LANE_LANE_28_LN_CFG_RX_SUBRATE_2_0, |
1319 | priv, |
1320 | SD25G_LANE_LANE_28(sd_index)); |
1321 | |
1322 | sdx5_rmw(SD25G_LANE_LANE_18_LN_CFG_CDRCK_EN_SET(params->cfg_cdrck_en), |
1323 | SD25G_LANE_LANE_18_LN_CFG_CDRCK_EN, |
1324 | priv, |
1325 | SD25G_LANE_LANE_18(sd_index)); |
1326 | |
1327 | sdx5_rmw(SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1_SET |
1328 | (params->cfg_dfetap_en_5_1), |
1329 | SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1, |
1330 | priv, |
1331 | SD25G_LANE_LANE_0F(sd_index)); |
1332 | |
1333 | sdx5_rmw(SD25G_LANE_LANE_18_LN_CFG_ERRAMP_PD_SET(params->cfg_erramp_pd), |
1334 | SD25G_LANE_LANE_18_LN_CFG_ERRAMP_PD, |
1335 | priv, |
1336 | SD25G_LANE_LANE_18(sd_index)); |
1337 | |
1338 | sdx5_rmw(SD25G_LANE_LANE_1D_LN_CFG_PI_DFE_EN_SET(params->cfg_pi_dfe_en), |
1339 | SD25G_LANE_LANE_1D_LN_CFG_PI_DFE_EN, |
1340 | priv, |
1341 | SD25G_LANE_LANE_1D(sd_index)); |
1342 | |
1343 | sdx5_rmw(SD25G_LANE_LANE_19_LN_CFG_ECDR_PD_SET(params->cfg_ecdr_pd), |
1344 | SD25G_LANE_LANE_19_LN_CFG_ECDR_PD, |
1345 | priv, |
1346 | SD25G_LANE_LANE_19(sd_index)); |
1347 | |
1348 | sdx5_rmw(SD25G_LANE_LANE_01_LN_CFG_ITX_IPDRIVER_BASE_2_0_SET |
1349 | (params->cfg_itx_ipdriver_base_2_0), |
1350 | SD25G_LANE_LANE_01_LN_CFG_ITX_IPDRIVER_BASE_2_0, |
1351 | priv, |
1352 | SD25G_LANE_LANE_01(sd_index)); |
1353 | |
1354 | sdx5_rmw(SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0_SET(params->cfg_tap_dly_4_0), |
1355 | SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0, |
1356 | priv, |
1357 | SD25G_LANE_LANE_03(sd_index)); |
1358 | |
1359 | sdx5_rmw(SD25G_LANE_LANE_06_LN_CFG_TAP_ADV_3_0_SET(params->cfg_tap_adv_3_0), |
1360 | SD25G_LANE_LANE_06_LN_CFG_TAP_ADV_3_0, |
1361 | priv, |
1362 | SD25G_LANE_LANE_06(sd_index)); |
1363 | |
1364 | sdx5_rmw(SD25G_LANE_LANE_07_LN_CFG_EN_ADV_SET(params->cfg_en_adv) | |
1365 | SD25G_LANE_LANE_07_LN_CFG_EN_DLY_SET(params->cfg_en_dly), |
1366 | SD25G_LANE_LANE_07_LN_CFG_EN_ADV | |
1367 | SD25G_LANE_LANE_07_LN_CFG_EN_DLY, |
1368 | priv, |
1369 | SD25G_LANE_LANE_07(sd_index)); |
1370 | |
1371 | sdx5_rmw(SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8_SET |
1372 | (params->cfg_tx_reserve_15_8), |
1373 | SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8, |
1374 | priv, |
1375 | SD25G_LANE_LANE_43(sd_index)); |
1376 | |
1377 | sdx5_rmw(SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0_SET |
1378 | (params->cfg_tx_reserve_7_0), |
1379 | SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0, |
1380 | priv, |
1381 | SD25G_LANE_LANE_42(sd_index)); |
1382 | |
1383 | sdx5_rmw(SD25G_LANE_LANE_05_LN_CFG_BW_1_0_SET(params->cfg_bw_1_0), |
1384 | SD25G_LANE_LANE_05_LN_CFG_BW_1_0, |
1385 | priv, |
1386 | SD25G_LANE_LANE_05(sd_index)); |
1387 | |
1388 | sdx5_rmw(SD25G_LANE_LANE_0B_LN_CFG_TXCAL_MAN_EN_SET |
1389 | (params->cfg_txcal_man_en), |
1390 | SD25G_LANE_LANE_0B_LN_CFG_TXCAL_MAN_EN, |
1391 | priv, |
1392 | SD25G_LANE_LANE_0B(sd_index)); |
1393 | |
1394 | sdx5_rmw(SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0_SET |
1395 | (params->cfg_txcal_shift_code_5_0), |
1396 | SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0, |
1397 | priv, |
1398 | SD25G_LANE_LANE_0A(sd_index)); |
1399 | |
1400 | sdx5_rmw(SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0_SET |
1401 | (params->cfg_txcal_valid_sel_3_0), |
1402 | SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0, |
1403 | priv, |
1404 | SD25G_LANE_LANE_09(sd_index)); |
1405 | |
1406 | sdx5_rmw(SD25G_LANE_LANE_1A_LN_CFG_CDR_KF_2_0_SET(params->cfg_cdr_kf_2_0), |
1407 | SD25G_LANE_LANE_1A_LN_CFG_CDR_KF_2_0, |
1408 | priv, |
1409 | SD25G_LANE_LANE_1A(sd_index)); |
1410 | |
1411 | sdx5_rmw(SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0_SET(params->cfg_cdr_m_7_0), |
1412 | SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0, |
1413 | priv, |
1414 | SD25G_LANE_LANE_1B(sd_index)); |
1415 | |
1416 | sdx5_rmw(SD25G_LANE_LANE_2B_LN_CFG_PI_BW_3_0_SET(params->cfg_pi_bw_3_0), |
1417 | SD25G_LANE_LANE_2B_LN_CFG_PI_BW_3_0, |
1418 | priv, |
1419 | SD25G_LANE_LANE_2B(sd_index)); |
1420 | |
1421 | sdx5_rmw(SD25G_LANE_LANE_2C_LN_CFG_DIS_2NDORDER_SET |
1422 | (params->cfg_dis_2ndorder), |
1423 | SD25G_LANE_LANE_2C_LN_CFG_DIS_2NDORDER, |
1424 | priv, |
1425 | SD25G_LANE_LANE_2C(sd_index)); |
1426 | |
1427 | sdx5_rmw(SD25G_LANE_LANE_2E_LN_CFG_CTLE_RSTN_SET(params->cfg_ctle_rstn), |
1428 | SD25G_LANE_LANE_2E_LN_CFG_CTLE_RSTN, |
1429 | priv, |
1430 | SD25G_LANE_LANE_2E(sd_index)); |
1431 | |
1432 | sdx5_rmw(SD25G_LANE_LANE_00_LN_CFG_ITX_IPCML_BASE_1_0_SET |
1433 | (params->cfg_itx_ipcml_base_1_0), |
1434 | SD25G_LANE_LANE_00_LN_CFG_ITX_IPCML_BASE_1_0, |
1435 | priv, |
1436 | SD25G_LANE_LANE_00(sd_index)); |
1437 | |
1438 | sdx5_rmw(SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0_SET |
1439 | (params->cfg_rx_reserve_7_0), |
1440 | SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0, |
1441 | priv, |
1442 | SD25G_LANE_LANE_44(sd_index)); |
1443 | |
1444 | sdx5_rmw(SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8_SET |
1445 | (params->cfg_rx_reserve_15_8), |
1446 | SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8, |
1447 | priv, |
1448 | SD25G_LANE_LANE_45(sd_index)); |
1449 | |
1450 | sdx5_rmw(SD25G_LANE_LANE_0D_LN_CFG_DFECK_EN_SET(params->cfg_dfeck_en) | |
1451 | SD25G_LANE_LANE_0D_LN_CFG_RXTERM_2_0_SET(params->cfg_rxterm_2_0), |
1452 | SD25G_LANE_LANE_0D_LN_CFG_DFECK_EN | |
1453 | SD25G_LANE_LANE_0D_LN_CFG_RXTERM_2_0, |
1454 | priv, |
1455 | SD25G_LANE_LANE_0D(sd_index)); |
1456 | |
1457 | sdx5_rmw(SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0_SET |
1458 | (params->cfg_vga_ctrl_byp_4_0), |
1459 | SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0, |
1460 | priv, |
1461 | SD25G_LANE_LANE_21(sd_index)); |
1462 | |
1463 | sdx5_rmw(SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0_SET |
1464 | (params->cfg_eqr_force_3_0), |
1465 | SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0, |
1466 | priv, |
1467 | SD25G_LANE_LANE_22(sd_index)); |
1468 | |
1469 | sdx5_rmw(SD25G_LANE_LANE_1C_LN_CFG_EQC_FORCE_3_0_SET |
1470 | (params->cfg_eqc_force_3_0) | |
1471 | SD25G_LANE_LANE_1C_LN_CFG_DFE_PD_SET(params->cfg_dfe_pd), |
1472 | SD25G_LANE_LANE_1C_LN_CFG_EQC_FORCE_3_0 | |
1473 | SD25G_LANE_LANE_1C_LN_CFG_DFE_PD, |
1474 | priv, |
1475 | SD25G_LANE_LANE_1C(sd_index)); |
1476 | |
1477 | sdx5_rmw(SD25G_LANE_LANE_1E_LN_CFG_SUM_SETCM_EN_SET |
1478 | (params->cfg_sum_setcm_en), |
1479 | SD25G_LANE_LANE_1E_LN_CFG_SUM_SETCM_EN, |
1480 | priv, |
1481 | SD25G_LANE_LANE_1E(sd_index)); |
1482 | |
1483 | sdx5_rmw(SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0_SET |
1484 | (params->cfg_init_pos_iscan_6_0), |
1485 | SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0, |
1486 | priv, |
1487 | SD25G_LANE_LANE_25(sd_index)); |
1488 | |
1489 | sdx5_rmw(SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0_SET |
1490 | (params->cfg_init_pos_ipi_6_0), |
1491 | SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0, |
1492 | priv, |
1493 | SD25G_LANE_LANE_26(sd_index)); |
1494 | |
1495 | sdx5_rmw(SD25G_LANE_LANE_18_LN_CFG_ERRAMP_PD_SET(params->cfg_erramp_pd), |
1496 | SD25G_LANE_LANE_18_LN_CFG_ERRAMP_PD, |
1497 | priv, |
1498 | SD25G_LANE_LANE_18(sd_index)); |
1499 | |
1500 | sdx5_rmw(SD25G_LANE_LANE_0E_LN_CFG_DFEDIG_M_2_0_SET |
1501 | (params->cfg_dfedig_m_2_0), |
1502 | SD25G_LANE_LANE_0E_LN_CFG_DFEDIG_M_2_0, |
1503 | priv, |
1504 | SD25G_LANE_LANE_0E(sd_index)); |
1505 | |
1506 | sdx5_rmw(SD25G_LANE_LANE_0E_LN_CFG_EN_DFEDIG_SET(params->cfg_en_dfedig), |
1507 | SD25G_LANE_LANE_0E_LN_CFG_EN_DFEDIG, |
1508 | priv, |
1509 | SD25G_LANE_LANE_0E(sd_index)); |
1510 | |
1511 | sdx5_rmw(SD25G_LANE_LANE_40_LN_R_TX_POL_INV_SET(params->r_tx_pol_inv) | |
1512 | SD25G_LANE_LANE_40_LN_R_RX_POL_INV_SET(params->r_rx_pol_inv), |
1513 | SD25G_LANE_LANE_40_LN_R_TX_POL_INV | |
1514 | SD25G_LANE_LANE_40_LN_R_RX_POL_INV, |
1515 | priv, |
1516 | SD25G_LANE_LANE_40(sd_index)); |
1517 | |
1518 | sdx5_rmw(SD25G_LANE_LANE_04_LN_CFG_RX2TX_LP_EN_SET(params->cfg_rx2tx_lp_en) | |
1519 | SD25G_LANE_LANE_04_LN_CFG_TX2RX_LP_EN_SET(params->cfg_tx2rx_lp_en), |
1520 | SD25G_LANE_LANE_04_LN_CFG_RX2TX_LP_EN | |
1521 | SD25G_LANE_LANE_04_LN_CFG_TX2RX_LP_EN, |
1522 | priv, |
1523 | SD25G_LANE_LANE_04(sd_index)); |
1524 | |
1525 | sdx5_rmw(SD25G_LANE_LANE_1E_LN_CFG_RXLB_EN_SET(params->cfg_rxlb_en), |
1526 | SD25G_LANE_LANE_1E_LN_CFG_RXLB_EN, |
1527 | priv, |
1528 | SD25G_LANE_LANE_1E(sd_index)); |
1529 | |
1530 | sdx5_rmw(SD25G_LANE_LANE_19_LN_CFG_TXLB_EN_SET(params->cfg_txlb_en), |
1531 | SD25G_LANE_LANE_19_LN_CFG_TXLB_EN, |
1532 | priv, |
1533 | SD25G_LANE_LANE_19(sd_index)); |
1534 | |
1535 | sdx5_rmw(SD25G_LANE_LANE_2E_LN_CFG_RSTN_DFEDIG_SET(0), |
1536 | SD25G_LANE_LANE_2E_LN_CFG_RSTN_DFEDIG, |
1537 | priv, |
1538 | SD25G_LANE_LANE_2E(sd_index)); |
1539 | |
1540 | sdx5_rmw(SD25G_LANE_LANE_2E_LN_CFG_RSTN_DFEDIG_SET(1), |
1541 | SD25G_LANE_LANE_2E_LN_CFG_RSTN_DFEDIG, |
1542 | priv, |
1543 | SD25G_LANE_LANE_2E(sd_index)); |
1544 | |
1545 | sdx5_rmw(SD_LANE_25G_SD_LANE_CFG_MACRO_RST_SET(0), |
1546 | SD_LANE_25G_SD_LANE_CFG_MACRO_RST, |
1547 | priv, |
1548 | SD_LANE_25G_SD_LANE_CFG(sd_index)); |
1549 | |
1550 | sdx5_rmw(SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN_SET(0), |
1551 | SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN, |
1552 | priv, |
1553 | SD25G_LANE_LANE_1C(sd_index)); |
1554 | |
1555 | usleep_range(min: 1000, max: 2000); |
1556 | |
1557 | sdx5_rmw(SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN_SET(1), |
1558 | SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN, |
1559 | priv, |
1560 | SD25G_LANE_LANE_1C(sd_index)); |
1561 | |
1562 | usleep_range(min: 10000, max: 20000); |
1563 | |
1564 | sdx5_rmw(SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_SET(0xff), |
1565 | SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX, |
1566 | priv, |
1567 | SD25G_LANE_CMU_FF(sd_index)); |
1568 | |
1569 | value = readl(addr: sdx5_addr(base: regs, SD25G_LANE_CMU_C0(sd_index))); |
1570 | value = SD25G_LANE_CMU_C0_PLL_LOL_UDL_GET(value); |
1571 | |
1572 | if (value) { |
1573 | dev_err(dev, "25G PLL Loss of Lock: 0x%x\n" , value); |
1574 | return -EINVAL; |
1575 | } |
1576 | |
1577 | value = readl(addr: sdx5_addr(base: regs, SD_LANE_25G_SD_LANE_STAT(sd_index))); |
1578 | value = SD_LANE_25G_SD_LANE_STAT_PMA_RST_DONE_GET(value); |
1579 | |
1580 | if (value != 0x1) { |
1581 | dev_err(dev, "25G PMA Reset failed: 0x%x\n" , value); |
1582 | return -EINVAL; |
1583 | } |
1584 | sdx5_rmw(SD25G_LANE_CMU_2A_R_DBG_LOL_STATUS_SET(0x1), |
1585 | SD25G_LANE_CMU_2A_R_DBG_LOL_STATUS, |
1586 | priv, |
1587 | SD25G_LANE_CMU_2A(sd_index)); |
1588 | |
1589 | sdx5_rmw(SD_LANE_25G_SD_SER_RST_SER_RST_SET(0x0), |
1590 | SD_LANE_25G_SD_SER_RST_SER_RST, |
1591 | priv, |
1592 | SD_LANE_25G_SD_SER_RST(sd_index)); |
1593 | |
1594 | sdx5_rmw(SD_LANE_25G_SD_DES_RST_DES_RST_SET(0x0), |
1595 | SD_LANE_25G_SD_DES_RST_DES_RST, |
1596 | priv, |
1597 | SD_LANE_25G_SD_DES_RST(sd_index)); |
1598 | |
1599 | sdx5_rmw(SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_SET(0), |
1600 | SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX, |
1601 | priv, |
1602 | SD25G_LANE_CMU_FF(sd_index)); |
1603 | |
1604 | sdx5_rmw(SD25G_LANE_LANE_2D_LN_CFG_ALOS_THR_2_0_SET |
1605 | (params->cfg_alos_thr_2_0), |
1606 | SD25G_LANE_LANE_2D_LN_CFG_ALOS_THR_2_0, |
1607 | priv, |
1608 | SD25G_LANE_LANE_2D(sd_index)); |
1609 | |
1610 | sdx5_rmw(SD25G_LANE_LANE_2E_LN_CFG_DIS_SQ_SET(0), |
1611 | SD25G_LANE_LANE_2E_LN_CFG_DIS_SQ, |
1612 | priv, |
1613 | SD25G_LANE_LANE_2E(sd_index)); |
1614 | |
1615 | sdx5_rmw(SD25G_LANE_LANE_2E_LN_CFG_PD_SQ_SET(0), |
1616 | SD25G_LANE_LANE_2E_LN_CFG_PD_SQ, |
1617 | priv, |
1618 | SD25G_LANE_LANE_2E(sd_index)); |
1619 | |
1620 | return 0; |
1621 | } |
1622 | |
1623 | static void sparx5_sd10g28_reset(void __iomem *regs[], u32 lane_index) |
1624 | { |
1625 | /* Note: SerDes SD10G_LANE_1 is configured in 10G_LAN mode */ |
1626 | sdx5_rmw_addr(SD_LANE_SD_LANE_CFG_EXT_CFG_RST_SET(1), |
1627 | SD_LANE_SD_LANE_CFG_EXT_CFG_RST, |
1628 | addr: sdx5_addr(base: regs, SD_LANE_SD_LANE_CFG(lane_index))); |
1629 | |
1630 | usleep_range(min: 1000, max: 2000); |
1631 | |
1632 | sdx5_rmw_addr(SD_LANE_SD_LANE_CFG_EXT_CFG_RST_SET(0), |
1633 | SD_LANE_SD_LANE_CFG_EXT_CFG_RST, |
1634 | addr: sdx5_addr(base: regs, SD_LANE_SD_LANE_CFG(lane_index))); |
1635 | } |
1636 | |
1637 | static int sparx5_sd10g28_apply_params(struct sparx5_serdes_macro *macro, |
1638 | struct sparx5_sd10g28_params *params) |
1639 | { |
1640 | struct sparx5_serdes_private *priv = macro->priv; |
1641 | void __iomem **regs = priv->regs; |
1642 | struct device *dev = priv->dev; |
1643 | u32 lane_index = macro->sidx; |
1644 | u32 sd_index = macro->stpidx; |
1645 | void __iomem *sd_inst; |
1646 | u32 value, cmu_idx; |
1647 | int err; |
1648 | |
1649 | /* Do not configure serdes if CMU is not to be configured too */ |
1650 | if (params->skip_cmu_cfg) |
1651 | return 0; |
1652 | |
1653 | cmu_idx = sparx5_serdes_cmu_get(mode: params->cmu_sel, sd_index: lane_index); |
1654 | err = sparx5_cmu_cfg(priv, cmu_idx); |
1655 | if (err) |
1656 | return err; |
1657 | |
1658 | if (params->is_6g) |
1659 | sd_inst = sdx5_inst_get(priv, id: TARGET_SD6G_LANE, tinst: sd_index); |
1660 | else |
1661 | sd_inst = sdx5_inst_get(priv, id: TARGET_SD10G_LANE, tinst: sd_index); |
1662 | |
1663 | sdx5_rmw(SD_LANE_SD_LANE_CFG_MACRO_RST_SET(1), |
1664 | SD_LANE_SD_LANE_CFG_MACRO_RST, |
1665 | priv, |
1666 | SD_LANE_SD_LANE_CFG(lane_index)); |
1667 | |
1668 | sdx5_inst_rmw(SD10G_LANE_LANE_93_R_DWIDTHCTRL_FROM_HWT_SET(0x0) | |
1669 | SD10G_LANE_LANE_93_R_REG_MANUAL_SET(0x1) | |
1670 | SD10G_LANE_LANE_93_R_AUXCKSEL_FROM_HWT_SET(0x1) | |
1671 | SD10G_LANE_LANE_93_R_LANE_ID_FROM_HWT_SET(0x1) | |
1672 | SD10G_LANE_LANE_93_R_EN_RATECHG_CTRL_SET(0x0), |
1673 | SD10G_LANE_LANE_93_R_DWIDTHCTRL_FROM_HWT | |
1674 | SD10G_LANE_LANE_93_R_REG_MANUAL | |
1675 | SD10G_LANE_LANE_93_R_AUXCKSEL_FROM_HWT | |
1676 | SD10G_LANE_LANE_93_R_LANE_ID_FROM_HWT | |
1677 | SD10G_LANE_LANE_93_R_EN_RATECHG_CTRL, |
1678 | iomem: sd_inst, |
1679 | SD10G_LANE_LANE_93(sd_index)); |
1680 | |
1681 | sdx5_inst_rmw(SD10G_LANE_LANE_94_R_ISCAN_REG_SET(0x1) | |
1682 | SD10G_LANE_LANE_94_R_TXEQ_REG_SET(0x1) | |
1683 | SD10G_LANE_LANE_94_R_MISC_REG_SET(0x1) | |
1684 | SD10G_LANE_LANE_94_R_SWING_REG_SET(0x1), |
1685 | SD10G_LANE_LANE_94_R_ISCAN_REG | |
1686 | SD10G_LANE_LANE_94_R_TXEQ_REG | |
1687 | SD10G_LANE_LANE_94_R_MISC_REG | |
1688 | SD10G_LANE_LANE_94_R_SWING_REG, |
1689 | iomem: sd_inst, |
1690 | SD10G_LANE_LANE_94(sd_index)); |
1691 | |
1692 | sdx5_inst_rmw(SD10G_LANE_LANE_9E_R_RXEQ_REG_SET(0x1), |
1693 | SD10G_LANE_LANE_9E_R_RXEQ_REG, |
1694 | iomem: sd_inst, |
1695 | SD10G_LANE_LANE_9E(sd_index)); |
1696 | |
1697 | sdx5_inst_rmw(SD10G_LANE_LANE_A1_R_SSC_FROM_HWT_SET(0x0) | |
1698 | SD10G_LANE_LANE_A1_R_CDR_FROM_HWT_SET(0x0) | |
1699 | SD10G_LANE_LANE_A1_R_PCLK_GATING_FROM_HWT_SET(0x1), |
1700 | SD10G_LANE_LANE_A1_R_SSC_FROM_HWT | |
1701 | SD10G_LANE_LANE_A1_R_CDR_FROM_HWT | |
1702 | SD10G_LANE_LANE_A1_R_PCLK_GATING_FROM_HWT, |
1703 | iomem: sd_inst, |
1704 | SD10G_LANE_LANE_A1(sd_index)); |
1705 | |
1706 | sdx5_rmw(SD_LANE_SD_LANE_CFG_RX_REF_SEL_SET(params->cmu_sel) | |
1707 | SD_LANE_SD_LANE_CFG_TX_REF_SEL_SET(params->cmu_sel), |
1708 | SD_LANE_SD_LANE_CFG_RX_REF_SEL | |
1709 | SD_LANE_SD_LANE_CFG_TX_REF_SEL, |
1710 | priv, |
1711 | SD_LANE_SD_LANE_CFG(lane_index)); |
1712 | |
1713 | sdx5_inst_rmw(SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0_SET |
1714 | (params->cfg_lane_reserve_7_0), |
1715 | SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0, |
1716 | iomem: sd_inst, |
1717 | SD10G_LANE_LANE_40(sd_index)); |
1718 | |
1719 | sdx5_inst_rmw(SD10G_LANE_LANE_50_CFG_SSC_RTL_CLK_SEL_SET |
1720 | (params->cfg_ssc_rtl_clk_sel), |
1721 | SD10G_LANE_LANE_50_CFG_SSC_RTL_CLK_SEL, |
1722 | iomem: sd_inst, |
1723 | SD10G_LANE_LANE_50(sd_index)); |
1724 | |
1725 | sdx5_inst_rmw(SD10G_LANE_LANE_35_CFG_TXRATE_1_0_SET |
1726 | (params->cfg_txrate_1_0) | |
1727 | SD10G_LANE_LANE_35_CFG_RXRATE_1_0_SET |
1728 | (params->cfg_rxrate_1_0), |
1729 | SD10G_LANE_LANE_35_CFG_TXRATE_1_0 | |
1730 | SD10G_LANE_LANE_35_CFG_RXRATE_1_0, |
1731 | iomem: sd_inst, |
1732 | SD10G_LANE_LANE_35(sd_index)); |
1733 | |
1734 | sdx5_inst_rmw(SD10G_LANE_LANE_94_R_DWIDTHCTRL_2_0_SET |
1735 | (params->r_d_width_ctrl_2_0), |
1736 | SD10G_LANE_LANE_94_R_DWIDTHCTRL_2_0, |
1737 | iomem: sd_inst, |
1738 | SD10G_LANE_LANE_94(sd_index)); |
1739 | |
1740 | sdx5_inst_rmw(SD10G_LANE_LANE_01_CFG_PMA_TX_CK_BITWIDTH_2_0_SET |
1741 | (params->cfg_pma_tx_ck_bitwidth_2_0), |
1742 | SD10G_LANE_LANE_01_CFG_PMA_TX_CK_BITWIDTH_2_0, |
1743 | iomem: sd_inst, |
1744 | SD10G_LANE_LANE_01(sd_index)); |
1745 | |
1746 | sdx5_inst_rmw(SD10G_LANE_LANE_30_CFG_RXDIV_SEL_2_0_SET |
1747 | (params->cfg_rxdiv_sel_2_0), |
1748 | SD10G_LANE_LANE_30_CFG_RXDIV_SEL_2_0, |
1749 | iomem: sd_inst, |
1750 | SD10G_LANE_LANE_30(sd_index)); |
1751 | |
1752 | sdx5_inst_rmw(SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0_SET |
1753 | (params->r_pcs2pma_phymode_4_0), |
1754 | SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0, |
1755 | iomem: sd_inst, |
1756 | SD10G_LANE_LANE_A2(sd_index)); |
1757 | |
1758 | sdx5_inst_rmw(SD10G_LANE_LANE_13_CFG_CDRCK_EN_SET(params->cfg_cdrck_en), |
1759 | SD10G_LANE_LANE_13_CFG_CDRCK_EN, |
1760 | iomem: sd_inst, |
1761 | SD10G_LANE_LANE_13(sd_index)); |
1762 | |
1763 | sdx5_inst_rmw(SD10G_LANE_LANE_23_CFG_DFECK_EN_SET |
1764 | (params->cfg_dfeck_en) | |
1765 | SD10G_LANE_LANE_23_CFG_DFE_PD_SET(params->cfg_dfe_pd) | |
1766 | SD10G_LANE_LANE_23_CFG_ERRAMP_PD_SET |
1767 | (params->cfg_erramp_pd), |
1768 | SD10G_LANE_LANE_23_CFG_DFECK_EN | |
1769 | SD10G_LANE_LANE_23_CFG_DFE_PD | |
1770 | SD10G_LANE_LANE_23_CFG_ERRAMP_PD, |
1771 | iomem: sd_inst, |
1772 | SD10G_LANE_LANE_23(sd_index)); |
1773 | |
1774 | sdx5_inst_rmw(SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1_SET |
1775 | (params->cfg_dfetap_en_5_1), |
1776 | SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1, |
1777 | iomem: sd_inst, |
1778 | SD10G_LANE_LANE_22(sd_index)); |
1779 | |
1780 | sdx5_inst_rmw(SD10G_LANE_LANE_1A_CFG_PI_DFE_EN_SET |
1781 | (params->cfg_pi_DFE_en), |
1782 | SD10G_LANE_LANE_1A_CFG_PI_DFE_EN, |
1783 | iomem: sd_inst, |
1784 | SD10G_LANE_LANE_1A(sd_index)); |
1785 | |
1786 | sdx5_inst_rmw(SD10G_LANE_LANE_02_CFG_EN_ADV_SET(params->cfg_en_adv) | |
1787 | SD10G_LANE_LANE_02_CFG_EN_MAIN_SET(params->cfg_en_main) | |
1788 | SD10G_LANE_LANE_02_CFG_EN_DLY_SET(params->cfg_en_dly) | |
1789 | SD10G_LANE_LANE_02_CFG_TAP_ADV_3_0_SET |
1790 | (params->cfg_tap_adv_3_0), |
1791 | SD10G_LANE_LANE_02_CFG_EN_ADV | |
1792 | SD10G_LANE_LANE_02_CFG_EN_MAIN | |
1793 | SD10G_LANE_LANE_02_CFG_EN_DLY | |
1794 | SD10G_LANE_LANE_02_CFG_TAP_ADV_3_0, |
1795 | iomem: sd_inst, |
1796 | SD10G_LANE_LANE_02(sd_index)); |
1797 | |
1798 | sdx5_inst_rmw(SD10G_LANE_LANE_03_CFG_TAP_MAIN_SET(params->cfg_tap_main), |
1799 | SD10G_LANE_LANE_03_CFG_TAP_MAIN, |
1800 | iomem: sd_inst, |
1801 | SD10G_LANE_LANE_03(sd_index)); |
1802 | |
1803 | sdx5_inst_rmw(SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0_SET |
1804 | (params->cfg_tap_dly_4_0), |
1805 | SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0, |
1806 | iomem: sd_inst, |
1807 | SD10G_LANE_LANE_04(sd_index)); |
1808 | |
1809 | sdx5_inst_rmw(SD10G_LANE_LANE_2F_CFG_VGA_CTRL_3_0_SET |
1810 | (params->cfg_vga_ctrl_3_0), |
1811 | SD10G_LANE_LANE_2F_CFG_VGA_CTRL_3_0, |
1812 | iomem: sd_inst, |
1813 | SD10G_LANE_LANE_2F(sd_index)); |
1814 | |
1815 | sdx5_inst_rmw(SD10G_LANE_LANE_2F_CFG_VGA_CP_2_0_SET |
1816 | (params->cfg_vga_cp_2_0), |
1817 | SD10G_LANE_LANE_2F_CFG_VGA_CP_2_0, |
1818 | iomem: sd_inst, |
1819 | SD10G_LANE_LANE_2F(sd_index)); |
1820 | |
1821 | sdx5_inst_rmw(SD10G_LANE_LANE_0B_CFG_EQ_RES_3_0_SET |
1822 | (params->cfg_eq_res_3_0), |
1823 | SD10G_LANE_LANE_0B_CFG_EQ_RES_3_0, |
1824 | iomem: sd_inst, |
1825 | SD10G_LANE_LANE_0B(sd_index)); |
1826 | |
1827 | sdx5_inst_rmw(SD10G_LANE_LANE_0D_CFG_EQR_BYP_SET(params->cfg_eq_r_byp), |
1828 | SD10G_LANE_LANE_0D_CFG_EQR_BYP, |
1829 | iomem: sd_inst, |
1830 | SD10G_LANE_LANE_0D(sd_index)); |
1831 | |
1832 | sdx5_inst_rmw(SD10G_LANE_LANE_0E_CFG_EQC_FORCE_3_0_SET |
1833 | (params->cfg_eq_c_force_3_0) | |
1834 | SD10G_LANE_LANE_0E_CFG_SUM_SETCM_EN_SET |
1835 | (params->cfg_sum_setcm_en), |
1836 | SD10G_LANE_LANE_0E_CFG_EQC_FORCE_3_0 | |
1837 | SD10G_LANE_LANE_0E_CFG_SUM_SETCM_EN, |
1838 | iomem: sd_inst, |
1839 | SD10G_LANE_LANE_0E(sd_index)); |
1840 | |
1841 | sdx5_inst_rmw(SD10G_LANE_LANE_23_CFG_EN_DFEDIG_SET |
1842 | (params->cfg_en_dfedig), |
1843 | SD10G_LANE_LANE_23_CFG_EN_DFEDIG, |
1844 | iomem: sd_inst, |
1845 | SD10G_LANE_LANE_23(sd_index)); |
1846 | |
1847 | sdx5_inst_rmw(SD10G_LANE_LANE_06_CFG_EN_PREEMPH_SET |
1848 | (params->cfg_en_preemph), |
1849 | SD10G_LANE_LANE_06_CFG_EN_PREEMPH, |
1850 | iomem: sd_inst, |
1851 | SD10G_LANE_LANE_06(sd_index)); |
1852 | |
1853 | sdx5_inst_rmw(SD10G_LANE_LANE_33_CFG_ITX_IPPREEMP_BASE_1_0_SET |
1854 | (params->cfg_itx_ippreemp_base_1_0) | |
1855 | SD10G_LANE_LANE_33_CFG_ITX_IPDRIVER_BASE_2_0_SET |
1856 | (params->cfg_itx_ipdriver_base_2_0), |
1857 | SD10G_LANE_LANE_33_CFG_ITX_IPPREEMP_BASE_1_0 | |
1858 | SD10G_LANE_LANE_33_CFG_ITX_IPDRIVER_BASE_2_0, |
1859 | iomem: sd_inst, |
1860 | SD10G_LANE_LANE_33(sd_index)); |
1861 | |
1862 | sdx5_inst_rmw(SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0_SET |
1863 | (params->cfg_ibias_tune_reserve_5_0), |
1864 | SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0, |
1865 | iomem: sd_inst, |
1866 | SD10G_LANE_LANE_52(sd_index)); |
1867 | |
1868 | sdx5_inst_rmw(SD10G_LANE_LANE_37_CFG_TXSWING_HALF_SET |
1869 | (params->cfg_txswing_half), |
1870 | SD10G_LANE_LANE_37_CFG_TXSWING_HALF, |
1871 | iomem: sd_inst, |
1872 | SD10G_LANE_LANE_37(sd_index)); |
1873 | |
1874 | sdx5_inst_rmw(SD10G_LANE_LANE_3C_CFG_DIS_2NDORDER_SET |
1875 | (params->cfg_dis_2nd_order), |
1876 | SD10G_LANE_LANE_3C_CFG_DIS_2NDORDER, |
1877 | iomem: sd_inst, |
1878 | SD10G_LANE_LANE_3C(sd_index)); |
1879 | |
1880 | sdx5_inst_rmw(SD10G_LANE_LANE_39_CFG_RX_SSC_LH_SET |
1881 | (params->cfg_rx_ssc_lh), |
1882 | SD10G_LANE_LANE_39_CFG_RX_SSC_LH, |
1883 | iomem: sd_inst, |
1884 | SD10G_LANE_LANE_39(sd_index)); |
1885 | |
1886 | sdx5_inst_rmw(SD10G_LANE_LANE_1A_CFG_PI_FLOOP_STEPS_1_0_SET |
1887 | (params->cfg_pi_floop_steps_1_0), |
1888 | SD10G_LANE_LANE_1A_CFG_PI_FLOOP_STEPS_1_0, |
1889 | iomem: sd_inst, |
1890 | SD10G_LANE_LANE_1A(sd_index)); |
1891 | |
1892 | sdx5_inst_rmw(SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16_SET |
1893 | (params->cfg_pi_ext_dac_23_16), |
1894 | SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16, |
1895 | iomem: sd_inst, |
1896 | SD10G_LANE_LANE_16(sd_index)); |
1897 | |
1898 | sdx5_inst_rmw(SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8_SET |
1899 | (params->cfg_pi_ext_dac_15_8), |
1900 | SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8, |
1901 | iomem: sd_inst, |
1902 | SD10G_LANE_LANE_15(sd_index)); |
1903 | |
1904 | sdx5_inst_rmw(SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0_SET |
1905 | (params->cfg_iscan_ext_dac_7_0), |
1906 | SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0, |
1907 | iomem: sd_inst, |
1908 | SD10G_LANE_LANE_26(sd_index)); |
1909 | |
1910 | sdx5_inst_rmw(SD10G_LANE_LANE_42_CFG_CDR_KF_GEN1_2_0_SET |
1911 | (params->cfg_cdr_kf_gen1_2_0), |
1912 | SD10G_LANE_LANE_42_CFG_CDR_KF_GEN1_2_0, |
1913 | iomem: sd_inst, |
1914 | SD10G_LANE_LANE_42(sd_index)); |
1915 | |
1916 | sdx5_inst_rmw(SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0_SET |
1917 | (params->r_cdr_m_gen1_7_0), |
1918 | SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0, |
1919 | iomem: sd_inst, |
1920 | SD10G_LANE_LANE_0F(sd_index)); |
1921 | |
1922 | sdx5_inst_rmw(SD10G_LANE_LANE_24_CFG_PI_BW_GEN1_3_0_SET |
1923 | (params->cfg_pi_bw_gen1_3_0), |
1924 | SD10G_LANE_LANE_24_CFG_PI_BW_GEN1_3_0, |
1925 | iomem: sd_inst, |
1926 | SD10G_LANE_LANE_24(sd_index)); |
1927 | |
1928 | sdx5_inst_rmw(SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0_SET |
1929 | (params->cfg_pi_ext_dac_7_0), |
1930 | SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0, |
1931 | iomem: sd_inst, |
1932 | SD10G_LANE_LANE_14(sd_index)); |
1933 | |
1934 | sdx5_inst_rmw(SD10G_LANE_LANE_1A_CFG_PI_STEPS_SET(params->cfg_pi_steps), |
1935 | SD10G_LANE_LANE_1A_CFG_PI_STEPS, |
1936 | iomem: sd_inst, |
1937 | SD10G_LANE_LANE_1A(sd_index)); |
1938 | |
1939 | sdx5_inst_rmw(SD10G_LANE_LANE_3A_CFG_MP_MAX_3_0_SET |
1940 | (params->cfg_mp_max_3_0), |
1941 | SD10G_LANE_LANE_3A_CFG_MP_MAX_3_0, |
1942 | iomem: sd_inst, |
1943 | SD10G_LANE_LANE_3A(sd_index)); |
1944 | |
1945 | sdx5_inst_rmw(SD10G_LANE_LANE_31_CFG_RSTN_DFEDIG_SET |
1946 | (params->cfg_rstn_dfedig), |
1947 | SD10G_LANE_LANE_31_CFG_RSTN_DFEDIG, |
1948 | iomem: sd_inst, |
1949 | SD10G_LANE_LANE_31(sd_index)); |
1950 | |
1951 | sdx5_inst_rmw(SD10G_LANE_LANE_48_CFG_ALOS_THR_3_0_SET |
1952 | (params->cfg_alos_thr_3_0), |
1953 | SD10G_LANE_LANE_48_CFG_ALOS_THR_3_0, |
1954 | iomem: sd_inst, |
1955 | SD10G_LANE_LANE_48(sd_index)); |
1956 | |
1957 | sdx5_inst_rmw(SD10G_LANE_LANE_36_CFG_PREDRV_SLEWRATE_1_0_SET |
1958 | (params->cfg_predrv_slewrate_1_0), |
1959 | SD10G_LANE_LANE_36_CFG_PREDRV_SLEWRATE_1_0, |
1960 | iomem: sd_inst, |
1961 | SD10G_LANE_LANE_36(sd_index)); |
1962 | |
1963 | sdx5_inst_rmw(SD10G_LANE_LANE_32_CFG_ITX_IPCML_BASE_1_0_SET |
1964 | (params->cfg_itx_ipcml_base_1_0), |
1965 | SD10G_LANE_LANE_32_CFG_ITX_IPCML_BASE_1_0, |
1966 | iomem: sd_inst, |
1967 | SD10G_LANE_LANE_32(sd_index)); |
1968 | |
1969 | sdx5_inst_rmw(SD10G_LANE_LANE_37_CFG_IP_PRE_BASE_1_0_SET |
1970 | (params->cfg_ip_pre_base_1_0), |
1971 | SD10G_LANE_LANE_37_CFG_IP_PRE_BASE_1_0, |
1972 | iomem: sd_inst, |
1973 | SD10G_LANE_LANE_37(sd_index)); |
1974 | |
1975 | sdx5_inst_rmw(SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8_SET |
1976 | (params->cfg_lane_reserve_15_8), |
1977 | SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8, |
1978 | iomem: sd_inst, |
1979 | SD10G_LANE_LANE_41(sd_index)); |
1980 | |
1981 | sdx5_inst_rmw(SD10G_LANE_LANE_9E_R_EN_AUTO_CDR_RSTN_SET |
1982 | (params->r_en_auto_cdr_rstn), |
1983 | SD10G_LANE_LANE_9E_R_EN_AUTO_CDR_RSTN, |
1984 | iomem: sd_inst, |
1985 | SD10G_LANE_LANE_9E(sd_index)); |
1986 | |
1987 | sdx5_inst_rmw(SD10G_LANE_LANE_0C_CFG_OSCAL_AFE_SET |
1988 | (params->cfg_oscal_afe) | |
1989 | SD10G_LANE_LANE_0C_CFG_PD_OSDAC_AFE_SET |
1990 | (params->cfg_pd_osdac_afe), |
1991 | SD10G_LANE_LANE_0C_CFG_OSCAL_AFE | |
1992 | SD10G_LANE_LANE_0C_CFG_PD_OSDAC_AFE, |
1993 | iomem: sd_inst, |
1994 | SD10G_LANE_LANE_0C(sd_index)); |
1995 | |
1996 | sdx5_inst_rmw(SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_AFE_SET |
1997 | (params->cfg_resetb_oscal_afe[0]), |
1998 | SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_AFE, |
1999 | iomem: sd_inst, |
2000 | SD10G_LANE_LANE_0B(sd_index)); |
2001 | |
2002 | sdx5_inst_rmw(SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_AFE_SET |
2003 | (params->cfg_resetb_oscal_afe[1]), |
2004 | SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_AFE, |
2005 | iomem: sd_inst, |
2006 | SD10G_LANE_LANE_0B(sd_index)); |
2007 | |
2008 | sdx5_inst_rmw(SD10G_LANE_LANE_83_R_TX_POL_INV_SET |
2009 | (params->r_tx_pol_inv) | |
2010 | SD10G_LANE_LANE_83_R_RX_POL_INV_SET |
2011 | (params->r_rx_pol_inv), |
2012 | SD10G_LANE_LANE_83_R_TX_POL_INV | |
2013 | SD10G_LANE_LANE_83_R_RX_POL_INV, |
2014 | iomem: sd_inst, |
2015 | SD10G_LANE_LANE_83(sd_index)); |
2016 | |
2017 | sdx5_inst_rmw(SD10G_LANE_LANE_06_CFG_RX2TX_LP_EN_SET |
2018 | (params->cfg_rx2tx_lp_en) | |
2019 | SD10G_LANE_LANE_06_CFG_TX2RX_LP_EN_SET |
2020 | (params->cfg_tx2rx_lp_en), |
2021 | SD10G_LANE_LANE_06_CFG_RX2TX_LP_EN | |
2022 | SD10G_LANE_LANE_06_CFG_TX2RX_LP_EN, |
2023 | iomem: sd_inst, |
2024 | SD10G_LANE_LANE_06(sd_index)); |
2025 | |
2026 | sdx5_inst_rmw(SD10G_LANE_LANE_0E_CFG_RXLB_EN_SET(params->cfg_rxlb_en) | |
2027 | SD10G_LANE_LANE_0E_CFG_TXLB_EN_SET(params->cfg_txlb_en), |
2028 | SD10G_LANE_LANE_0E_CFG_RXLB_EN | |
2029 | SD10G_LANE_LANE_0E_CFG_TXLB_EN, |
2030 | iomem: sd_inst, |
2031 | SD10G_LANE_LANE_0E(sd_index)); |
2032 | |
2033 | sdx5_rmw(SD_LANE_SD_LANE_CFG_MACRO_RST_SET(0), |
2034 | SD_LANE_SD_LANE_CFG_MACRO_RST, |
2035 | priv, |
2036 | SD_LANE_SD_LANE_CFG(lane_index)); |
2037 | |
2038 | sdx5_inst_rmw(SD10G_LANE_LANE_50_CFG_SSC_RESETB_SET(1), |
2039 | SD10G_LANE_LANE_50_CFG_SSC_RESETB, |
2040 | iomem: sd_inst, |
2041 | SD10G_LANE_LANE_50(sd_index)); |
2042 | |
2043 | sdx5_rmw(SD10G_LANE_LANE_50_CFG_SSC_RESETB_SET(1), |
2044 | SD10G_LANE_LANE_50_CFG_SSC_RESETB, |
2045 | priv, |
2046 | SD10G_LANE_LANE_50(sd_index)); |
2047 | |
2048 | sdx5_rmw(SD_LANE_MISC_SD_125_RST_DIS_SET(params->fx_100), |
2049 | SD_LANE_MISC_SD_125_RST_DIS, |
2050 | priv, |
2051 | SD_LANE_MISC(lane_index)); |
2052 | |
2053 | sdx5_rmw(SD_LANE_MISC_RX_ENA_SET(params->fx_100), |
2054 | SD_LANE_MISC_RX_ENA, |
2055 | priv, |
2056 | SD_LANE_MISC(lane_index)); |
2057 | |
2058 | sdx5_rmw(SD_LANE_MISC_MUX_ENA_SET(params->fx_100), |
2059 | SD_LANE_MISC_MUX_ENA, |
2060 | priv, |
2061 | SD_LANE_MISC(lane_index)); |
2062 | |
2063 | usleep_range(min: 3000, max: 6000); |
2064 | |
2065 | value = readl(addr: sdx5_addr(base: regs, SD_LANE_SD_LANE_STAT(lane_index))); |
2066 | value = SD_LANE_SD_LANE_STAT_PMA_RST_DONE_GET(value); |
2067 | if (value != 1) { |
2068 | dev_err(dev, "10G PMA Reset failed: 0x%x\n" , value); |
2069 | return -EINVAL; |
2070 | } |
2071 | |
2072 | sdx5_rmw(SD_LANE_SD_SER_RST_SER_RST_SET(0x0), |
2073 | SD_LANE_SD_SER_RST_SER_RST, |
2074 | priv, |
2075 | SD_LANE_SD_SER_RST(lane_index)); |
2076 | |
2077 | sdx5_rmw(SD_LANE_SD_DES_RST_DES_RST_SET(0x0), |
2078 | SD_LANE_SD_DES_RST_DES_RST, |
2079 | priv, |
2080 | SD_LANE_SD_DES_RST(lane_index)); |
2081 | |
2082 | return 0; |
2083 | } |
2084 | |
2085 | static int sparx5_sd25g28_config(struct sparx5_serdes_macro *macro, bool reset) |
2086 | { |
2087 | struct sparx5_sd25g28_media_preset media = media_presets_25g[macro->media]; |
2088 | struct sparx5_sd25g28_mode_preset mode; |
2089 | struct sparx5_sd25g28_args args = { |
2090 | .rxinvert = 1, |
2091 | .txinvert = 0, |
2092 | .txswing = 240, |
2093 | .com_pll_reserve = 0xf, |
2094 | .reg_rst = reset, |
2095 | }; |
2096 | struct sparx5_sd25g28_params params; |
2097 | int err; |
2098 | |
2099 | err = sparx5_sd10g25_get_mode_preset(macro, mode: &mode); |
2100 | if (err) |
2101 | return err; |
2102 | sparx5_sd25g28_get_params(macro, media: &media, mode: &mode, args: &args, params: ¶ms); |
2103 | sparx5_sd25g28_reset(regs: macro->priv->regs, params: ¶ms, sd_index: macro->stpidx); |
2104 | return sparx5_sd25g28_apply_params(macro, params: ¶ms); |
2105 | } |
2106 | |
2107 | static int sparx5_sd10g28_config(struct sparx5_serdes_macro *macro, bool reset) |
2108 | { |
2109 | struct sparx5_sd10g28_media_preset media = media_presets_10g[macro->media]; |
2110 | struct sparx5_sd10g28_mode_preset mode; |
2111 | struct sparx5_sd10g28_params params; |
2112 | struct sparx5_sd10g28_args args = { |
2113 | .is_6g = (macro->serdestype == SPX5_SDT_6G), |
2114 | .txinvert = 0, |
2115 | .rxinvert = 1, |
2116 | .txswing = 240, |
2117 | .reg_rst = reset, |
2118 | .skip_cmu_cfg = reset, |
2119 | }; |
2120 | int err; |
2121 | |
2122 | err = sparx5_sd10g28_get_mode_preset(macro, mode: &mode, args: &args); |
2123 | if (err) |
2124 | return err; |
2125 | sparx5_sd10g28_get_params(macro, media: &media, mode: &mode, args: &args, params: ¶ms); |
2126 | sparx5_sd10g28_reset(regs: macro->priv->regs, lane_index: macro->sidx); |
2127 | return sparx5_sd10g28_apply_params(macro, params: ¶ms); |
2128 | } |
2129 | |
2130 | /* Power down serdes TX driver */ |
2131 | static int sparx5_serdes_power_save(struct sparx5_serdes_macro *macro, u32 pwdn) |
2132 | { |
2133 | struct sparx5_serdes_private *priv = macro->priv; |
2134 | void __iomem *sd_inst, *sd_lane_inst; |
2135 | |
2136 | if (macro->serdestype == SPX5_SDT_6G) |
2137 | sd_inst = sdx5_inst_get(priv, id: TARGET_SD6G_LANE, tinst: macro->stpidx); |
2138 | else if (macro->serdestype == SPX5_SDT_10G) |
2139 | sd_inst = sdx5_inst_get(priv, id: TARGET_SD10G_LANE, tinst: macro->stpidx); |
2140 | else |
2141 | sd_inst = sdx5_inst_get(priv, id: TARGET_SD25G_LANE, tinst: macro->stpidx); |
2142 | |
2143 | if (macro->serdestype == SPX5_SDT_25G) { |
2144 | sd_lane_inst = sdx5_inst_get(priv, id: TARGET_SD_LANE_25G, |
2145 | tinst: macro->stpidx); |
2146 | /* Take serdes out of reset */ |
2147 | sdx5_inst_rmw(SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST_SET(0), |
2148 | SD_LANE_25G_SD_LANE_CFG_EXT_CFG_RST, iomem: sd_lane_inst, |
2149 | SD_LANE_25G_SD_LANE_CFG(0)); |
2150 | |
2151 | /* Configure optimal settings for quiet mode */ |
2152 | sdx5_inst_rmw(SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL), |
2153 | SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE, |
2154 | iomem: sd_lane_inst, SD_LANE_25G_QUIET_MODE_6G(0)); |
2155 | |
2156 | sdx5_inst_rmw(SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER_SET(pwdn), |
2157 | SD25G_LANE_LANE_04_LN_CFG_PD_DRIVER, |
2158 | iomem: sd_inst, |
2159 | SD25G_LANE_LANE_04(0)); |
2160 | } else { |
2161 | /* 6G and 10G */ |
2162 | sd_lane_inst = sdx5_inst_get(priv, id: TARGET_SD_LANE, tinst: macro->sidx); |
2163 | |
2164 | /* Take serdes out of reset */ |
2165 | sdx5_inst_rmw(SD_LANE_SD_LANE_CFG_EXT_CFG_RST_SET(0), |
2166 | SD_LANE_SD_LANE_CFG_EXT_CFG_RST, iomem: sd_lane_inst, |
2167 | SD_LANE_SD_LANE_CFG(0)); |
2168 | |
2169 | /* Configure optimal settings for quiet mode */ |
2170 | sdx5_inst_rmw(SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(SPX5_SERDES_QUIET_MODE_VAL), |
2171 | SD_LANE_QUIET_MODE_6G_QUIET_MODE, iomem: sd_lane_inst, |
2172 | SD_LANE_QUIET_MODE_6G(0)); |
2173 | |
2174 | sdx5_inst_rmw(SD10G_LANE_LANE_06_CFG_PD_DRIVER_SET(pwdn), |
2175 | SD10G_LANE_LANE_06_CFG_PD_DRIVER, |
2176 | iomem: sd_inst, |
2177 | SD10G_LANE_LANE_06(0)); |
2178 | } |
2179 | return 0; |
2180 | } |
2181 | |
2182 | static int sparx5_serdes_clock_config(struct sparx5_serdes_macro *macro) |
2183 | { |
2184 | struct sparx5_serdes_private *priv = macro->priv; |
2185 | |
2186 | if (macro->serdesmode == SPX5_SD_MODE_100FX) { |
2187 | u32 freq = priv->coreclock == 250000000 ? 2 : |
2188 | priv->coreclock == 500000000 ? 1 : 0; |
2189 | |
2190 | sdx5_rmw(SD_LANE_MISC_CORE_CLK_FREQ_SET(freq), |
2191 | SD_LANE_MISC_CORE_CLK_FREQ, |
2192 | priv, |
2193 | SD_LANE_MISC(macro->sidx)); |
2194 | } |
2195 | return 0; |
2196 | } |
2197 | |
2198 | static int sparx5_serdes_get_serdesmode(phy_interface_t portmode, int speed) |
2199 | { |
2200 | switch (portmode) { |
2201 | case PHY_INTERFACE_MODE_1000BASEX: |
2202 | case PHY_INTERFACE_MODE_2500BASEX: |
2203 | if (speed == SPEED_2500) |
2204 | return SPX5_SD_MODE_2G5; |
2205 | if (speed == SPEED_100) |
2206 | return SPX5_SD_MODE_100FX; |
2207 | return SPX5_SD_MODE_1000BASEX; |
2208 | case PHY_INTERFACE_MODE_SGMII: |
2209 | /* The same Serdes mode is used for both SGMII and 1000BaseX */ |
2210 | return SPX5_SD_MODE_1000BASEX; |
2211 | case PHY_INTERFACE_MODE_QSGMII: |
2212 | return SPX5_SD_MODE_QSGMII; |
2213 | case PHY_INTERFACE_MODE_10GBASER: |
2214 | return SPX5_SD_MODE_SFI; |
2215 | default: |
2216 | return -EINVAL; |
2217 | } |
2218 | } |
2219 | |
2220 | static int sparx5_serdes_config(struct sparx5_serdes_macro *macro) |
2221 | { |
2222 | struct device *dev = macro->priv->dev; |
2223 | int serdesmode; |
2224 | int err; |
2225 | |
2226 | serdesmode = sparx5_serdes_get_serdesmode(portmode: macro->portmode, speed: macro->speed); |
2227 | if (serdesmode < 0) { |
2228 | dev_err(dev, "SerDes %u, interface not supported: %s\n" , |
2229 | macro->sidx, |
2230 | phy_modes(macro->portmode)); |
2231 | return serdesmode; |
2232 | } |
2233 | macro->serdesmode = serdesmode; |
2234 | |
2235 | sparx5_serdes_clock_config(macro); |
2236 | |
2237 | if (macro->serdestype == SPX5_SDT_25G) |
2238 | err = sparx5_sd25g28_config(macro, reset: false); |
2239 | else |
2240 | err = sparx5_sd10g28_config(macro, reset: false); |
2241 | if (err) { |
2242 | dev_err(dev, "SerDes %u, config error: %d\n" , |
2243 | macro->sidx, err); |
2244 | } |
2245 | return err; |
2246 | } |
2247 | |
2248 | static int sparx5_serdes_power_on(struct phy *phy) |
2249 | { |
2250 | struct sparx5_serdes_macro *macro = phy_get_drvdata(phy); |
2251 | |
2252 | return sparx5_serdes_power_save(macro, pwdn: false); |
2253 | } |
2254 | |
2255 | static int sparx5_serdes_power_off(struct phy *phy) |
2256 | { |
2257 | struct sparx5_serdes_macro *macro = phy_get_drvdata(phy); |
2258 | |
2259 | return sparx5_serdes_power_save(macro, pwdn: true); |
2260 | } |
2261 | |
2262 | static int sparx5_serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode) |
2263 | { |
2264 | struct sparx5_serdes_macro *macro; |
2265 | |
2266 | if (mode != PHY_MODE_ETHERNET) |
2267 | return -EINVAL; |
2268 | |
2269 | switch (submode) { |
2270 | case PHY_INTERFACE_MODE_1000BASEX: |
2271 | case PHY_INTERFACE_MODE_2500BASEX: |
2272 | case PHY_INTERFACE_MODE_SGMII: |
2273 | case PHY_INTERFACE_MODE_QSGMII: |
2274 | case PHY_INTERFACE_MODE_10GBASER: |
2275 | macro = phy_get_drvdata(phy); |
2276 | macro->portmode = submode; |
2277 | sparx5_serdes_config(macro); |
2278 | return 0; |
2279 | default: |
2280 | return -EINVAL; |
2281 | } |
2282 | } |
2283 | |
2284 | static int sparx5_serdes_set_media(struct phy *phy, enum phy_media media) |
2285 | { |
2286 | struct sparx5_serdes_macro *macro = phy_get_drvdata(phy); |
2287 | |
2288 | if (media != macro->media) { |
2289 | macro->media = media; |
2290 | if (macro->serdesmode != SPX5_SD_MODE_NONE) |
2291 | sparx5_serdes_config(macro); |
2292 | } |
2293 | return 0; |
2294 | } |
2295 | |
2296 | static int sparx5_serdes_set_speed(struct phy *phy, int speed) |
2297 | { |
2298 | struct sparx5_serdes_macro *macro = phy_get_drvdata(phy); |
2299 | |
2300 | if (macro->sidx < SPX5_SERDES_10G_START && speed > SPEED_5000) |
2301 | return -EINVAL; |
2302 | if (macro->sidx < SPX5_SERDES_25G_START && speed > SPEED_10000) |
2303 | return -EINVAL; |
2304 | if (speed != macro->speed) { |
2305 | macro->speed = speed; |
2306 | if (macro->serdesmode != SPX5_SD_MODE_NONE) |
2307 | sparx5_serdes_config(macro); |
2308 | } |
2309 | return 0; |
2310 | } |
2311 | |
2312 | static int sparx5_serdes_reset(struct phy *phy) |
2313 | { |
2314 | struct sparx5_serdes_macro *macro = phy_get_drvdata(phy); |
2315 | int err; |
2316 | |
2317 | if (macro->serdestype == SPX5_SDT_25G) |
2318 | err = sparx5_sd25g28_config(macro, reset: true); |
2319 | else |
2320 | err = sparx5_sd10g28_config(macro, reset: true); |
2321 | if (err) { |
2322 | dev_err(&phy->dev, "SerDes %u, reset error: %d\n" , |
2323 | macro->sidx, err); |
2324 | } |
2325 | return err; |
2326 | } |
2327 | |
2328 | static int sparx5_serdes_validate(struct phy *phy, enum phy_mode mode, |
2329 | int submode, |
2330 | union phy_configure_opts *opts) |
2331 | { |
2332 | struct sparx5_serdes_macro *macro = phy_get_drvdata(phy); |
2333 | |
2334 | if (mode != PHY_MODE_ETHERNET) |
2335 | return -EINVAL; |
2336 | |
2337 | if (macro->speed == 0) |
2338 | return -EINVAL; |
2339 | |
2340 | if (macro->sidx < SPX5_SERDES_10G_START && macro->speed > SPEED_5000) |
2341 | return -EINVAL; |
2342 | if (macro->sidx < SPX5_SERDES_25G_START && macro->speed > SPEED_10000) |
2343 | return -EINVAL; |
2344 | |
2345 | switch (submode) { |
2346 | case PHY_INTERFACE_MODE_1000BASEX: |
2347 | if (macro->speed != SPEED_100 && /* This is for 100BASE-FX */ |
2348 | macro->speed != SPEED_1000) |
2349 | return -EINVAL; |
2350 | break; |
2351 | case PHY_INTERFACE_MODE_SGMII: |
2352 | case PHY_INTERFACE_MODE_2500BASEX: |
2353 | case PHY_INTERFACE_MODE_QSGMII: |
2354 | if (macro->speed >= SPEED_5000) |
2355 | return -EINVAL; |
2356 | break; |
2357 | case PHY_INTERFACE_MODE_10GBASER: |
2358 | if (macro->speed < SPEED_5000) |
2359 | return -EINVAL; |
2360 | break; |
2361 | default: |
2362 | return -EINVAL; |
2363 | } |
2364 | return 0; |
2365 | } |
2366 | |
2367 | static const struct phy_ops sparx5_serdes_ops = { |
2368 | .power_on = sparx5_serdes_power_on, |
2369 | .power_off = sparx5_serdes_power_off, |
2370 | .set_mode = sparx5_serdes_set_mode, |
2371 | .set_media = sparx5_serdes_set_media, |
2372 | .set_speed = sparx5_serdes_set_speed, |
2373 | .reset = sparx5_serdes_reset, |
2374 | .validate = sparx5_serdes_validate, |
2375 | .owner = THIS_MODULE, |
2376 | }; |
2377 | |
2378 | static int sparx5_phy_create(struct sparx5_serdes_private *priv, |
2379 | int idx, struct phy **phy) |
2380 | { |
2381 | struct sparx5_serdes_macro *macro; |
2382 | |
2383 | *phy = devm_phy_create(dev: priv->dev, NULL, ops: &sparx5_serdes_ops); |
2384 | if (IS_ERR(ptr: *phy)) |
2385 | return PTR_ERR(ptr: *phy); |
2386 | |
2387 | macro = devm_kzalloc(dev: priv->dev, size: sizeof(*macro), GFP_KERNEL); |
2388 | if (!macro) |
2389 | return -ENOMEM; |
2390 | |
2391 | macro->sidx = idx; |
2392 | macro->priv = priv; |
2393 | macro->speed = SPEED_UNKNOWN; |
2394 | if (idx < SPX5_SERDES_10G_START) { |
2395 | macro->serdestype = SPX5_SDT_6G; |
2396 | macro->stpidx = macro->sidx; |
2397 | } else if (idx < SPX5_SERDES_25G_START) { |
2398 | macro->serdestype = SPX5_SDT_10G; |
2399 | macro->stpidx = macro->sidx - SPX5_SERDES_10G_START; |
2400 | } else { |
2401 | macro->serdestype = SPX5_SDT_25G; |
2402 | macro->stpidx = macro->sidx - SPX5_SERDES_25G_START; |
2403 | } |
2404 | |
2405 | phy_set_drvdata(phy: *phy, data: macro); |
2406 | |
2407 | /* Power off serdes by default */ |
2408 | sparx5_serdes_power_off(phy: *phy); |
2409 | |
2410 | return 0; |
2411 | } |
2412 | |
2413 | static struct sparx5_serdes_io_resource sparx5_serdes_iomap[] = { |
2414 | { TARGET_SD_CMU, 0x0 }, /* 0x610808000: sd_cmu_0 */ |
2415 | { TARGET_SD_CMU + 1, 0x8000 }, /* 0x610810000: sd_cmu_1 */ |
2416 | { TARGET_SD_CMU + 2, 0x10000 }, /* 0x610818000: sd_cmu_2 */ |
2417 | { TARGET_SD_CMU + 3, 0x18000 }, /* 0x610820000: sd_cmu_3 */ |
2418 | { TARGET_SD_CMU + 4, 0x20000 }, /* 0x610828000: sd_cmu_4 */ |
2419 | { TARGET_SD_CMU + 5, 0x28000 }, /* 0x610830000: sd_cmu_5 */ |
2420 | { TARGET_SD_CMU + 6, 0x30000 }, /* 0x610838000: sd_cmu_6 */ |
2421 | { TARGET_SD_CMU + 7, 0x38000 }, /* 0x610840000: sd_cmu_7 */ |
2422 | { TARGET_SD_CMU + 8, 0x40000 }, /* 0x610848000: sd_cmu_8 */ |
2423 | { TARGET_SD_CMU_CFG, 0x48000 }, /* 0x610850000: sd_cmu_cfg_0 */ |
2424 | { TARGET_SD_CMU_CFG + 1, 0x50000 }, /* 0x610858000: sd_cmu_cfg_1 */ |
2425 | { TARGET_SD_CMU_CFG + 2, 0x58000 }, /* 0x610860000: sd_cmu_cfg_2 */ |
2426 | { TARGET_SD_CMU_CFG + 3, 0x60000 }, /* 0x610868000: sd_cmu_cfg_3 */ |
2427 | { TARGET_SD_CMU_CFG + 4, 0x68000 }, /* 0x610870000: sd_cmu_cfg_4 */ |
2428 | { TARGET_SD_CMU_CFG + 5, 0x70000 }, /* 0x610878000: sd_cmu_cfg_5 */ |
2429 | { TARGET_SD_CMU_CFG + 6, 0x78000 }, /* 0x610880000: sd_cmu_cfg_6 */ |
2430 | { TARGET_SD_CMU_CFG + 7, 0x80000 }, /* 0x610888000: sd_cmu_cfg_7 */ |
2431 | { TARGET_SD_CMU_CFG + 8, 0x88000 }, /* 0x610890000: sd_cmu_cfg_8 */ |
2432 | { TARGET_SD6G_LANE, 0x90000 }, /* 0x610898000: sd6g_lane_0 */ |
2433 | { TARGET_SD6G_LANE + 1, 0x98000 }, /* 0x6108a0000: sd6g_lane_1 */ |
2434 | { TARGET_SD6G_LANE + 2, 0xa0000 }, /* 0x6108a8000: sd6g_lane_2 */ |
2435 | { TARGET_SD6G_LANE + 3, 0xa8000 }, /* 0x6108b0000: sd6g_lane_3 */ |
2436 | { TARGET_SD6G_LANE + 4, 0xb0000 }, /* 0x6108b8000: sd6g_lane_4 */ |
2437 | { TARGET_SD6G_LANE + 5, 0xb8000 }, /* 0x6108c0000: sd6g_lane_5 */ |
2438 | { TARGET_SD6G_LANE + 6, 0xc0000 }, /* 0x6108c8000: sd6g_lane_6 */ |
2439 | { TARGET_SD6G_LANE + 7, 0xc8000 }, /* 0x6108d0000: sd6g_lane_7 */ |
2440 | { TARGET_SD6G_LANE + 8, 0xd0000 }, /* 0x6108d8000: sd6g_lane_8 */ |
2441 | { TARGET_SD6G_LANE + 9, 0xd8000 }, /* 0x6108e0000: sd6g_lane_9 */ |
2442 | { TARGET_SD6G_LANE + 10, 0xe0000 }, /* 0x6108e8000: sd6g_lane_10 */ |
2443 | { TARGET_SD6G_LANE + 11, 0xe8000 }, /* 0x6108f0000: sd6g_lane_11 */ |
2444 | { TARGET_SD6G_LANE + 12, 0xf0000 }, /* 0x6108f8000: sd6g_lane_12 */ |
2445 | { TARGET_SD10G_LANE, 0xf8000 }, /* 0x610900000: sd10g_lane_0 */ |
2446 | { TARGET_SD10G_LANE + 1, 0x100000 }, /* 0x610908000: sd10g_lane_1 */ |
2447 | { TARGET_SD10G_LANE + 2, 0x108000 }, /* 0x610910000: sd10g_lane_2 */ |
2448 | { TARGET_SD10G_LANE + 3, 0x110000 }, /* 0x610918000: sd10g_lane_3 */ |
2449 | { TARGET_SD_LANE, 0x1a0000 }, /* 0x6109a8000: sd_lane_0 */ |
2450 | { TARGET_SD_LANE + 1, 0x1a8000 }, /* 0x6109b0000: sd_lane_1 */ |
2451 | { TARGET_SD_LANE + 2, 0x1b0000 }, /* 0x6109b8000: sd_lane_2 */ |
2452 | { TARGET_SD_LANE + 3, 0x1b8000 }, /* 0x6109c0000: sd_lane_3 */ |
2453 | { TARGET_SD_LANE + 4, 0x1c0000 }, /* 0x6109c8000: sd_lane_4 */ |
2454 | { TARGET_SD_LANE + 5, 0x1c8000 }, /* 0x6109d0000: sd_lane_5 */ |
2455 | { TARGET_SD_LANE + 6, 0x1d0000 }, /* 0x6109d8000: sd_lane_6 */ |
2456 | { TARGET_SD_LANE + 7, 0x1d8000 }, /* 0x6109e0000: sd_lane_7 */ |
2457 | { TARGET_SD_LANE + 8, 0x1e0000 }, /* 0x6109e8000: sd_lane_8 */ |
2458 | { TARGET_SD_LANE + 9, 0x1e8000 }, /* 0x6109f0000: sd_lane_9 */ |
2459 | { TARGET_SD_LANE + 10, 0x1f0000 }, /* 0x6109f8000: sd_lane_10 */ |
2460 | { TARGET_SD_LANE + 11, 0x1f8000 }, /* 0x610a00000: sd_lane_11 */ |
2461 | { TARGET_SD_LANE + 12, 0x200000 }, /* 0x610a08000: sd_lane_12 */ |
2462 | { TARGET_SD_LANE + 13, 0x208000 }, /* 0x610a10000: sd_lane_13 */ |
2463 | { TARGET_SD_LANE + 14, 0x210000 }, /* 0x610a18000: sd_lane_14 */ |
2464 | { TARGET_SD_LANE + 15, 0x218000 }, /* 0x610a20000: sd_lane_15 */ |
2465 | { TARGET_SD_LANE + 16, 0x220000 }, /* 0x610a28000: sd_lane_16 */ |
2466 | { TARGET_SD_CMU + 9, 0x400000 }, /* 0x610c08000: sd_cmu_9 */ |
2467 | { TARGET_SD_CMU + 10, 0x408000 }, /* 0x610c10000: sd_cmu_10 */ |
2468 | { TARGET_SD_CMU + 11, 0x410000 }, /* 0x610c18000: sd_cmu_11 */ |
2469 | { TARGET_SD_CMU + 12, 0x418000 }, /* 0x610c20000: sd_cmu_12 */ |
2470 | { TARGET_SD_CMU + 13, 0x420000 }, /* 0x610c28000: sd_cmu_13 */ |
2471 | { TARGET_SD_CMU_CFG + 9, 0x428000 }, /* 0x610c30000: sd_cmu_cfg_9 */ |
2472 | { TARGET_SD_CMU_CFG + 10, 0x430000 }, /* 0x610c38000: sd_cmu_cfg_10 */ |
2473 | { TARGET_SD_CMU_CFG + 11, 0x438000 }, /* 0x610c40000: sd_cmu_cfg_11 */ |
2474 | { TARGET_SD_CMU_CFG + 12, 0x440000 }, /* 0x610c48000: sd_cmu_cfg_12 */ |
2475 | { TARGET_SD_CMU_CFG + 13, 0x448000 }, /* 0x610c50000: sd_cmu_cfg_13 */ |
2476 | { TARGET_SD10G_LANE + 4, 0x450000 }, /* 0x610c58000: sd10g_lane_4 */ |
2477 | { TARGET_SD10G_LANE + 5, 0x458000 }, /* 0x610c60000: sd10g_lane_5 */ |
2478 | { TARGET_SD10G_LANE + 6, 0x460000 }, /* 0x610c68000: sd10g_lane_6 */ |
2479 | { TARGET_SD10G_LANE + 7, 0x468000 }, /* 0x610c70000: sd10g_lane_7 */ |
2480 | { TARGET_SD10G_LANE + 8, 0x470000 }, /* 0x610c78000: sd10g_lane_8 */ |
2481 | { TARGET_SD10G_LANE + 9, 0x478000 }, /* 0x610c80000: sd10g_lane_9 */ |
2482 | { TARGET_SD10G_LANE + 10, 0x480000 }, /* 0x610c88000: sd10g_lane_10 */ |
2483 | { TARGET_SD10G_LANE + 11, 0x488000 }, /* 0x610c90000: sd10g_lane_11 */ |
2484 | { TARGET_SD25G_LANE, 0x490000 }, /* 0x610c98000: sd25g_lane_0 */ |
2485 | { TARGET_SD25G_LANE + 1, 0x498000 }, /* 0x610ca0000: sd25g_lane_1 */ |
2486 | { TARGET_SD25G_LANE + 2, 0x4a0000 }, /* 0x610ca8000: sd25g_lane_2 */ |
2487 | { TARGET_SD25G_LANE + 3, 0x4a8000 }, /* 0x610cb0000: sd25g_lane_3 */ |
2488 | { TARGET_SD25G_LANE + 4, 0x4b0000 }, /* 0x610cb8000: sd25g_lane_4 */ |
2489 | { TARGET_SD25G_LANE + 5, 0x4b8000 }, /* 0x610cc0000: sd25g_lane_5 */ |
2490 | { TARGET_SD25G_LANE + 6, 0x4c0000 }, /* 0x610cc8000: sd25g_lane_6 */ |
2491 | { TARGET_SD25G_LANE + 7, 0x4c8000 }, /* 0x610cd0000: sd25g_lane_7 */ |
2492 | { TARGET_SD_LANE + 17, 0x550000 }, /* 0x610d58000: sd_lane_17 */ |
2493 | { TARGET_SD_LANE + 18, 0x558000 }, /* 0x610d60000: sd_lane_18 */ |
2494 | { TARGET_SD_LANE + 19, 0x560000 }, /* 0x610d68000: sd_lane_19 */ |
2495 | { TARGET_SD_LANE + 20, 0x568000 }, /* 0x610d70000: sd_lane_20 */ |
2496 | { TARGET_SD_LANE + 21, 0x570000 }, /* 0x610d78000: sd_lane_21 */ |
2497 | { TARGET_SD_LANE + 22, 0x578000 }, /* 0x610d80000: sd_lane_22 */ |
2498 | { TARGET_SD_LANE + 23, 0x580000 }, /* 0x610d88000: sd_lane_23 */ |
2499 | { TARGET_SD_LANE + 24, 0x588000 }, /* 0x610d90000: sd_lane_24 */ |
2500 | { TARGET_SD_LANE_25G, 0x590000 }, /* 0x610d98000: sd_lane_25g_25 */ |
2501 | { TARGET_SD_LANE_25G + 1, 0x598000 }, /* 0x610da0000: sd_lane_25g_26 */ |
2502 | { TARGET_SD_LANE_25G + 2, 0x5a0000 }, /* 0x610da8000: sd_lane_25g_27 */ |
2503 | { TARGET_SD_LANE_25G + 3, 0x5a8000 }, /* 0x610db0000: sd_lane_25g_28 */ |
2504 | { TARGET_SD_LANE_25G + 4, 0x5b0000 }, /* 0x610db8000: sd_lane_25g_29 */ |
2505 | { TARGET_SD_LANE_25G + 5, 0x5b8000 }, /* 0x610dc0000: sd_lane_25g_30 */ |
2506 | { TARGET_SD_LANE_25G + 6, 0x5c0000 }, /* 0x610dc8000: sd_lane_25g_31 */ |
2507 | { TARGET_SD_LANE_25G + 7, 0x5c8000 }, /* 0x610dd0000: sd_lane_25g_32 */ |
2508 | }; |
2509 | |
2510 | /* Client lookup function, uses serdes index */ |
2511 | static struct phy *sparx5_serdes_xlate(struct device *dev, |
2512 | const struct of_phandle_args *args) |
2513 | { |
2514 | struct sparx5_serdes_private *priv = dev_get_drvdata(dev); |
2515 | int idx; |
2516 | unsigned int sidx; |
2517 | |
2518 | if (args->args_count != 1) |
2519 | return ERR_PTR(error: -EINVAL); |
2520 | |
2521 | sidx = args->args[0]; |
2522 | |
2523 | /* Check validity: ERR_PTR(-ENODEV) if not valid */ |
2524 | for (idx = 0; idx < SPX5_SERDES_MAX; idx++) { |
2525 | struct sparx5_serdes_macro *macro = |
2526 | phy_get_drvdata(phy: priv->phys[idx]); |
2527 | |
2528 | if (sidx != macro->sidx) |
2529 | continue; |
2530 | |
2531 | return priv->phys[idx]; |
2532 | } |
2533 | return ERR_PTR(error: -ENODEV); |
2534 | } |
2535 | |
2536 | static int sparx5_serdes_probe(struct platform_device *pdev) |
2537 | { |
2538 | struct device_node *np = pdev->dev.of_node; |
2539 | struct sparx5_serdes_private *priv; |
2540 | struct phy_provider *provider; |
2541 | struct resource *iores; |
2542 | void __iomem *iomem; |
2543 | unsigned long clock; |
2544 | struct clk *clk; |
2545 | int idx; |
2546 | int err; |
2547 | |
2548 | if (!np && !pdev->dev.platform_data) |
2549 | return -ENODEV; |
2550 | |
2551 | priv = devm_kzalloc(dev: &pdev->dev, size: sizeof(*priv), GFP_KERNEL); |
2552 | if (!priv) |
2553 | return -ENOMEM; |
2554 | |
2555 | platform_set_drvdata(pdev, data: priv); |
2556 | priv->dev = &pdev->dev; |
2557 | |
2558 | /* Get coreclock */ |
2559 | clk = devm_clk_get(dev: priv->dev, NULL); |
2560 | if (IS_ERR(ptr: clk)) { |
2561 | dev_err(priv->dev, "Failed to get coreclock\n" ); |
2562 | return PTR_ERR(ptr: clk); |
2563 | } |
2564 | clock = clk_get_rate(clk); |
2565 | if (clock == 0) { |
2566 | dev_err(priv->dev, "Invalid coreclock %lu\n" , clock); |
2567 | return -EINVAL; |
2568 | } |
2569 | priv->coreclock = clock; |
2570 | |
2571 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2572 | if (!iores) { |
2573 | dev_err(priv->dev, "Invalid resource\n" ); |
2574 | return -EINVAL; |
2575 | } |
2576 | iomem = devm_ioremap(dev: priv->dev, offset: iores->start, size: resource_size(res: iores)); |
2577 | if (!iomem) { |
2578 | dev_err(priv->dev, "Unable to get serdes registers: %s\n" , |
2579 | iores->name); |
2580 | return -ENOMEM; |
2581 | } |
2582 | for (idx = 0; idx < ARRAY_SIZE(sparx5_serdes_iomap); idx++) { |
2583 | struct sparx5_serdes_io_resource *iomap = &sparx5_serdes_iomap[idx]; |
2584 | |
2585 | priv->regs[iomap->id] = iomem + iomap->offset; |
2586 | } |
2587 | for (idx = 0; idx < SPX5_SERDES_MAX; idx++) { |
2588 | err = sparx5_phy_create(priv, idx, phy: &priv->phys[idx]); |
2589 | if (err) |
2590 | return err; |
2591 | } |
2592 | |
2593 | /* Power down all CMUs by default */ |
2594 | sparx5_serdes_cmu_power_off(priv); |
2595 | |
2596 | provider = devm_of_phy_provider_register(priv->dev, sparx5_serdes_xlate); |
2597 | |
2598 | return PTR_ERR_OR_ZERO(ptr: provider); |
2599 | } |
2600 | |
2601 | static const struct of_device_id sparx5_serdes_match[] = { |
2602 | { .compatible = "microchip,sparx5-serdes" }, |
2603 | { } |
2604 | }; |
2605 | MODULE_DEVICE_TABLE(of, sparx5_serdes_match); |
2606 | |
2607 | static struct platform_driver sparx5_serdes_driver = { |
2608 | .probe = sparx5_serdes_probe, |
2609 | .driver = { |
2610 | .name = "sparx5-serdes" , |
2611 | .of_match_table = sparx5_serdes_match, |
2612 | }, |
2613 | }; |
2614 | |
2615 | module_platform_driver(sparx5_serdes_driver); |
2616 | |
2617 | MODULE_DESCRIPTION("Microchip Sparx5 switch serdes driver" ); |
2618 | MODULE_AUTHOR("Steen Hegelund <steen.hegelund@microchip.com>" ); |
2619 | MODULE_LICENSE("GPL v2" ); |
2620 | |