diff options
Diffstat (limited to 'drivers/ddr')
-rw-r--r-- | drivers/ddr/imx/imx8ulp/Kconfig | 2 | ||||
-rw-r--r-- | drivers/ddr/imx/imx8ulp/ddr_init.c | 55 | ||||
-rw-r--r-- | drivers/ddr/marvell/a38x/ddr3_init.h | 1 | ||||
-rw-r--r-- | drivers/ddr/marvell/a38x/seq_exec.h | 64 |
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*/ |