blob: 639f40136e0e59bb4a8b97747a81339b94b072ed [file] [log] [blame]
T Michael Turney050be722019-10-22 06:25:09 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (c) 2019 Qualcomm Technologies
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and
8 * only version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
T Michael Turney050be722019-10-22 06:25:09 -070016#include <stdlib.h>
17#include <console/console.h>
18#include <delay.h>
Patrick Georgib9d5b262019-12-05 19:56:53 +010019#include <device/mmio.h>
T Michael Turney050be722019-10-22 06:25:09 -070020#include <soc/usb.h>
21#include <soc/clock.h>
22#include <soc/addressmap.h>
23#include <soc/efuse.h>
24#include <timer.h>
25
26struct usb_qusb_phy_dig {
27 u8 rsvd1[16];
28 u32 pwr_ctrl1;
29 u32 pwr_ctrl2;
30 u8 rsvd2[8];
31 u32 imp_ctrl1;
32 u32 imp_ctrl2;
33 u8 rsvd3[20];
34 u32 chg_ctrl2;
35 u32 tune1;
36 u32 tune2;
37 u32 tune3;
38 u32 tune4;
39 u32 tune5;
40 u8 rsvd4[44];
41 u32 debug_ctrl2;
42 u8 rsvd5[28];
43 u32 debug_stat5;
44};
45check_member(usb_qusb_phy_dig, tune5, 0x50);
46check_member(usb_qusb_phy_dig, debug_ctrl2, 0x80);
47check_member(usb_qusb_phy_dig, debug_stat5, 0xA0);
48
49struct usb_qusb_phy_pll {
50 u8 rsvd0[4];
51 u32 analog_controls_two;
52 u8 rsvd1[36];
53 u32 cmode;
54 u8 rsvd2[132];
55 u32 dig_tim;
56 u8 rsvd3[204];
57 u32 lock_delay;
58 u8 rsvd4[4];
59 u32 clock_inverters;
60 u8 rsvd5[4];
61 u32 bias_ctrl_1;
62 u32 bias_ctrl_2;
63};
64check_member(usb_qusb_phy_pll, cmode, 0x2C);
65check_member(usb_qusb_phy_pll, bias_ctrl_2, 0x198);
66check_member(usb_qusb_phy_pll, dig_tim, 0xB4);
67
68/* Only for QMP V3 PHY - QSERDES COM registers */
69struct usb3_phy_qserdes_com_reg_layout {
70 u8 _reserved1[16];
71 u32 com_ssc_en_center;
72 u32 com_ssc_adj_per1;
73 u32 com_ssc_adj_per2;
74 u32 com_ssc_per1;
75 u32 com_ssc_per2;
76 u32 com_ssc_step_size1;
77 u32 com_ssc_step_size2;
78 u8 _reserved2[8];
79 u32 com_bias_en_clkbuflr_en;
80 u32 com_sys_clk_enable1;
81 u32 com_sys_clk_ctrl;
82 u32 com_sysclk_buf_enable;
83 u32 com_pll_en;
84 u32 com_pll_ivco;
85 u8 _reserved3[20];
86 u32 com_cp_ctrl_mode0;
87 u8 _reserved4[4];
88 u32 com_pll_rctrl_mode0;
89 u8 _reserved5[4];
90 u32 com_pll_cctrl_mode0;
91 u8 _reserved6[12];
92 u32 com_sysclk_en_sel;
93 u8 _reserved7[8];
94 u32 com_resetsm_ctrl2;
95 u32 com_lock_cmp_en;
96 u32 com_lock_cmp_cfg;
97 u32 com_lock_cmp1_mode0;
98 u32 com_lock_cmp2_mode0;
99 u32 com_lock_cmp3_mode0;
100 u8 _reserved8[12];
101 u32 com_dec_start_mode0;
102 u8 _reserved9[4];
103 u32 com_div_frac_start1_mode0;
104 u32 com_div_frac_start2_mode0;
105 u32 com_div_frac_start3_mode0;
106 u8 _reserved10[20];
107 u32 com_integloop_gain0_mode0;
108 u32 com_integloop_gain1_mode0;
109 u8 _reserved11[16];
110 u32 com_vco_tune_map;
111 u32 com_vco_tune1_mode0;
112 u32 com_vco_tune2_mode0;
113 u8 _reserved12[60];
114 u32 com_clk_select;
115 u32 com_hsclk_sel;
116 u8 _reserved13[8];
117 u32 com_coreclk_div_mode0;
118 u8 _reserved14[8];
119 u32 com_core_clk_en;
120 u32 com_c_ready_status;
121 u32 com_cmn_config;
122 u32 com_cmn_rate_override;
123 u32 com_svs_mode_clk_sel;
124};
125check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_en_center, 0x010);
126check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_adj_per1, 0x014);
127check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_adj_per2, 0x018);
128check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_per1, 0x01c);
129check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_per2, 0x020);
130check_member(usb3_phy_qserdes_com_reg_layout, com_bias_en_clkbuflr_en, 0x034);
131check_member(usb3_phy_qserdes_com_reg_layout, com_pll_ivco, 0x048);
132check_member(usb3_phy_qserdes_com_reg_layout, com_cp_ctrl_mode0, 0x060);
133check_member(usb3_phy_qserdes_com_reg_layout, com_sysclk_en_sel, 0x080);
134check_member(usb3_phy_qserdes_com_reg_layout, com_resetsm_ctrl2, 0x08c);
135check_member(usb3_phy_qserdes_com_reg_layout, com_dec_start_mode0, 0x0b0);
136check_member(usb3_phy_qserdes_com_reg_layout, com_div_frac_start1_mode0, 0x0b8);
137check_member(usb3_phy_qserdes_com_reg_layout, com_integloop_gain0_mode0, 0x0d8);
138check_member(usb3_phy_qserdes_com_reg_layout, com_vco_tune_map, 0x0f0);
139check_member(usb3_phy_qserdes_com_reg_layout, com_clk_select, 0x138);
140check_member(usb3_phy_qserdes_com_reg_layout, com_coreclk_div_mode0, 0x148);
141check_member(usb3_phy_qserdes_com_reg_layout, com_core_clk_en, 0x154);
142check_member(usb3_phy_qserdes_com_reg_layout, com_svs_mode_clk_sel, 0x164);
143
144/* Only for QMP V3 PHY - TX registers */
145struct usb3_phy_qserdes_tx_reg_layout {
146 u8 _reserved1[68];
147 u32 tx_res_code_lane_offset_tx;
148 u32 tx_res_code_lane_offset_rx;
149 u8 _reserved2[20];
150 u32 tx_highz_drvr_en;
151 u8 _reserved3[40];
152 u32 tx_lane_mode_1;
153 u8 _reserved4[20];
154 u32 tx_rcv_detect_lvl_2;
155};
156check_member(usb3_phy_qserdes_tx_reg_layout, tx_res_code_lane_offset_tx, 0x044);
157check_member(usb3_phy_qserdes_tx_reg_layout, tx_res_code_lane_offset_rx, 0x048);
158check_member(usb3_phy_qserdes_tx_reg_layout, tx_highz_drvr_en, 0x060);
159check_member(usb3_phy_qserdes_tx_reg_layout, tx_lane_mode_1, 0x08c);
160check_member(usb3_phy_qserdes_tx_reg_layout, tx_rcv_detect_lvl_2, 0x0a4);
161
162/* Only for QMP V3 PHY - RX registers */
163struct usb3_phy_qserdes_rx_reg_layout {
164 u8 _reserved1[8];
165 u32 rx_ucdr_fo_gain;
166 u32 rx_ucdr_so_gain_half;
167 u8 _reserved2[32];
168 u32 rx_ucdr_fastlock_fo_gain;
169 u32 rx_ucdr_so_saturtn_and_en;
170 u8 _reserved3[12];
171 u32 rx_ucdr_pi_cntrls;
172 u8 _reserved4[120];
173 u32 rx_vga_cal_ctrl2;
174 u8 _reserved5[16];
175 u32 rx_rx_equ_adap_ctrl2;
176 u32 rx_rx_equ_adap_ctrl3;
177 u32 rx_rx_equ_adap_ctrl4;
178 u8 _reserved6[24];
179 u32 rx_rx_eq_offset_adap_ctrl1;
180 u32 rx_rx_offset_adap_ctrl2;
181 u32 rx_sigdet_enables;
182 u32 rx_sigdet_ctrl;
183 u8 _reserved7[4];
184 u32 rx_sigdet_deglitch_ctrl;
185 u32 rx_rx_band;
186 u8 _reserved8[80];
187 u32 rx_rx_mode_00;
188};
189check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_fo_gain, 0x008);
190check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_so_gain_half, 0x00c);
191check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_fastlock_fo_gain, 0x030);
192check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_so_saturtn_and_en, 0x034);
193check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_pi_cntrls, 0x044);
194check_member(usb3_phy_qserdes_rx_reg_layout, rx_vga_cal_ctrl2, 0x0c0);
195check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adap_ctrl2, 0x0d4);
196check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adap_ctrl3, 0x0d8);
197check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adap_ctrl4, 0x0dc);
198check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_eq_offset_adap_ctrl1, 0x0f8);
199check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_offset_adap_ctrl2, 0x0fc);
200check_member(usb3_phy_qserdes_rx_reg_layout, rx_sigdet_enables, 0x100);
201check_member(usb3_phy_qserdes_rx_reg_layout, rx_sigdet_ctrl, 0x104);
202check_member(usb3_phy_qserdes_rx_reg_layout, rx_sigdet_deglitch_ctrl, 0x10c);
203check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_band, 0x110);
204check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_00, 0x164);
205
206/* Only for QMP V3 PHY - PCS registers */
207struct usb3_phy_pcs_reg_layout {
208 u32 pcs_sw_reset;
209 u32 pcs_power_down_control;
210 u32 pcs_start_control;
211 u32 pcs_txmgn_v0;
212 u32 pcs_txmgn_v1;
213 u32 pcs_txmgn_v2;
214 u32 pcs_txmgn_v3;
215 u32 pcs_txmgn_v4;
216 u32 pcs_txmgn_ls;
217 u32 pcs_txdeemph_m6db_v0;
218 u32 pcs_txdeemph_m3p5db_v0;
219 u32 pcs_txdeemph_m6db_v1;
220 u32 pcs_txdeemph_m3p5db_v1;
221 u32 pcs_txdeemph_m6db_v2;
222 u32 pcs_txdeemph_m3p5db_v2;
223 u32 pcs_txdeemph_m6db_v3;
224 u32 pcs_txdeemph_m3p5db_v3;
225 u32 pcs_txdeemph_m6db_v4;
226 u32 pcs_txdeemph_m3p5db_v4;
227 u32 pcs_txdeemph_m6db_ls;
228 u32 pcs_txdeemph_m3p5db_ls;
229 u8 _reserved1[8];
230 u32 pcs_rate_slew_cntrl;
231 u8 _reserved2[4];
232 u32 pcs_power_state_config2;
233 u8 _reserved3[8];
234 u32 pcs_rcvr_dtct_dly_p1u2_l;
235 u32 pcs_rcvr_dtct_dly_p1u2_h;
236 u32 pcs_rcvr_dtct_dly_u3_l;
237 u32 pcs_rcvr_dtct_dly_u3_h;
238 u32 pcs_lock_detect_config1;
239 u32 pcs_lock_detect_config2;
240 u32 pcs_lock_detect_config3;
241 u32 pcs_tsync_rsync_time;
242 u8 _reserved4[16];
243 u32 pcs_pwrup_reset_dly_time_auxclk;
244 u8 _reserved5[12];
245 u32 pcs_lfps_ecstart_eqtlock;
246 u8 _reserved6[4];
247 u32 pcs_rxeqtraining_wait_time;
248 u32 pcs_rxeqtraining_run_time;
249 u8 _reserved7[4];
250 u32 pcs_fll_ctrl1;
251 u32 pcs_fll_ctrl2;
252 u32 pcs_fll_cnt_val_l;
253 u32 pcs_fll_cnt_val_h_tol;
254 u32 pcs_fll_man_code;
255 u32 pcs_autonomous_mode_ctrl;
256 u8 _reserved8[152];
257 u32 pcs_ready_status;
258 u8 _reserved9[96];
259 u32 pcs_rx_sigdet_lvl;
260 u8 _reserved10[48];
261 u32 pcs_refgen_req_config1;
262 u32 pcs_refgen_req_config2;
263};
264check_member(usb3_phy_pcs_reg_layout, pcs_sw_reset, 0x000);
265check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v0, 0x00c);
266check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v1, 0x010);
267check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v2, 0x014);
268check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v3, 0x018);
269check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_v4, 0x01c);
270check_member(usb3_phy_pcs_reg_layout, pcs_txmgn_ls, 0x020);
271check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v0, 0x024);
272check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v0, 0x028);
273check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v1, 0x02c);
274check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v1, 0x030);
275check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v2, 0x034);
276check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v2, 0x038);
277check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v3, 0x03c);
278check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v3, 0x040);
279check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_v4, 0x044);
280check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_v4, 0x048);
281check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m6db_ls, 0x04c);
282check_member(usb3_phy_pcs_reg_layout, pcs_txdeemph_m3p5db_ls, 0x050);
283check_member(usb3_phy_pcs_reg_layout, pcs_rate_slew_cntrl, 0x05c);
284check_member(usb3_phy_pcs_reg_layout, pcs_power_state_config2, 0x064);
285check_member(usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_p1u2_l, 0x070);
286check_member(usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_p1u2_h, 0x074);
287check_member(usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_u3_l, 0x078);
288check_member(usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_u3_h, 0x07c);
289check_member(usb3_phy_pcs_reg_layout, pcs_lock_detect_config1, 0x080);
290check_member(usb3_phy_pcs_reg_layout, pcs_lock_detect_config2, 0x084);
291check_member(usb3_phy_pcs_reg_layout, pcs_lock_detect_config3, 0x088);
292check_member(usb3_phy_pcs_reg_layout, pcs_pwrup_reset_dly_time_auxclk, 0x0a0);
293check_member(usb3_phy_pcs_reg_layout, pcs_rxeqtraining_wait_time, 0x0b8);
294check_member(usb3_phy_pcs_reg_layout, pcs_fll_cnt_val_h_tol, 0x0d0);
295check_member(usb3_phy_pcs_reg_layout, pcs_autonomous_mode_ctrl, 0x0d8);
296check_member(usb3_phy_pcs_reg_layout, pcs_ready_status, 0x174);
297check_member(usb3_phy_pcs_reg_layout, pcs_refgen_req_config2, 0x210);
298
299static struct usb3_phy_qserdes_com_reg_layout *const qserdes_com_reg_layout =
300 (void *)QMP_PHY_QSERDES_COM_REG_BASE;
301static struct usb3_phy_qserdes_tx_reg_layout *const qserdes_tx_reg_layout =
302 (void *)QMP_PHY_QSERDES_TX_REG_BASE;
303static struct usb3_phy_qserdes_rx_reg_layout *const qserdes_rx_reg_layout =
304 (void *)QMP_PHY_QSERDES_RX_REG_BASE;
305static struct usb3_phy_pcs_reg_layout *const pcs_reg_layout =
306 (void *)QMP_PHY_PCS_REG_BASE;
307
308
309
310struct usb_dwc3 {
311 u32 sbuscfg0;
312 u32 sbuscfg1;
313 u32 txthrcfg;
314 u32 rxthrcfg;
315 u32 ctl;
316 u32 pmsts;
317 u32 sts;
318 u32 uctl1;
319 u32 snpsid;
320 u32 gpio;
321 u32 uid;
322 u32 uctl;
323 u64 buserraddr;
324 u64 prtbimap;
325 u8 reserved1[32];
326 u32 dbgfifospace;
327 u32 dbgltssm;
328 u32 dbglnmcc;
329 u32 dbgbmu;
330 u32 dbglspmux;
331 u32 dbglsp;
332 u32 dbgepinfo0;
333 u32 dbgepinfo1;
334 u64 prtbimap_hs;
335 u64 prtbimap_fs;
336 u8 reserved2[112];
337 u32 usb2phycfg;
338 u8 reserved3[124];
339 u32 usb2phyacc;
340 u8 reserved4[60];
341 u32 usb3pipectl;
342 u8 reserved5[60];
343};
344check_member(usb_dwc3, usb3pipectl, 0x1c0);
345
346static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = {
347 {&qserdes_com_reg_layout->com_pll_ivco, 0x07},
348 {&qserdes_com_reg_layout->com_sysclk_en_sel, 0x14},
349 {&qserdes_com_reg_layout->com_bias_en_clkbuflr_en, 0x08},
350 {&qserdes_com_reg_layout->com_clk_select, 0x30},
351 {&qserdes_com_reg_layout->com_sys_clk_ctrl, 0x02},
352 {&qserdes_com_reg_layout->com_resetsm_ctrl2, 0x08},
353 {&qserdes_com_reg_layout->com_cmn_config, 0x16},
354 {&qserdes_com_reg_layout->com_svs_mode_clk_sel, 0x01},
355 {&qserdes_com_reg_layout->com_hsclk_sel, 0x80},
356 {&qserdes_com_reg_layout->com_dec_start_mode0, 0x82},
357 {&qserdes_com_reg_layout->com_div_frac_start1_mode0, 0xab},
358 {&qserdes_com_reg_layout->com_div_frac_start2_mode0, 0xea},
359 {&qserdes_com_reg_layout->com_div_frac_start3_mode0, 0x02},
360 {&qserdes_com_reg_layout->com_cp_ctrl_mode0, 0x06},
361 {&qserdes_com_reg_layout->com_pll_rctrl_mode0, 0x16},
362 {&qserdes_com_reg_layout->com_pll_cctrl_mode0, 0x36},
363 {&qserdes_com_reg_layout->com_integloop_gain1_mode0, 0x00},
364 {&qserdes_com_reg_layout->com_integloop_gain0_mode0, 0x3f},
365 {&qserdes_com_reg_layout->com_vco_tune2_mode0, 0x01},
366 {&qserdes_com_reg_layout->com_vco_tune1_mode0, 0xc9},
367 {&qserdes_com_reg_layout->com_coreclk_div_mode0, 0x0a},
368 {&qserdes_com_reg_layout->com_lock_cmp3_mode0, 0x00},
369 {&qserdes_com_reg_layout->com_lock_cmp2_mode0, 0x34},
370 {&qserdes_com_reg_layout->com_lock_cmp1_mode0, 0x15},
371 {&qserdes_com_reg_layout->com_lock_cmp_en, 0x04},
372 {&qserdes_com_reg_layout->com_core_clk_en, 0x00},
373 {&qserdes_com_reg_layout->com_lock_cmp_cfg, 0x00},
374 {&qserdes_com_reg_layout->com_vco_tune_map, 0x00},
375 {&qserdes_com_reg_layout->com_sysclk_buf_enable, 0x0a},
376 {&qserdes_com_reg_layout->com_ssc_en_center, 0x01},
377 {&qserdes_com_reg_layout->com_ssc_per1, 0x31},
378 {&qserdes_com_reg_layout->com_ssc_per2, 0x01},
379 {&qserdes_com_reg_layout->com_ssc_adj_per1, 0x00},
380 {&qserdes_com_reg_layout->com_ssc_adj_per2, 0x00},
381 {&qserdes_com_reg_layout->com_ssc_step_size1, 0x85},
382 {&qserdes_com_reg_layout->com_ssc_step_size2, 0x07},
383};
384
385static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = {
386 {&qserdes_tx_reg_layout->tx_highz_drvr_en, 0x10},
387 {&qserdes_tx_reg_layout->tx_rcv_detect_lvl_2, 0x12},
388 {&qserdes_tx_reg_layout->tx_lane_mode_1, 0x16},
389 {&qserdes_tx_reg_layout->tx_res_code_lane_offset_rx, 0x09},
390 {&qserdes_tx_reg_layout->tx_res_code_lane_offset_tx, 0x06},
391};
392
393static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = {
394 {&qserdes_rx_reg_layout->rx_ucdr_fastlock_fo_gain, 0x0b},
395 {&qserdes_rx_reg_layout->rx_rx_equ_adap_ctrl2, 0x0f},
396 {&qserdes_rx_reg_layout->rx_rx_equ_adap_ctrl3, 0x4e},
397 {&qserdes_rx_reg_layout->rx_rx_equ_adap_ctrl4, 0x18},
398 {&qserdes_rx_reg_layout->rx_rx_eq_offset_adap_ctrl1, 0x77},
399 {&qserdes_rx_reg_layout->rx_rx_offset_adap_ctrl2, 0x80},
400 {&qserdes_rx_reg_layout->rx_sigdet_ctrl, 0x03},
401 {&qserdes_rx_reg_layout->rx_sigdet_deglitch_ctrl, 0x16},
402 {&qserdes_rx_reg_layout->rx_ucdr_so_saturtn_and_en, 0x75},
403 {&qserdes_rx_reg_layout->rx_ucdr_pi_cntrls, 0x80},
404 {&qserdes_rx_reg_layout->rx_ucdr_fo_gain, 0x0a},
405 {&qserdes_rx_reg_layout->rx_ucdr_so_gain_half, 0x06},
406 {&qserdes_rx_reg_layout->rx_sigdet_enables, 0x00},
407};
408
409static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = {
410 /* FLL settings */
411 {&pcs_reg_layout->pcs_fll_ctrl2, 0x83},
412 {&pcs_reg_layout->pcs_fll_cnt_val_l, 0x09},
413 {&pcs_reg_layout->pcs_fll_cnt_val_h_tol, 0xa2},
414 {&pcs_reg_layout->pcs_fll_man_code, 0x40},
415 {&pcs_reg_layout->pcs_fll_ctrl1, 0x02},
416
417 /* Lock Det settings */
418 {&pcs_reg_layout->pcs_lock_detect_config1, 0xd1},
419 {&pcs_reg_layout->pcs_lock_detect_config2, 0x1f},
420 {&pcs_reg_layout->pcs_lock_detect_config3, 0x47},
421 {&pcs_reg_layout->pcs_power_state_config2, 0x1b},
422
423 {&pcs_reg_layout->pcs_rx_sigdet_lvl, 0xba},
424 {&pcs_reg_layout->pcs_txmgn_v0, 0x9f},
425 {&pcs_reg_layout->pcs_txmgn_v1, 0x9f},
426 {&pcs_reg_layout->pcs_txmgn_v2, 0xb7},
427 {&pcs_reg_layout->pcs_txmgn_v3, 0x4e},
428 {&pcs_reg_layout->pcs_txmgn_v4, 0x65},
429 {&pcs_reg_layout->pcs_txmgn_ls, 0x6b},
430 {&pcs_reg_layout->pcs_txdeemph_m6db_v0, 0x15},
431 {&pcs_reg_layout->pcs_txdeemph_m3p5db_v0, 0x0d},
432 {&pcs_reg_layout->pcs_txdeemph_m6db_v1, 0x15},
433 {&pcs_reg_layout->pcs_txdeemph_m3p5db_v1, 0x0d},
434 {&pcs_reg_layout->pcs_txdeemph_m6db_v2, 0x15},
435 {&pcs_reg_layout->pcs_txdeemph_m3p5db_v2, 0x0d},
436 {&pcs_reg_layout->pcs_txdeemph_m6db_v3, 0x15},
437 {&pcs_reg_layout->pcs_txdeemph_m3p5db_v3, 0x1d},
438 {&pcs_reg_layout->pcs_txdeemph_m6db_v4, 0x15},
439 {&pcs_reg_layout->pcs_txdeemph_m3p5db_v4, 0x0d},
440 {&pcs_reg_layout->pcs_txdeemph_m6db_ls, 0x15},
441 {&pcs_reg_layout->pcs_txdeemph_m3p5db_ls, 0x0d},
442 {&pcs_reg_layout->pcs_rate_slew_cntrl, 0x02},
443 {&pcs_reg_layout->pcs_pwrup_reset_dly_time_auxclk, 0x04},
444 {&pcs_reg_layout->pcs_tsync_rsync_time, 0x44},
445 {&pcs_reg_layout->pcs_rcvr_dtct_dly_p1u2_l, 0xe7},
446 {&pcs_reg_layout->pcs_rcvr_dtct_dly_p1u2_h, 0x03},
447 {&pcs_reg_layout->pcs_rcvr_dtct_dly_u3_l, 0x40},
448 {&pcs_reg_layout->pcs_rcvr_dtct_dly_u3_h, 0x00},
449 {&pcs_reg_layout->pcs_rxeqtraining_wait_time, 0x75},
450 {&pcs_reg_layout->pcs_lfps_ecstart_eqtlock, 0x86},
451 {&pcs_reg_layout->pcs_rxeqtraining_run_time, 0x13},
452};
453
454
455
456struct usb_dwc3_cfg {
457 struct usb_dwc3 *usb_host_dwc3;
458 struct usb_qusb_phy_pll *qusb_phy_pll;
459 struct usb_qusb_phy_dig *qusb_phy_dig;
460 /* Init sequence for QMP PHY blocks - serdes, tx, rx, pcs */
461 const struct qmp_phy_init_tbl *serdes_tbl;
462 int serdes_tbl_num;
463 const struct qmp_phy_init_tbl *tx_tbl;
464 int tx_tbl_num;
465 const struct qmp_phy_init_tbl *rx_tbl;
466 int rx_tbl_num;
467 const struct qmp_phy_init_tbl *pcs_tbl;
468 int pcs_tbl_num;
469 struct usb3_phy_pcs_reg_layout *qmp_pcs_reg;
470
471 u32 *usb3_bcr;
472 u32 *qusb2phy_bcr;
473 u32 *gcc_usb3phy_bcr_reg;
474 u32 *gcc_qmpphy_bcr_reg;
475 struct usb_board_data *board_data;
476 u32 efuse_offset;
477};
478
479static struct usb_dwc3_cfg usb_port0 = {
480 .usb_host_dwc3 = (void *)USB_HOST_DWC3_BASE,
481 .qusb_phy_pll = (void *)QUSB_PRIM_PHY_BASE,
482 .qusb_phy_dig = (void *)QUSB_PRIM_PHY_DIG_BASE,
483 .serdes_tbl = qmp_v3_usb3_serdes_tbl,
484 .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl),
485 .tx_tbl = qmp_v3_usb3_tx_tbl,
486 .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl),
487 .rx_tbl = qmp_v3_usb3_rx_tbl,
488 .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl),
489 .pcs_tbl = qmp_v3_usb3_pcs_tbl,
490 .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl),
491 .qmp_pcs_reg = (void *)QMP_PHY_PCS_REG_BASE,
492 .usb3_bcr = &gcc->usb30_prim_bcr,
493 .qusb2phy_bcr = &gcc->qusb2phy_prim_bcr,
494 .gcc_usb3phy_bcr_reg = &gcc->usb3_dp_phy_prim_bcr,
495 .gcc_qmpphy_bcr_reg = &gcc->usb3_phy_prim_bcr,
496 .efuse_offset = 25,
497};
498
499
500static struct qfprom_corr * const qfprom_corr_efuse = (void *)QFPROM_BASE;
501
502static void reset_usb(struct usb_dwc3_cfg *dwc3)
503{
504 /* Assert Core reset */
505 clock_reset_bcr(dwc3->usb3_bcr, 1);
506
507 /* Assert QUSB PHY reset */
508 clock_reset_bcr(dwc3->qusb2phy_bcr, 1);
509
510 /* Assert QMP PHY reset */
511 clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 1);
512 clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 1);
513}
514
515void reset_usb0(void)
516{
517 /* Before Resetting PHY, put Core in Reset */
518 printk(BIOS_INFO, "Starting DWC3 and PHY resets for USB(0)\n");
519
520 reset_usb(&usb_port0);
521}
522
523
524/*
525 * Update board specific PHY tuning override values that specified from
526 * board file.
527 */
528static void qusb2_phy_override_phy_params(struct usb_dwc3_cfg *dwc3)
529{
530 /* Override preemphasis value */
531 write32(&dwc3->qusb_phy_dig->tune1,
532 dwc3->board_data->port_tune1);
533
534 /* Override BIAS_CTRL_2 to reduce the TX swing overshooting. */
535 write32(&dwc3->qusb_phy_pll->bias_ctrl_2,
536 dwc3->board_data->pll_bias_control_2);
537
538 /* Override IMP_RES_OFFSET value */
539 write32(&dwc3->qusb_phy_dig->imp_ctrl1,
540 dwc3->board_data->imp_ctrl1);
541}
542
543/*
544 * Fetches HS Tx tuning value from efuse register and sets the
545 * QUSB2PHY_PORT_TUNE1/2 register.
546 * For error case, skip setting the value and use the default value.
547 */
548static void qusb2_phy_set_tune_param(struct usb_dwc3_cfg *dwc3)
549{
550 /*
551 * Efuse registers 3 bit value specifies tuning for HSTX
552 * output current in TUNE1 Register. Hence Extract 3 bits from
553 * EFUSE at correct position.
554 */
555
556 const int efuse_bits = 3;
557 int bit_pos = dwc3->efuse_offset;
558
559 u32 bit_mask = (1 << efuse_bits) - 1;
560 u32 tune_val =
561 (read32(&qfprom_corr_efuse->qusb_hstx_trim_lsb) >> bit_pos)
562 & bit_mask;
563 /*
564 * if efuse reg is updated (i.e non-zero) then use it to program
565 * tune parameters.
566 */
567 if (tune_val)
Patrick Georgib9d5b262019-12-05 19:56:53 +0100568 clrsetbits32(&dwc3->qusb_phy_dig->tune1,
T Michael Turney050be722019-10-22 06:25:09 -0700569 PORT_TUNE1_MASK, tune_val << 4);
570}
571
572static void tune_phy(struct usb_dwc3_cfg *dwc3, struct usb_qusb_phy_dig *phy)
573{
574 write32(&phy->pwr_ctrl2, QUSB2PHY_PWR_CTRL2);
575 /* IMP_CTRL1: Control the impedance reduction */
576 write32(&phy->imp_ctrl1, QUSB2PHY_IMP_CTRL1);
577 /* IMP_CTRL2: Impedance offset/mapping slope */
578 write32(&phy->imp_ctrl2, QUSB2PHY_IMP_CTRL1);
579 write32(&phy->chg_ctrl2, QUSB2PHY_IMP_CTRL2);
580 /*
581 * TUNE1: Sets HS Impedance to approx 45 ohms
582 * then override with efuse value.
583 */
584 write32(&phy->tune1, QUSB2PHY_PORT_TUNE1);
585 /* TUNE2: Tuning for HS Disconnect Level */
586 write32(&phy->tune2, QUSB2PHY_PORT_TUNE2);
587 /* TUNE3: Tune squelch range */
588 write32(&phy->tune3, QUSB2PHY_PORT_TUNE3);
589 /* TUNE4: Sets EOP_DLY(Squelch rising edge to linestate falling edge) */
590 write32(&phy->tune4, QUSB2PHY_PORT_TUNE4);
591 write32(&phy->tune5, QUSB2PHY_PORT_TUNE5);
592
593 if (dwc3->board_data) {
594 /* Override board specific PHY tuning values */
595 qusb2_phy_override_phy_params(dwc3);
596
597 /* Set efuse value for tuning the PHY */
598 qusb2_phy_set_tune_param(dwc3);
599 }
600}
601
602static void hs_qusb_phy_init(struct usb_dwc3_cfg *dwc3)
603{
604 /* PWR_CTRL: set the power down bit to disable the PHY */
Patrick Georgib9d5b262019-12-05 19:56:53 +0100605 setbits32(&dwc3->qusb_phy_dig->pwr_ctrl1, POWER_DOWN);
T Michael Turney050be722019-10-22 06:25:09 -0700606
607 write32(&dwc3->qusb_phy_pll->analog_controls_two,
608 QUSB2PHY_PLL_ANALOG_CONTROLS_TWO);
609 write32(&dwc3->qusb_phy_pll->clock_inverters,
610 QUSB2PHY_PLL_CLOCK_INVERTERS);
611 write32(&dwc3->qusb_phy_pll->cmode,
612 QUSB2PHY_PLL_CMODE);
613 write32(&dwc3->qusb_phy_pll->lock_delay,
614 QUSB2PHY_PLL_LOCK_DELAY);
615 write32(&dwc3->qusb_phy_pll->dig_tim,
616 QUSB2PHY_PLL_DIGITAL_TIMERS_TWO);
617 write32(&dwc3->qusb_phy_pll->bias_ctrl_1,
618 QUSB2PHY_PLL_BIAS_CONTROL_1);
619 write32(&dwc3->qusb_phy_pll->bias_ctrl_2,
620 QUSB2PHY_PLL_BIAS_CONTROL_2);
621
622 tune_phy(dwc3, dwc3->qusb_phy_dig);
623
624 /* PWR_CTRL1: Clear the power down bit to enable the PHY */
Patrick Georgib9d5b262019-12-05 19:56:53 +0100625 clrbits32(&dwc3->qusb_phy_dig->pwr_ctrl1, POWER_DOWN);
T Michael Turney050be722019-10-22 06:25:09 -0700626
627 write32(&dwc3->qusb_phy_dig->debug_ctrl2,
628 DEBUG_CTRL2_MUX_PLL_LOCK_STATUS);
629
630 /*
631 * DEBUG_STAT5: wait for 160uS for PLL lock;
632 * vstatus[0] changes from 0 to 1.
633 */
634 long lock_us = wait_us(160, read32(&dwc3->qusb_phy_dig->debug_stat5) &
635 VSTATUS_PLL_LOCK_STATUS_MASK);
636 if (!lock_us)
637 printk(BIOS_ERR, "ERROR: QUSB PHY PLL LOCK fails\n");
638 else
639 printk(BIOS_DEBUG, "QUSB PHY initialized and locked in %ldus\n",
640 lock_us);
641}
642
643static void qcom_qmp_phy_configure(const struct qmp_phy_init_tbl tbl[],
644 int num)
645{
646 int i;
647 const struct qmp_phy_init_tbl *t = tbl;
648
649 if (!t)
650 return;
651
652 for (i = 0; i < num; i++, t++)
653 write32(t->address, t->val);
654}
655
656static void ss_qmp_phy_init(struct usb_dwc3_cfg *dwc3)
657{
658 /* power up USB3 PHY */
659 write32(&dwc3->qmp_pcs_reg->pcs_power_down_control, 0x01);
660
661 /* Serdes configuration */
662 qcom_qmp_phy_configure(dwc3->serdes_tbl, dwc3->serdes_tbl_num);
663 /* Tx, Rx, and PCS configurations */
664 qcom_qmp_phy_configure(dwc3->tx_tbl, dwc3->tx_tbl_num);
665 qcom_qmp_phy_configure(dwc3->rx_tbl, dwc3->rx_tbl_num);
666 qcom_qmp_phy_configure(dwc3->pcs_tbl, dwc3->pcs_tbl_num);
667
668 /* perform software reset of PCS/Serdes */
669 write32(&dwc3->qmp_pcs_reg->pcs_sw_reset, 0x00);
670 /* start PCS/Serdes to operation mode */
671 write32(&dwc3->qmp_pcs_reg->pcs_start_control, 0x03);
672
673 /*
674 * Wait for PHY initialization to be done
675 * PCS_STATUS: wait for 1ms for PHY STATUS;
676 * SW can continuously check for PHYSTATUS = 1.b0.
677 */
678 long lock_us = wait_us(1000,
679 !(read32(&dwc3->qmp_pcs_reg->pcs_ready_status) &
680 USB3_PCS_PHYSTATUS));
681 if (!lock_us)
682 printk(BIOS_ERR, "ERROR: QMP PHY PLL LOCK fails:\n");
683 else
684 printk(BIOS_DEBUG, "QMP PHY initialized and locked in %ldus\n",
685 lock_us);
686}
687
688static void setup_dwc3(struct usb_dwc3 *dwc3)
689{
690 /* core exits U1/U2/U3 only in PHY power state P1/P2/P3 respectively */
Patrick Georgib9d5b262019-12-05 19:56:53 +0100691 clrsetbits32(&dwc3->usb3pipectl,
T Michael Turney050be722019-10-22 06:25:09 -0700692 DWC3_GUSB3PIPECTL_DELAYP1TRANS,
693 DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX);
694
695 /*
696 * Configure USB phy interface of DWC3 core.
697 * 1. Select UTMI+ PHY with 16-bit interface.
698 * 2. Set USBTRDTIM to the corresponding value
699 * according to the UTMI+ PHY interface.
700 */
Patrick Georgib9d5b262019-12-05 19:56:53 +0100701 clrsetbits32(&dwc3->usb2phycfg,
T Michael Turney050be722019-10-22 06:25:09 -0700702 (DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK |
703 DWC3_GUSB2PHYCFG_PHYIF_MASK),
704 (DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
705 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT)));
706
Patrick Georgib9d5b262019-12-05 19:56:53 +0100707 clrsetbits32(&dwc3->ctl, (DWC3_GCTL_SCALEDOWN_MASK |
T Michael Turney050be722019-10-22 06:25:09 -0700708 DWC3_GCTL_DISSCRAMBLE),
709 DWC3_GCTL_U2EXIT_LFPS | DWC3_GCTL_DSBLCLKGTNG);
710
711 /* configure controller in Host mode */
Patrick Georgib9d5b262019-12-05 19:56:53 +0100712 clrsetbits32(&dwc3->ctl, (DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)),
T Michael Turney050be722019-10-22 06:25:09 -0700713 DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST));
714 printk(BIOS_SPEW, "Configure USB in Host mode\n");
715}
716
717/* Initialization of DWC3 Core and PHY */
718static void setup_usb_host(struct usb_dwc3_cfg *dwc3,
719 struct usb_board_data *board_data)
720{
721 dwc3->board_data = board_data;
722
723 /* Clear core reset. */
724 clock_reset_bcr(dwc3->usb3_bcr, 0);
725
726 /* Clear QUSB PHY reset. */
727 clock_reset_bcr(dwc3->qusb2phy_bcr, 0);
728
729 /* Initialize QUSB PHY */
730 hs_qusb_phy_init(dwc3);
731
732 /* Clear QMP PHY resets. */
733 clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 0);
734 clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 0);
735
736 /* Initialize QMP PHY */
737 ss_qmp_phy_init(dwc3);
738
739 setup_dwc3(dwc3->usb_host_dwc3);
740
741 printk(BIOS_INFO, "DWC3 and PHY setup finished\n");
742}
743
744void setup_usb_host0(struct usb_board_data *board_data)
745{
746 printk(BIOS_INFO, "Setting up USB HOST0 controller.\n");
747 setup_usb_host(&usb_port0, board_data);
748}