aboutsummaryrefslogtreecommitdiff
path: root/src/soc/mediatek/mt8173/emi.c
diff options
context:
space:
mode:
authorPeter Kao <peter.kao@mediatek.com>2015-07-31 17:11:14 +0800
committerPatrick Georgi <pgeorgi@google.com>2016-03-12 09:00:21 +0100
commitda1e02a3a0cd8de244a03cc84d5ecc9663e5e694 (patch)
tree561d900efe1632f802de2eee84ff11d6f4465ed5 /src/soc/mediatek/mt8173/emi.c
parentb74a2eca80deed3e7d21ba1123c2b986abcfcc10 (diff)
mediatek/mt8173: Add EMI driver, DRAM initialization
BUG=none TEST=emerge-oak coreboot BRANCH=none Change-Id: I6b05898de2d0022e0de7b18f1db3c3e9c06d8135 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: b614eeb1bba5660438c214e82225832809caca8e Original-Change-Id: I0f7b0a426dae1548b34114a024c92befdf6002f6 Original-Signed-off-by: Peter Kao <peter.kao@mediatek.com> Original-Reviewed-on: https://chromium-review.googlesource.com/292692 Original-Commit-Ready: Yidi Lin <yidi.lin@mediatek.com> Original-Tested-by: Yidi Lin <yidi.lin@mediatek.com> Original-Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/13105 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/soc/mediatek/mt8173/emi.c')
-rw-r--r--src/soc/mediatek/mt8173/emi.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/soc/mediatek/mt8173/emi.c b/src/soc/mediatek/mt8173/emi.c
new file mode 100644
index 0000000000..f6ef40f8f3
--- /dev/null
+++ b/src/soc/mediatek/mt8173/emi.c
@@ -0,0 +1,142 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <assert.h>
+#include <boardid.h>
+#include <console/console.h>
+#include <delay.h>
+#include <string.h>
+#include <soc/addressmap.h>
+#include <soc/dramc_common.h>
+#include <soc/dramc_register.h>
+#include <soc/dramc_pi_api.h>
+#include <soc/mt6391.h>
+#include <soc/pll.h>
+
+struct emi_regs *emi_regs = (void *)EMI_BASE;
+
+static void dram_vcore_adjust(void)
+{
+ /* options: Vcore_HV_LPPDR3/Vcore_NV_LPPDR3/Vcore_LV_LPPDR3 */
+ mt6391_write(PMIC_RG_VCORE_CON9, Vcore_NV_LPPDR3, 0x7F, 0);
+ mt6391_write(PMIC_RG_VCORE_CON10, Vcore_NV_LPPDR3, 0x7F, 0);
+}
+
+static void dram_vmem_adjust(void)
+{
+ /* options: Vmem_HV_LPPDR3/Vmem_NV_LPPDR3/Vmem_LV_LPPDR3 */
+ mt6391_write(PMIC_RG_VDRM_CON9, Vmem_NV_LPDDR3, 0x7F, 0);
+ mt6391_write(PMIC_RG_VDRM_CON10, Vmem_NV_LPDDR3, 0x7F, 0);
+}
+
+static void emi_init(const struct mt8173_sdram_params *sdram_params)
+{
+ /* EMI setting initialization */
+ write32(&emi_regs->emi_conf, sdram_params->emi_set.conf);
+ write32(&emi_regs->emi_conm, sdram_params->emi_set.conm_1);
+ write32(&emi_regs->emi_arbi, sdram_params->emi_set.arbi);
+ write32(&emi_regs->emi_arba, sdram_params->emi_set.arba);
+ write32(&emi_regs->emi_arbc, sdram_params->emi_set.arbc);
+ write32(&emi_regs->emi_arbd, sdram_params->emi_set.arbd);
+ write32(&emi_regs->emi_arbe, sdram_params->emi_set.arbe);
+ write32(&emi_regs->emi_arbf, sdram_params->emi_set.arbf);
+ write32(&emi_regs->emi_arbg, sdram_params->emi_set.arbg);
+ write32(&emi_regs->emi_arbj, sdram_params->emi_set.arbj);
+ write32(&emi_regs->emi_cona, sdram_params->emi_set.cona);
+ write32(&emi_regs->emi_testd, sdram_params->emi_set.testd);
+ write32(&emi_regs->emi_bmen, sdram_params->emi_set.bmen);
+ write32(&emi_regs->emi_conb, sdram_params->emi_set.conb);
+ write32(&emi_regs->emi_conc, sdram_params->emi_set.conc);
+ write32(&emi_regs->emi_cond, sdram_params->emi_set.cond);
+ write32(&emi_regs->emi_cone, sdram_params->emi_set.cone);
+ write32(&emi_regs->emi_cong, sdram_params->emi_set.cong);
+ write32(&emi_regs->emi_conh, sdram_params->emi_set.conh);
+ write32(&emi_regs->emi_slct, sdram_params->emi_set.slct_1);
+ write32(&emi_regs->emi_mdct, sdram_params->emi_set.mdct_1);
+ write32(&emi_regs->emi_arbk, sdram_params->emi_set.arbk);
+ write32(&emi_regs->emi_testc, sdram_params->emi_set.testc);
+ write32(&emi_regs->emi_mdct, sdram_params->emi_set.mdct_2);
+ write32(&emi_regs->emi_testb, sdram_params->emi_set.testb);
+ write32(&emi_regs->emi_slct, sdram_params->emi_set.slct_2);
+ write32(&emi_regs->emi_conm, sdram_params->emi_set.conm_2);
+ write32(&emi_regs->emi_test0, sdram_params->emi_set.test0);
+ write32(&emi_regs->emi_test1, sdram_params->emi_set.test1);
+}
+
+static void do_calib(const struct mt8173_sdram_params *sdram_params)
+{
+ u32 channel;
+
+ sw_impedance_cal(CHANNEL_A, sdram_params);
+ sw_impedance_cal(CHANNEL_B, sdram_params);
+
+ /* SPM_CONTROL_AFTERK */
+ transfer_to_reg_control();
+
+ /* do dram calibration for channel A and B */
+ for(channel = 0; channel < CHANNEL_NUM; channel++) {
+ ca_training(channel, sdram_params);
+ write_leveling(channel, sdram_params);
+
+ /* rx gating and datlat for single or dual rank */
+ if (is_dual_rank(channel, sdram_params)) {
+ dual_rank_rx_dqs_gating_cal(channel, sdram_params);
+ dual_rank_rx_datlat_cal(channel, sdram_params);
+ } else {
+ rx_dqs_gating_cal(channel, 0, sdram_params);
+ rx_datlat_cal(channel, 0, sdram_params);
+ }
+
+ clk_duty_cal(channel);
+ /* rx window perbit calibration */
+ perbit_window_cal(channel, RX_WIN);
+ /* tx window perbit calibration */
+ perbit_window_cal(channel, TX_WIN);
+
+ dramc_rankinctl_config(channel, sdram_params);
+ dramc_runtime_config(channel, sdram_params);
+ }
+
+ /* SPM_CONTROL_AFTERK */
+ transfer_to_spm_control();
+}
+
+static void init_dram(const struct mt8173_sdram_params *sdram_params)
+{
+ emi_init(sdram_params);
+
+ dramc_pre_init(CHANNEL_A, sdram_params);
+ dramc_pre_init(CHANNEL_B, sdram_params);
+
+ div2_phase_sync();
+
+ dramc_init(CHANNEL_A, sdram_params);
+ dramc_init(CHANNEL_B, sdram_params);
+}
+
+void mt_set_emi(const struct mt8173_sdram_params *sdram_params)
+{
+ /* voltage info */
+ dram_vcore_adjust();
+ dram_vmem_adjust();
+
+ if (sdram_params->type != TYPE_LPDDR3) {
+ die("The DRAM type is not supported");
+ }
+
+ init_dram(sdram_params);
+ do_calib(sdram_params);
+}