
From: YouMin Chen cym@rock-chips.com
Add common sdram driver including functions share for all SoCs, controller and phy common functions.
Signed-off-by: YouMin Chen cym@rock-chips.com Signed-off-by: Kever Yang kever.yang@rock-chips.com ---
arch/arm/include/asm/arch-rockchip/sdram.h | 104 +---- .../include/asm/arch-rockchip/sdram_common.h | 144 +++++++ .../include/asm/arch-rockchip/sdram_msch.h | 85 ++++ .../asm/arch-rockchip/sdram_pctl_px30.h | 139 ++++++ .../asm/arch-rockchip/sdram_phy_px30.h | 62 +++ .../arch-rockchip/sdram_phy_ron_rtt_px30.h | 59 +++ .../include/asm/arch-rockchip/sdram_rk3328.h | 1 + .../include/asm/arch-rockchip/sdram_rk3399.h | 1 + drivers/ram/rockchip/Kconfig | 6 + drivers/ram/rockchip/Makefile | 2 +- drivers/ram/rockchip/sdram_common.c | 400 ++++++++++++++++++ drivers/ram/rockchip/sdram_debug.c | 147 ------- drivers/ram/rockchip/sdram_pctl_px30.c | 205 +++++++++ drivers/ram/rockchip/sdram_phy_px30.c | 205 +++++++++ drivers/ram/rockchip/sdram_rk3399.c | 4 - 15 files changed, 1329 insertions(+), 235 deletions(-) create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_common.h create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_msch.h create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_phy_px30.h create mode 100644 arch/arm/include/asm/arch-rockchip/sdram_phy_ron_rtt_px30.h create mode 100644 drivers/ram/rockchip/sdram_common.c delete mode 100644 drivers/ram/rockchip/sdram_debug.c create mode 100644 drivers/ram/rockchip/sdram_pctl_px30.c create mode 100644 drivers/ram/rockchip/sdram_phy_px30.c
diff --git a/arch/arm/include/asm/arch-rockchip/sdram.h b/arch/arm/include/asm/arch-rockchip/sdram.h index 3866d0b4d4..2aaeb4327d 100644 --- a/arch/arm/include/asm/arch-rockchip/sdram.h +++ b/arch/arm/include/asm/arch-rockchip/sdram.h @@ -15,34 +15,6 @@ enum { UNUSED = 0xFF };
-struct sdram_cap_info { - unsigned int rank; - /* dram column number, 0 means this channel is invalid */ - unsigned int col; - /* dram bank number, 3:8bank, 2:4bank */ - unsigned int bk; - /* channel buswidth, 2:32bit, 1:16bit, 0:8bit */ - unsigned int bw; - /* die buswidth, 2:32bit, 1:16bit, 0:8bit */ - unsigned int dbw; - /* - * row_3_4 = 1: 6Gb or 12Gb die - * row_3_4 = 0: normal die, power of 2 - */ - unsigned int row_3_4; - unsigned int cs0_row; - unsigned int cs1_row; - unsigned int ddrconfig; -}; - -struct sdram_base_params { - unsigned int ddr_freq; - unsigned int dramtype; - unsigned int num_channels; - unsigned int stride; - unsigned int odt; -}; - /* * sys_reg bitfield struct * [31] row_3_4_ch1 @@ -51,72 +23,58 @@ struct sdram_base_params { * [27] rank_ch1 * [26:25] col_ch1 * [24] bk_ch1 - * [23:22] cs0_row_ch1 - * [21:20] cs1_row_ch1 + * [23:22] low bits of cs0_row_ch1 + * [21:20] low bits of cs1_row_ch1 * [19:18] bw_ch1 * [17:16] dbw_ch1; * [15:13] ddrtype * [12] channelnum * [11] rank_ch0 - * [10:9] col_ch0 + * [10:9] col_ch0, * [8] bk_ch0 - * [7:6] cs0_row_ch0 - * [5:4] cs1_row_ch0 + * [7:6] low bits of cs0_row_ch0 + * [5:4] low bits of cs1_row_ch0 * [3:2] bw_ch0 * [1:0] dbw_ch0 + * + * sys_reg1 bitfield struct + * [7] high bit of cs0_row_ch1 + * [6] high bit of cs1_row_ch1 + * [5] high bit of cs0_row_ch0 + * [4] high bit of cs1_row_ch0 + * [3:2] cs1_col_ch1 + * [1:0] cs1_col_ch0 */ #define SYS_REG_DDRTYPE_SHIFT 13 -#define DDR_SYS_REG_VERSION 2 #define SYS_REG_DDRTYPE_MASK 7 #define SYS_REG_NUM_CH_SHIFT 12 #define SYS_REG_NUM_CH_MASK 1 #define SYS_REG_ROW_3_4_SHIFT(ch) (30 + (ch)) #define SYS_REG_ROW_3_4_MASK 1 -#define SYS_REG_ENC_ROW_3_4(n, ch) ((n) << (30 + (ch))) #define SYS_REG_CHINFO_SHIFT(ch) (28 + (ch)) -#define SYS_REG_ENC_CHINFO(ch) (1 << SYS_REG_CHINFO_SHIFT(ch)) -#define SYS_REG_ENC_DDRTYPE(n) ((n) << SYS_REG_DDRTYPE_SHIFT) -#define SYS_REG_ENC_NUM_CH(n) (((n) - SYS_REG_NUM_CH_MASK) << \ - SYS_REG_NUM_CH_SHIFT) #define SYS_REG_RANK_SHIFT(ch) (11 + (ch) * 16) #define SYS_REG_RANK_MASK 1 -#define SYS_REG_ENC_RANK(n, ch) (((n) - SYS_REG_RANK_MASK) << \ - SYS_REG_RANK_SHIFT(ch)) #define SYS_REG_COL_SHIFT(ch) (9 + (ch) * 16) #define SYS_REG_COL_MASK 3 -#define SYS_REG_ENC_COL(n, ch) (((n) - 9) << SYS_REG_COL_SHIFT(ch)) #define SYS_REG_BK_SHIFT(ch) (8 + (ch) * 16) #define SYS_REG_BK_MASK 1 -#define SYS_REG_ENC_BK(n, ch) (((n) == 3 ? 0 : 1) << \ - SYS_REG_BK_SHIFT(ch)) #define SYS_REG_CS0_ROW_SHIFT(ch) (6 + (ch) * 16) #define SYS_REG_CS0_ROW_MASK 3 #define SYS_REG_CS1_ROW_SHIFT(ch) (4 + (ch) * 16) #define SYS_REG_CS1_ROW_MASK 3 #define SYS_REG_BW_SHIFT(ch) (2 + (ch) * 16) #define SYS_REG_BW_MASK 3 -#define SYS_REG_ENC_BW(n, ch) ((2 >> (n)) << SYS_REG_BW_SHIFT(ch)) #define SYS_REG_DBW_SHIFT(ch) ((ch) * 16) #define SYS_REG_DBW_MASK 3 -#define SYS_REG_ENC_DBW(n, ch) ((2 >> (n)) << SYS_REG_DBW_SHIFT(ch)) - -#define SYS_REG_ENC_VERSION(n) ((n) << 28) -#define SYS_REG_ENC_CS0_ROW(n, os_reg2, os_reg3, ch) do { \ - (os_reg2) |= (((n) - 13) & 0x3) << (6 + 16 * (ch)); \ - (os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \ - (5 + 2 * (ch)); \ - } while (0)
-#define SYS_REG_ENC_CS1_ROW(n, os_reg2, os_reg3, ch) do { \ - (os_reg2) &= (~(0x3 << (4 + 16 * (ch)))); \ - (os_reg3) &= (~(0x1 << (4 + 2 * (ch)))); \ - (os_reg2) |= (((n) - 13) & 0x3) << (4 + 16 * (ch)); \ - (os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \ - (4 + 2 * (ch)); \ - } while (0) - -#define SYS_REG_CS1_COL_SHIFT(ch) (0 + 2 * (ch)) -#define SYS_REG_ENC_CS1_COL(n, ch) (((n) - 9) << SYS_REG_CS1_COL_SHIFT(ch)) +#define SYS_REG1_VERSION_SHIFT 28 +#define SYS_REG1_VERSION_MASK 0xf +#define SYS_REG1_EXTEND_CS0_ROW_SHIFT(ch) (5 + (ch) * 2) +#define SYS_REG1_EXTEND_CS0_ROW_MASK 1 +#define SYS_REG1_EXTEND_CS1_ROW_SHIFT(ch) (4 + (ch) * 2) +#define SYS_REG1_EXTEND_CS1_ROW_MASK 1 +#define SYS_REG1_CS1_COL_SHIFT(ch) (0 + (ch) * 2) +#define SYS_REG1_CS1_COL_MASK 3
/* Get sdram size decode from reg */ size_t rockchip_sdram_size(phys_addr_t reg); @@ -124,24 +82,4 @@ size_t rockchip_sdram_size(phys_addr_t reg); /* Called by U-Boot board_init_r for Rockchip SoCs */ int dram_init(void);
-#if !defined(CONFIG_RAM_ROCKCHIP_DEBUG) -inline void sdram_print_dram_type(unsigned char dramtype) -{ -} - -inline void sdram_print_ddr_info(struct sdram_cap_info *cap_info, - struct sdram_base_params *base) -{ -} - -inline void sdram_print_stride(unsigned int stride) -{ -} -#else -void sdram_print_dram_type(unsigned char dramtype); -void sdram_print_ddr_info(struct sdram_cap_info *cap_info, - struct sdram_base_params *base); -void sdram_print_stride(unsigned int stride); -#endif /* CONFIG_RAM_ROCKCHIP_DEBUG */ - #endif diff --git a/arch/arm/include/asm/arch-rockchip/sdram_common.h b/arch/arm/include/asm/arch-rockchip/sdram_common.h new file mode 100644 index 0000000000..dd593ae5e0 --- /dev/null +++ b/arch/arm/include/asm/arch-rockchip/sdram_common.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Rockchip Electronics Co., Ltd + */ + +#ifndef _ASM_ARCH_SDRAM_SHARE_H +#define _ASM_ARCH_SDRAM_SHARE_H + +#ifndef MHZ +#define MHZ (1000 * 1000) +#endif + +#define PATTERN (0x5aa5f00f) + +#define MIN(a, b) (((a) > (b)) ? (b) : (a)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +struct sdram_cap_info { + unsigned int rank; + /* dram column number, 0 means this channel is invalid */ + unsigned int col; + /* dram bank number, 3:8bank, 2:4bank */ + unsigned int bk; + /* channel buswidth, 2:32bit, 1:16bit, 0:8bit */ + unsigned int bw; + /* die buswidth, 2:32bit, 1:16bit, 0:8bit */ + unsigned int dbw; + /* + * row_3_4 = 1: 6Gb or 12Gb die + * row_3_4 = 0: normal die, power of 2 + */ + unsigned int row_3_4; + unsigned int cs0_row; + unsigned int cs1_row; + unsigned int cs0_high16bit_row; + unsigned int cs1_high16bit_row; + unsigned int ddrconfig; +}; + +struct sdram_base_params { + unsigned int ddr_freq; + unsigned int dramtype; + unsigned int num_channels; + unsigned int stride; + unsigned int odt; +}; + +/* + * sys_reg bitfield struct + * [31] row_3_4_ch1 + * [30] row_3_4_ch0 + * [29:28] chinfo + * [27] rank_ch1 + * [26:25] col_ch1 + * [24] bk_ch1 + * [23:22] cs0_row_ch1 + * [21:20] cs1_row_ch1 + * [19:18] bw_ch1 + * [17:16] dbw_ch1; + * [15:13] ddrtype + * [12] channelnum + * [11] rank_ch0 + * [10:9] col_ch0 + * [8] bk_ch0 + * [7:6] cs0_row_ch0 + * [5:4] cs1_row_ch0 + * [3:2] bw_ch0 + * [1:0] dbw_ch0 + */ + +#define DDR_SYS_REG_VERSION (0x2) +#define SYS_REG_ENC_ROW_3_4(n, ch) ((n) << (30 + (ch))) +#define SYS_REG_DEC_ROW_3_4(n, ch) (((n) >> (30 + (ch))) & 0x1) +#define SYS_REG_ENC_CHINFO(ch) (1 << (28 + (ch))) +#define SYS_REG_ENC_DDRTYPE(n) ((n) << 13) +#define SYS_REG_DEC_DDRTYPE(n) (((n) >> 13) & 0x7) +#define SYS_REG_ENC_NUM_CH(n) (((n) - 1) << 12) +#define SYS_REG_DEC_NUM_CH(n) (1 + (((n) >> 12) & 0x1)) +#define SYS_REG_ENC_RANK(n, ch) (((n) - 1) << (11 + ((ch) * 16))) +#define SYS_REG_DEC_RANK(n, ch) (1 + (((n) >> (11 + 16 * (ch))) & 0x1)) +#define SYS_REG_ENC_COL(n, ch) (((n) - 9) << (9 + ((ch) * 16))) +#define SYS_REG_DEC_COL(n, ch) (9 + (((n) >> (9 + 16 * (ch))) & 0x3)) +#define SYS_REG_ENC_BK(n, ch) (((n) == 3 ? 0 : 1) << \ + (8 + ((ch) * 16))) +#define SYS_REG_DEC_BK(n, ch) (3 - (((n) >> (8 + 16 * (ch))) & 0x1)) +#define SYS_REG_ENC_BW(n, ch) ((2 >> (n)) << (2 + ((ch) * 16))) +#define SYS_REG_DEC_BW(n, ch) (2 >> (((n) >> (2 + 16 * (ch))) & 0x3)) +#define SYS_REG_ENC_DBW(n, ch) ((2 >> (n)) << (0 + ((ch) * 16))) +#define SYS_REG_DEC_DBW(n, ch) (2 >> (((n) >> (0 + 16 * (ch))) & 0x3)) +/* sys reg 3 */ +#define SYS_REG_ENC_VERSION(n) ((n) << 28) +#define SYS_REG_DEC_VERSION(n) (((n) >> 28) & 0xf) +#define SYS_REG_ENC_CS0_ROW(n, os_reg2, os_reg3, ch) do { \ + (os_reg2) |= (((n) - 13) & 0x3) << (6 + 16 * (ch)); \ + (os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \ + (5 + 2 * (ch)); \ + } while (0) + +#define SYS_REG_DEC_CS0_ROW(os_reg2, os_reg3, ch) \ + ((((((os_reg2) >> (6 + 16 * (ch)) & 0x3) | \ + ((((os_reg3) >> (5 + 2 * (ch))) & 0x1) << 2)) + 1) & 0x7) + 12) + +#define SYS_REG_ENC_CS1_ROW(n, os_reg2, os_reg3, ch) do { \ + (os_reg2) &= (~(0x3 << (4 + 16 * (ch)))); \ + (os_reg3) &= (~(0x1 << (4 + 2 * (ch)))); \ + (os_reg2) |= (((n) - 13) & 0x3) << (4 + 16 * (ch)); \ + (os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \ + (4 + 2 * (ch)); \ + } while (0) + +#define SYS_REG_DEC_CS1_ROW(os_reg2, os_reg3, ch) \ + ((((((os_reg2) >> (4 + 16 * (ch)) & 0x3) | \ + ((((os_reg3) >> (4 + 2 * (ch))) & 0x1) << 2)) + 1) & 0x7) + 12) + +#define SYS_REG_ENC_CS1_COL(n, ch) (((n) - 9) << (0 + 2 * (ch))) +#define SYS_REG_DEC_CS1_COL(n, ch) (9 + (((n) >> (0 + 2 * (ch))) & 0x3)) + +void sdram_org_config(struct sdram_cap_info *cap_info, + struct sdram_base_params *base, + u32 *p_os_reg2, u32 *p_os_reg3, u32 channel); + +int sdram_detect_bw(struct sdram_cap_info *cap_info); +int sdram_detect_cs(struct sdram_cap_info *cap_info); +int sdram_detect_col(struct sdram_cap_info *cap_info, + u32 coltmp); +int sdram_detect_bank(struct sdram_cap_info *cap_info, + u32 coltmp, u32 bktmp); +int sdram_detect_bg(struct sdram_cap_info *cap_info, + u32 coltmp); +int sdram_detect_dbw(struct sdram_cap_info *cap_info, u32 dram_type); +int sdram_detect_row(struct sdram_cap_info *cap_info, + u32 coltmp, u32 bktmp, u32 rowtmp); +int sdram_detect_row_3_4(struct sdram_cap_info *cap_info, + u32 coltmp, u32 bktmp); +int sdram_detect_high_row(struct sdram_cap_info *cap_info); +int sdram_detect_cs1_row(struct sdram_cap_info *cap_info, u32 dram_type); + +void sdram_print_dram_type(unsigned char dramtype); +void sdram_print_ddr_info(struct sdram_cap_info *cap_info, + struct sdram_base_params *base, u32 split); +u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type); +void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n); + +#endif diff --git a/arch/arm/include/asm/arch-rockchip/sdram_msch.h b/arch/arm/include/asm/arch-rockchip/sdram_msch.h new file mode 100644 index 0000000000..cfb3d9cc86 --- /dev/null +++ b/arch/arm/include/asm/arch-rockchip/sdram_msch.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Rockchip Electronics Co., Ltd + */ + +#ifndef _ASM_ARCH_SDRAM_MSCH_H +#define _ASM_ARCH_SDRAM_MSCH_H + +union noc_ddrtiminga0 { + u32 d32; + struct { + unsigned acttoact : 6; + unsigned reserved0 : 2; + unsigned rdtomiss : 6; + unsigned reserved1 : 2; + unsigned wrtomiss : 6; + unsigned reserved2 : 2; + unsigned readlatency : 8; + } b; +}; + +union noc_ddrtimingb0 { + u32 d32; + struct { + unsigned rdtowr : 5; + unsigned reserved0 : 3; + unsigned wrtord : 5; + unsigned reserved1 : 3; + unsigned rrd : 4; + unsigned reserved2 : 4; + unsigned faw : 6; + unsigned reserved3 : 2; + } b; +}; + +union noc_ddrtimingc0 { + u32 d32; + struct { + unsigned burstpenalty : 4; + unsigned reserved0 : 4; + unsigned wrtomwr : 6; + unsigned reserved1 : 18; + } b; +}; + +union noc_devtodev0 { + u32 d32; + struct { + unsigned busrdtord : 3; + unsigned reserved0 : 1; + unsigned busrdtowr : 3; + unsigned reserved1 : 1; + unsigned buswrtord : 3; + unsigned reserved2 : 1; + unsigned buswrtowr : 3; + unsigned reserved3 : 17; + } 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; +}; + +union noc_ddr4timing { + u32 d32; + struct { + unsigned ccdl : 3; + unsigned wrtordl : 5; + unsigned rrdl : 4; + unsigned reserved1 : 20; + } b; +}; + +#endif diff --git a/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h b/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h new file mode 100644 index 0000000000..9781881738 --- /dev/null +++ b/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Rockchip Electronics Co., Ltd + */ + +#ifndef _ASM_ARCH_SDRAM_PCTL_PX30_H +#define _ASM_ARCH_SDRAM_PCTL_PX30_H +#include <asm/arch-rockchip/sdram_common.h> + +struct ddr_pctl_regs { + u32 pctl[30][2]; +}; + +/* ddr pctl registers define */ +#define DDR_PCTL2_MSTR 0x0 +#define DDR_PCTL2_STAT 0x4 +#define DDR_PCTL2_MSTR1 0x8 +#define DDR_PCTL2_MRCTRL0 0x10 +#define DDR_PCTL2_MRCTRL1 0x14 +#define DDR_PCTL2_MRSTAT 0x18 +#define DDR_PCTL2_MRCTRL2 0x1c +#define DDR_PCTL2_DERATEEN 0x20 +#define DDR_PCTL2_DERATEINT 0x24 +#define DDR_PCTL2_PWRCTL 0x30 +#define DDR_PCTL2_PWRTMG 0x34 +#define DDR_PCTL2_HWLPCTL 0x38 +#define DDR_PCTL2_RFSHCTL0 0x50 +#define DDR_PCTL2_RFSHCTL1 0x54 +#define DDR_PCTL2_RFSHCTL2 0x58 +#define DDR_PCTL2_RFSHCTL4 0x5c +#define DDR_PCTL2_RFSHCTL3 0x60 +#define DDR_PCTL2_RFSHTMG 0x64 +#define DDR_PCTL2_RFSHTMG1 0x68 +#define DDR_PCTL2_RFSHCTL5 0x6c +#define DDR_PCTL2_INIT0 0xd0 +#define DDR_PCTL2_INIT1 0xd4 +#define DDR_PCTL2_INIT2 0xd8 +#define DDR_PCTL2_INIT3 0xdc +#define DDR_PCTL2_INIT4 0xe0 +#define DDR_PCTL2_INIT5 0xe4 +#define DDR_PCTL2_INIT6 0xe8 +#define DDR_PCTL2_INIT7 0xec +#define DDR_PCTL2_DIMMCTL 0xf0 +#define DDR_PCTL2_RANKCTL 0xf4 +#define DDR_PCTL2_CHCTL 0xfc +#define DDR_PCTL2_DRAMTMG0 0x100 +#define DDR_PCTL2_DRAMTMG1 0x104 +#define DDR_PCTL2_DRAMTMG2 0x108 +#define DDR_PCTL2_DRAMTMG3 0x10c +#define DDR_PCTL2_DRAMTMG4 0x110 +#define DDR_PCTL2_DRAMTMG5 0x114 +#define DDR_PCTL2_DRAMTMG6 0x118 +#define DDR_PCTL2_DRAMTMG7 0x11c +#define DDR_PCTL2_DRAMTMG8 0x120 +#define DDR_PCTL2_DRAMTMG9 0x124 +#define DDR_PCTL2_DRAMTMG10 0x128 +#define DDR_PCTL2_DRAMTMG11 0x12c +#define DDR_PCTL2_DRAMTMG12 0x130 +#define DDR_PCTL2_DRAMTMG13 0x134 +#define DDR_PCTL2_DRAMTMG14 0x138 +#define DDR_PCTL2_DRAMTMG15 0x13c +#define DDR_PCTL2_DRAMTMG16 0x140 +#define DDR_PCTL2_ZQCTL0 0x180 +#define DDR_PCTL2_ZQCTL1 0x184 +#define DDR_PCTL2_ZQCTL2 0x188 +#define DDR_PCTL2_ZQSTAT 0x18c +#define DDR_PCTL2_DFITMG0 0x190 +#define DDR_PCTL2_DFITMG1 0x194 +#define DDR_PCTL2_DFILPCFG0 0x198 +#define DDR_PCTL2_DFILPCFG1 0x19c +#define DDR_PCTL2_DFIUPD0 0x1a0 +#define DDR_PCTL2_DFIUPD1 0x1a4 +#define DDR_PCTL2_DFIUPD2 0x1a8 +#define DDR_PCTL2_DFIMISC 0x1b0 +#define DDR_PCTL2_DFITMG2 0x1b4 +#define DDR_PCTL2_DFITMG3 0x1b8 +#define DDR_PCTL2_DFISTAT 0x1bc +#define DDR_PCTL2_DBICTL 0x1c0 +#define DDR_PCTL2_ADDRMAP0 0x200 +#define DDR_PCTL2_ADDRMAP1 0x204 +#define DDR_PCTL2_ADDRMAP2 0x208 +#define DDR_PCTL2_ADDRMAP3 0x20c +#define DDR_PCTL2_ADDRMAP4 0x210 +#define DDR_PCTL2_ADDRMAP5 0x214 +#define DDR_PCTL2_ADDRMAP6 0x218 +#define DDR_PCTL2_ADDRMAP7 0x21c +#define DDR_PCTL2_ADDRMAP8 0x220 +#define DDR_PCTL2_ADDRMAP9 0x224 +#define DDR_PCTL2_ADDRMAP10 0x228 +#define DDR_PCTL2_ADDRMAP11 0x22c +#define DDR_PCTL2_ODTCFG 0x240 +#define DDR_PCTL2_ODTMAP 0x244 +#define DDR_PCTL2_SCHED 0x250 +#define DDR_PCTL2_SCHED1 0x254 +#define DDR_PCTL2_PERFHPR1 0x25c +#define DDR_PCTL2_PERFLPR1 0x264 +#define DDR_PCTL2_PERFWR1 0x26c +#define DDR_PCTL2_DQMAP0 0x280 +#define DDR_PCTL2_DQMAP1 0x284 +#define DDR_PCTL2_DQMAP2 0x288 +#define DDR_PCTL2_DQMAP3 0x28c +#define DDR_PCTL2_DQMAP4 0x290 +#define DDR_PCTL2_DQMAP5 0x294 +#define DDR_PCTL2_DBG0 0x300 +#define DDR_PCTL2_DBG1 0x304 +#define DDR_PCTL2_DBGCAM 0x308 +#define DDR_PCTL2_DBGCMD 0x30c +#define DDR_PCTL2_DBGSTAT 0x310 +#define DDR_PCTL2_SWCTL 0x320 +#define DDR_PCTL2_SWSTAT 0x324 +#define DDR_PCTL2_POISONCFG 0x36c +#define DDR_PCTL2_POISONSTAT 0x370 +#define DDR_PCTL2_ADVECCINDEX 0x374 +#define DDR_PCTL2_ADVECCSTAT 0x378 +#define DDR_PCTL2_PSTAT 0x3fc +#define DDR_PCTL2_PCCFG 0x400 +#define DDR_PCTL2_PCFGR_n 0x404 +#define DDR_PCTL2_PCFGW_n 0x408 +#define DDR_PCTL2_PCTRL_n 0x490 + +/* PCTL2_MRSTAT */ +#define MR_WR_BUSY BIT(0) + +void pctl_read_mr(void __iomem *pctl_base, u32 rank, u32 mr_num); +int pctl_write_mr(void __iomem *pctl_base, u32 rank, u32 mr_num, u32 arg, + u32 dramtype); +int pctl_write_vrefdq(void __iomem *pctl_base, u32 rank, u32 vrefrate, + u32 dramtype); + +u32 pctl_dis_zqcs_aref(void __iomem *pctl_base); +void pctl_rest_zqcs_aref(void __iomem *pctl_base, u32 dis_auto_zq); + +u32 pctl_remodify_sdram_params(struct ddr_pctl_regs *pctl_regs, + struct sdram_cap_info *cap_info, + u32 dram_type); +int pctl_cfg(void __iomem *pctl_base, struct ddr_pctl_regs *pctl_regs, + u32 sr_idle, u32 pd_idle); + +#endif diff --git a/arch/arm/include/asm/arch-rockchip/sdram_phy_px30.h b/arch/arm/include/asm/arch-rockchip/sdram_phy_px30.h new file mode 100644 index 0000000000..c75a633c91 --- /dev/null +++ b/arch/arm/include/asm/arch-rockchip/sdram_phy_px30.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Rockchip Electronics Co., Ltd + */ + +#ifndef _ASM_ARCH_SDRAM_PHY_PX30_H +#define _ASM_ARCH_SDRAM_PHY_PX30_H +#include <asm/arch-rockchip/sdram_common.h> +#include <asm/arch-rockchip/sdram_phy_ron_rtt_px30.h> + +struct ddr_phy_regs { + u32 phy[5][2]; +}; + +#define PHY_REG(base, n) ((base) + 4 * (n)) + +/* PHY_REG0 */ +#define DIGITAL_DERESET BIT(3) +#define ANALOG_DERESET BIT(2) +#define DIGITAL_RESET (0 << 3) +#define ANALOG_RESET (0 << 2) + +/* PHY_REG1 */ +#define PHY_DDR2 (0) +#define PHY_LPDDR2 (1) +#define PHY_DDR3 (2) +#define PHY_LPDDR3 (3) +#define PHY_DDR4 (4) +#define PHY_BL_4 (0 << 2) +#define PHY_BL_8 BIT(2) + +/* PHY_REG2 */ +#define PHY_DTT_EN BIT(0) +#define PHY_DTT_DISB (0 << 0) +#define PHY_WRITE_LEVELING_EN BIT(2) +#define PHY_WRITE_LEVELING_DISB (0 << 2) +#define PHY_SELECT_CS0 (2) +#define PHY_SELECT_CS1 (1) +#define PHY_SELECT_CS0_1 (0) +#define PHY_WRITE_LEVELING_SELECTCS(n) ((n) << 6) +#define PHY_DATA_TRAINING_SELECTCS(n) ((n) << 4) + +struct ddr_phy_skew { + u32 a0_a1_skew[15]; + u32 cs0_dm0_skew[11]; + u32 cs0_dm1_skew[11]; + u32 cs0_dm2_skew[11]; + u32 cs0_dm3_skew[11]; + u32 cs1_dm0_skew[11]; + u32 cs1_dm1_skew[11]; + u32 cs1_dm2_skew[11]; + u32 cs1_dm3_skew[11]; +}; + +void phy_soft_reset(void __iomem *phy_base); +void phy_dram_set_bw(void __iomem *phy_base, u32 bw); +void phy_cfg(void __iomem *phy_base, + struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew, + struct sdram_base_params *base, u32 bw); +int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype); + +#endif diff --git a/arch/arm/include/asm/arch-rockchip/sdram_phy_ron_rtt_px30.h b/arch/arm/include/asm/arch-rockchip/sdram_phy_ron_rtt_px30.h new file mode 100644 index 0000000000..9c15232047 --- /dev/null +++ b/arch/arm/include/asm/arch-rockchip/sdram_phy_ron_rtt_px30.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Rockchip Electronics Co., Ltd + */ + +#ifndef _ASM_ARCH_SDRAM_PHY_RON_RTT_PX30_H +#define _ASM_ARCH_SDRAM_PHY_RON_RTT_PX30_H + +#define PHY_DDR3_RON_RTT_DISABLE (0) +#define PHY_DDR3_RON_RTT_451ohm (1) +#define PHY_DDR3_RON_RTT_225ohm (2) +#define PHY_DDR3_RON_RTT_150ohm (3) +#define PHY_DDR3_RON_RTT_112ohm (4) +#define PHY_DDR3_RON_RTT_90ohm (5) +#define PHY_DDR3_RON_RTT_75ohm (6) +#define PHY_DDR3_RON_RTT_64ohm (7) +#define PHY_DDR3_RON_RTT_56ohm (16) +#define PHY_DDR3_RON_RTT_50ohm (17) +#define PHY_DDR3_RON_RTT_45ohm (18) +#define PHY_DDR3_RON_RTT_41ohm (19) +#define PHY_DDR3_RON_RTT_37ohm (20) +#define PHY_DDR3_RON_RTT_34ohm (21) +#define PHY_DDR3_RON_RTT_33ohm (22) +#define PHY_DDR3_RON_RTT_30ohm (23) +#define PHY_DDR3_RON_RTT_28ohm (24) +#define PHY_DDR3_RON_RTT_26ohm (25) +#define PHY_DDR3_RON_RTT_25ohm (26) +#define PHY_DDR3_RON_RTT_23ohm (27) +#define PHY_DDR3_RON_RTT_22ohm (28) +#define PHY_DDR3_RON_RTT_21ohm (29) +#define PHY_DDR3_RON_RTT_20ohm (30) +#define PHY_DDR3_RON_RTT_19ohm (31) + +#define PHY_DDR4_LPDDR3_RON_RTT_DISABLE (0) +#define PHY_DDR4_LPDDR3_RON_RTT_480ohm (1) +#define PHY_DDR4_LPDDR3_RON_RTT_240ohm (2) +#define PHY_DDR4_LPDDR3_RON_RTT_160ohm (3) +#define PHY_DDR4_LPDDR3_RON_RTT_120ohm (4) +#define PHY_DDR4_LPDDR3_RON_RTT_96ohm (5) +#define PHY_DDR4_LPDDR3_RON_RTT_80ohm (6) +#define PHY_DDR4_LPDDR3_RON_RTT_68ohm (7) +#define PHY_DDR4_LPDDR3_RON_RTT_60ohm (16) +#define PHY_DDR4_LPDDR3_RON_RTT_53ohm (17) +#define PHY_DDR4_LPDDR3_RON_RTT_48ohm (18) +#define PHY_DDR4_LPDDR3_RON_RTT_43ohm (19) +#define PHY_DDR4_LPDDR3_RON_RTT_40ohm (20) +#define PHY_DDR4_LPDDR3_RON_RTT_37ohm (21) +#define PHY_DDR4_LPDDR3_RON_RTT_34ohm (22) +#define PHY_DDR4_LPDDR3_RON_RTT_32ohm (23) +#define PHY_DDR4_LPDDR3_RON_RTT_30ohm (24) +#define PHY_DDR4_LPDDR3_RON_RTT_28ohm (25) +#define PHY_DDR4_LPDDR3_RON_RTT_26ohm (26) +#define PHY_DDR4_LPDDR3_RON_RTT_25ohm (27) +#define PHY_DDR4_LPDDR3_RON_RTT_24ohm (28) +#define PHY_DDR4_LPDDR3_RON_RTT_22ohm (29) +#define PHY_DDR4_LPDDR3_RON_RTT_21ohm (30) +#define PHY_DDR4_LPDDR3_RON_RTT_20ohm (31) + +#endif diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h index 11411ead10..c747b461a1 100644 --- a/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h +++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h @@ -6,6 +6,7 @@
#ifndef _ASM_ARCH_SDRAM_RK3328_H #define _ASM_ARCH_SDRAM_RK3328_H +#include <asm/arch-rockchip/sdram_common.h>
#define SR_IDLE 93 #define PD_IDLE 13 diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h index dc65ae7924..485bb3d889 100644 --- a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h +++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h @@ -5,6 +5,7 @@
#ifndef _ASM_ARCH_SDRAM_RK3399_H #define _ASM_ARCH_SDRAM_RK3399_H +#include <asm/arch-rockchip/sdram_common.h>
struct rk3399_ddr_pctl_regs { u32 denali_ctl[332]; diff --git a/drivers/ram/rockchip/Kconfig b/drivers/ram/rockchip/Kconfig index 4f274e01b3..dcc06b3fd3 100644 --- a/drivers/ram/rockchip/Kconfig +++ b/drivers/ram/rockchip/Kconfig @@ -5,6 +5,12 @@ config RAM_ROCKCHIP help This enables support for ram drivers Rockchip SoCs.
+config ROCKCHIP_SDRAM_COMMON + bool "Enable rockchip sdram common driver" + depends on TPL_RAM || SPL_RAM + help + This enable sdram common driver + if RAM_ROCKCHIP
config RAM_ROCKCHIP_DEBUG diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile index feb1f82d00..3d4f2f4ebf 100644 --- a/drivers/ram/rockchip/Makefile +++ b/drivers/ram/rockchip/Makefile @@ -2,7 +2,7 @@ # # 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 diff --git a/drivers/ram/rockchip/sdram_common.c b/drivers/ram/rockchip/sdram_common.c new file mode 100644 index 0000000000..47c29f6b52 --- /dev/null +++ b/drivers/ram/rockchip/sdram_common.c @@ -0,0 +1,400 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2018 Rockchip Electronics Co., Ltd. + */ + +#include <common.h> +#include <debug_uart.h> +#include <ram.h> +#include <asm/io.h> +#include <asm/arch-rockchip/sdram.h> +#include <asm/arch-rockchip/sdram_common.h> + +void sdram_print_dram_type(unsigned char dramtype) +{ + switch (dramtype) { + case DDR3: + printascii("DDR3"); + break; + case DDR4: + printascii("DDR4"); + break; + case LPDDR2: + printascii("LPDDR2"); + break; + case LPDDR3: + printascii("LPDDR3"); + break; + case LPDDR4: + printascii("LPDDR4"); + break; + default: + printascii("Unknown Device"); + break; + } +} + +void sdram_print_ddr_info(struct sdram_cap_info *cap_info, + struct sdram_base_params *base, u32 split) +{ + u64 cap; + u32 bg; + + bg = (cap_info->dbw == 0) ? 2 : 1; + + sdram_print_dram_type(base->dramtype); + + printascii(", "); + printdec(base->ddr_freq); + printascii("MHz\n"); + + printascii("BW="); + printdec(8 << cap_info->bw); + printascii(" Col="); + printdec(cap_info->col); + printascii(" Bk="); + printdec(0x1 << cap_info->bk); + if (base->dramtype == DDR4) { + printascii(" BG="); + printdec(1 << bg); + } + printascii(" CS0 Row="); + printdec(cap_info->cs0_row); + if (cap_info->cs0_high16bit_row != + cap_info->cs0_row) { + printascii("/"); + printdec(cap_info->cs0_high16bit_row); + } + if (cap_info->rank > 1) { + printascii(" CS1 Row="); + printdec(cap_info->cs1_row); + if (cap_info->cs1_high16bit_row != + cap_info->cs1_row) { + printascii("/"); + printdec(cap_info->cs1_high16bit_row); + } + } + printascii(" CS="); + printdec(cap_info->rank); + printascii(" Die BW="); + printdec(8 << cap_info->dbw); + + cap = sdram_get_cs_cap(cap_info, 3, base->dramtype); + if (cap_info->row_3_4) + cap = cap * 3 / 4; + else if (split) + cap = cap / 2 + (split << 24) / 2; + + printascii(" Size="); + printdec(cap >> 20); + printascii("MB\n"); +} + +/* + * cs: 0:cs0 + * 1:cs1 + * else cs0+cs1 + * note: it didn't consider about row_3_4 + */ +u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type) +{ + u32 bg; + u64 cap[2]; + + if (dram_type == DDR4) + /* DDR4 8bit dram BG = 2(4bank groups), + * 16bit dram BG = 1 (2 bank groups) + */ + bg = (cap_info->dbw == 0) ? 2 : 1; + else + bg = 0; + cap[0] = 1llu << (cap_info->bw + cap_info->col + + bg + cap_info->bk + cap_info->cs0_row); + + if (cap_info->rank == 2) + cap[1] = 1llu << (cap_info->bw + cap_info->col + + bg + cap_info->bk + cap_info->cs1_row); + else + cap[1] = 0; + + if (cs == 0) + return cap[0]; + else if (cs == 1) + return cap[1]; + else + return (cap[0] + cap[1]); +} + +/* n: Unit bytes */ +void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n) +{ + int i; + + for (i = 0; i < n / sizeof(u32); i++) { + writel(*src, dest); + src++; + dest++; + } +} + +void sdram_org_config(struct sdram_cap_info *cap_info, + struct sdram_base_params *base, + u32 *p_os_reg2, u32 *p_os_reg3, u32 channel) +{ + *p_os_reg2 |= SYS_REG_ENC_DDRTYPE(base->dramtype); + *p_os_reg2 |= SYS_REG_ENC_NUM_CH(base->num_channels); + + *p_os_reg2 |= SYS_REG_ENC_ROW_3_4(cap_info->row_3_4, channel); + *p_os_reg2 |= SYS_REG_ENC_CHINFO(channel); + *p_os_reg2 |= SYS_REG_ENC_RANK(cap_info->rank, channel); + *p_os_reg2 |= SYS_REG_ENC_COL(cap_info->col, channel); + *p_os_reg2 |= SYS_REG_ENC_BK(cap_info->bk, channel); + *p_os_reg2 |= SYS_REG_ENC_BW(cap_info->bw, channel); + *p_os_reg2 |= SYS_REG_ENC_DBW(cap_info->dbw, channel); + + SYS_REG_ENC_CS0_ROW(cap_info->cs0_row, *p_os_reg2, *p_os_reg3, channel); + if (cap_info->cs1_row) + SYS_REG_ENC_CS1_ROW(cap_info->cs1_row, *p_os_reg2, + *p_os_reg3, channel); + *p_os_reg3 |= SYS_REG_ENC_CS1_COL(cap_info->col, channel); + *p_os_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION); +} + +int sdram_detect_bw(struct sdram_cap_info *cap_info) +{ + return 0; +} + +int sdram_detect_cs(struct sdram_cap_info *cap_info) +{ + return 0; +} + +int sdram_detect_col(struct sdram_cap_info *cap_info, + u32 coltmp) +{ + void __iomem *test_addr; + u32 col; + u32 bw = cap_info->bw; + + for (col = coltmp; col >= 9; col -= 1) { + writel(0, CONFIG_SYS_SDRAM_BASE); + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE + + (1ul << (col + bw - 1ul))); + writel(PATTERN, test_addr); + if ((readl(test_addr) == PATTERN) && + (readl(CONFIG_SYS_SDRAM_BASE) == 0)) + break; + } + if (col == 8) { + printascii("col error\n"); + return -1; + } + + cap_info->col = col; + + return 0; +} + +int sdram_detect_bank(struct sdram_cap_info *cap_info, + u32 coltmp, u32 bktmp) +{ + void __iomem *test_addr; + u32 bk; + u32 bw = cap_info->bw; + + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE + + (1ul << (coltmp + bktmp + bw - 1ul))); + writel(0, CONFIG_SYS_SDRAM_BASE); + writel(PATTERN, test_addr); + if ((readl(test_addr) == PATTERN) && + (readl(CONFIG_SYS_SDRAM_BASE) == 0)) + bk = 3; + else + bk = 2; + + cap_info->bk = bk; + + return 0; +} + +/* detect bg for ddr4 */ +int sdram_detect_bg(struct sdram_cap_info *cap_info, + u32 coltmp) +{ + void __iomem *test_addr; + u32 dbw; + u32 bw = cap_info->bw; + + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE + + (1ul << (coltmp + bw + 1ul))); + writel(0, CONFIG_SYS_SDRAM_BASE); + writel(PATTERN, test_addr); + if ((readl(test_addr) == PATTERN) && + (readl(CONFIG_SYS_SDRAM_BASE) == 0)) + dbw = 0; + else + dbw = 1; + + cap_info->dbw = dbw; + + return 0; +} + +/* detect dbw for ddr3,lpddr2,lpddr3,lpddr4 */ +int sdram_detect_dbw(struct sdram_cap_info *cap_info, u32 dram_type) +{ + u32 row, col, bk, bw, cs_cap, cs; + u32 die_bw_0 = 0, die_bw_1 = 0; + + if (dram_type == DDR3 || dram_type == LPDDR4) { + cap_info->dbw = 1; + } else if (dram_type == LPDDR3 || dram_type == LPDDR2) { + row = cap_info->cs0_row; + col = cap_info->col; + bk = cap_info->bk; + cs = cap_info->rank; + bw = cap_info->bw; + cs_cap = (1 << (row + col + bk + bw - 20)); + if (bw == 2) { + if (cs_cap <= 0x2000000) /* 256Mb */ + die_bw_0 = (col < 9) ? 2 : 1; + else if (cs_cap <= 0x10000000) /* 2Gb */ + die_bw_0 = (col < 10) ? 2 : 1; + else if (cs_cap <= 0x40000000) /* 8Gb */ + die_bw_0 = (col < 11) ? 2 : 1; + else + die_bw_0 = (col < 12) ? 2 : 1; + if (cs > 1) { + row = cap_info->cs1_row; + cs_cap = (1 << (row + col + bk + bw - 20)); + if (cs_cap <= 0x2000000) /* 256Mb */ + die_bw_0 = (col < 9) ? 2 : 1; + else if (cs_cap <= 0x10000000) /* 2Gb */ + die_bw_0 = (col < 10) ? 2 : 1; + else if (cs_cap <= 0x40000000) /* 8Gb */ + die_bw_0 = (col < 11) ? 2 : 1; + else + die_bw_0 = (col < 12) ? 2 : 1; + } + } else { + die_bw_1 = 1; + die_bw_0 = 1; + } + cap_info->dbw = (die_bw_0 > die_bw_1) ? die_bw_0 : die_bw_1; + } + + return 0; +} + +int sdram_detect_row(struct sdram_cap_info *cap_info, + u32 coltmp, u32 bktmp, u32 rowtmp) +{ + u32 row; + u32 bw = cap_info->bw; + void __iomem *test_addr; + + for (row = rowtmp; row > 12; row--) { + writel(0, CONFIG_SYS_SDRAM_BASE); + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE + + (1ul << (row + bktmp + coltmp + bw - 1ul))); + writel(PATTERN, test_addr); + if ((readl(test_addr) == PATTERN) && + (readl(CONFIG_SYS_SDRAM_BASE) == 0)) + break; + } + if (row == 12) { + printascii("row error"); + return -1; + } + + cap_info->cs0_row = row; + + return 0; +} + +int sdram_detect_row_3_4(struct sdram_cap_info *cap_info, + u32 coltmp, u32 bktmp) +{ + u32 row_3_4; + u32 bw = cap_info->bw; + u32 row = cap_info->cs0_row; + void __iomem *test_addr, *test_addr1; + + test_addr = CONFIG_SYS_SDRAM_BASE; + test_addr1 = (void __iomem *)(CONFIG_SYS_SDRAM_BASE + + (0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul))); + + writel(0, test_addr); + writel(PATTERN, test_addr1); + if ((readl(test_addr) == 0) && (readl(test_addr1) == PATTERN)) + row_3_4 = 0; + else + row_3_4 = 1; + + cap_info->row_3_4 = row_3_4; + + return 0; +} + +int sdram_detect_high_row(struct sdram_cap_info *cap_info) +{ + cap_info->cs0_high16bit_row = cap_info->cs0_row; + cap_info->cs1_high16bit_row = cap_info->cs1_row; + + return 0; +} + +int sdram_detect_cs1_row(struct sdram_cap_info *cap_info, u32 dram_type) +{ + void __iomem *test_addr; + u32 row = 0, bktmp, coltmp, bw; + ulong cs0_cap; + u32 byte_mask; + + if (cap_info->rank == 2) { + cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type); + + if (dram_type == DDR4) { + if (cap_info->dbw == 0) + bktmp = cap_info->bk + 2; + else + bktmp = cap_info->bk + 1; + } else { + bktmp = cap_info->bk; + } + bw = cap_info->bw; + coltmp = cap_info->col; + + /* + * because px30 support axi split,min bandwidth + * is 8bit. if cs0 is 32bit, cs1 may 32bit or 16bit + * so we check low 16bit data when detect cs1 row. + * if cs0 is 16bit/8bit, we check low 8bit data. + */ + if (bw == 2) + byte_mask = 0xFFFF; + else + byte_mask = 0xFF; + + /* detect cs1 row */ + for (row = cap_info->cs0_row; row > 12; row--) { + test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE + + cs0_cap + + (1ul << (row + bktmp + coltmp + bw - 1ul))); + writel(0, CONFIG_SYS_SDRAM_BASE + cs0_cap); + writel(PATTERN, test_addr); + + if (((readl(test_addr) & byte_mask) == + (PATTERN & byte_mask)) && + ((readl(CONFIG_SYS_SDRAM_BASE + cs0_cap) & + byte_mask) == 0)) { + break; + } + } + } + + cap_info->cs1_row = row; + + return 0; +} diff --git a/drivers/ram/rockchip/sdram_debug.c b/drivers/ram/rockchip/sdram_debug.c deleted file mode 100644 index 133d1938d5..0000000000 --- a/drivers/ram/rockchip/sdram_debug.c +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * (C) Copyright 2019 Rockchip Electronics Co., Ltd - * (C) Copyright 2019 Amarula Solutions. - * Author: Jagan Teki jagan@amarulasolutions.com - */ - -#include <common.h> -#include <debug_uart.h> -#include <asm/arch-rockchip/sdram.h> - -void sdram_print_dram_type(unsigned char dramtype) -{ - switch (dramtype) { - case DDR3: - printascii("DDR3"); - break; - case DDR4: - printascii("DDR4"); - break; - case LPDDR2: - printascii("LPDDR2"); - break; - case LPDDR3: - printascii("LPDDR3"); - break; - case LPDDR4: - printascii("LPDDR4"); - break; - default: - printascii("Unknown Device"); - break; - } -} - -/** - * cs = 0, cs0 - * cs = 1, cs1 - * cs => 2, cs0+cs1 - * note: it didn't consider about row_3_4 - */ -u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type) -{ - u32 bg; - u64 cap[2]; - - if (dram_type == DDR4) - /* DDR4 8bit dram BG = 2(4bank groups), - * 16bit dram BG = 1 (2 bank groups) - */ - bg = (cap_info->dbw == 0) ? 2 : 1; - else - bg = 0; - - cap[0] = 1llu << (cap_info->bw + cap_info->col + - bg + cap_info->bk + cap_info->cs0_row); - - if (cap_info->rank == 2) - cap[1] = 1llu << (cap_info->bw + cap_info->col + - bg + cap_info->bk + cap_info->cs1_row); - else - cap[1] = 0; - - if (cs == 0) - return cap[0]; - else if (cs == 1) - return cap[1]; - else - return (cap[0] + cap[1]); -} - -void sdram_print_ddr_info(struct sdram_cap_info *cap_info, - struct sdram_base_params *base) -{ - u32 bg, cap; - - bg = (cap_info->dbw == 0) ? 2 : 1; - - sdram_print_dram_type(base->dramtype); - - printascii(", "); - printdec(base->ddr_freq); - printascii("MHz\n"); - - printascii("BW="); - printdec(8 << cap_info->bw); - - printascii(" Col="); - printdec(cap_info->col); - - printascii(" Bk="); - printdec(0x1 << cap_info->bk); - if (base->dramtype == DDR4) { - printascii(" BG="); - printdec(1 << bg); - } - - printascii(" CS0 Row="); - printdec(cap_info->cs0_row); - if (cap_info->rank > 1) { - printascii(" CS1 Row="); - printdec(cap_info->cs1_row); - } - - printascii(" CS="); - printdec(cap_info->rank); - - printascii(" Die BW="); - printdec(8 << cap_info->dbw); - - cap = sdram_get_cs_cap(cap_info, 3, base->dramtype); - if (cap_info->row_3_4) - cap = cap * 3 / 4; - - printascii(" Size="); - printdec(cap >> 20); - printascii("MB\n"); -} - -void sdram_print_stride(unsigned int stride) -{ - switch (stride) { - case 0xc: - printf("128B stride\n"); - break; - case 5: - case 9: - case 0xd: - case 0x11: - case 0x19: - printf("256B stride\n"); - break; - case 0xa: - case 0xe: - case 0x12: - printf("512B stride\n"); - break; - case 0xf: - printf("4K stride\n"); - break; - case 0x1f: - printf("32MB + 256B stride\n"); - break; - default: - printf("no stride\n"); - } -} diff --git a/drivers/ram/rockchip/sdram_pctl_px30.c b/drivers/ram/rockchip/sdram_pctl_px30.c new file mode 100644 index 0000000000..1839cebb67 --- /dev/null +++ b/drivers/ram/rockchip/sdram_pctl_px30.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2018 Rockchip Electronics Co., Ltd. + */ + +#include <common.h> +#include <ram.h> +#include <asm/io.h> +#include <asm/arch-rockchip/sdram.h> +#include <asm/arch-rockchip/sdram_pctl_px30.h> + +/* + * rank = 1: cs0 + * rank = 2: cs1 + */ +void pctl_read_mr(void __iomem *pctl_base, u32 rank, u32 mr_num) +{ + writel((rank << 4) | (1 << 0), pctl_base + DDR_PCTL2_MRCTRL0); + writel((mr_num << 8), pctl_base + DDR_PCTL2_MRCTRL1); + setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31); + while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31)) + continue; + while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY) + continue; +} + +/* rank = 1: cs0 + * rank = 2: cs1 + * rank = 3: cs0 & cs1 + * note: be careful of keep mr original val + */ +int pctl_write_mr(void __iomem *pctl_base, u32 rank, u32 mr_num, u32 arg, + u32 dramtype) +{ + while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY) + continue; + if (dramtype == DDR3 || dramtype == DDR4) { + writel((mr_num << 12) | (rank << 4) | (0 << 0), + pctl_base + DDR_PCTL2_MRCTRL0); + writel(arg, pctl_base + DDR_PCTL2_MRCTRL1); + } else { + writel((rank << 4) | (0 << 0), + pctl_base + DDR_PCTL2_MRCTRL0); + writel((mr_num << 8) | (arg & 0xff), + pctl_base + DDR_PCTL2_MRCTRL1); + } + + setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31); + while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31)) + continue; + while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY) + continue; + + return 0; +} + +/* + * rank : 1:cs0, 2:cs1, 3:cs0&cs1 + * vrefrate: 4500: 45%, + */ +int pctl_write_vrefdq(void __iomem *pctl_base, u32 rank, u32 vrefrate, + u32 dramtype) +{ + u32 tccd_l, value; + u32 dis_auto_zq = 0; + + if (dramtype != DDR4 || vrefrate < 4500 || + vrefrate > 9200) + return (-1); + + tccd_l = (readl(pctl_base + DDR_PCTL2_DRAMTMG4) >> 16) & 0xf; + tccd_l = (tccd_l - 4) << 10; + + if (vrefrate > 7500) { + /* range 1 */ + value = ((vrefrate - 6000) / 65) | tccd_l; + } else { + /* range 2 */ + value = ((vrefrate - 4500) / 65) | tccd_l | (1 << 6); + } + + dis_auto_zq = pctl_dis_zqcs_aref(pctl_base); + + /* enable vrefdq calibratin */ + pctl_write_mr(pctl_base, rank, 6, value | (1 << 7), dramtype); + udelay(1);/* tvrefdqe */ + /* write vrefdq value */ + pctl_write_mr(pctl_base, rank, 6, value | (1 << 7), dramtype); + udelay(1);/* tvref_time */ + pctl_write_mr(pctl_base, rank, 6, value | (0 << 7), dramtype); + udelay(1);/* tvrefdqx */ + + pctl_rest_zqcs_aref(pctl_base, dis_auto_zq); + + return 0; +} + +static int upctl2_update_ref_reg(void __iomem *pctl_base) +{ + u32 ret; + + ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1); + writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3); + + return 0; +} + +u32 pctl_dis_zqcs_aref(void __iomem *pctl_base) +{ + u32 dis_auto_zq = 0; + + /* disable zqcs */ + if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) & + (1ul << 31))) { + dis_auto_zq = 1; + setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31); + } + + /* disable auto refresh */ + setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1); + + upctl2_update_ref_reg(pctl_base); + + return dis_auto_zq; +} + +void pctl_rest_zqcs_aref(void __iomem *pctl_base, u32 dis_auto_zq) +{ + /* restore zqcs */ + if (dis_auto_zq) + clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31); + + /* restore auto refresh */ + clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1); + + upctl2_update_ref_reg(pctl_base); +} + +u32 pctl_remodify_sdram_params(struct ddr_pctl_regs *pctl_regs, + struct sdram_cap_info *cap_info, + u32 dram_type) +{ + u32 tmp = 0, tmp_adr = 0, i; + + for (i = 0; pctl_regs->pctl[i][0] != 0xFFFFFFFF; i++) { + if (pctl_regs->pctl[i][0] == 0) { + tmp = pctl_regs->pctl[i][1];/* MSTR */ + tmp_adr = i; + } + } + + tmp &= ~((3ul << 30) | (3ul << 24) | (3ul << 12)); + + switch (cap_info->dbw) { + case 2: + tmp |= (3ul << 30); + break; + case 1: + tmp |= (2ul << 30); + break; + case 0: + default: + tmp |= (1ul << 30); + break; + } + + /* + * If DDR3 or DDR4 MSTR.active_ranks=1, + * it will gate memory clock when enter power down. + * Force set active_ranks to 3 to workaround it. + */ + if (cap_info->rank == 2 || dram_type == DDR3 || + dram_type == DDR4) + tmp |= 3 << 24; + else + tmp |= 1 << 24; + + tmp |= (2 - cap_info->bw) << 12; + + pctl_regs->pctl[tmp_adr][1] = tmp; + + return 0; +} + +int pctl_cfg(void __iomem *pctl_base, struct ddr_pctl_regs *pctl_regs, + u32 sr_idle, u32 pd_idle) +{ + u32 i; + + for (i = 0; pctl_regs->pctl[i][0] != 0xFFFFFFFF; i++) { + writel(pctl_regs->pctl[i][1], + pctl_base + pctl_regs->pctl[i][0]); + } + clrsetbits_le32(pctl_base + DDR_PCTL2_PWRTMG, + (0xff << 16) | 0x1f, + ((sr_idle & 0xff) << 16) | (pd_idle & 0x1f)); + + clrsetbits_le32(pctl_base + DDR_PCTL2_HWLPCTL, + 0xfff << 16, + 5 << 16); + /* disable zqcs */ + setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1u << 31); + + return 0; +} diff --git a/drivers/ram/rockchip/sdram_phy_px30.c b/drivers/ram/rockchip/sdram_phy_px30.c new file mode 100644 index 0000000000..5de73770a8 --- /dev/null +++ b/drivers/ram/rockchip/sdram_phy_px30.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2018 Rockchip Electronics Co., Ltd. + */ + +#include <common.h> +#include <ram.h> +#include <asm/io.h> +#include <asm/arch-rockchip/sdram.h> +#include <asm/arch-rockchip/sdram_common.h> +#include <asm/arch-rockchip/sdram_phy_px30.h> + +static void sdram_phy_dll_bypass_set(void __iomem *phy_base, u32 freq) +{ + u32 tmp; + u32 i, j; + u32 dqs_dll_freq; + + setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4); + clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3); + for (i = 0; i < 4; i++) { + j = 0x26 + i * 0x10; + setbits_le32(PHY_REG(phy_base, j), 1 << 4); + clrbits_le32(PHY_REG(phy_base, j + 0x1), 1 << 3); + } + + if (freq <= 400) + /* DLL bypass */ + setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f); + else + clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f); + + #ifdef CONFIG_ROCKCHIP_RK3328 + dqs_dll_freq = 680; + #else + dqs_dll_freq = 801; + #endif + + if (freq <= dqs_dll_freq) + tmp = 2; + else + tmp = 1; + + for (i = 0; i < 4; i++) { + j = 0x28 + i * 0x10; + writel(tmp, PHY_REG(phy_base, j)); + } +} + +static void sdram_phy_set_ds_odt(void __iomem *phy_base, + u32 dram_type) +{ + u32 cmd_drv, clk_drv, dqs_drv, dqs_odt; + u32 i, j; + + if (dram_type == DDR3) { + cmd_drv = PHY_DDR3_RON_RTT_34ohm; + clk_drv = PHY_DDR3_RON_RTT_45ohm; + dqs_drv = PHY_DDR3_RON_RTT_34ohm; + dqs_odt = PHY_DDR3_RON_RTT_225ohm; + } else { + cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm; + clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm; + dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm; + if (dram_type == LPDDR2) + dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_DISABLE; + else + dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm; + } + /* DS */ + writel(cmd_drv, PHY_REG(phy_base, 0x11)); + clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3); + writel(clk_drv, PHY_REG(phy_base, 0x16)); + writel(clk_drv, PHY_REG(phy_base, 0x18)); + + for (i = 0; i < 4; i++) { + j = 0x20 + i * 0x10; + writel(dqs_drv, PHY_REG(phy_base, j)); + writel(dqs_drv, PHY_REG(phy_base, j + 0xf)); + /* ODT */ + writel(dqs_odt, PHY_REG(phy_base, j + 0x1)); + writel(dqs_odt, PHY_REG(phy_base, j + 0xe)); + } +} + +void phy_soft_reset(void __iomem *phy_base) +{ + clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2); + udelay(1); + setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET); + udelay(5); + setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET); + udelay(1); +} + +void phy_dram_set_bw(void __iomem *phy_base, u32 bw) +{ + if (bw == 2) { + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4); + setbits_le32(PHY_REG(phy_base, 0x46), 1 << 3); + setbits_le32(PHY_REG(phy_base, 0x56), 1 << 3); + } else if (bw == 1) { + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4); + clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3); + clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3); + } else if (bw == 0) { + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4); + clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3); + clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3); + clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3); + } + + phy_soft_reset(phy_base); +} + +int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype) +{ + u32 ret; + u32 odt_val; + u32 i, j; + + odt_val = readl(PHY_REG(phy_base, 0x2e)); + + for (i = 0; i < 4; i++) { + j = 0x20 + i * 0x10; + writel(PHY_DDR3_RON_RTT_225ohm, PHY_REG(phy_base, j + 0x1)); + writel(0, PHY_REG(phy_base, j + 0xe)); + } + + if (dramtype == DDR4) { + clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0); + clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0); + clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0); + clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0); + } + /* choose training cs */ + clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs)); + /* enable gate training */ + clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1); + udelay(50); + ret = readl(PHY_REG(phy_base, 0xff)); + /* disable gate training */ + clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0); + #ifndef CONFIG_ROCKCHIP_RK3328 + clrbits_le32(PHY_REG(phy_base, 2), 0x30); + #endif + + if (dramtype == DDR4) { + clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2); + clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2); + clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2); + clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2); + } + + if (ret & 0x10) { + ret = -1; + } else { + ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4); + ret = (ret == 0) ? 0 : -1; + } + + for (i = 0; i < 4; i++) { + j = 0x20 + i * 0x10; + writel(odt_val, PHY_REG(phy_base, j + 0x1)); + writel(odt_val, PHY_REG(phy_base, j + 0xe)); + } + return ret; +} + +void phy_cfg(void __iomem *phy_base, + struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew, + struct sdram_base_params *base, u32 bw) +{ + u32 i; + + sdram_phy_dll_bypass_set(phy_base, base->ddr_freq); + for (i = 0; phy_regs->phy[i][0] != 0xFFFFFFFF; i++) { + writel(phy_regs->phy[i][1], + phy_base + phy_regs->phy[i][0]); + } + if (bw == 2) { + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4); + } else if (bw == 1) { + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4); + /* disable DQS2,DQS3 tx dll for saving power */ + clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3); + clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3); + } else { + clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4); + /* disable DQS2,DQS3 tx dll for saving power */ + clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3); + clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3); + clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3); + } + sdram_phy_set_ds_odt(phy_base, base->dramtype); + + /* deskew */ + setbits_le32(PHY_REG(phy_base, 2), 8); + sdram_copy_to_reg(PHY_REG(phy_base, 0xb0), + &skew->a0_a1_skew[0], 15 * 4); + sdram_copy_to_reg(PHY_REG(phy_base, 0x70), + &skew->cs0_dm0_skew[0], 44 * 4); + sdram_copy_to_reg(PHY_REG(phy_base, 0xc0), + &skew->cs1_dm0_skew[0], 44 * 4); +} diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c index 9b7de4ae41..b5a0bac99b 100644 --- a/drivers/ram/rockchip/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c @@ -2473,8 +2473,6 @@ static unsigned char calculate_stride(struct rk3399_sdram_params *params) } }
- sdram_print_stride(stride); - return stride; }
@@ -2591,7 +2589,6 @@ static int sdram_init(struct dram_info *dram, } }
- sdram_print_ddr_info(cap_info, ¶ms->base); set_memory_map(chan, channel, params); cap_info->ddrconfig = calculate_ddrconfig(params, channel);
@@ -2601,7 +2598,6 @@ static int sdram_init(struct dram_info *dram,
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; }