blob: ab7f04b4b582dc9e4a1d4151dafd12fd20d3a260 [file] [log] [blame]
Vinod Polimera4e93e942022-02-25 13:21:42 +05301/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <console/console.h>
4#include <delay.h>
5#include <device/mmio.h>
6#include <edid.h>
7#include <lib.h>
8#include <soc/clock.h>
9#include <soc/display/edp_reg.h>
10#include <soc/display/edp_phy.h>
11#include <string.h>
12#include <timer.h>
13
14static void edp_phy_ssc_en(bool en)
15{
16 if (en) {
17 write32(&edp_phy_pll->qserdes_com_ssc_en_center, 0x01);
18 write32(&edp_phy_pll->qserdes_com_ssc_adj_per1, 0x00);
19 write32(&edp_phy_pll->qserdes_com_ssc_per1, 0x36);
20 write32(&edp_phy_pll->qserdes_com_ssc_per2, 0x01);
21 write32(&edp_phy_pll->qserdes_com_ssc_step_size1_mode0, 0x5c);
22 write32(&edp_phy_pll->qserdes_com_ssc_step_size2_mode0, 0x08);
23 } else {
24 write32(&edp_phy_pll->qserdes_com_ssc_en_center, 0x00);
25 }
26}
27
28int edp_phy_enable(void)
29{
30 write32(&edp_phy->pd_ctl, 0x7D);
31 write32(&edp_phy_pll->qserdes_com_bias_en_clkbuflr_en, 0x17);
32 write32(&edp_phy->aux_cfg[1], 0x13);
33 write32(&edp_phy->aux_cfg[2], 0x24);
34 write32(&edp_phy->aux_cfg[3], 0x00);
35 write32(&edp_phy->aux_cfg[4], 0x0a);
36 write32(&edp_phy->aux_cfg[5], 0x26);
37 write32(&edp_phy->aux_cfg[6], 0x0a);
38 write32(&edp_phy->aux_cfg[7], 0x03);
39 write32(&edp_phy->aux_cfg[8], 0x37);
40 write32(&edp_phy->aux_cfg[9], 0x03);
41 write32(&edp_phy->aux_interrupt_mask, 0x1f);
42 write32(&edp_phy->mode, 0xFC);
43
44 if (!wait_us(1000, read32(&edp_phy_pll->qserdes_com_cmn_status) & BIT(7)))
45 printk(BIOS_ERR, "%s: refgen not ready : 0x%x\n", __func__,
46 read32(&edp_phy_pll->qserdes_com_cmn_status));
47
48 write32(&edp_phy_lane_tx0->tx_ldo_config, 0x01);
49 write32(&edp_phy_lane_tx1->tx_ldo_config, 0x01);
50 write32(&edp_phy_lane_tx0->tx_lane_mode1, 0x00);
51 write32(&edp_phy_lane_tx1->tx_lane_mode1, 0x00);
52
53 return 0;
54}
55
56static const u8 edp_hbr2_pre_emphasis[4][4] = {
57 {0x0c, 0x15, 0x19, 0x1e}, /* pe0, 0 db */
58 {0x08, 0x15, 0x19, 0xFF}, /* pe1, 3.5 db */
59 {0x0e, 0x14, 0xFF, 0xFF}, /* pe2, 6.0 db */
60 {0x0d, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */
61};
62
63static const u8 edp_hbr2_voltage_swing[4][4] = {
64 {0xb, 0x11, 0x17, 0x1c}, /* sw0, 0.4v */
65 {0x10, 0x19, 0x1f, 0xFF}, /* sw1, 0.6 v */
66 {0x19, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8 v */
67 {0x1f, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
68};
69
70void edp_phy_vm_pe_init(void)
71{
72 write32(&edp_phy_lane_tx0->tx_drv_lvl, edp_hbr2_voltage_swing[0][0]);
73 write32(&edp_phy_lane_tx0->tx_emp_post1_lvl,
74 edp_hbr2_pre_emphasis[0][0]);
75 write32(&edp_phy_lane_tx1->tx_drv_lvl, edp_hbr2_voltage_swing[0][0]);
76 write32(&edp_phy_lane_tx1->tx_emp_post1_lvl,
77 edp_hbr2_pre_emphasis[0][0]);
78
79 write32(&edp_phy_lane_tx0->tx_highz_drvr_en, 4);
80 write32(&edp_phy_lane_tx0->tx_transceiver_bias_en, 3);
81 write32(&edp_phy_lane_tx1->tx_highz_drvr_en, 7);
82 write32(&edp_phy_lane_tx1->tx_transceiver_bias_en, 0);
83 write32(&edp_phy->cfg1, 3);
84}
85
86void edp_phy_config(u8 v_level, u8 p_level)
87{
88 write32(&edp_phy_lane_tx0->tx_drv_lvl,
89 edp_hbr2_voltage_swing[v_level][p_level]);
90 write32(&edp_phy_lane_tx0->tx_emp_post1_lvl,
91 edp_hbr2_pre_emphasis[v_level][p_level]);
92 write32(&edp_phy_lane_tx1->tx_drv_lvl,
93 edp_hbr2_voltage_swing[v_level][p_level]);
94 write32(&edp_phy_lane_tx1->tx_emp_post1_lvl,
95 edp_hbr2_pre_emphasis[v_level][p_level]);
96}
97
98static void edp_phy_pll_vco_init(uint32_t link_rate)
99{
100 edp_phy_ssc_en(true);
101 write32(&edp_phy_pll->qserdes_com_svs_mode_clk_sel, 0x01);
102 write32(&edp_phy_pll->qserdes_com_sysclk_en_sel, 0x0b);
103 write32(&edp_phy_pll->qserdes_com_sys_clk_ctrl, 0x02);
104 write32(&edp_phy_pll->qserdes_com_clk_enable1, 0x0c);
105 write32(&edp_phy_pll->qserdes_com_sysclk_buf_enable, 0x06);
106 write32(&edp_phy_pll->qserdes_com_clk_sel, 0x30);
107 write32(&edp_phy_pll->qserdes_com_pll_ivco, 0x07);
108 write32(&edp_phy_pll->qserdes_com_lock_cmp_en, 0x04);
109 write32(&edp_phy_pll->qserdes_com_pll_cctrl_mode0, 0x36);
110 write32(&edp_phy_pll->qserdes_com_pll_rctrl_mode0, 0x16);
111 write32(&edp_phy_pll->qserdes_com_cp_ctrl_mode0, 0x06);
112 write32(&edp_phy_pll->qserdes_com_div_frac_start1_mode0, 0x00);
113 write32(&edp_phy_pll->qserdes_com_cmn_config, 0x02);
114 write32(&edp_phy_pll->qserdes_com_integloop_gain0_mode0, 0x3f);
115 write32(&edp_phy_pll->qserdes_com_integloop_gain1_mode0, 0x00);
116 write32(&edp_phy_pll->qserdes_com_vco_tune_map, 0x00);
117 write32(&edp_phy_pll->qserdes_com_bg_timer, 0x0a);
118 write32(&edp_phy_pll->qserdes_com_coreclk_div_mode0, 0x14);
119 write32(&edp_phy_pll->qserdes_com_vco_tune_ctrl, 0x00);
120 write32(&edp_phy_pll->qserdes_com_bias_en_clkbuflr_en, 0x17);
121 write32(&edp_phy_pll->qserdes_com_core_clk_en, 0x0f);
122
123 switch (link_rate) {
124 case 162000:
125 write32(&edp_phy_pll->qserdes_com_hsclk_sel, 0x05);
126 write32(&edp_phy_pll->qserdes_com_dec_start_mode0, 0x69);
127 write32(&edp_phy_pll->qserdes_com_div_frac_start2_mode0, 0x80);
128 write32(&edp_phy_pll->qserdes_com_div_frac_start3_mode0, 0x07);
129 write32(&edp_phy_pll->qserdes_com_lock_cmp1_mode0, 0x6f);
130 write32(&edp_phy_pll->qserdes_com_lock_cmp2_mode0, 0x08);
131 write32(&edp_phy_pll->qserdes_com_vco_tune1_mode0, 0xa0);
132 write32(&edp_phy_pll->qserdes_com_vco_tune2_mode0, 0x03);
133 break;
134 case 216000:
135 write32(&edp_phy_pll->qserdes_com_hsclk_sel, 0x04);
136 write32(&edp_phy_pll->qserdes_com_dec_start_mode0, 0x70);
137 write32(&edp_phy_pll->qserdes_com_div_frac_start2_mode0, 0x00);
138 write32(&edp_phy_pll->qserdes_com_div_frac_start3_mode0, 0x08);
139 write32(&edp_phy_pll->qserdes_com_lock_cmp1_mode0, 0x3f);
140 write32(&edp_phy_pll->qserdes_com_lock_cmp2_mode0, 0x0b);
141 write32(&edp_phy_pll->qserdes_com_vco_tune1_mode0, 0x34);
142 write32(&edp_phy_pll->qserdes_com_vco_tune2_mode0, 0x03);
143 break;
144 case 243000:
145 write32(&edp_phy_pll->qserdes_com_hsclk_sel, 0x04);
146 write32(&edp_phy_pll->qserdes_com_dec_start_mode0, 0x7e);
147 write32(&edp_phy_pll->qserdes_com_div_frac_start2_mode0, 0x00);
148 write32(&edp_phy_pll->qserdes_com_div_frac_start3_mode0, 0x09);
149 write32(&edp_phy_pll->qserdes_com_lock_cmp1_mode0, 0xa7);
150 write32(&edp_phy_pll->qserdes_com_lock_cmp2_mode0, 0x0c);
151 write32(&edp_phy_pll->qserdes_com_vco_tune1_mode0, 0x5c);
152 write32(&edp_phy_pll->qserdes_com_vco_tune2_mode0, 0x02);
153 break;
154 case 270000:
155 write32(&edp_phy_pll->qserdes_com_hsclk_sel, 0x03);
156 write32(&edp_phy_pll->qserdes_com_dec_start_mode0, 0x69);
157 write32(&edp_phy_pll->qserdes_com_div_frac_start2_mode0, 0x80);
158 write32(&edp_phy_pll->qserdes_com_div_frac_start3_mode0, 0x07);
159 write32(&edp_phy_pll->qserdes_com_lock_cmp1_mode0, 0x0f);
160 write32(&edp_phy_pll->qserdes_com_lock_cmp2_mode0, 0x0e);
161 write32(&edp_phy_pll->qserdes_com_vco_tune1_mode0, 0xa0);
162 write32(&edp_phy_pll->qserdes_com_vco_tune2_mode0, 0x03);
163 break;
164 case 324000:
165 write32(&edp_phy_pll->qserdes_com_hsclk_sel, 0x03);
166 write32(&edp_phy_pll->qserdes_com_dec_start_mode0, 0x7e);
167 write32(&edp_phy_pll->qserdes_com_div_frac_start2_mode0, 0x00);
168 write32(&edp_phy_pll->qserdes_com_div_frac_start3_mode0, 0x09);
169 write32(&edp_phy_pll->qserdes_com_lock_cmp1_mode0, 0xdf);
170 write32(&edp_phy_pll->qserdes_com_lock_cmp2_mode0, 0x10);
171 write32(&edp_phy_pll->qserdes_com_vco_tune1_mode0, 0x5c);
172 write32(&edp_phy_pll->qserdes_com_vco_tune2_mode0, 0x02);
173 break;
174 case 432000:
175 write32(&edp_phy_pll->qserdes_com_hsclk_sel, 0x01);
176 write32(&edp_phy_pll->qserdes_com_dec_start_mode0, 0x70);
177 write32(&edp_phy_pll->qserdes_com_div_frac_start2_mode0, 0x00);
178 write32(&edp_phy_pll->qserdes_com_div_frac_start3_mode0, 0x08);
179 write32(&edp_phy_pll->qserdes_com_lock_cmp1_mode0, 0x7f);
180 write32(&edp_phy_pll->qserdes_com_lock_cmp2_mode0, 0x16);
181 write32(&edp_phy_pll->qserdes_com_vco_tune1_mode0, 0x34);
182 write32(&edp_phy_pll->qserdes_com_vco_tune2_mode0, 0x03);
183 break;
184 case 540000:
185 write32(&edp_phy_pll->qserdes_com_hsclk_sel, 0x01);
186 write32(&edp_phy_pll->qserdes_com_dec_start_mode0, 0x8c);
187 write32(&edp_phy_pll->qserdes_com_div_frac_start2_mode0, 0x00);
188 write32(&edp_phy_pll->qserdes_com_div_frac_start3_mode0, 0x0a);
189 write32(&edp_phy_pll->qserdes_com_lock_cmp1_mode0, 0x1f);
190 write32(&edp_phy_pll->qserdes_com_lock_cmp2_mode0, 0x1c);
191 write32(&edp_phy_pll->qserdes_com_vco_tune1_mode0, 0x84);
192 write32(&edp_phy_pll->qserdes_com_vco_tune2_mode0, 0x01);
193 break;
194 case 594000:
195 write32(&edp_phy_pll->qserdes_com_hsclk_sel, 0x01);
196 write32(&edp_phy_pll->qserdes_com_dec_start_mode0, 0x9a);
197 write32(&edp_phy_pll->qserdes_com_div_frac_start2_mode0, 0x00);
198 write32(&edp_phy_pll->qserdes_com_div_frac_start3_mode0, 0x0b);
199 write32(&edp_phy_pll->qserdes_com_lock_cmp1_mode0, 0xef);
200 write32(&edp_phy_pll->qserdes_com_lock_cmp2_mode0, 0x1e);
201 write32(&edp_phy_pll->qserdes_com_vco_tune1_mode0, 0xac);
202 write32(&edp_phy_pll->qserdes_com_vco_tune2_mode0, 0x00);
203 break;
204 case 810000:
205 write32(&edp_phy_pll->qserdes_com_hsclk_sel, 0x00);
206 write32(&edp_phy_pll->qserdes_com_dec_start_mode0, 0x69);
207 write32(&edp_phy_pll->qserdes_com_div_frac_start2_mode0, 0x80);
208 write32(&edp_phy_pll->qserdes_com_div_frac_start3_mode0, 0x07);
209 write32(&edp_phy_pll->qserdes_com_lock_cmp1_mode0, 0x2f);
210 write32(&edp_phy_pll->qserdes_com_lock_cmp2_mode0, 0x2a);
211 write32(&edp_phy_pll->qserdes_com_vco_tune1_mode0, 0xa0);
212 write32(&edp_phy_pll->qserdes_com_vco_tune2_mode0, 0x03);
213 break;
214 default:
215 printk(BIOS_ERR, "%s: Invalid link rate. rate = %u\n", __func__,
216 link_rate);
217 break;
218 }
219}
220
221static void edp_phy_lanes_init(void)
222{
223 write32(&edp_phy_lane_tx0->tx_transceiver_bias_en, 0x03);
224 write32(&edp_phy_lane_tx0->tx_clk_buf_enable, 0x0f);
225 write32(&edp_phy_lane_tx0->tx_reset_tsync_en, 0x03);
226 write32(&edp_phy_lane_tx0->tx_tran_drvr_emp_en, 0x01);
227 write32(&edp_phy_lane_tx0->tx_tx_band, 0x4);
228
229 write32(&edp_phy_lane_tx1->tx_transceiver_bias_en, 0x03);
230 write32(&edp_phy_lane_tx1->tx_clk_buf_enable, 0x0f);
231 write32(&edp_phy_lane_tx1->tx_reset_tsync_en, 0x03);
232 write32(&edp_phy_lane_tx1->tx_tran_drvr_emp_en, 0x01);
233 write32(&edp_phy_lane_tx1->tx_tx_band, 0x4);
234}
235
236static void edp_lanes_configure(void)
237{
238 write32(&edp_phy_lane_tx0->tx_highz_drvr_en, 0x1f);
239 write32(&edp_phy_lane_tx0->tx_highz_drvr_en, 0x04);
240 write32(&edp_phy_lane_tx0->tx_tx_pol_inv, 0x00);
241
242 write32(&edp_phy_lane_tx1->tx_highz_drvr_en, 0x1f);
243 write32(&edp_phy_lane_tx1->tx_highz_drvr_en, 0x04);
244 write32(&edp_phy_lane_tx1->tx_tx_pol_inv, 0x00);
245
246 write32(&edp_phy_lane_tx1->tx_highz_drvr_en, 0x04);
247 write32(&edp_phy_lane_tx1->tx_tx_pol_inv, 0x00);
248
249 write32(&edp_phy_lane_tx0->tx_drv_lvl_offset, 0x10);
250 write32(&edp_phy_lane_tx1->tx_drv_lvl_offset, 0x10);
251
252 write32(&edp_phy_lane_tx0->tx_rescode_lane_offset_tx0, 0x11);
253 write32(&edp_phy_lane_tx0->tx_rescode_lane_offset_tx1, 0x11);
254
255 write32(&edp_phy_lane_tx1->tx_rescode_lane_offset_tx0, 0x11);
256 write32(&edp_phy_lane_tx1->tx_rescode_lane_offset_tx1, 0x11);
257}
258
259static int edp_phy_pll_vco_configure(uint32_t link_rate)
260{
261 u32 phy_vco_div = 0;
262
263 switch (link_rate) {
264 case 162000:
265 phy_vco_div = 2;
266 break;
267 case 216000:
268 case 243000:
269 case 270000:
270 phy_vco_div = 1;
271 break;
272 case 324000:
273 case 432000:
274 case 540000:
275 phy_vco_div = 2;
276 break;
277 case 594000:
278 case 810000:
279 phy_vco_div = 0;
280 break;
281 default:
282 printk(BIOS_ERR, "%s: Invalid link rate. rate = %u\n", __func__,
283 link_rate);
284 break;
285 }
286
287 write32(&edp_phy->vco_div, phy_vco_div);
288 write32(&edp_phy->cfg, 0x01);
289 write32(&edp_phy->cfg, 0x05);
290 write32(&edp_phy->cfg, 0x01);
291 write32(&edp_phy->cfg, 0x09);
292 write32(&edp_phy_pll->qserdes_com_resetsm_cntrl, 0x20);
293 if (!wait_us(10000, read32(&edp_phy_pll->qserdes_com_c_ready_status) & BIT(0))) {
294 printk(BIOS_ERR, "%s: PLL not locked. Status\n", __func__);
295 return -1;
296 }
297
298 write32(&edp_phy->cfg, 0x19);
299 edp_lanes_configure();
300 edp_phy_vm_pe_init();
301 if (!wait_us(10000, read32(&edp_phy->status) & BIT(1))) {
302 printk(BIOS_ERR, "%s: PHY not ready. Status\n", __func__);
303 return -1;
304 }
305
306 write32(&edp_phy->cfg, 0x18);
307 write32(&edp_phy->cfg, 0x19);
308 if (!wait_us(10000, read32(&edp_phy_pll->qserdes_com_c_ready_status) & BIT(0))) {
309 printk(BIOS_ERR, "%s: PLL not locked. Status\n", __func__);
310 return -1;
311 }
312
313 return 0;
314}
315
316int edp_phy_power_on(uint32_t link_rate)
317{
318 int ret = 0;
319 edp_phy_pll_vco_init(link_rate);
320
321 write32(&edp_phy->tx0_tx1_lane_ctl, 0x5);
322 write32(&edp_phy->tx2_tx3_lane_ctl, 0x5);
323 edp_phy_lanes_init();
324 ret = edp_phy_pll_vco_configure(link_rate);
325
326 return ret;
327}