blob: 4a884b19761b6e031e5216b8abf396046503a9b9 [file] [log] [blame]
Angel Ponse67ab182020-04-04 18:51:11 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Huayang Duan6c36d152018-09-26 15:37:58 +08002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Huayang Duan6c36d152018-09-26 15:37:58 +08004#include <delay.h>
5#include <soc/emi.h>
Huayang Duan7b78a802018-09-26 21:09:54 +08006#include <soc/spm.h>
Huayang Duan6c36d152018-09-26 15:37:58 +08007#include <soc/dramc_register.h>
8#include <soc/dramc_pi_api.h>
9
Huayang Duan73780152019-08-19 14:06:31 +080010u8 get_freq_fsq(u8 freq)
11{
12 if (freq == LP4X_DDR1600 || freq == LP4X_DDR2400)
13 return FSP_0;
14 else
15 return FSP_1;
16}
17
mtk1119516ad2d72019-01-23 11:41:19 +080018static void dramc_sw_imp_cal_vref_sel(u8 term_option, u8 impcal_stage)
Huayang Duan6c36d152018-09-26 15:37:58 +080019{
20 u8 vref_sel = 0;
21
Huayang Duan73780152019-08-19 14:06:31 +080022 if (term_option == ODT_ON)
Huayang Duan6c36d152018-09-26 15:37:58 +080023 vref_sel = IMP_LP4X_TERM_VREF_SEL;
24 else {
25 switch (impcal_stage) {
26 case IMPCAL_STAGE_DRVP:
27 vref_sel = IMP_DRVP_LP4X_UNTERM_VREF_SEL;
28 break;
29 case IMPCAL_STAGE_DRVN:
30 vref_sel = IMP_DRVN_LP4X_UNTERM_VREF_SEL;
31 break;
32 default:
33 vref_sel = IMP_TRACK_LP4X_UNTERM_VREF_SEL;
34 break;
35 }
36 }
37
Julius Werner55009af2019-12-02 22:03:27 -080038 clrsetbits32(&ch[0].phy.shu[0].ca_cmd[11], 0x3f << 8, vref_sel << 8);
Huayang Duan6c36d152018-09-26 15:37:58 +080039}
40
Yu-Ping Wu4d4ccce2019-10-03 08:49:23 +080041void dramc_sw_impedance_cal(const struct sdram_params *params, u8 term,
42 struct dram_impedance *impedance)
Huayang Duan6c36d152018-09-26 15:37:58 +080043{
Huayang Duan73780152019-08-19 14:06:31 +080044 u32 broadcast_bak, impcal_bak, imp_cal_result;
45 u32 DRVP_result = 0xff, ODTN_result = 0xff, DRVN_result = 0x9;
46
47 broadcast_bak = dramc_get_broadcast();
48 dramc_set_broadcast(DRAMC_BROADCAST_OFF);
49
Huayang Duancac990f2020-06-08 17:40:55 +080050 for (u8 chn = 0; chn < CHANNEL_MAX; chn++) {
51 clrbits32(&ch[chn].phy.misc_spm_ctrl1, 0xf << 0);
52 write32(&ch[chn].phy.misc_spm_ctrl2, 0x0);
53 write32(&ch[chn].phy.misc_spm_ctrl0, 0x0);
54 clrbits32(&ch[chn].ao.impcal, 0x1 << 31);
55 }
Huayang Duan73780152019-08-19 14:06:31 +080056
57 impcal_bak = read32(&ch[0].ao.impcal);
58 dramc_sw_imp_cal_vref_sel(term, IMPCAL_STAGE_DRVP);
Julius Werner55009af2019-12-02 22:03:27 -080059 clrbits32(&ch[0].phy.misc_imp_ctrl1, 0x1 << 6);
60 clrsetbits32(&ch[0].ao.impcal, 0x1 << 21, 0x3 << 24);
61 clrsetbits32(&ch[0].phy.misc_imp_ctrl0, 0x7 << 4, 0x3 << 4);
Huayang Duan73780152019-08-19 14:06:31 +080062 udelay(1);
63
Yu-Ping Wu31ec0c42019-10-09 16:11:47 +080064 dramc_dbg("impedance: K DRVP\n");
Julius Werner55009af2019-12-02 22:03:27 -080065 setbits32(&ch[0].ao.impcal, 0x1 << 23);
66 setbits32(&ch[0].ao.impcal, 0x1 << 22);
67 clrbits32(&ch[0].ao.impcal, 0x1 << 21);
68 clrbits32(&ch[0].ao.shu[0].impcal1, 0x1f << 4 | 0x1f << 11);
69 clrsetbits32(&ch[0].phy.shu[0].ca_cmd[11], 0xff << 0, 0x3);
Huayang Duan73780152019-08-19 14:06:31 +080070
71 for (u8 impx_drv = 0; impx_drv < 32; impx_drv++) {
72 impx_drv = (impx_drv == 16) ? 29 : impx_drv;
73
Julius Werner55009af2019-12-02 22:03:27 -080074 clrsetbits32(&ch[0].ao.shu[0].impcal1,
Huayang Duan73780152019-08-19 14:06:31 +080075 0x1f << 4, impx_drv << 4);
76 udelay(1);
77 imp_cal_result = (read32(&ch[0].phy_nao.misc_phy_rgs_cmd) >>
78 24) & 0x1;
Yu-Ping Wu31ec0c42019-10-09 16:11:47 +080079 dramc_dbg("1. OCD DRVP=%d CALOUT=%d\n",
Yu-Ping Wuc5568a12019-10-24 15:13:28 +080080 impx_drv, imp_cal_result);
Huayang Duan73780152019-08-19 14:06:31 +080081
82 if (imp_cal_result == 1 && DRVP_result == 0xff) {
83 DRVP_result = impx_drv;
Yu-Ping Wu31ec0c42019-10-09 16:11:47 +080084 dramc_dbg("1. OCD DRVP calibration OK! DRVP=%d\n",
Yu-Ping Wuc5568a12019-10-24 15:13:28 +080085 DRVP_result);
Huayang Duan73780152019-08-19 14:06:31 +080086 break;
87 }
88 }
89
Yu-Ping Wu31ec0c42019-10-09 16:11:47 +080090 dramc_dbg("impedance: K ODTN\n");
Huayang Duan73780152019-08-19 14:06:31 +080091 dramc_sw_imp_cal_vref_sel(term, IMPCAL_STAGE_DRVN);
Julius Werner55009af2019-12-02 22:03:27 -080092 clrbits32(&ch[0].ao.impcal, 0x1 << 22);
Huayang Duan73780152019-08-19 14:06:31 +080093 if (term == ODT_ON)
Julius Werner55009af2019-12-02 22:03:27 -080094 setbits32(&ch[0].ao.impcal, 0x1 << 21);
95 clrsetbits32(&ch[0].ao.shu[0].impcal1, 0x1f << 4 | 0x1f << 11,
Huayang Duancac990f2020-06-08 17:40:55 +080096 DRVP_result << 4);
Julius Werner55009af2019-12-02 22:03:27 -080097 clrsetbits32(&ch[0].phy.shu[0].ca_cmd[11], 0xff << 0, 0x3);
Huayang Duan73780152019-08-19 14:06:31 +080098
99 for (u8 impx_drv = 0; impx_drv < 32; impx_drv++) {
100 impx_drv = (impx_drv == 16) ? 29 : impx_drv;
101
Julius Werner55009af2019-12-02 22:03:27 -0800102 clrsetbits32(&ch[0].ao.shu[0].impcal1,
Huayang Duan73780152019-08-19 14:06:31 +0800103 0x1f << 11, impx_drv << 11);
104 udelay(1);
105 imp_cal_result = (read32(&ch[0].phy_nao.misc_phy_rgs_cmd) >>
106 24) & 0x1;
Yu-Ping Wu31ec0c42019-10-09 16:11:47 +0800107 dramc_dbg("3. OCD ODTN=%d CALOUT=%d\n",
Yu-Ping Wuc5568a12019-10-24 15:13:28 +0800108 impx_drv, imp_cal_result);
Huayang Duan73780152019-08-19 14:06:31 +0800109
110 if (imp_cal_result == 0 && ODTN_result == 0xff) {
111 ODTN_result = impx_drv;
Yu-Ping Wu31ec0c42019-10-09 16:11:47 +0800112 dramc_dbg("3. OCD ODTN calibration OK! ODTN=%d\n",
Yu-Ping Wuc5568a12019-10-24 15:13:28 +0800113 ODTN_result);
Huayang Duan73780152019-08-19 14:06:31 +0800114 break;
115 }
116 }
117
118 write32(&ch[0].ao.impcal, impcal_bak);
119
Yu-Ping Wu85ca1fe2019-10-03 09:45:16 +0800120 dramc_dbg("impedance: term=%d, DRVP=%d, DRVN=%d, ODTN=%d\n",
121 term, DRVP_result, DRVN_result, ODTN_result);
Yu-Ping Wu4d4ccce2019-10-03 08:49:23 +0800122 u32 *imp = impedance->data[term];
Huayang Duan73780152019-08-19 14:06:31 +0800123 if (term == ODT_OFF) {
Yu-Ping Wu4d4ccce2019-10-03 08:49:23 +0800124 imp[0] = DRVP_result;
125 imp[1] = ODTN_result;
126 imp[2] = 0;
127 imp[3] = 15;
Huayang Duan73780152019-08-19 14:06:31 +0800128 } else {
Yu-Ping Wu4d4ccce2019-10-03 08:49:23 +0800129 imp[0] = (DRVP_result <= 3) ? (DRVP_result * 3) : DRVP_result;
130 imp[1] = (DRVN_result <= 3) ? (DRVN_result * 3) : DRVN_result;
131 imp[2] = 0;
132 imp[3] = (ODTN_result <= 3) ? (ODTN_result * 3) : ODTN_result;
Huayang Duan73780152019-08-19 14:06:31 +0800133 }
134 dramc_sw_imp_cal_vref_sel(term, IMPCAL_STAGE_TRACKING);
135
136 dramc_set_broadcast(broadcast_bak);
137}
138
Yu-Ping Wu4d4ccce2019-10-03 08:49:23 +0800139void dramc_sw_impedance_save_reg(u8 freq_group,
140 const struct dram_impedance *impedance)
Huayang Duan73780152019-08-19 14:06:31 +0800141{
142 u8 ca_term = ODT_OFF, dq_term = ODT_ON;
Huayang Duan6c36d152018-09-26 15:37:58 +0800143 u32 sw_impedance[2][4] = {0};
144
Huayang Duan73780152019-08-19 14:06:31 +0800145 if (get_freq_fsq(freq_group) == FSP_0)
146 dq_term = ODT_OFF;
147
148 for (u8 term = 0; term < 2; term++)
Huayang Duan6c36d152018-09-26 15:37:58 +0800149 for (u8 i = 0; i < 4; i++)
Yu-Ping Wu4d4ccce2019-10-03 08:49:23 +0800150 sw_impedance[term][i] = impedance->data[term][i];
Huayang Duan6c36d152018-09-26 15:37:58 +0800151
152 sw_impedance[ODT_OFF][2] = sw_impedance[ODT_ON][2];
153 sw_impedance[ODT_OFF][3] = sw_impedance[ODT_ON][3];
154
Huayang Duan6c36d152018-09-26 15:37:58 +0800155 /* DQ */
Julius Werner55009af2019-12-02 22:03:27 -0800156 clrsetbits32(&ch[0].ao.shu[0].drving[0], (0x1f << 5) | (0x1f << 0),
Huayang Duan6c36d152018-09-26 15:37:58 +0800157 (sw_impedance[dq_term][0] << 5) |
158 (sw_impedance[dq_term][1] << 0));
Julius Werner55009af2019-12-02 22:03:27 -0800159 clrsetbits32(&ch[0].ao.shu[0].drving[1],
Yu-Ping Wua39cd992019-08-29 10:54:14 +0800160 (0x1f << 25) | (0x1f << 20) | (1 << 31),
Huayang Duan6c36d152018-09-26 15:37:58 +0800161 (sw_impedance[dq_term][0] << 25) |
162 (sw_impedance[dq_term][1] << 20) | (!dq_term << 31));
Julius Werner55009af2019-12-02 22:03:27 -0800163 clrsetbits32(&ch[0].ao.shu[0].drving[2], (0x1f << 5) | (0x1f << 0),
Huayang Duan6c36d152018-09-26 15:37:58 +0800164 (sw_impedance[dq_term][2] << 5) |
165 (sw_impedance[dq_term][3] << 0));
Julius Werner55009af2019-12-02 22:03:27 -0800166 clrsetbits32(&ch[0].ao.shu[0].drving[3], (0x1f << 25) | (0x1f << 20),
Huayang Duan6c36d152018-09-26 15:37:58 +0800167 (sw_impedance[dq_term][2] << 25) |
168 (sw_impedance[dq_term][3] << 20));
169
170 /* DQS */
171 for (u8 i = 0; i <= 2; i += 2) {
Julius Werner55009af2019-12-02 22:03:27 -0800172 clrsetbits32(&ch[0].ao.shu[0].drving[i],
Huayang Duan6c36d152018-09-26 15:37:58 +0800173 (0x1f << 25) | (0x1f << 20),
174 (sw_impedance[dq_term][i] << 25) |
175 (sw_impedance[dq_term][i + 1] << 20));
Julius Werner55009af2019-12-02 22:03:27 -0800176 clrsetbits32(&ch[0].ao.shu[0].drving[i],
Huayang Duan6c36d152018-09-26 15:37:58 +0800177 (0x1f << 15) | (0x1f << 10),
178 (sw_impedance[dq_term][i] << 15) |
179 (sw_impedance[dq_term][i + 1] << 10));
180 }
181
182 /* CMD & CLK */
183 for (u8 i = 1; i <= 3; i += 2) {
Julius Werner55009af2019-12-02 22:03:27 -0800184 clrsetbits32(&ch[0].ao.shu[0].drving[i],
Huayang Duan6c36d152018-09-26 15:37:58 +0800185 (0x1f << 15) | (0x1f << 10),
186 (sw_impedance[ca_term][i - 1] << 15) |
187 (sw_impedance[ca_term][i] << 10));
Julius Werner55009af2019-12-02 22:03:27 -0800188 clrsetbits32(&ch[0].ao.shu[0].drving[i],
Huayang Duan6c36d152018-09-26 15:37:58 +0800189 (0x1f << 5) | (0x1f << 0),
190 (sw_impedance[ca_term][i - 1] << 5) |
191 (sw_impedance[ca_term][i] << 0));
192 }
193
Julius Werner55009af2019-12-02 22:03:27 -0800194 clrsetbits32(&ch[0].phy.shu[0].ca_cmd[11], 0x1f << 17,
Huayang Duan6c36d152018-09-26 15:37:58 +0800195 sw_impedance[ca_term][0] << 17);
Julius Werner55009af2019-12-02 22:03:27 -0800196 clrsetbits32(&ch[0].phy.shu[0].ca_cmd[11], 0x1f << 22,
Huayang Duan6c36d152018-09-26 15:37:58 +0800197 sw_impedance[ca_term][1] << 22);
198
Hung-Te Lin5b29f172019-09-19 17:49:34 +0800199 SET32_BITFIELDS(&ch[0].phy.shu[0].ca_cmd[3],
200 SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE, 1);
201 SET32_BITFIELDS(&ch[0].phy.shu[0].ca_cmd[0],
202 SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE, 0);
Huayang Duan6c36d152018-09-26 15:37:58 +0800203
Huayang Duancac990f2020-06-08 17:40:55 +0800204 dramc_set_broadcast(DRAMC_BROADCAST_OFF);
Julius Werner55009af2019-12-02 22:03:27 -0800205 clrsetbits32(&ch[0].phy.shu[0].ca_dll[1], 0x1f << 16, 0x9 << 16);
Huayang Duancac990f2020-06-08 17:40:55 +0800206 clrsetbits32(&ch[1].phy.shu[0].ca_dll[1], 0x1f << 16, 0x9 << 16);
207 dramc_set_broadcast(DRAMC_BROADCAST_ON);
Huayang Duan6c36d152018-09-26 15:37:58 +0800208}
Huayang Duan7b78a802018-09-26 21:09:54 +0800209
210static void transfer_pll_to_spm_control(void)
211{
Huayang Duanc157ee92019-07-14 15:46:08 +0800212 u8 shu_lev = (read32(&ch[0].ao.shustatus) >> 1) & 0x3;
Huayang Duan7b78a802018-09-26 21:09:54 +0800213
Julius Werner55009af2019-12-02 22:03:27 -0800214 clrsetbits32(&mtk_spm->poweron_config_set,
Huayang Duan7b78a802018-09-26 21:09:54 +0800215 (0xffff << 16) | (0x1 << 0),
216 (0xb16 << 16) | (0x1 << 0));
217
218 /* Set SPM pinmux */
Julius Werner55009af2019-12-02 22:03:27 -0800219 clrbits32(&mtk_spm->pcm_pwr_io_en, (0xff << 0) | (0xff << 16));
220 setbits32(&mtk_spm->dramc_dpy_clk_sw_con_sel, 0xffffffff);
221 setbits32(&mtk_spm->dramc_dpy_clk_sw_con_sel2, 0xffffffff);
Huayang Duan7b78a802018-09-26 21:09:54 +0800222
Julius Werner55009af2019-12-02 22:03:27 -0800223 setbits32(&mtk_spm->spm_power_on_val0, (0x1 << 8) | (0xf << 12));
224 setbits32(&mtk_spm->spm_s1_mode_ch, 0x3 << 0);
Huayang Duan7b78a802018-09-26 21:09:54 +0800225
226 shu_lev = (shu_lev == 1) ? 2 : 1;
Julius Werner55009af2019-12-02 22:03:27 -0800227 clrsetbits32(&mtk_spm->spm_power_on_val0, 0x3 << 28, shu_lev << 28);
228 clrsetbits32(&mtk_spm->dramc_dpy_clk_sw_con2,
Huayang Duan7b78a802018-09-26 21:09:54 +0800229 0x3 << 2, shu_lev << 2);
230
231 udelay(1);
232 for (size_t chn = CHANNEL_A; chn < CHANNEL_MAX; chn++) {
Julius Werner55009af2019-12-02 22:03:27 -0800233 clrbits32(&ch[chn].phy.pll1, 0x1 << 31);
234 clrbits32(&ch[chn].phy.pll2, 0x1 << 31);
Huayang Duan7b78a802018-09-26 21:09:54 +0800235 }
236}
237
238static void dramc_rx_input_delay_tracking(u8 chn)
239{
240 /* Enable RX_FIFO macro DIV4 clock CG */
241 write32(&ch[chn].phy.misc_cg_ctrl1, 0xffffffff);
242
243 /* DVS mode to RG mode */
244 for (size_t r = 0; r < 2; r++)
245 for (size_t b = 0; b < 2; b++)
Julius Werner55009af2019-12-02 22:03:27 -0800246 clrbits32(&ch[chn].phy.r[r].b[b].rxdvs[2], 3 << 30);
Huayang Duan7b78a802018-09-26 21:09:54 +0800247
Julius Werner55009af2019-12-02 22:03:27 -0800248 clrsetbits32(&ch[chn].phy.b0_rxdvs[0], 0x1 << 19, 0x1 << 9);
249 clrsetbits32(&ch[chn].phy.b1_rxdvs[0], 0x1 << 19, 0x1 << 9);
Huayang Duan7b78a802018-09-26 21:09:54 +0800250
251 for (size_t r = 0; r < 2; r++)
252 for (size_t b = 0; b < 2; b++) {
Julius Werner55009af2019-12-02 22:03:27 -0800253 clrbits32(&ch[chn].phy.r[r].b[b].rxdvs[2], 1 << 29);
254 clrsetbits32(&ch[chn].phy.r[r].b[b].rxdvs[7],
Huayang Duan7b78a802018-09-26 21:09:54 +0800255 (0x3f << 0) | (0x3f << 8) |
256 (0x7f << 16) | (0x7f << 24),
257 (0x0 << 0) | (0x3f << 8) |
258 (0x0 << 16) | (0x7f << 24));
Julius Werner55009af2019-12-02 22:03:27 -0800259 clrsetbits32(&ch[chn].phy.r[r].b[b].rxdvs[1],
Huayang Duan7b78a802018-09-26 21:09:54 +0800260 (0xffff << 16) | (0xffff << 0),
261 (0x2 << 16) | (0x2 << 0));
262
263 /* DQ/DQS Rx DLY adjustment for tracking mode */
Julius Werner55009af2019-12-02 22:03:27 -0800264 clrbits32(&ch[chn].phy.r[r].b[b].rxdvs[2],
Huayang Duan7b78a802018-09-26 21:09:54 +0800265 (0x3 << 26) | (0x3 << 24) |
266 (0x3 << 18) | (0x3 << 16));
267 }
268
Huayang Duan7b78a802018-09-26 21:09:54 +0800269 /* Rx DLY tracking setting (Static) */
Julius Werner55009af2019-12-02 22:03:27 -0800270 clrsetbits32(&ch[chn].phy.b0_rxdvs[0],
Huayang Duan7b78a802018-09-26 21:09:54 +0800271 (0x1 << 29) | (0xf << 4) | (0x1 << 0),
272 (0x1 << 29) | (0x0 << 4) | (0x1 << 0));
Julius Werner55009af2019-12-02 22:03:27 -0800273 clrsetbits32(&ch[chn].phy.b1_rxdvs[0],
Huayang Duan7b78a802018-09-26 21:09:54 +0800274 (0x1 << 29) | (0xf << 4) | (0x1 << 0),
275 (0x1 << 29) | (0x0 << 4) | (0x1 << 0));
276
Huayang Duan04571d82020-01-21 10:40:01 +0800277 for (u8 b = 0; b < 2; b++)
Julius Werner55009af2019-12-02 22:03:27 -0800278 clrsetbits32(&ch[chn].phy.b[b].dq[9],
Huayang Duan04571d82020-01-21 10:40:01 +0800279 (0x7 << 28) | (0x7 << 24),
280 (0x1 << 28) | (0x0 << 24));
Julius Werner55009af2019-12-02 22:03:27 -0800281 clrbits32(&ch[chn].phy.ca_cmd[10], (0x7 << 28) | (0x7 << 24));
Huayang Duan04571d82020-01-21 10:40:01 +0800282 for (u8 b = 0; b < 2; b++)
283 setbits32(&ch[chn].phy.b[b].dq[5], 0x1 << 31);
Huayang Duan7b78a802018-09-26 21:09:54 +0800284
Julius Werner55009af2019-12-02 22:03:27 -0800285 setbits32(&ch[chn].phy.b0_rxdvs[0], (0x1 << 28) | (0x1 << 31));
286 setbits32(&ch[chn].phy.b1_rxdvs[0], (0x1 << 28) | (0x1 << 31));
Huayang Duan7b78a802018-09-26 21:09:54 +0800287 for (u8 rank = RANK_0; rank < RANK_MAX; rank++)
288 for (u8 b = 0; b < 2; b++)
Julius Werner55009af2019-12-02 22:03:27 -0800289 clrsetbits32(&ch[chn].phy.r[rank].b[b].rxdvs[2],
Huayang Duan7b78a802018-09-26 21:09:54 +0800290 (0x3 << 30) | (0x1 << 28) | (0x1 << 23),
291 (0x2 << 30) | (0x1 << 28) | (0x1 << 23));
292
293}
294
295static void dramc_hw_dqs_gating_tracking(u8 chn)
296{
Julius Werner55009af2019-12-02 22:03:27 -0800297 clrsetbits32(&ch[chn].ao.stbcal,
mtk1119516ad2d72019-01-23 11:41:19 +0800298 (0x1 << 21) | (0x3 << 15) | (0x1f << 8) | (0x1 << 4),
299 (0x3 << 26) | (0x1 << 0));
Julius Werner55009af2019-12-02 22:03:27 -0800300 clrsetbits32(&ch[chn].ao.stbcal1,
Huayang Duan7b78a802018-09-26 21:09:54 +0800301 (0xffff << 16) | (0x1 << 8) | (0x1 << 6),
mtk1119516ad2d72019-01-23 11:41:19 +0800302 (0x1 << 16) | (0x1 << 8) | (0x1 << 6));
Huayang Duan7b78a802018-09-26 21:09:54 +0800303
Julius Werner55009af2019-12-02 22:03:27 -0800304 clrsetbits32(&ch[chn].phy.misc_ctrl0,
Huayang Duan7b78a802018-09-26 21:09:54 +0800305 (0x1 << 24) | (0x1f << 11) | (0xf << 0),
306 (0x1 << 24) | (0x0 << 11) | (0x0 << 0));
307
Julius Werner55009af2019-12-02 22:03:27 -0800308 clrbits32(&ch[chn].phy.b[0].dq[6], 0x1 << 31);
309 clrbits32(&ch[chn].phy.b[1].dq[6], 0x1 << 31);
310 clrbits32(&ch[chn].phy.ca_cmd[6], 0x1 << 31);
Huayang Duan7b78a802018-09-26 21:09:54 +0800311}
312
Huayang Duan04571d82020-01-21 10:40:01 +0800313static void dramc_hw_gating_init(u8 chn)
Huayang Duan7b78a802018-09-26 21:09:54 +0800314{
Huayang Duan04571d82020-01-21 10:40:01 +0800315 clrbits32(&ch[chn].ao.stbcal,
316 (0x7 << 22) | (0x3 << 14) | (0x1 << 19) | (0x1 << 21));
317 setbits32(&ch[chn].ao.stbcal, (0x1 << 20) | (0x3 << 28));
318 setbits32(&ch[chn].phy.misc_ctrl1, 0x1 << 24);
Huayang Duan7b78a802018-09-26 21:09:54 +0800319
Huayang Duan04571d82020-01-21 10:40:01 +0800320 dramc_hw_dqs_gating_tracking(chn);
Huayang Duan7b78a802018-09-26 21:09:54 +0800321}
322
323static void dramc_impedance_tracking_enable(void)
324{
Julius Werner55009af2019-12-02 22:03:27 -0800325 setbits32(&ch[0].phy.misc_ctrl0, 0x1 << 10);
Huayang Duan7b78a802018-09-26 21:09:54 +0800326 for (size_t chn = 0; chn < CHANNEL_MAX; chn++) {
Julius Werner55009af2019-12-02 22:03:27 -0800327 setbits32(&ch[chn].ao.impcal, (0x1 << 31) | (0x1 << 29) |
Huayang Duan7b78a802018-09-26 21:09:54 +0800328 (0x1 << 26) | (0x1 << 17) | (0x7 << 11));
Julius Werner55009af2019-12-02 22:03:27 -0800329 clrbits32(&ch[chn].ao.impcal, 0x1 << 30);
330 setbits32(&ch[chn].phy.misc_ctrl0, 0x1 << 18);
331 setbits32(&ch[chn].ao.impcal, 0x1 << 19);
Huayang Duan7b78a802018-09-26 21:09:54 +0800332 }
Julius Werner55009af2019-12-02 22:03:27 -0800333 setbits32(&ch[0].ao.impcal, 0x1 << 14);
Huayang Duan7b78a802018-09-26 21:09:54 +0800334 for (size_t chn = 0; chn < CHANNEL_MAX; chn++)
Julius Werner55009af2019-12-02 22:03:27 -0800335 setbits32(&ch[chn].ao.refctrl0, (0x1 << 2) | (0x1 << 3));
Huayang Duan7b78a802018-09-26 21:09:54 +0800336}
337
Huayang Duan04571d82020-01-21 10:40:01 +0800338static void dramc_phy_low_power_enable(u8 chn)
Huayang Duan7b78a802018-09-26 21:09:54 +0800339{
Huayang Duan04571d82020-01-21 10:40:01 +0800340 for (u8 b = 0; b < 2; b++) {
341 clrbits32(&ch[chn].phy.b[b].dll_fine_tune[2], 0x3fffff << 10);
342 write32(&ch[chn].phy.b[b].dll_fine_tune[3], 0x2e800);
Huayang Duan7b78a802018-09-26 21:09:54 +0800343 }
Huayang Duan04571d82020-01-21 10:40:01 +0800344 clrsetbits32(&ch[chn].phy.ca_dll_fine_tune[2],
345 0x3fffff << 10, 0x2 << 10);
346 write32(&ch[chn].phy.ca_dll_fine_tune[3],
347 (chn == CHANNEL_A) ? 0xba000 : 0x3a000);
Huayang Duan7b78a802018-09-26 21:09:54 +0800348}
mtk1119516ad2d72019-01-23 11:41:19 +0800349
350static void dramc_dummy_read_for_tracking_enable(u8 chn)
351{
Julius Werner55009af2019-12-02 22:03:27 -0800352 setbits32(&ch[chn].ao.dummy_rd, 0x3 << 16);
mtk1119516ad2d72019-01-23 11:41:19 +0800353
354 for (size_t r = 0; r < 2; r++)
355 for (size_t i = 0; i < 4; i++)
356 write32(&ch[chn].ao.rk[r].dummy_rd_wdata[i],
357 0xaaaa5555);
358
Julius Werner55009af2019-12-02 22:03:27 -0800359 clrsetbits32(&ch[chn].ao.test2_4, 0x7 << 28, 0x4 << 28);
mtk1119516ad2d72019-01-23 11:41:19 +0800360 for (size_t r = 0; r < 2; r++) {
Julius Werner55009af2019-12-02 22:03:27 -0800361 clrsetbits32(&ch[chn].ao.rk[r].dummy_rd_adr,
mtk1119516ad2d72019-01-23 11:41:19 +0800362 (0x1ffff << 0) | (0x7ff << 17) | (0xf << 28),
Huayang Duanc157ee92019-07-14 15:46:08 +0800363 (0xffff << 0) | (0x3f0 << 17));
Julius Werner55009af2019-12-02 22:03:27 -0800364 clrbits32(&ch[chn].ao.rk[r].dummy_rd_bk, 0x7 << 0);
mtk1119516ad2d72019-01-23 11:41:19 +0800365 }
366
Julius Werner55009af2019-12-02 22:03:27 -0800367 clrbits32(&ch[chn].ao.dummy_rd, 0x1 << 25 | 0x1 << 20);
mtk1119516ad2d72019-01-23 11:41:19 +0800368}
369
370static void dramc_set_CKE_2_rank_independent(u8 chn)
371{
Julius Werner55009af2019-12-02 22:03:27 -0800372 clrsetbits32(&ch[chn].ao.rkcfg, (0x1 << 15) | (0x1 << 12), 0x1 << 2);
373 clrsetbits32(&ch[chn].ao.ckectrl,
mtk1119516ad2d72019-01-23 11:41:19 +0800374 (0x1 << 1) | (0xf << 8) | (0x7 << 13),
375 (0x4 << 8) | (0x2 << 13));
376
377 for (u8 shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++)
Julius Werner55009af2019-12-02 22:03:27 -0800378 setbits32(&ch[chn].ao.shu[shu].conf[2],
mtk1119516ad2d72019-01-23 11:41:19 +0800379 (0x1 << 29) | (0x1 << 31));
Julius Werner55009af2019-12-02 22:03:27 -0800380 clrbits32(&ch[chn].ao.dramctrl, 0x1 << 9);
mtk1119516ad2d72019-01-23 11:41:19 +0800381}
382
383static void dramc_pa_improve(u8 chn)
384{
Julius Werner55009af2019-12-02 22:03:27 -0800385 clrbits32(&ch[chn].ao.clkar, 0xffff);
386 clrbits32(&ch[chn].ao.srefctrl, 0xf << 12);
387 clrbits32(&ch[chn].ao.zqcs, 0x1 << 19);
388 clrbits32(&ch[chn].ao.pre_tdqsck[0], 0x1 << 17);
389 clrbits32(&ch[chn].ao.zqcs, 0x1 << 19);
390 clrbits32(&ch[chn].ao.pre_tdqsck[0], 0x1 << 17);
mtk1119516ad2d72019-01-23 11:41:19 +0800391
392 for (u8 shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++)
Julius Werner55009af2019-12-02 22:03:27 -0800393 clrbits32(&ch[chn].ao.shu[shu].odtctrl, 0x3 << 2);
mtk1119516ad2d72019-01-23 11:41:19 +0800394}
395
396static void dramc_enable_dramc_dcm(void)
397{
398 for (size_t chn = 0; chn < CHANNEL_MAX; chn++) {
Julius Werner55009af2019-12-02 22:03:27 -0800399 clrsetbits32(&ch[chn].ao.dramc_pd_ctrl,
mtk1119516ad2d72019-01-23 11:41:19 +0800400 (0x7 << 0) | (0x1 << 26) | (0x1 << 30) | (0x1 << 31),
401 (0x7 << 0) | (0x1 << 30) | (0x1 << 31));
Julius Werner55009af2019-12-02 22:03:27 -0800402 setbits32(&ch[chn].ao.clkar, 0x1 << 31);
mtk1119516ad2d72019-01-23 11:41:19 +0800403 }
404}
405
Huayang Duan7b78a802018-09-26 21:09:54 +0800406void dramc_runtime_config(void)
407{
Huayang Duan04571d82020-01-21 10:40:01 +0800408 for (u8 chn = 0; chn < CHANNEL_MAX; chn++)
409 clrbits32(&ch[chn].ao.refctrl0, 0x1 << 29);
Huayang Duan7b78a802018-09-26 21:09:54 +0800410
411 transfer_pll_to_spm_control();
Julius Werner55009af2019-12-02 22:03:27 -0800412 setbits32(&mtk_spm->spm_power_on_val0, 0x1 << 25);
Huayang Duan7b78a802018-09-26 21:09:54 +0800413
Huayang Duan04571d82020-01-21 10:40:01 +0800414 for (u8 chn = 0; chn < CHANNEL_MAX; chn++) {
Huayang Duan25930f42019-12-30 13:19:05 +0800415 dramc_hw_dqsosc(chn);
416
Huayang Duan04571d82020-01-21 10:40:01 +0800417 /* RX_TRACKING: ON */
Huayang Duan7b78a802018-09-26 21:09:54 +0800418 dramc_rx_input_delay_tracking(chn);
419
Huayang Duan04571d82020-01-21 10:40:01 +0800420 /* HW_GATING: ON */
421 dramc_hw_gating_init(chn);
422 dramc_hw_gating_onoff(chn, true);
Huayang Duan7b78a802018-09-26 21:09:54 +0800423
Huayang Duan04571d82020-01-21 10:40:01 +0800424 /* HW_GATING DBG: OFF */
Julius Werner55009af2019-12-02 22:03:27 -0800425 clrbits32(&ch[chn].ao.stbcal2,
Huayang Duan04571d82020-01-21 10:40:01 +0800426 (0x3 << 4) | (0x3 << 8) | (0x1 << 28));
Huayang Duan7b78a802018-09-26 21:09:54 +0800427
Huayang Duan04571d82020-01-21 10:40:01 +0800428 /* DUMMY_READ_FOR_TRACKING: ON */
mtk1119516ad2d72019-01-23 11:41:19 +0800429 dramc_dummy_read_for_tracking_enable(chn);
430
Huayang Duan04571d82020-01-21 10:40:01 +0800431 /* ZQCS_ENABLE_LP4: ON */
432 clrbits32(&ch[chn].ao.spcmdctrl, 0x1 << 30);
Huayang Duan7b78a802018-09-26 21:09:54 +0800433
Huayang Duan04571d82020-01-21 10:40:01 +0800434 /* LOWPOWER_GOLDEN_SETTINGS(DCM): ON */
435 dramc_phy_low_power_enable(chn);
436 dramc_enable_phy_dcm(chn, true);
Huayang Duan7b78a802018-09-26 21:09:54 +0800437
Huayang Duan04571d82020-01-21 10:40:01 +0800438 /* DUMMY_READ_FOR_DQS_GATING_RETRY: OFF */
Huayang Duan7b78a802018-09-26 21:09:54 +0800439 for (size_t shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++)
Julius Werner55009af2019-12-02 22:03:27 -0800440 clrbits32(&ch[chn].ao.shu[shu].dqsg_retry,
Huayang Duan04571d82020-01-21 10:40:01 +0800441 (0x1 << 1) | (0x3 << 13));
442 }
Huayang Duan7b78a802018-09-26 21:09:54 +0800443
mtk1119516ad2d72019-01-23 11:41:19 +0800444 /* SPM_CONTROL_AFTERK: ON */
Huayang Duan7b78a802018-09-26 21:09:54 +0800445 write32(&ch[0].phy.misc_spm_ctrl0, 0xfbffefff);
446 write32(&ch[1].phy.misc_spm_ctrl0, 0xfbffefff);
447 write32(&ch[0].phy.misc_spm_ctrl2, 0xffffffef);
448 write32(&ch[1].phy.misc_spm_ctrl2, 0x7fffffef);
449
mtk1119516ad2d72019-01-23 11:41:19 +0800450 /* IMPEDANCE_TRACKING: ON */
Huayang Duan7b78a802018-09-26 21:09:54 +0800451 dramc_impedance_tracking_enable();
452
453 for (size_t chn = 0; chn < CHANNEL_MAX; chn++) {
mtk1119516ad2d72019-01-23 11:41:19 +0800454 /* TEMP_SENSOR: ON */
Julius Werner55009af2019-12-02 22:03:27 -0800455 clrbits32(&ch[chn].ao.spcmdctrl, 0x3 << 28);
456 setbits32(&ch[chn].ao.hw_mrr_fun, (0x1 << 0) | (0x1 << 11));
mtk1119516ad2d72019-01-23 11:41:19 +0800457
458 /* PER_BANK_REFRESH: ON */
Julius Werner55009af2019-12-02 22:03:27 -0800459 clrbits32(&ch[chn].ao.refctrl0, 0x1 << 18);
mtk1119516ad2d72019-01-23 11:41:19 +0800460
461 /* HW_SAVE_FOR_SR: ON */
Julius Werner55009af2019-12-02 22:03:27 -0800462 clrbits32(&ch[chn].ao.rstmask, (0x1 << 25) | (0x1 << 28));
463 setbits32(&ch[chn].ao.refctrl1, 0x1 << 0);
464 clrsetbits32(&ch[chn].ao.srefctrl, 0x1 << 20, 0x1 << 22);
mtk1119516ad2d72019-01-23 11:41:19 +0800465
466 /* SET_CKE_2_RANK_INDEPENDENT_RUN_TIME: ON */
467 dramc_set_CKE_2_rank_independent(chn);
468
469 /* CLK_FREE_FUN_FOR_DRAMC_PSEL: ON */
Julius Werner55009af2019-12-02 22:03:27 -0800470 clrbits32(&ch[chn].ao.refctrl1, (0x1 << 6) | (0x3 << 2));
471 clrbits32(&ch[chn].ao.clkar, 0x1 << 19);
mtk1119516ad2d72019-01-23 11:41:19 +0800472
473 /* PA_IMPROVEMENT_FOR_DRAMC_ACTIVE_POWER: ON */
474 dramc_pa_improve(chn);
475
476 /* DRAM DRS DISABLE */
Julius Werner55009af2019-12-02 22:03:27 -0800477 clrsetbits32(&ch[chn].ao.drsctrl,
Huayang Duan31b081a2020-03-18 13:49:00 +0800478 (0x1 << 0) | (0x1 << 2) | (0x1 << 4) | (0x1 << 5) | (0x1 << 6) |
479 (0xf << 8) | (0x7f << 12) | (0x1 << 19) | (0x1 << 21),
480 (0x1 << 0) | (0x0 << 2) | (0x0 << 4) | (0x1 << 5) | (0x0 << 6) |
481 (0x8 << 8) | (0x3 << 12) | (0x1 << 19) | (0x0 << 21));
Julius Werner55009af2019-12-02 22:03:27 -0800482 setbits32(&ch[chn].ao.dummy_rd, 0x3 << 26);
Huayang Duan7b78a802018-09-26 21:09:54 +0800483 }
Huayang Duan25930f42019-12-30 13:19:05 +0800484 dramc_dqs_precalculation_preset();
mtk1119516ad2d72019-01-23 11:41:19 +0800485
486 enable_emi_dcm();
487 dramc_enable_dramc_dcm();
Huayang Duan7b78a802018-09-26 21:09:54 +0800488}