From: YouMin Chen <c...@rock-chips.com> RK3399's controller and phy are able to re-use the common code, migrate to use the common driver and remove duplicated code.
Signed-off-by: YouMin Chen <c...@rock-chips.com> Signed-off-by: Kever Yang <kever.y...@rock-chips.com> --- arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi | 4 + arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi | 4 + arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi | 4 + .../arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi | 4 + .../arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi | 4 + .../rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi | 4 + arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi | 4 + .../include/asm/arch-rockchip/sdram_rk3399.h | 97 +- arch/arm/mach-rockchip/Kconfig | 1 + drivers/ram/rockchip/Kconfig | 21 +- drivers/ram/rockchip/Makefile | 3 +- .../ram/rockchip/sdram-rk3399-lpddr4-400.inc | 28 +- .../ram/rockchip/sdram-rk3399-lpddr4-800.inc | 28 +- drivers/ram/rockchip/sdram_rk3399.c | 970 ++++++++++++------ 14 files changed, 787 insertions(+), 389 deletions(-) diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi index 3708bd674b..7fae249536 100644 --- a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi +++ b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi @@ -13,6 +13,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x80120e12 0x11030802 @@ -28,6 +30,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x80120e12 0x11030802 diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi index fcd01f8b46..23c7c34a9a 100644 --- a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi +++ b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi @@ -13,6 +13,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x80151015 0x14040902 @@ -28,6 +30,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x80151015 0x14040902 diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi index c46c1996be..ea029ca90a 100644 --- a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi +++ b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi @@ -13,6 +13,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x80181219 0x17050a03 @@ -28,6 +30,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x80181219 0x17050a03 diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi index d14e833d22..7296dbb80e 100644 --- a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi +++ b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi @@ -14,6 +14,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x1d191519 0x14040808 @@ -29,6 +31,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x1d191519 0x14040808 diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi index fc4cccb6a0..bf429c21e4 100644 --- a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi +++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi @@ -13,6 +13,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x1d191519 0x14040808 @@ -28,6 +30,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x1d191519 0x14040808 diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi index 2a627e1be5..96f459fd0b 100644 --- a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi +++ b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi @@ -13,6 +13,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x801d181e @@ -30,6 +32,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x801d181e diff --git a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi index 4a4414a960..f0c478d189 100644 --- a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi +++ b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi @@ -15,6 +15,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x80241d22 0x15050f08 @@ -30,6 +32,8 @@ 0x0 0xf 0xf + 0xf + 0xf 1 0x80241d22 0x15050f08 diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h index 485bb3d889..9e1e22520f 100644 --- a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h +++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h @@ -6,6 +6,7 @@ #ifndef _ASM_ARCH_SDRAM_RK3399_H #define _ASM_ARCH_SDRAM_RK3399_H #include <asm/arch-rockchip/sdram_common.h> +#include <asm/arch-rockchip/sdram_msch.h> struct rk3399_ddr_pctl_regs { u32 denali_ctl[332]; @@ -19,55 +20,6 @@ struct rk3399_ddr_pi_regs { u32 denali_pi[200]; }; -union noc_ddrtimingc0 { - u32 d32; - struct { - unsigned burstpenalty : 4; - unsigned reserved0 : 4; - unsigned wrtomwr : 6; - unsigned reserved1 : 18; - } b; -}; - -union noc_ddrmode { - u32 d32; - struct { - unsigned autoprecharge : 1; - unsigned bypassfiltering : 1; - unsigned fawbank : 1; - unsigned burstsize : 2; - unsigned mwrsize : 2; - unsigned reserved2 : 1; - unsigned forceorder : 8; - unsigned forceorderstate : 8; - unsigned reserved3 : 8; - } b; -}; - -struct rk3399_msch_regs { - u32 coreid; - u32 revisionid; - u32 ddrconf; - u32 ddrsize; - u32 ddrtiminga0; - u32 ddrtimingb0; - u32 ddrtimingc0; - u32 devtodev0; - u32 reserved0[(0x110 - 0x20) / 4]; - u32 ddrmode; - u32 reserved1[(0x1000 - 0x114) / 4]; - u32 agingx0; -}; - -struct rk3399_msch_timings { - u32 ddrtiminga0; - u32 ddrtimingb0; - union noc_ddrtimingc0 ddrtimingc0; - u32 devtodev0; - union noc_ddrmode ddrmode; - u32 agingx0; -}; - struct rk3399_ddr_cic_regs { u32 cic_ctrl0; u32 cic_ctrl1; @@ -84,14 +36,38 @@ struct rk3399_ddr_cic_regs { #define START 1 /* DENALI_CTL_68 */ -#define PWRUP_SREFRESH_EXIT (1 << 16) +#define PWRUP_SREFRESH_EXIT BIT(16) /* DENALI_CTL_274 */ #define MEM_RST_VALID 1 +struct msch_regs { + u32 coreid; + u32 revisionid; + u32 ddrconf; + u32 ddrsize; + union noc_ddrtiminga0 ddrtiminga0; + union noc_ddrtimingb0 ddrtimingb0; + union noc_ddrtimingc0 ddrtimingc0; + union noc_devtodev0 devtodev0; + u32 reserved0[(0x110 - 0x20) / 4]; + union noc_ddrmode ddrmode; + u32 reserved1[(0x1000 - 0x114) / 4]; + u32 agingx0; +}; + +struct sdram_msch_timings { + union noc_ddrtiminga0 ddrtiminga0; + union noc_ddrtimingb0 ddrtimingb0; + union noc_ddrtimingc0 ddrtimingc0; + union noc_devtodev0 devtodev0; + union noc_ddrmode ddrmode; + u32 agingx0; +}; + struct rk3399_sdram_channel { struct sdram_cap_info cap_info; - struct rk3399_msch_timings noc_timings; + struct sdram_msch_timings noc_timings; }; struct rk3399_sdram_params { @@ -102,11 +78,20 @@ struct rk3399_sdram_params { struct rk3399_ddr_publ_regs phy_regs; }; -#define PI_CA_TRAINING (1 << 0) -#define PI_WRITE_LEVELING (1 << 1) -#define PI_READ_GATE_TRAINING (1 << 2) -#define PI_READ_LEVELING (1 << 3) -#define PI_WDQ_LEVELING (1 << 4) +#define PI_CA_TRAINING BIT(0) +#define PI_WRITE_LEVELING BIT(1) +#define PI_READ_GATE_TRAINING BIT(2) +#define PI_READ_LEVELING BIT(3) +#define PI_WDQ_LEVELING BIT(4) #define PI_FULL_TRAINING 0xff +enum { + STRIDE_128B = 0, + STRIDE_256B = 1, + STRIDE_512B = 2, + STRIDE_4KB = 3, + UN_STRIDE = 4, + PART_STRIDE = 5 +}; + #endif diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 5f1ad51cac..7746b661e5 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -184,6 +184,7 @@ config ROCKCHIP_RK3399 select DM_REGULATOR_FIXED select BOARD_LATE_INIT imply ROCKCHIP_COMMON_BOARD + imply ROCKCHIP_SDRAM_COMMON imply SPL_ROCKCHIP_COMMON_BOARD imply TPL_SERIAL_SUPPORT imply TPL_LIBCOMMON_SUPPORT diff --git a/drivers/ram/rockchip/Kconfig b/drivers/ram/rockchip/Kconfig index dcc06b3fd3..3f44fb3fce 100644 --- a/drivers/ram/rockchip/Kconfig +++ b/drivers/ram/rockchip/Kconfig @@ -11,29 +11,10 @@ config ROCKCHIP_SDRAM_COMMON help This enable sdram common driver -if RAM_ROCKCHIP - -config RAM_ROCKCHIP_DEBUG - bool "Rockchip ram drivers debugging" - help - This enables debugging ram driver API's for the platforms - based on Rockchip SoCs. - - This is an option for developers to understand the ram drivers - initialization, configurations and etc. - -config RAM_RK3399 - bool "Ram driver for Rockchip RK3399" - default ROCKCHIP_RK3399 - help - This enables ram drivers support for the platforms based on - Rockchip RK3399 SoC. - config RAM_RK3399_LPDDR4 bool "LPDDR4 support for Rockchip RK3399" - depends on RAM_RK3399 + depends on RAM_ROCKCHIP && ROCKCHIP_RK3399 help This enables LPDDR4 sdram code support for the platforms based on Rockchip RK3399 SoC. -endif # RAM_ROCKCHIP diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile index 3f19fa09a5..47b9b1bebb 100644 --- a/drivers/ram/rockchip/Makefile +++ b/drivers/ram/rockchip/Makefile @@ -3,11 +3,10 @@ # Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH # obj-$(CONFIG_ROCKCHIP_SDRAM_COMMON) += sdram_common.o -obj-$(CONFIG_RAM_ROCKCHIP_DEBUG) += sdram_debug.o obj-$(CONFIG_ROCKCHIP_RK3368) = dmc-rk3368.o obj-$(CONFIG_ROCKCHIP_RK3128) = sdram_rk3128.o obj-$(CONFIG_ROCKCHIP_RK3188) = sdram_rk3188.o obj-$(CONFIG_ROCKCHIP_RK322X) = sdram_rk322x.o obj-$(CONFIG_ROCKCHIP_RK3288) = sdram_rk3288.o obj-$(CONFIG_ROCKCHIP_RK3328) += sdram_rk3328.o sdram_pctl_px30.o sdram_phy_px30.o -obj-$(CONFIG_RAM_RK3399) += sdram_rk3399.o +obj-$(CONFIG_ROCKCHIP_RK3399) += sdram_rk3399.o diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc index c50a03d9dd..6ddc01c49d 100644 --- a/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc +++ b/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc @@ -16,15 +16,23 @@ .row_3_4 = 0x0, .cs0_row = 0xF, .cs1_row = 0xF, + .cs0_high16bit_row = 0xF, + .cs1_high16bit_row = 0xF, .ddrconfig = 1, }, { - .ddrtiminga0 = 0x80241d22, - .ddrtimingb0 = 0x15050f08, + .ddrtiminga0 = { + 0x80241d22, + }, + .ddrtimingb0 = { + 0x15050f08, + }, .ddrtimingc0 = { 0x00000602, }, - .devtodev0 = 0x00002122, + .devtodev0 = { + 0x00002122, + }, .ddrmode = { 0x0000004c, }, @@ -41,15 +49,23 @@ .row_3_4 = 0x0, .cs0_row = 0xF, .cs1_row = 0xF, + .cs0_high16bit_row = 0xF, + .cs1_high16bit_row = 0xF, .ddrconfig = 1, }, { - .ddrtiminga0 = 0x80241d22, - .ddrtimingb0 = 0x15050f08, + .ddrtiminga0 = { + 0x80241d22, + }, + .ddrtimingb0 = { + 0x15050f08, + }, .ddrtimingc0 = { 0x00000602, }, - .devtodev0 = 0x00002122, + .devtodev0 = { + 0x00002122, + }, .ddrmode = { 0x0000004c, }, diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc index d8ae3359a3..307f6ee458 100644 --- a/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc +++ b/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc @@ -16,15 +16,23 @@ .row_3_4 = 0x0, .cs0_row = 0xF, .cs1_row = 0xF, + .cs0_high16bit_row = 0xF, + .cs1_high16bit_row = 0xF, .ddrconfig = 1, }, { - .ddrtiminga0 = 0x80241d22, - .ddrtimingb0 = 0x15050f08, + .ddrtiminga0 = { + 0x80241d22, + }, + .ddrtimingb0 = { + 0x15050f08, + }, .ddrtimingc0 = { 0x00000602, }, - .devtodev0 = 0x00002122, + .devtodev0 = { + 0x00002122, + }, .ddrmode = { 0x0000004c, }, @@ -41,15 +49,23 @@ .row_3_4 = 0x0, .cs0_row = 0xF, .cs1_row = 0xF, + .cs0_high16bit_row = 0xF, + .cs1_high16bit_row = 0xF, .ddrconfig = 1, }, { - .ddrtiminga0 = 0x80241d22, - .ddrtimingb0 = 0x15050f08, + .ddrtiminga0 = { + 0x80241d22, + }, + .ddrtimingb0 = { + 0x15050f08, + }, .ddrtimingc0 = { 0x00000602, }, - .devtodev0 = 0x00002122, + .devtodev0 = { + 0x00002122, + }, .ddrmode = { 0x0000004c, }, diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c index b5a0bac99b..223ebadaec 100644 --- a/drivers/ram/rockchip/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c @@ -52,7 +52,7 @@ struct chan_info { struct rk3399_ddr_pctl_regs *pctl; struct rk3399_ddr_pi_regs *pi; struct rk3399_ddr_publ_regs *publ; - struct rk3399_msch_regs *msch; + struct msch_regs *msch; }; struct dram_info { @@ -74,10 +74,15 @@ struct dram_info { }; struct sdram_rk3399_ops { - int (*data_training)(struct dram_info *dram, u32 channel, u8 rank, - struct rk3399_sdram_params *sdram); - int (*set_rate)(struct dram_info *dram, - struct rk3399_sdram_params *params); + int (*data_training_first)(struct dram_info *dram, u32 channel, u8 rank, + struct rk3399_sdram_params *sdram); + int (*set_rate_index)(struct dram_info *dram, + struct rk3399_sdram_params *params); + void (*modify_param)(const struct chan_info *chan, + struct rk3399_sdram_params *params); + struct rk3399_sdram_params * + (*get_phy_index_params)(u32 phy_fn, + struct rk3399_sdram_params *params); }; #if defined(CONFIG_TPL_BUILD) || \ @@ -196,11 +201,6 @@ struct io_setting { }, }; -/** - * phy = 0, PHY boot freq - * phy = 1, PHY index 0 - * phy = 2, PHY index 1 - */ static struct io_setting * lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5) { @@ -223,32 +223,21 @@ lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5) return io; } -static void *get_denali_phy(const struct chan_info *chan, - struct rk3399_sdram_params *params, bool reg) -{ - return reg ? &chan->publ->denali_phy : ¶ms->phy_regs.denali_phy; -} - static void *get_denali_ctl(const struct chan_info *chan, struct rk3399_sdram_params *params, bool reg) { return reg ? &chan->pctl->denali_ctl : ¶ms->pctl_regs.denali_ctl; } -static void *get_ddrc0_con(struct dram_info *dram, u8 channel) +static void *get_denali_phy(const struct chan_info *chan, + struct rk3399_sdram_params *params, bool reg) { - return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc0_con1; + return reg ? &chan->publ->denali_phy : ¶ms->phy_regs.denali_phy; } -static void copy_to_reg(u32 *dest, const u32 *src, u32 n) +static void *get_ddrc0_con(struct dram_info *dram, u8 channel) { - int i; - - for (i = 0; i < n / sizeof(u32); i++) { - writel(*src, dest); - src++; - dest++; - } + return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc1_con0; } static void rkclk_ddr_reset(struct rk3399_cru *cru, u32 channel, u32 ctl, @@ -344,7 +333,7 @@ static void set_memory_map(const struct chan_info *chan, u32 channel, ((3 - sdram_ch->cap_info.bk) << 16) | ((16 - row) << 24)); - if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) { + if (params->base.dramtype == LPDDR4) { if (cs_map == 1) cs_map = 0x5; else if (cs_map == 2) @@ -496,7 +485,7 @@ static int phy_io_config(const struct chan_info *chan, /* PHY_939 PHY_PAD_CS_DRIVE */ clrsetbits_le32(&denali_phy[939], 0x7 << 14, mode_sel << 14); - if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) { + if (params->base.dramtype == LPDDR4) { /* BOOSTP_EN & BOOSTN_EN */ reg_value = ((PHY_BOOSTP_EN << 4) | PHY_BOOSTN_EN); /* PHY_925 PHY_PAD_FDBK_DRIVE2 */ @@ -563,7 +552,7 @@ static int phy_io_config(const struct chan_info *chan, /* PHY_939 PHY_PAD_CS_DRIVE */ clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17); - if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) { + if (params->base.dramtype == LPDDR4) { /* RX_CM_INPUT */ reg_value = PHY_RX_CM_INPUT; /* PHY_924 PHY_PAD_FDBK_DRIVE */ @@ -733,7 +722,7 @@ static void set_ds_odt(const struct chan_info *chan, /* phy_adr_tsel_select_ 8bits DENALI_PHY_544/672/800 offset_0 */ reg_value = tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 0x4); - if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) { + if (params->base.dramtype == LPDDR4) { /* LPDDR4 these register read always return 0, so * can not use clrsetbits_le32(), need to write32 */ @@ -810,46 +799,107 @@ static void set_ds_odt(const struct chan_info *chan, phy_io_config(chan, params, mr5); } -static void pctl_start(struct dram_info *dram, u8 channel) +static void pctl_start(struct dram_info *dram, + struct rk3399_sdram_params *params, + u32 channel_mask) { - const struct chan_info *chan = &dram->chan[channel]; - u32 *denali_ctl = chan->pctl->denali_ctl; - u32 *denali_phy = chan->publ->denali_phy; - u32 *ddrc0_con = get_ddrc0_con(dram, channel); + const struct chan_info *chan_0 = &dram->chan[0]; + const struct chan_info *chan_1 = &dram->chan[1]; + + u32 *denali_ctl_0 = chan_0->pctl->denali_ctl; + u32 *denali_phy_0 = chan_0->publ->denali_phy; + u32 *ddrc0_con_0 = get_ddrc0_con(dram, 0); + u32 *denali_ctl_1 = chan_1->pctl->denali_ctl; + u32 *denali_phy_1 = chan_1->publ->denali_phy; + u32 *ddrc1_con_0 = get_ddrc0_con(dram, 1); u32 count = 0; u32 byte, tmp; - writel(0x01000000, &ddrc0_con); + /* PHY_DLL_RST_EN */ + if (channel_mask & 1) { + writel(0x01000000, &ddrc0_con_0); + clrsetbits_le32(&denali_phy_0[957], 0x3 << 24, 0x2 << 24); + } - clrsetbits_le32(&denali_phy[957], 0x3 << 24, 0x2 << 24); + if (channel_mask & 1) { + count = 0; + while (!(readl(&denali_ctl_0[203]) & (1 << 3))) { + if (count > 1000) { + printf("%s: Failed to init pctl channel 0\n", + __func__); + while (1) + ; + } + udelay(1); + count++; + } - while (!(readl(&denali_ctl[203]) & (1 << 3))) { - if (count > 1000) { - printf("%s: Failed to init pctl for channel %d\n", - __func__, channel); - while (1) - ; + writel(0x01000100, &ddrc0_con_0); + for (byte = 0; byte < 4; byte++) { + tmp = 0x820; + writel((tmp << 16) | tmp, + &denali_phy_0[53 + (128 * byte)]); + writel((tmp << 16) | tmp, + &denali_phy_0[54 + (128 * byte)]); + writel((tmp << 16) | tmp, + &denali_phy_0[55 + (128 * byte)]); + writel((tmp << 16) | tmp, + &denali_phy_0[56 + (128 * byte)]); + writel((tmp << 16) | tmp, + &denali_phy_0[57 + (128 * byte)]); + clrsetbits_le32(&denali_phy_0[58 + (128 * byte)], + 0xffff, tmp); } + clrsetbits_le32(&denali_ctl_0[68], PWRUP_SREFRESH_EXIT, + dram->pwrup_srefresh_exit[0]); + } - udelay(1); - count++; + if (channel_mask & 2) { + writel(0x01000000, &ddrc1_con_0); + clrsetbits_le32(&denali_phy_1[957], 0x3 << 24, 0x2 << 24); } + if (channel_mask & 2) { + count = 0; + while (!(readl(&denali_ctl_1[203]) & (1 << 3))) { + if (count > 1000) { + printf("%s: Failed to init pctl channel 1\n", + __func__); + while (1) + ; + } + udelay(1); + count++; + } - writel(0x01000100, &ddrc0_con); + writel(0x01000100, &ddrc1_con_0); + for (byte = 0; byte < 4; byte++) { + tmp = 0x820; + writel((tmp << 16) | tmp, + &denali_phy_1[53 + (128 * byte)]); + writel((tmp << 16) | tmp, + &denali_phy_1[54 + (128 * byte)]); + writel((tmp << 16) | tmp, + &denali_phy_1[55 + (128 * byte)]); + writel((tmp << 16) | tmp, + &denali_phy_1[56 + (128 * byte)]); + writel((tmp << 16) | tmp, + &denali_phy_1[57 + (128 * byte)]); + clrsetbits_le32(&denali_phy_1[58 + (128 * byte)], + 0xffff, tmp); + } - for (byte = 0; byte < 4; byte++) { - tmp = 0x820; - writel((tmp << 16) | tmp, &denali_phy[53 + (128 * byte)]); - writel((tmp << 16) | tmp, &denali_phy[54 + (128 * byte)]); - writel((tmp << 16) | tmp, &denali_phy[55 + (128 * byte)]); - writel((tmp << 16) | tmp, &denali_phy[56 + (128 * byte)]); - writel((tmp << 16) | tmp, &denali_phy[57 + (128 * byte)]); + clrsetbits_le32(&denali_ctl_1[68], PWRUP_SREFRESH_EXIT, + dram->pwrup_srefresh_exit[1]); - clrsetbits_le32(&denali_phy[58 + (128 * byte)], 0xffff, tmp); + /* + * restore channel 1 RESET original setting + * to avoid 240ohm too weak to prevent ESD test + */ + if (params->base.dramtype == LPDDR4) + clrsetbits_le32(&denali_phy_1[937], 0xff, + params->phy_regs.denali_phy[937] & + 0xFF); } - - clrsetbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT, - dram->pwrup_srefresh_exit[channel]); } static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan, @@ -861,13 +911,16 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan, const u32 *params_ctl = params->pctl_regs.denali_ctl; const u32 *params_phy = params->phy_regs.denali_phy; u32 tmp, tmp1, tmp2; + struct rk3399_sdram_params *params_cfg; + u32 byte; + dram->ops->modify_param(chan, params); /* * work around controller bug: * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed */ - copy_to_reg(&denali_ctl[1], ¶ms_ctl[1], - sizeof(struct rk3399_ddr_pctl_regs) - 4); + sdram_copy_to_reg(&denali_ctl[1], ¶ms_ctl[1], + sizeof(struct rk3399_ddr_pctl_regs) - 4); writel(params_ctl[0], &denali_ctl[0]); /* @@ -884,8 +937,8 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan, writel(tmp + tmp1, &denali_ctl[14]); } - copy_to_reg(denali_pi, ¶ms->pi_regs.denali_pi[0], - sizeof(struct rk3399_ddr_pi_regs)); + sdram_copy_to_reg(denali_pi, ¶ms->pi_regs.denali_pi[0], + sizeof(struct rk3399_ddr_pi_regs)); /* rank count need to set for init */ set_memory_map(chan, channel, params); @@ -894,7 +947,7 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan, writel(params->phy_regs.denali_phy[911], &denali_phy[911]); writel(params->phy_regs.denali_phy[912], &denali_phy[912]); - if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) { + if (params->base.dramtype == LPDDR4) { writel(params->phy_regs.denali_phy[898], &denali_phy[898]); writel(params->phy_regs.denali_phy[919], &denali_phy[919]); } @@ -927,41 +980,67 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan, } } - copy_to_reg(&denali_phy[896], ¶ms_phy[896], (958 - 895) * 4); - copy_to_reg(&denali_phy[0], ¶ms_phy[0], (90 - 0 + 1) * 4); - copy_to_reg(&denali_phy[128], ¶ms_phy[128], (218 - 128 + 1) * 4); - copy_to_reg(&denali_phy[256], ¶ms_phy[256], (346 - 256 + 1) * 4); - copy_to_reg(&denali_phy[384], ¶ms_phy[384], (474 - 384 + 1) * 4); - copy_to_reg(&denali_phy[512], ¶ms_phy[512], (549 - 512 + 1) * 4); - copy_to_reg(&denali_phy[640], ¶ms_phy[640], (677 - 640 + 1) * 4); - copy_to_reg(&denali_phy[768], ¶ms_phy[768], (805 - 768 + 1) * 4); - set_ds_odt(chan, params, true, 0); + sdram_copy_to_reg(&denali_phy[896], ¶ms_phy[896], (958 - 895) * 4); + sdram_copy_to_reg(&denali_phy[0], ¶ms_phy[0], (90 - 0 + 1) * 4); + sdram_copy_to_reg(&denali_phy[128], ¶ms_phy[128], + (218 - 128 + 1) * 4); + sdram_copy_to_reg(&denali_phy[256], ¶ms_phy[256], + (346 - 256 + 1) * 4); + sdram_copy_to_reg(&denali_phy[384], ¶ms_phy[384], + (474 - 384 + 1) * 4); + sdram_copy_to_reg(&denali_phy[512], ¶ms_phy[512], + (549 - 512 + 1) * 4); + sdram_copy_to_reg(&denali_phy[640], ¶ms_phy[640], + (677 - 640 + 1) * 4); + sdram_copy_to_reg(&denali_phy[768], ¶ms_phy[768], + (805 - 768 + 1) * 4); - /* - * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8 - * dqs_tsel_wr_end[7:4] add Half cycle - */ - tmp = (readl(&denali_phy[84]) >> 8) & 0xff; - clrsetbits_le32(&denali_phy[84], 0xff << 8, (tmp + 0x10) << 8); - tmp = (readl(&denali_phy[212]) >> 8) & 0xff; - clrsetbits_le32(&denali_phy[212], 0xff << 8, (tmp + 0x10) << 8); - tmp = (readl(&denali_phy[340]) >> 8) & 0xff; - clrsetbits_le32(&denali_phy[340], 0xff << 8, (tmp + 0x10) << 8); - tmp = (readl(&denali_phy[468]) >> 8) & 0xff; - clrsetbits_le32(&denali_phy[468], 0xff << 8, (tmp + 0x10) << 8); + if (params->base.dramtype == LPDDR4) + params_cfg = dram->ops->get_phy_index_params(1, params); + else + params_cfg = dram->ops->get_phy_index_params(0, params); + + clrsetbits_le32(¶ms_cfg->phy_regs.denali_phy[896], 0x3 << 8, + 0 << 8); + writel(params_cfg->phy_regs.denali_phy[896], &denali_phy[896]); + + writel(params->phy_regs.denali_phy[83] + (0x10 << 16), + &denali_phy[83]); + writel(params->phy_regs.denali_phy[84] + (0x10 << 8), + &denali_phy[84]); + writel(params->phy_regs.denali_phy[211] + (0x10 << 16), + &denali_phy[211]); + writel(params->phy_regs.denali_phy[212] + (0x10 << 8), + &denali_phy[212]); + writel(params->phy_regs.denali_phy[339] + (0x10 << 16), + &denali_phy[339]); + writel(params->phy_regs.denali_phy[340] + (0x10 << 8), + &denali_phy[340]); + writel(params->phy_regs.denali_phy[467] + (0x10 << 16), + &denali_phy[467]); + writel(params->phy_regs.denali_phy[468] + (0x10 << 8), + &denali_phy[468]); - /* - * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_83/211/339/467 offset_8 - * dq_tsel_wr_end[7:4] add Half cycle - */ - tmp = (readl(&denali_phy[83]) >> 16) & 0xff; - clrsetbits_le32(&denali_phy[83], 0xff << 16, (tmp + 0x10) << 16); - tmp = (readl(&denali_phy[211]) >> 16) & 0xff; - clrsetbits_le32(&denali_phy[211], 0xff << 16, (tmp + 0x10) << 16); - tmp = (readl(&denali_phy[339]) >> 16) & 0xff; - clrsetbits_le32(&denali_phy[339], 0xff << 16, (tmp + 0x10) << 16); - tmp = (readl(&denali_phy[467]) >> 16) & 0xff; - clrsetbits_le32(&denali_phy[467], 0xff << 16, (tmp + 0x10) << 16); + if (params->base.dramtype == LPDDR4) { + /* + * to improve write dqs and dq phase from 1.5ns to 3.5ns + * at 50MHz. this's the measure result from oscilloscope + * of dqs and dq write signal. + */ + for (byte = 0; byte < 4; byte++) { + tmp = 0x680; + clrsetbits_le32(&denali_phy[1 + (128 * byte)], + 0xfff << 8, tmp << 8); + } + /* + * to workaround 366ball two channel's RESET connect to + * one RESET signal of die + */ + if (channel == 1) + clrsetbits_le32(&denali_phy[937], 0xff, + PHY_DRV_ODT_240 | + (PHY_DRV_ODT_240 << 0x4)); + } return 0; } @@ -1392,7 +1471,7 @@ static void set_ddrconfig(const struct chan_info *chan, unsigned char channel, u32 ddrconfig) { /* only need to set ddrconfig */ - struct rk3399_msch_regs *ddr_msch_regs = chan->msch; + struct msch_regs *ddr_msch_regs = chan->msch; unsigned int cs0_cap = 0; unsigned int cs1_cap = 0; @@ -1413,52 +1492,43 @@ static void set_ddrconfig(const struct chan_info *chan, &ddr_msch_regs->ddrsize); } +static void sdram_msch_config(struct msch_regs *msch, + struct sdram_msch_timings *noc_timings) +{ + writel(noc_timings->ddrtiminga0.d32, + &msch->ddrtiminga0.d32); + writel(noc_timings->ddrtimingb0.d32, + &msch->ddrtimingb0.d32); + writel(noc_timings->ddrtimingc0.d32, + &msch->ddrtimingc0.d32); + writel(noc_timings->devtodev0.d32, + &msch->devtodev0.d32); + writel(noc_timings->ddrmode.d32, + &msch->ddrmode.d32); +} + static void dram_all_config(struct dram_info *dram, - const struct rk3399_sdram_params *params) + struct rk3399_sdram_params *params) { u32 sys_reg2 = 0; u32 sys_reg3 = 0; unsigned int channel, idx; - sys_reg2 |= SYS_REG_ENC_DDRTYPE(params->base.dramtype); - sys_reg2 |= SYS_REG_ENC_NUM_CH(params->base.num_channels); - for (channel = 0, idx = 0; (idx < params->base.num_channels) && (channel < 2); channel++) { - const struct rk3399_sdram_channel *info = ¶ms->ch[channel]; - struct rk3399_msch_regs *ddr_msch_regs; - const struct rk3399_msch_timings *noc_timing; + struct msch_regs *ddr_msch_regs; + struct sdram_msch_timings *noc_timing; if (params->ch[channel].cap_info.col == 0) continue; idx++; - sys_reg2 |= SYS_REG_ENC_ROW_3_4(info->cap_info.row_3_4, channel); - sys_reg2 |= SYS_REG_ENC_CHINFO(channel); - sys_reg2 |= SYS_REG_ENC_RANK(info->cap_info.rank, channel); - sys_reg2 |= SYS_REG_ENC_COL(info->cap_info.col, channel); - sys_reg2 |= SYS_REG_ENC_BK(info->cap_info.bk, channel); - sys_reg2 |= SYS_REG_ENC_BW(info->cap_info.bw, channel); - sys_reg2 |= SYS_REG_ENC_DBW(info->cap_info.dbw, channel); - SYS_REG_ENC_CS0_ROW(info->cap_info.cs0_row, sys_reg2, sys_reg3, channel); - if (info->cap_info.cs1_row) - SYS_REG_ENC_CS1_ROW(info->cap_info.cs1_row, sys_reg2, - sys_reg3, channel); - sys_reg3 |= SYS_REG_ENC_CS1_COL(info->cap_info.col, channel); - sys_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION); - + sdram_org_config(¶ms->ch[channel].cap_info, + ¶ms->base, &sys_reg2, + &sys_reg3, channel); ddr_msch_regs = dram->chan[channel].msch; noc_timing = ¶ms->ch[channel].noc_timings; - writel(noc_timing->ddrtiminga0, - &ddr_msch_regs->ddrtiminga0); - writel(noc_timing->ddrtimingb0, - &ddr_msch_regs->ddrtimingb0); - writel(noc_timing->ddrtimingc0.d32, - &ddr_msch_regs->ddrtimingc0); - writel(noc_timing->devtodev0, - &ddr_msch_regs->devtodev0); - writel(noc_timing->ddrmode.d32, - &ddr_msch_regs->ddrmode); + sdram_msch_config(ddr_msch_regs, noc_timing); /** * rank 1 memory clock disable (dfi_dram_clk_disable = 1) @@ -1494,7 +1564,7 @@ static void set_cap_relate_config(const struct chan_info *chan, { u32 *denali_ctl = chan->pctl->denali_ctl; u32 tmp; - struct rk3399_msch_timings *noc_timing; + struct sdram_msch_timings *noc_timing; if (params->base.dramtype == LPDDR3) { tmp = (8 << params->ch[channel].cap_info.bw) / @@ -1566,9 +1636,14 @@ static u32 calculate_ddrconfig(struct rk3399_sdram_params *params, u32 channel) return i; } +static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride) +{ + rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10); +} + #if !defined(CONFIG_RAM_RK3399_LPDDR4) -static int default_data_training(struct dram_info *dram, u32 channel, u8 rank, - struct rk3399_sdram_params *params) +static int data_training_first(struct dram_info *dram, u32 channel, u8 rank, + struct rk3399_sdram_params *params) { u8 training_flag = PI_READ_GATE_TRAINING; @@ -1629,31 +1704,72 @@ static int switch_to_phy_index1(struct dram_info *dram, return 0; } +struct rk3399_sdram_params + *get_phy_index_params(u32 phy_fn, + struct rk3399_sdram_params *params) +{ + if (phy_fn == 0) + return params; + else + return NULL; +} + +void modify_param(const struct chan_info *chan, + struct rk3399_sdram_params *params) +{ + struct rk3399_sdram_params *params_cfg; + u32 *denali_pi_params; + + denali_pi_params = params->pi_regs.denali_pi; + + /* modify PHY F0/F1/F2 params */ + params_cfg = get_phy_index_params(0, params); + set_ds_odt(chan, params_cfg, false, 0); + + clrsetbits_le32(&denali_pi_params[45], 0x1 << 24, 0x1 << 24); + clrsetbits_le32(&denali_pi_params[61], 0x1 << 24, 0x1 << 24); + clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24); + clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1); +} #else -struct rk3399_sdram_params lpddr4_timings[] = { - #include "sdram-rk3399-lpddr4-400.inc" - #include "sdram-rk3399-lpddr4-800.inc" +struct rk3399_sdram_params dfs_cfgs_lpddr4[] = { +#include "sdram-rk3399-lpddr4-400.inc" +#include "sdram-rk3399-lpddr4-800.inc" }; +static struct rk3399_sdram_params + *lpddr4_get_phy_index_params(u32 phy_fn, + struct rk3399_sdram_params *params) +{ + if (phy_fn == 0) + return params; + else if (phy_fn == 1) + return &dfs_cfgs_lpddr4[1]; + else if (phy_fn == 2) + return &dfs_cfgs_lpddr4[0]; + else + return NULL; +} + static void *get_denali_pi(const struct chan_info *chan, struct rk3399_sdram_params *params, bool reg) { return reg ? &chan->pi->denali_pi : ¶ms->pi_regs.denali_pi; } -static u32 lpddr4_get_phy(struct rk3399_sdram_params *params, u32 ctl) +static u32 lpddr4_get_phy_fn(struct rk3399_sdram_params *params, u32 ctl_fn) { - u32 lpddr4_phy[] = {1, 0, 0xb}; + u32 lpddr4_phy_fn[] = {1, 0, 0xb}; - return lpddr4_phy[ctl]; + return lpddr4_phy_fn[ctl_fn]; } -static u32 lpddr4_get_ctl(struct rk3399_sdram_params *params, u32 phy) +static u32 lpddr4_get_ctl_fn(struct rk3399_sdram_params *params, u32 phy_fn) { - u32 lpddr4_ctl[] = {1, 0, 2}; + u32 lpddr4_ctl_fn[] = {1, 0, 2}; - return lpddr4_ctl[phy]; + return lpddr4_ctl_fn[phy_fn]; } static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf) @@ -1661,12 +1777,7 @@ static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf) return ((readl(&pmusgrf->soc_con4) >> 10) & 0x1F); } -static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride) -{ - rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10); -} - -/** +/* * read mr_num mode register * rank = 1: cs0 * rank = 2: cs1 @@ -1797,7 +1908,7 @@ end: } static void set_lpddr4_dq_odt(const struct chan_info *chan, - struct rk3399_sdram_params *params, u32 ctl, + struct rk3399_sdram_params *params, u32 ctl_fn, bool en, bool ctl_phy_reg, u32 mr5) { u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg); @@ -1805,14 +1916,13 @@ static void set_lpddr4_dq_odt(const struct chan_info *chan, struct io_setting *io; u32 reg_value; - if (!en) - return; - io = lpddr4_get_io_settings(params, mr5); + if (en) + reg_value = io->dq_odt; + else + reg_value = 0; - reg_value = io->dq_odt; - - switch (ctl) { + switch (ctl_fn) { case 0: clrsetbits_le32(&denali_ctl[139], 0x7 << 24, reg_value << 24); clrsetbits_le32(&denali_ctl[153], 0x7 << 24, reg_value << 24); @@ -1845,7 +1955,7 @@ static void set_lpddr4_dq_odt(const struct chan_info *chan, } static void set_lpddr4_ca_odt(const struct chan_info *chan, - struct rk3399_sdram_params *params, u32 ctl, + struct rk3399_sdram_params *params, u32 ctl_fn, bool en, bool ctl_phy_reg, u32 mr5) { u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg); @@ -1853,14 +1963,13 @@ static void set_lpddr4_ca_odt(const struct chan_info *chan, struct io_setting *io; u32 reg_value; - if (!en) - return; - io = lpddr4_get_io_settings(params, mr5); + if (en) + reg_value = io->ca_odt; + else + reg_value = 0; - reg_value = io->ca_odt; - - switch (ctl) { + switch (ctl_fn) { case 0: clrsetbits_le32(&denali_ctl[139], 0x7 << 28, reg_value << 28); clrsetbits_le32(&denali_ctl[153], 0x7 << 28, reg_value << 28); @@ -1893,7 +2002,7 @@ static void set_lpddr4_ca_odt(const struct chan_info *chan, } static void set_lpddr4_MR3(const struct chan_info *chan, - struct rk3399_sdram_params *params, u32 ctl, + struct rk3399_sdram_params *params, u32 ctl_fn, bool ctl_phy_reg, u32 mr5) { u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg); @@ -1905,7 +2014,7 @@ static void set_lpddr4_MR3(const struct chan_info *chan, reg_value = ((io->pdds << 3) | 1); - switch (ctl) { + switch (ctl_fn) { case 0: clrsetbits_le32(&denali_ctl[138], 0xFFFF, reg_value); clrsetbits_le32(&denali_ctl[152], 0xFFFF, reg_value); @@ -1940,7 +2049,7 @@ static void set_lpddr4_MR3(const struct chan_info *chan, } static void set_lpddr4_MR12(const struct chan_info *chan, - struct rk3399_sdram_params *params, u32 ctl, + struct rk3399_sdram_params *params, u32 ctl_fn, bool ctl_phy_reg, u32 mr5) { u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg); @@ -1952,7 +2061,7 @@ static void set_lpddr4_MR12(const struct chan_info *chan, reg_value = io->ca_vref; - switch (ctl) { + switch (ctl_fn) { case 0: clrsetbits_le32(&denali_ctl[140], 0xFFFF << 16, reg_value << 16); @@ -1989,7 +2098,7 @@ static void set_lpddr4_MR12(const struct chan_info *chan, } static void set_lpddr4_MR14(const struct chan_info *chan, - struct rk3399_sdram_params *params, u32 ctl, + struct rk3399_sdram_params *params, u32 ctl_fn, bool ctl_phy_reg, u32 mr5) { u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg); @@ -2001,7 +2110,7 @@ static void set_lpddr4_MR14(const struct chan_info *chan, reg_value = io->dq_vref; - switch (ctl) { + switch (ctl_fn) { case 0: clrsetbits_le32(&denali_ctl[142], 0xFFFF << 16, reg_value << 16); @@ -2037,22 +2146,73 @@ static void set_lpddr4_MR14(const struct chan_info *chan, } } +void lpddr4_modify_param(const struct chan_info *chan, + struct rk3399_sdram_params *params) +{ + struct rk3399_sdram_params *params_cfg; + u32 *denali_ctl_params; + u32 *denali_pi_params; + u32 *denali_phy_params; + + denali_ctl_params = params->pctl_regs.denali_ctl; + denali_pi_params = params->pi_regs.denali_pi; + denali_phy_params = params->phy_regs.denali_phy; + + set_lpddr4_dq_odt(chan, params, 2, true, false, 0); + set_lpddr4_ca_odt(chan, params, 2, true, false, 0); + set_lpddr4_MR3(chan, params, 2, false, 0); + set_lpddr4_MR12(chan, params, 2, false, 0); + set_lpddr4_MR14(chan, params, 2, false, 0); + params_cfg = lpddr4_get_phy_index_params(0, params); + set_ds_odt(chan, params_cfg, false, 0); + /* read two cycle preamble */ + clrsetbits_le32(&denali_ctl_params[200], 0x3 << 24, 0x3 << 24); + clrsetbits_le32(&denali_phy_params[7], 0x3 << 24, 0x3 << 24); + clrsetbits_le32(&denali_phy_params[135], 0x3 << 24, 0x3 << 24); + clrsetbits_le32(&denali_phy_params[263], 0x3 << 24, 0x3 << 24); + clrsetbits_le32(&denali_phy_params[391], 0x3 << 24, 0x3 << 24); + + /* boot frequency two cycle preamble */ + clrsetbits_le32(&denali_phy_params[2], 0x3 << 16, 0x3 << 16); + clrsetbits_le32(&denali_phy_params[130], 0x3 << 16, 0x3 << 16); + clrsetbits_le32(&denali_phy_params[258], 0x3 << 16, 0x3 << 16); + clrsetbits_le32(&denali_phy_params[386], 0x3 << 16, 0x3 << 16); + + clrsetbits_le32(&denali_pi_params[45], 0x3 << 8, 0x3 << 8); + clrsetbits_le32(&denali_pi_params[58], 0x1, 0x1); + + /* + * bypass mode need PHY_SLICE_PWR_RDC_DISABLE_x = 1, + * boot frequency mode use bypass mode + */ + setbits_le32(&denali_phy_params[10], 1 << 16); + setbits_le32(&denali_phy_params[138], 1 << 16); + setbits_le32(&denali_phy_params[266], 1 << 16); + setbits_le32(&denali_phy_params[394], 1 << 16); + + clrsetbits_le32(&denali_pi_params[45], 0x1 << 24, 0x1 << 24); + clrsetbits_le32(&denali_pi_params[61], 0x1 << 24, 0x1 << 24); + clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24); + clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1); +} + static void lpddr4_copy_phy(struct dram_info *dram, - struct rk3399_sdram_params *params, u32 phy, - struct rk3399_sdram_params *timings, + struct rk3399_sdram_params *params, u32 phy_fn, + struct rk3399_sdram_params *params_cfg, u32 channel) { u32 *denali_ctl, *denali_phy; u32 *denali_phy_params; u32 speed = 0; - u32 ctl, mr5; + u32 ctl_fn, mr5; denali_ctl = dram->chan[channel].pctl->denali_ctl; denali_phy = dram->chan[channel].publ->denali_phy; - denali_phy_params = timings->phy_regs.denali_phy; + denali_phy_params = params_cfg->phy_regs.denali_phy; /* switch index */ - clrsetbits_le32(&denali_phy_params[896], 0x3 << 8, phy << 8); + clrsetbits_le32(&denali_phy_params[896], 0x3 << 8, + phy_fn << 8); writel(denali_phy_params[896], &denali_phy[896]); /* phy_pll_ctrl_ca, phy_pll_ctrl */ @@ -2112,14 +2272,14 @@ static void lpddr4_copy_phy(struct dram_info *dram, * phy_clk_wrdqz_slave_delay_x * phy_clk_wrdqs_slave_delay_x */ - copy_to_reg((u32 *)&denali_phy[59], (u32 *)&denali_phy_params[59], - (63 - 58) * 4); - copy_to_reg((u32 *)&denali_phy[187], (u32 *)&denali_phy_params[187], - (191 - 186) * 4); - copy_to_reg((u32 *)&denali_phy[315], (u32 *)&denali_phy_params[315], - (319 - 314) * 4); - copy_to_reg((u32 *)&denali_phy[443], (u32 *)&denali_phy_params[443], - (447 - 442) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[59], + (u32 *)&denali_phy_params[59], (63 - 58) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[187], + (u32 *)&denali_phy_params[187], (191 - 186) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[315], + (u32 *)&denali_phy_params[315], (319 - 314) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[443], + (u32 *)&denali_phy_params[443], (447 - 442) * 4); /* * phy_dqs_tsel_wr_timing_x 8bits denali_phy_84/212/340/468 offset_8 @@ -2218,31 +2378,30 @@ static void lpddr4_copy_phy(struct dram_info *dram, * phy_wrlvl_delay_period_threshold_x * phy_wrlvl_early_force_zero_x */ - copy_to_reg((u32 *)&denali_phy[64], (u32 *)&denali_phy_params[64], - (67 - 63) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[64], + (u32 *)&denali_phy_params[64], (67 - 63) * 4); clrsetbits_le32(&denali_phy[68], 0xfffffc00, denali_phy_params[68] & 0xfffffc00); - copy_to_reg((u32 *)&denali_phy[69], (u32 *)&denali_phy_params[69], - (79 - 68) * 4); - copy_to_reg((u32 *)&denali_phy[192], (u32 *)&denali_phy_params[192], - (195 - 191) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[69], + (u32 *)&denali_phy_params[69], (79 - 68) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[192], + (u32 *)&denali_phy_params[192], (195 - 191) * 4); clrsetbits_le32(&denali_phy[196], 0xfffffc00, denali_phy_params[196] & 0xfffffc00); - copy_to_reg((u32 *)&denali_phy[197], (u32 *)&denali_phy_params[197], - (207 - 196) * 4); - copy_to_reg((u32 *)&denali_phy[320], (u32 *)&denali_phy_params[320], - (323 - 319) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[197], + (u32 *)&denali_phy_params[197], (207 - 196) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[320], + (u32 *)&denali_phy_params[320], (323 - 319) * 4); clrsetbits_le32(&denali_phy[324], 0xfffffc00, denali_phy_params[324] & 0xfffffc00); - copy_to_reg((u32 *)&denali_phy[325], (u32 *)&denali_phy_params[325], - (335 - 324) * 4); - - copy_to_reg((u32 *)&denali_phy[448], (u32 *)&denali_phy_params[448], - (451 - 447) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[325], + (u32 *)&denali_phy_params[325], (335 - 324) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[448], + (u32 *)&denali_phy_params[448], (451 - 447) * 4); clrsetbits_le32(&denali_phy[452], 0xfffffc00, denali_phy_params[452] & 0xfffffc00); - copy_to_reg((u32 *)&denali_phy[453], (u32 *)&denali_phy_params[453], - (463 - 452) * 4); + sdram_copy_to_reg((u32 *)&denali_phy[453], + (u32 *)&denali_phy_params[453], (463 - 452) * 4); /* phy_two_cyc_preamble_x */ clrsetbits_le32(&denali_phy[7], 0x3 << 24, @@ -2255,11 +2414,11 @@ static void lpddr4_copy_phy(struct dram_info *dram, denali_phy_params[391] & (0x3 << 24)); /* speed */ - if (timings->base.ddr_freq < 400 * MHz) + if (params_cfg->base.ddr_freq < 400) speed = 0x0; - else if (timings->base.ddr_freq < 800 * MHz) + else if (params_cfg->base.ddr_freq < 800) speed = 0x1; - else if (timings->base.ddr_freq < 1200 * MHz) + else if (params_cfg->base.ddr_freq < 1200) speed = 0x2; /* phy_924 phy_pad_fdbk_drive */ @@ -2279,52 +2438,75 @@ static void lpddr4_copy_phy(struct dram_info *dram, /* phy_939 phy_pad_cs_drive */ clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17); - read_mr(dram->chan[channel].pctl, 1, 5, &mr5); - set_ds_odt(&dram->chan[channel], timings, true, mr5); + if (params_cfg->base.dramtype == LPDDR4) { + read_mr(dram->chan[channel].pctl, 1, 5, &mr5); + set_ds_odt(&dram->chan[channel], params_cfg, true, mr5); + set_ds_odt(&dram->chan[channel], params_cfg, true, mr5); + + ctl_fn = lpddr4_get_ctl_fn(params_cfg, phy_fn); + set_lpddr4_dq_odt(&dram->chan[channel], params_cfg, + ctl_fn, true, true, mr5); + set_lpddr4_ca_odt(&dram->chan[channel], params_cfg, + ctl_fn, true, true, mr5); + set_lpddr4_MR3(&dram->chan[channel], params_cfg, + ctl_fn, true, mr5); + set_lpddr4_MR12(&dram->chan[channel], params_cfg, + ctl_fn, true, mr5); + set_lpddr4_MR14(&dram->chan[channel], params_cfg, + ctl_fn, true, mr5); + + set_lpddr4_dq_odt(&dram->chan[channel], params_cfg, + ctl_fn, true, true, mr5); + set_lpddr4_ca_odt(&dram->chan[channel], params_cfg, + ctl_fn, true, true, mr5); + set_lpddr4_MR3(&dram->chan[channel], params_cfg, + ctl_fn, true, mr5); + set_lpddr4_MR12(&dram->chan[channel], params_cfg, + ctl_fn, true, mr5); + set_lpddr4_MR14(&dram->chan[channel], params_cfg, + ctl_fn, true, mr5); - ctl = lpddr4_get_ctl(timings, phy); - set_lpddr4_dq_odt(&dram->chan[channel], timings, ctl, true, true, mr5); - set_lpddr4_ca_odt(&dram->chan[channel], timings, ctl, true, true, mr5); - set_lpddr4_MR3(&dram->chan[channel], timings, ctl, true, mr5); - set_lpddr4_MR12(&dram->chan[channel], timings, ctl, true, mr5); - set_lpddr4_MR14(&dram->chan[channel], timings, ctl, true, mr5); - - /* - * if phy_sw_master_mode_x not bypass mode, - * clear phy_slice_pwr_rdc_disable. - * note: need use timings, not ddr_publ_regs - */ - if (!((denali_phy_params[86] >> 8) & (1 << 2))) { - clrbits_le32(&denali_phy[10], 1 << 16); - clrbits_le32(&denali_phy[138], 1 << 16); - clrbits_le32(&denali_phy[266], 1 << 16); - clrbits_le32(&denali_phy[394], 1 << 16); - } + /* + * if phy_sw_master_mode_x not bypass mode, + * clear phy_slice_pwr_rdc_disable. + * note: need use timings, not ddr_publ_regs + */ + if (!((denali_phy_params[86] >> 8) & (1 << 2))) { + clrbits_le32(&denali_phy[10], 1 << 16); + clrbits_le32(&denali_phy[138], 1 << 16); + clrbits_le32(&denali_phy[266], 1 << 16); + clrbits_le32(&denali_phy[394], 1 << 16); + } - /* - * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't - * smaller than 8 - * NOTE: need use timings, not ddr_publ_regs - */ - if ((denali_phy_params[84] >> 16) & 1) { - if (((readl(&denali_ctl[217 + ctl]) >> 16) & 0x1f) < 8) - clrsetbits_le32(&denali_ctl[217 + ctl], - 0x1f << 16, 8 << 16); + /* + * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't + * smaller than 8 + * NOTE: need use timings, not ddr_publ_regs + */ + if ((denali_phy_params[84] >> 16) & 1) { + if (((readl(&denali_ctl[217 + ctl_fn]) >> + 16) & 0x1f) < 8) + clrsetbits_le32(&denali_ctl[217 + ctl_fn], + 0x1f << 16, + 8 << 16); + } } } static void lpddr4_set_phy(struct dram_info *dram, - struct rk3399_sdram_params *params, u32 phy, - struct rk3399_sdram_params *timings) + struct rk3399_sdram_params *params, u32 phy_fn, + struct rk3399_sdram_params *params_cfg) { u32 channel; for (channel = 0; channel < 2; channel++) - lpddr4_copy_phy(dram, params, phy, timings, channel); + lpddr4_copy_phy(dram, params, phy_fn, params_cfg, + channel); } static int lpddr4_set_ctl(struct dram_info *dram, - struct rk3399_sdram_params *params, u32 ctl, u32 hz) + struct rk3399_sdram_params *params, + u32 fn, u32 hz) { u32 channel; int ret_clk, ret; @@ -2343,7 +2525,7 @@ static int lpddr4_set_ctl(struct dram_info *dram, /* change freq */ writel((((0x3 << 4) | (1 << 2) | 1) << 16) | - (ctl << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0); + (fn << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0); while (!(readl(&dram->cic->cic_status0) & (1 << 2))) ; @@ -2366,12 +2548,12 @@ static int lpddr4_set_ctl(struct dram_info *dram, clrbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7)); /* lpddr4 ctl2 can not do training, all training will fail */ - if (!(params->base.dramtype == LPDDR4 && ctl == 2)) { + if (!(params->base.dramtype == LPDDR4 && fn == 2)) { for (channel = 0; channel < 2; channel++) { if (!(params->ch[channel].cap_info.col)) continue; ret = data_training(dram, channel, params, - PI_FULL_TRAINING); + PI_FULL_TRAINING); if (ret) printf("%s: channel %d training failed!\n", __func__, channel); @@ -2387,24 +2569,221 @@ static int lpddr4_set_ctl(struct dram_info *dram, static int lpddr4_set_rate(struct dram_info *dram, struct rk3399_sdram_params *params) { - u32 ctl; - u32 phy; + u32 ctl_fn; + u32 phy_fn; - for (ctl = 0; ctl < 2; ctl++) { - phy = lpddr4_get_phy(params, ctl); + for (ctl_fn = 0; ctl_fn < 2; ctl_fn++) { + phy_fn = lpddr4_get_phy_fn(params, ctl_fn); - lpddr4_set_phy(dram, params, phy, &lpddr4_timings[ctl]); - lpddr4_set_ctl(dram, params, ctl, - lpddr4_timings[ctl].base.ddr_freq); + lpddr4_set_phy(dram, params, phy_fn, &dfs_cfgs_lpddr4[ctl_fn]); + lpddr4_set_ctl(dram, params, ctl_fn, + dfs_cfgs_lpddr4[ctl_fn].base.ddr_freq); - debug("%s: change freq to %d mhz %d, %d\n", __func__, - lpddr4_timings[ctl].base.ddr_freq / MHz, ctl, phy); + printf("%s: change freq to %d mhz %d, %d\n", __func__, + dfs_cfgs_lpddr4[ctl_fn].base.ddr_freq, ctl_fn, phy_fn); } return 0; } #endif /* CONFIG_RAM_RK3399_LPDDR4 */ +/* CS0,n=1 + * CS1,n=2 + * CS0 & CS1, n=3 + * cs0_cap: MB unit + */ +static void dram_set_cs(const struct chan_info *chan, u32 cs_map, u32 cs0_cap, + unsigned char dramtype) +{ + u32 *denali_ctl = chan->pctl->denali_ctl; + u32 *denali_pi = chan->pi->denali_pi; + struct msch_regs *ddr_msch_regs = chan->msch; + + clrsetbits_le32(&denali_ctl[196], 0x3, cs_map); + writel((cs0_cap / 32) | (((4096 - cs0_cap) / 32) << 8), + &ddr_msch_regs->ddrsize); + if (dramtype == LPDDR4) { + if (cs_map == 1) + cs_map = 0x5; + else if (cs_map == 2) + cs_map = 0xa; + else + cs_map = 0xF; + } + /*PI_41 PI_CS_MAP:RW:24:4*/ + clrsetbits_le32(&denali_pi[41], + 0xf << 24, cs_map << 24); + if (cs_map == 1 && dramtype == DDR3) + writel(0x2EC7FFFF, &denali_pi[34]); +} + +static void dram_set_bw(const struct chan_info *chan, u32 bw) +{ + u32 *denali_ctl = chan->pctl->denali_ctl; + + if (bw == 2) + clrbits_le32(&denali_ctl[196], 1 << 16); + else + setbits_le32(&denali_ctl[196], 1 << 16); +} + +static void dram_set_max_col(const struct chan_info *chan, u32 bw, u32 *pcol) +{ + u32 *denali_ctl = chan->pctl->denali_ctl; + struct msch_regs *ddr_msch_regs = chan->msch; + u32 *denali_pi = chan->pi->denali_pi; + u32 ddrconfig; + + clrbits_le32(&denali_ctl[191], 0xf); + clrsetbits_le32(&denali_ctl[190], + (7 << 24), + ((16 - ((bw == 2) ? 14 : 15)) << 24)); + /*PI_199 PI_COL_DIFF:RW:0:4*/ + clrbits_le32(&denali_pi[199], 0xf); + /*PI_155 PI_ROW_DIFF:RW:24:3*/ + clrsetbits_le32(&denali_pi[155], + (7 << 24), + ((16 - 12) << 24)); + ddrconfig = (bw == 2) ? 3 : 2; + writel(ddrconfig | (ddrconfig << 8), &ddr_msch_regs->ddrconf); + /* set max cs0 size */ + writel((4096 / 32) | ((0 / 32) << 8), + &ddr_msch_regs->ddrsize); + + *pcol = 12; +} + +static void dram_set_max_bank(const struct chan_info *chan, u32 bw, u32 *pbank, + u32 *pcol) +{ + u32 *denali_ctl = chan->pctl->denali_ctl; + u32 *denali_pi = chan->pi->denali_pi; + + clrbits_le32(&denali_ctl[191], 0xf); + clrbits_le32(&denali_ctl[190], (3 << 16)); + /*PI_199 PI_COL_DIFF:RW:0:4*/ + clrbits_le32(&denali_pi[199], 0xf); + /*PI_155 PI_BANK_DIFF:RW:16:2*/ + clrbits_le32(&denali_pi[155], (3 << 16)); + + *pbank = 3; + *pcol = 12; +} + +static void dram_set_max_row(const struct chan_info *chan, u32 bw, u32 *prow, + u32 *pbank, u32 *pcol) +{ + u32 *denali_ctl = chan->pctl->denali_ctl; + u32 *denali_pi = chan->pi->denali_pi; + struct msch_regs *ddr_msch_regs = chan->msch; + + clrsetbits_le32(&denali_ctl[191], 0xf, 12 - 10); + clrbits_le32(&denali_ctl[190], + (0x3 << 16) | (0x7 << 24)); + /*PI_199 PI_COL_DIFF:RW:0:4*/ + clrsetbits_le32(&denali_pi[199], 0xf, 12 - 10); + /*PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2*/ + clrbits_le32(&denali_pi[155], + (0x3 << 16) | (0x7 << 24)); + writel(1 | (1 << 8), &ddr_msch_regs->ddrconf); + /* set max cs0 size */ + writel((4096 / 32) | ((0 / 32) << 8), + &ddr_msch_regs->ddrsize); + + *prow = 16; + *pbank = 3; + *pcol = (bw == 2) ? 10 : 11; +} + +static u64 dram_detect_cap(struct dram_info *dram, + struct rk3399_sdram_params *params, + unsigned char channel) +{ + const struct chan_info *chan = &dram->chan[channel]; + struct sdram_cap_info *cap_info = ¶ms->ch[channel].cap_info; + u32 bw; + u32 col_tmp; + u32 bk_tmp; + u32 row_tmp; + u32 cs0_cap; + u32 training_flag; + u32 ddrconfig; + + /* detect bw */ + bw = 2; + if (params->base.dramtype != LPDDR4) { + dram_set_bw(chan, bw); + cap_info->bw = bw; + if (data_training(dram, channel, params, + PI_READ_GATE_TRAINING)) { + bw = 1; + dram_set_bw(chan, 1); + cap_info->bw = bw; + if (data_training(dram, channel, params, + PI_READ_GATE_TRAINING)) { + printf("16bit error!!!\n"); + goto error; + } + } + } + /* + * LPDDR3 CA training msut be trigger before other training. + * DDR3 is not have CA training. + */ + if (params->base.dramtype == LPDDR3) + training_flag = PI_WRITE_LEVELING; + else + training_flag = PI_FULL_TRAINING; + + if (params->base.dramtype != LPDDR4) { + if (data_training(dram, channel, params, training_flag)) { + printf("full training error!!!\n"); + goto error; + } + } + + /* detect col */ + dram_set_max_col(chan, bw, &col_tmp); + if (sdram_detect_col(cap_info, col_tmp) != 0) + goto error; + + /* detect bank */ + dram_set_max_bank(chan, bw, &bk_tmp, &col_tmp); + sdram_detect_bank(cap_info, col_tmp, bk_tmp); + + /* detect row */ + dram_set_max_row(chan, bw, &row_tmp, &bk_tmp, &col_tmp); + if (sdram_detect_row(cap_info, col_tmp, bk_tmp, row_tmp) != 0) + goto error; + + /* detect row_3_4 */ + sdram_detect_row_3_4(cap_info, col_tmp, bk_tmp); + + /* set ddrconfig */ + cs0_cap = (1 << (cap_info->cs0_row + cap_info->col + cap_info->bk + + cap_info->bw - 20)); + if (cap_info->row_3_4) + cs0_cap = cs0_cap * 3 / 4; + + cap_info->cs1_row = cap_info->cs0_row; + set_memory_map(chan, channel, params); + ddrconfig = calculate_ddrconfig(params, channel); + if (-1 == ddrconfig) + goto error; + set_ddrconfig(chan, params, channel, + cap_info->ddrconfig); + + /* detect cs1 row */ + sdram_detect_cs1_row(cap_info, params->base.dramtype); + + /* detect die bw */ + sdram_detect_dbw(cap_info, params->base.dramtype); + + return 0; +error: + return (-1); +} + static unsigned char calculate_stride(struct rk3399_sdram_params *params) { unsigned int stride = params->base.stride; @@ -2489,39 +2868,13 @@ static void clear_channel_params(struct rk3399_sdram_params *params, u8 channel) params->ch[channel].cap_info.ddrconfig = 0; } -static int pctl_init(struct dram_info *dram, struct rk3399_sdram_params *params) -{ - int channel; - int ret; - - for (channel = 0; channel < 2; channel++) { - const struct chan_info *chan = &dram->chan[channel]; - struct rk3399_cru *cru = dram->cru; - struct rk3399_ddr_publ_regs *publ = chan->publ; - - phy_pctrl_reset(cru, channel); - phy_dll_bypass_set(publ, params->base.ddr_freq); - - ret = pctl_cfg(dram, chan, channel, params); - if (ret < 0) { - printf("%s: pctl config failed\n", __func__); - return ret; - } - - /* start to trigger initialization */ - pctl_start(dram, channel); - } - - return 0; -} - static int sdram_init(struct dram_info *dram, struct rk3399_sdram_params *params) { unsigned char dramtype = params->base.dramtype; unsigned int ddr_freq = params->base.ddr_freq; int channel, ch, rank; - int ret; + u32 tmp, ret; debug("Starting SDRAM initialization...\n"); @@ -2532,22 +2885,35 @@ static int sdram_init(struct dram_info *dram, return -E2BIG; } + /* detect rank */ for (ch = 0; ch < 2; ch++) { params->ch[ch].cap_info.rank = 2; for (rank = 2; rank != 0; rank--) { - ret = pctl_init(dram, params); - if (ret < 0) { - printf("%s: pctl init failed\n", __func__); - return ret; + for (channel = 0; channel < 2; channel++) { + const struct chan_info *chan = + &dram->chan[channel]; + struct rk3399_cru *cru = dram->cru; + struct rk3399_ddr_publ_regs *publ = chan->publ; + + phy_pctrl_reset(cru, channel); + phy_dll_bypass_set(publ, ddr_freq); + pctl_cfg(dram, chan, channel, params); } + /* start to trigger initialization */ + pctl_start(dram, params, 3); + /* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */ if (dramtype == LPDDR3) udelay(10); + tmp = (rank == 2) ? 3 : 1; + dram_set_cs(&dram->chan[ch], tmp, 2048, + params->base.dramtype); params->ch[ch].cap_info.rank = rank; - ret = dram->ops->data_training(dram, ch, rank, params); + ret = dram->ops->data_training_first(dram, ch, + rank, params); if (!ret) { debug("%s: data trained for rank %d, ch %d\n", __func__, rank, ch); @@ -2561,50 +2927,52 @@ static int sdram_init(struct dram_info *dram, params->base.num_channels = 0; for (channel = 0; channel < 2; channel++) { const struct chan_info *chan = &dram->chan[channel]; - struct sdram_cap_info *cap_info = ¶ms->ch[channel].cap_info; - u8 training_flag = PI_FULL_TRAINING; + struct sdram_cap_info *cap_info = + ¶ms->ch[channel].cap_info; if (cap_info->rank == 0) { - clear_channel_params(params, channel); + clear_channel_params(params, 1); continue; } else { params->base.num_channels++; } - debug("Channel "); - debug(channel ? "1: " : "0: "); + printf("Channel "); + printf(channel ? "1: " : "0: "); - /* LPDDR3 should have write and read gate training */ - if (params->base.dramtype == LPDDR3) - training_flag = PI_WRITE_LEVELING | - PI_READ_GATE_TRAINING; + if (channel == 0) + set_ddr_stride(dram->pmusgrf, 0x17); + else + set_ddr_stride(dram->pmusgrf, 0x18); - if (params->base.dramtype != LPDDR4) { - ret = data_training(dram, channel, params, - training_flag); - if (!ret) { - debug("%s: data train failed for channel %d\n", - __func__, ret); - continue; - } + if (dram_detect_cap(dram, params, channel)) { + printf("Cap error!\n"); + continue; } + sdram_print_ddr_info(cap_info, ¶ms->base, 0); set_memory_map(chan, channel, params); - cap_info->ddrconfig = calculate_ddrconfig(params, channel); - + cap_info->ddrconfig = + calculate_ddrconfig(params, channel); + if (-1 == cap_info->ddrconfig) { + printf("no ddrconfig find, Cap not support!\n"); + continue; + } set_ddrconfig(chan, params, channel, cap_info->ddrconfig); set_cap_relate_config(chan, params, channel); } if (params->base.num_channels == 0) { printf("%s: ", __func__); + sdram_print_dram_type(params->base.dramtype); printf(" - %dMHz failed!\n", params->base.ddr_freq); return -EINVAL; } params->base.stride = calculate_stride(params); dram_all_config(dram, params); - dram->ops->set_rate(dram, params); + + dram->ops->set_rate_index(dram, params); debug("Finish SDRAM initialization...\n"); return 0; @@ -2651,11 +3019,15 @@ static int conv_of_platdata(struct udevice *dev) static const struct sdram_rk3399_ops rk3399_ops = { #if !defined(CONFIG_RAM_RK3399_LPDDR4) - .data_training = default_data_training, - .set_rate = switch_to_phy_index1, + .data_training_first = data_training_first, + .set_rate_index = switch_to_phy_index1, + .modify_param = modify_param, + .get_phy_index_params = get_phy_index_params, #else - .data_training = lpddr4_mr_detect, - .set_rate = lpddr4_set_rate, + .data_training_first = lpddr4_mr_detect, + .set_rate_index = lpddr4_set_rate, + .modify_param = lpddr4_modify_param, + .get_phy_index_params = lpddr4_get_phy_index_params, #endif }; -- 2.17.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot