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