summaryrefslogtreecommitdiff
path: root/drivers/ddr
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ddr')
-rw-r--r--drivers/ddr/imx/imx8ulp/Kconfig2
-rw-r--r--drivers/ddr/imx/imx8ulp/ddr_init.c55
-rw-r--r--drivers/ddr/marvell/a38x/ddr3_init.h1
-rw-r--r--drivers/ddr/marvell/a38x/seq_exec.h64
4 files changed, 44 insertions, 78 deletions
diff --git a/drivers/ddr/imx/imx8ulp/Kconfig b/drivers/ddr/imx/imx8ulp/Kconfig
index 42848863aae..5448c33838c 100644
--- a/drivers/ddr/imx/imx8ulp/Kconfig
+++ b/drivers/ddr/imx/imx8ulp/Kconfig
@@ -13,6 +13,6 @@ config SAVED_DRAM_TIMING_BASE
help
The DRAM config timing data need to be saved into sram
for low power use.
- default 0x2006c000
+ default 0x20055000
endmenu
diff --git a/drivers/ddr/imx/imx8ulp/ddr_init.c b/drivers/ddr/imx/imx8ulp/ddr_init.c
index a5a9fd8d7c8..c362a2da338 100644
--- a/drivers/ddr/imx/imx8ulp/ddr_init.c
+++ b/drivers/ddr/imx/imx8ulp/ddr_init.c
@@ -31,6 +31,7 @@
#define DENALI_CTL_25 (DDR_CTL_BASE_ADDR + 4 * 25)
#define DENALI_PHY_1624 (DDR_PHY_BASE_ADDR + 4 * 1624)
+#define DENALI_PHY_1625 (DDR_PHY_BASE_ADDR + 4 * 1625)
#define DENALI_PHY_1537 (DDR_PHY_BASE_ADDR + 4 * 1537)
#define PHY_FREQ_SEL_MULTICAST_EN(X) ((X) << 8)
#define PHY_FREQ_SEL_INDEX(X) ((X) << 16)
@@ -82,25 +83,39 @@ int ddr_calibration(unsigned int fsp_table[3])
u32 int_status_init, phy_freq_req, phy_freq_type;
u32 lock_0, lock_1, lock_2;
u32 freq_chg_pt, freq_chg_cnt;
+ u32 is_lpddr4 = 0;
if (IS_ENABLED(CONFIG_IMX8ULP_DRAM_PHY_PLL_BYPASS)) {
ddr_enable_pll_bypass();
freq_chg_cnt = 0;
freq_chg_pt = 0;
} else {
- reg_val = readl(DENALI_CTL_250);
- if (((reg_val >> 16) & 0x3) == 1)
- freq_chg_cnt = 2;
- else
- freq_chg_cnt = 3;
-
- reg_val = readl(DENALI_PI_12);
- if (reg_val == 0x3) {
- freq_chg_pt = 1;
- } else if (reg_val == 0x7) {
- freq_chg_pt = 2;
+ reg_val = (readl(DENALI_CTL_00)>>8)&0xf;
+ if(reg_val == 0x7) {
+ /* LPDDR3 type */
+ set_ddr_clk(fsp_table[1] >> 1);
+ freq_chg_cnt = 0;
+ freq_chg_pt = 0;
+ } else if(reg_val == 0xb) {
+ /* LPDDR4/4x type */
+ is_lpddr4 = 1;
+ reg_val = readl(DENALI_CTL_250);
+ if (((reg_val >> 16) & 0x3) == 1)
+ freq_chg_cnt = 2;
+ else
+ freq_chg_cnt = 3;
+
+ reg_val = readl(DENALI_PI_12);
+ if(reg_val == 0x3)
+ freq_chg_pt = 1;
+ else if(reg_val == 0x7)
+ freq_chg_pt = 2;
+ else {
+ printf("frequency map(0x%x) is wrong, please check!\r\n", reg_val);
+ return -1;
+ }
} else {
- printf("frequency map(0x%x) is wrong, please check!\r\n", reg_val);
+ printf("Incorrect DDR type configured!\r\n");
return -1;
}
}
@@ -179,6 +194,22 @@ int ddr_calibration(unsigned int fsp_table[3])
}
debug("De-Skew PLL is locked and ready\n");
+
+ /* Change LPDDR4 FREQ1 to bypass mode if it is lower than 200MHz */
+ if(is_lpddr4 && fsp_table[1] < 400) {
+ /* Set FREQ1 to bypass mode */
+ reg_val = PHY_FREQ_SEL_MULTICAST_EN(0) | PHY_FREQ_SEL_INDEX(0);
+ writel(reg_val, DENALI_PHY_1537);
+
+ /* PHY_PLL_BYPASS=0x1 (DENALI_PHY_1624) */
+ reg_val =readl(DENALI_PHY_1624) | 0x1;
+ writel(reg_val, DENALI_PHY_1624);
+
+ /* DENALI_PHY_1625: bypass mode in PHY PLL */
+ reg_val =readl(DENALI_PHY_1625) & ~0xf;
+ writel(reg_val, DENALI_PHY_1625);
+ }
+
return 0;
}
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.h b/drivers/ddr/marvell/a38x/ddr3_init.h
index ba9f7881d54..6854bb49de1 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.h
+++ b/drivers/ddr/marvell/a38x/ddr3_init.h
@@ -9,7 +9,6 @@
#include "ddr_ml_wrapper.h"
#include "mv_ddr_plat.h"
-#include "seq_exec.h"
#include "ddr3_logging_def.h"
#include "ddr3_training_hw_algo.h"
#include "ddr3_training_ip.h"
diff --git a/drivers/ddr/marvell/a38x/seq_exec.h b/drivers/ddr/marvell/a38x/seq_exec.h
deleted file mode 100644
index fe0cb8f75df..00000000000
--- a/drivers/ddr/marvell/a38x/seq_exec.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) Marvell International Ltd. and its affiliates
- */
-
-#ifndef _SEQ_EXEC_H
-#define _SEQ_EXEC_H
-
-#define NA 0xff
-#define DEFAULT_PARAM 0
-#define MV_BOARD_TCLK_ERROR 0xffffffff
-
-#define NO_DATA 0xffffffff
-#define MAX_DATA_ARRAY 5
-#define FIRST_CELL 0
-
-/* Operation types */
-enum mv_op {
- WRITE_OP,
- DELAY_OP,
- POLL_OP,
-};
-
-/* Operation parameters */
-struct op_params {
- u32 unit_base_reg;
- u32 unit_offset;
- u32 mask;
- u32 data[MAX_DATA_ARRAY]; /* data array */
- u8 wait_time; /* msec */
- u16 num_of_loops; /* for polling only */
-};
-
-/*
- * Sequence parameters. Each sequence contains:
- * 1. Sequence id.
- * 2. Sequence size (total amount of operations during the sequence)
- * 3. a series of operations. operations can be write, poll or delay
- * 4. index in the data array (the entry where the relevant data sits)
- */
-struct cfg_seq {
- struct op_params *op_params_ptr;
- u8 cfg_seq_size;
- u8 data_arr_idx;
-};
-
-extern struct cfg_seq serdes_seq_db[];
-
-/*
- * A generic function type for executing an operation (write, poll or delay)
- */
-typedef int (*op_execute_func_ptr)(u32 serdes_num, struct op_params *params,
- u32 data_arr_idx);
-
-/* Specific functions for executing each operation */
-int write_op_execute(u32 serdes_num, struct op_params *params,
- u32 data_arr_idx);
-int delay_op_execute(u32 serdes_num, struct op_params *params,
- u32 data_arr_idx);
-int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx);
-enum mv_op get_cfg_seq_op(struct op_params *params);
-int mv_seq_exec(u32 serdes_num, u32 seq_id);
-
-#endif /*_SEQ_EXEC_H*/