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