summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/mediatek/mt8192/dramc_pi_basic_api.c1
-rw-r--r--src/soc/mediatek/mt8192/dramc_pi_calibration_api.c78
2 files changed, 79 insertions, 0 deletions
diff --git a/src/soc/mediatek/mt8192/dramc_pi_basic_api.c b/src/soc/mediatek/mt8192/dramc_pi_basic_api.c
index 24f9620149..eeeeceae8a 100644
--- a/src/soc/mediatek/mt8192/dramc_pi_basic_api.c
+++ b/src/soc/mediatek/mt8192/dramc_pi_basic_api.c
@@ -3791,6 +3791,7 @@ static void dramc_init(const struct ddr_cali *cali)
dramc_setting(cali);
dramc_reset_delay_chain_before_calibration();
dramc_8_phase_cal(cali);
+ dramc_duty_calibration(cali->params);
}
static void dramc_before_calibration(const struct ddr_cali *cali)
diff --git a/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c
index 19a964ae77..e4dc896829 100644
--- a/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c
+++ b/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c
@@ -577,3 +577,81 @@ void dramc_8_phase_cal(const struct ddr_cali *cali)
for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++)
write32(regs_bak[i].addr, regs_bak[i].value);
}
+
+static void duty_delay_reg_convert(s8 duty_delay, u8 *delay)
+{
+ if (duty_delay < 0)
+ *delay = -duty_delay;
+ else if (duty_delay > 0)
+ *delay = duty_delay + (1 << 5);
+ else
+ *delay = 0;
+}
+
+static void dramc_duty_set_clk_delay_cell(u8 chn, const s8 *duty_delay)
+{
+ u8 delay;
+
+ duty_delay_reg_convert(duty_delay[RANK_0], &delay);
+ SET32_BITFIELDS(&ch[chn].phy_ao.shu_ca_txduty,
+ SHU_CA_TXDUTY_DA_TX_ARCLK_DUTY_DLY, delay);
+}
+
+static void dramc_duty_set_dqs_delay_cell(u8 chn, const s8 *duty_delay)
+{
+ u8 dqs;
+ u8 delay;
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ duty_delay_reg_convert(duty_delay[dqs], &delay);
+ SET32_BITFIELDS(&ch[chn].phy_ao.byte[dqs].shu_b0_txduty,
+ SHU_B0_TXDUTY_DA_TX_ARDQS_DUTY_DLY_B0, delay);
+ }
+}
+
+static void dramc_duty_set_wck_delay_cell(u8 chn, const s8 *duty_delay)
+{
+ u8 dqs;
+ u8 delay;
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ duty_delay_reg_convert(duty_delay[dqs], &delay);
+ SET32_BITFIELDS(&ch[chn].phy_ao.byte[dqs].shu_b0_txduty,
+ SHU_B0_TXDUTY_DA_TX_ARWCK_DUTY_DLY_B0, delay);
+ }
+}
+
+static void dramc_duty_set_dqdqm_delay_cell(u8 chn, const s8 *duty_delay,
+ u8 k_type)
+{
+ u8 dqs;
+ u8 delay;
+
+ for (dqs = 0; dqs < DQS_NUMBER; dqs++) {
+ duty_delay_reg_convert(duty_delay[dqs], &delay);
+
+ if (k_type == DUTYSCAN_K_DQ)
+ SET32_BITFIELDS(&ch[chn].phy_ao.byte[dqs].shu_b0_txduty,
+ SHU_B0_TXDUTY_DA_TX_ARDQ_DUTY_DLY_B0, delay);
+ else if (k_type == DUTYSCAN_K_DQM)
+ SET32_BITFIELDS(&ch[chn].phy_ao.byte[dqs].shu_b0_txduty,
+ SHU_B0_TXDUTY_DA_TX_ARDQM_DUTY_DLY_B0, delay);
+ }
+}
+
+void dramc_duty_calibration(const struct sdram_params *params)
+{
+ u32 bc_bak = dramc_get_broadcast();
+ dramc_set_broadcast(DRAMC_BROADCAST_OFF);
+ for (u8 chn = 0; chn < CHANNEL_MAX; chn++) {
+ dramc_duty_set_clk_delay_cell(chn, params->duty_clk_delay[chn]);
+ dramc_duty_set_dqs_delay_cell(chn, params->duty_dqs_delay[chn]);
+ dramc_duty_set_wck_delay_cell(chn, params->duty_wck_delay[chn]);
+ dramc_duty_set_dqdqm_delay_cell(chn, params->duty_dqm_delay[chn],
+ DUTYSCAN_K_DQM);
+ dramc_duty_set_dqdqm_delay_cell(chn, params->duty_dq_delay[chn],
+ DUTYSCAN_K_DQ);
+ }
+
+ dramc_set_broadcast(bc_bak);
+}