1f520bb22SYouMin Chen // SPDX-License-Identifier: GPL-2.0 2f520bb22SYouMin Chen /* 3f520bb22SYouMin Chen * (C) Copyright 2020 Rockchip Electronics Co., Ltd. 4f520bb22SYouMin Chen */ 5f520bb22SYouMin Chen 6f520bb22SYouMin Chen #include <common.h> 7f520bb22SYouMin Chen #include <debug_uart.h> 8f520bb22SYouMin Chen #include <dm.h> 9f520bb22SYouMin Chen #include <ram.h> 10f520bb22SYouMin Chen #include <syscon.h> 11f520bb22SYouMin Chen #include <asm/io.h> 12f520bb22SYouMin Chen #include <asm/arch/clock.h> 13f520bb22SYouMin Chen #include <asm/arch/hardware.h> 14f520bb22SYouMin Chen #include <asm/arch/rk_atags.h> 15f520bb22SYouMin Chen #include <asm/arch/cru_rv1126.h> 16f520bb22SYouMin Chen #include <asm/arch/grf_rv1126.h> 17f520bb22SYouMin Chen #include <asm/arch/sdram_common.h> 18f520bb22SYouMin Chen #include <asm/arch/sdram_rv1126.h> 19f520bb22SYouMin Chen 20f520bb22SYouMin Chen /* define training flag */ 21f520bb22SYouMin Chen #define CA_TRAINING (0x1 << 0) 22f520bb22SYouMin Chen #define READ_GATE_TRAINING (0x1 << 1) 23f520bb22SYouMin Chen #define WRITE_LEVELING (0x1 << 2) 24f520bb22SYouMin Chen #define WRITE_TRAINING (0x1 << 3) 25f520bb22SYouMin Chen #define READ_TRAINING (0x1 << 4) 26f520bb22SYouMin Chen #define FULL_TRAINING (0xff) 27f520bb22SYouMin Chen 28f520bb22SYouMin Chen #define SKEW_RX_SIGNAL (0) 29f520bb22SYouMin Chen #define SKEW_TX_SIGNAL (1) 30f520bb22SYouMin Chen #define SKEW_CA_SIGNAL (2) 31f520bb22SYouMin Chen 32f520bb22SYouMin Chen #define DESKEW_MDF_ABS_VAL (0) 33f520bb22SYouMin Chen #define DESKEW_MDF_DIFF_VAL (1) 34f520bb22SYouMin Chen 35f520bb22SYouMin Chen #ifdef CONFIG_TPL_BUILD 36f520bb22SYouMin Chen #ifndef CONFIG_TPL_TINY_FRAMEWORK 37f520bb22SYouMin Chen #error please defined CONFIG_TPL_TINY_FRAMEWORK for RV1126 !!! 38f520bb22SYouMin Chen #endif 39f520bb22SYouMin Chen #endif 40f520bb22SYouMin Chen 41f520bb22SYouMin Chen #ifdef CONFIG_TPL_BUILD 42f520bb22SYouMin Chen 43f520bb22SYouMin Chen struct dram_info { 44f520bb22SYouMin Chen void __iomem *pctl; 45f520bb22SYouMin Chen void __iomem *phy; 46f520bb22SYouMin Chen struct rv1126_cru *cru; 47f520bb22SYouMin Chen struct msch_regs *msch; 48f520bb22SYouMin Chen struct rv1126_ddrgrf *ddrgrf; 49f520bb22SYouMin Chen struct rv1126_grf *grf; 50f520bb22SYouMin Chen struct ram_info info; 51f520bb22SYouMin Chen struct rv1126_pmugrf *pmugrf; 52f520bb22SYouMin Chen u32 sr_idle; 53f520bb22SYouMin Chen u32 pd_idle; 54f520bb22SYouMin Chen }; 55f520bb22SYouMin Chen 56f520bb22SYouMin Chen #define GRF_BASE_ADDR 0xfe000000 57f520bb22SYouMin Chen #define PMU_GRF_BASE_ADDR 0xfe020000 58f520bb22SYouMin Chen #define DDR_GRF_BASE_ADDR 0xfe030000 59f520bb22SYouMin Chen #define BUS_SGRF_BASE_ADDR 0xfe0a0000 60f520bb22SYouMin Chen #define SERVER_MSCH_BASE_ADDR 0xfe800000 61f520bb22SYouMin Chen #define CRU_BASE_ADDR 0xff490000 62f520bb22SYouMin Chen #define DDR_PHY_BASE_ADDR 0xff4a0000 63f520bb22SYouMin Chen #define UPCTL2_BASE_ADDR 0xffa50000 64f520bb22SYouMin Chen 65f520bb22SYouMin Chen #define SGRF_SOC_CON12 0x30 66f520bb22SYouMin Chen #define SGRF_SOC_CON13 0x34 67f520bb22SYouMin Chen 68f520bb22SYouMin Chen struct dram_info dram_info; 69f520bb22SYouMin Chen 70970fa5d8STang Yun ping #if (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 3) 71f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = { 72112c8ab5SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-328.inc" 73f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-396.inc" 74f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-528.inc" 75f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-664.inc" 76f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-784.inc" 77f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-924.inc" 7805431850SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-1056.inc" 79f520bb22SYouMin Chen }; 80970fa5d8STang Yun ping #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 0) 81f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = { 82112c8ab5SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-328.inc" 83f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-396.inc" 84f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-528.inc" 85f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-664.inc" 86f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-784.inc" 87f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-924.inc" 88f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-1056.inc" 89f520bb22SYouMin Chen }; 90970fa5d8STang Yun ping #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 6) 91f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = { 92112c8ab5SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-328.inc" 93f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-396.inc" 94f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-528.inc" 95f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-664.inc" 96f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-784.inc" 97f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-924.inc" 9805431850SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-1056.inc" 99f520bb22SYouMin Chen }; 100970fa5d8STang Yun ping #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 7) 101f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = { 102112c8ab5SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-328.inc" 103f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-396.inc" 104f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-528.inc" 105f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-664.inc" 106f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-784.inc" 107f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-924.inc" 108f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-1056.inc" 109f520bb22SYouMin Chen }; 110f520bb22SYouMin Chen #endif 111f520bb22SYouMin Chen 112f520bb22SYouMin Chen u32 common_info[] = { 113f520bb22SYouMin Chen #include "sdram_inc/rv1126/sdram-rv1126-loader_params.inc" 114f520bb22SYouMin Chen }; 115f520bb22SYouMin Chen 116c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL) 117c71eeac4SWesley Yao static struct rw_trn_result rw_trn_result; 118c71eeac4SWesley Yao #endif 119c71eeac4SWesley Yao 120f520bb22SYouMin Chen static struct rv1126_fsp_param fsp_param[MAX_IDX]; 121f520bb22SYouMin Chen 122f520bb22SYouMin Chen static u8 lp3_odt_value; 123f520bb22SYouMin Chen 124d5bb9a92STang Yun ping static s8 wrlvl_result[2][4]; 125f520bb22SYouMin Chen 126f520bb22SYouMin Chen /* DDR configuration 0-9 */ 127f520bb22SYouMin Chen u16 ddr_cfg_2_rbc[] = { 128f520bb22SYouMin Chen ((0 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 3), /* 0 */ 129f520bb22SYouMin Chen ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 2), /* 1 */ 130f520bb22SYouMin Chen ((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 3), /* 2 */ 131f520bb22SYouMin Chen ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 1), /* 3 */ 132f520bb22SYouMin Chen ((0 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 4), /* 4 */ 133f520bb22SYouMin Chen ((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 1), /* 5 */ 134f520bb22SYouMin Chen ((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 2), /* 6 */ 135f520bb22SYouMin Chen ((0 << 8) | (2 << 5) | (1 << 4) | (1 << 3) | 3), /* 7 */ 136f520bb22SYouMin Chen ((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 2), /* 8 */ 137f520bb22SYouMin Chen ((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 2) /* 9 */ 138f520bb22SYouMin Chen }; 139f520bb22SYouMin Chen 140f520bb22SYouMin Chen /* DDR configuration 10-21 */ 141f520bb22SYouMin Chen u8 ddr4_cfg_2_rbc[] = { 142f520bb22SYouMin Chen ((0 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 0), /* 10 */ 143f520bb22SYouMin Chen ((1 << 7) | (2 << 4) | (0 << 3) | (2 << 1) | 0), /* 11 */ 144f520bb22SYouMin Chen ((0 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 0), /* 12 */ 145f520bb22SYouMin Chen ((1 << 7) | (3 << 4) | (0 << 3) | (1 << 1) | 0), /* 13 */ 146f520bb22SYouMin Chen ((0 << 7) | (4 << 4) | (0 << 3) | (2 << 1) | 1), /* 14 */ 147f520bb22SYouMin Chen ((1 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 1), /* 15 */ 148f520bb22SYouMin Chen ((1 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 1), /* 16 */ 149f520bb22SYouMin Chen ((0 << 7) | (2 << 4) | (1 << 3) | (2 << 1) | 0), /* 17 */ 150f520bb22SYouMin Chen ((0 << 7) | (3 << 4) | (1 << 3) | (1 << 1) | 0), /* 18 */ 151f520bb22SYouMin Chen ((0 << 7) | (3 << 4) | (1 << 3) | (2 << 1) | 1), /* 19 */ 152f520bb22SYouMin Chen ((0 << 7) | (4 << 4) | (1 << 3) | (1 << 1) | 1), /* 20 */ 153f520bb22SYouMin Chen ((1 << 7) | (4 << 4) | (0 << 3) | (0 << 1) | 0) /* 21 */ 154f520bb22SYouMin Chen }; 155f520bb22SYouMin Chen 156f520bb22SYouMin Chen /* DDR configuration 22-28 */ 157f520bb22SYouMin Chen u16 ddr_cfg_2_rbc_p2[] = { 158f520bb22SYouMin Chen ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 0), /* 22 */ 159f520bb22SYouMin Chen ((0 << 8) | (4 << 5) | (0 << 4) | (1 << 3) | 2), /* 23 */ 160f520bb22SYouMin Chen ((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 3), /* 24 */ 161f520bb22SYouMin Chen ((0 << 8) | (3 << 5) | (1 << 4) | (0 << 3) | 3), /* 25 */ 162f520bb22SYouMin Chen ((0 << 8) | (4 << 5) | (1 << 4) | (0 << 3) | 2), /* 26 */ 163f520bb22SYouMin Chen ((1 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 2), /* 27 */ 164f520bb22SYouMin Chen ((0 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 3) /* 28 */ 165f520bb22SYouMin Chen }; 166f520bb22SYouMin Chen 167f520bb22SYouMin Chen u8 d4_rbc_2_d3_rbc[][2] = { 168f520bb22SYouMin Chen {10, 0}, 169f520bb22SYouMin Chen {11, 2}, 170f520bb22SYouMin Chen {12, 23}, 171f520bb22SYouMin Chen {13, 1}, 172f520bb22SYouMin Chen {14, 28}, 173f520bb22SYouMin Chen {15, 24}, 174f520bb22SYouMin Chen {16, 27}, 175f520bb22SYouMin Chen {17, 7}, 176f520bb22SYouMin Chen {18, 6}, 177f520bb22SYouMin Chen {19, 25}, 178f520bb22SYouMin Chen {20, 26}, 179f520bb22SYouMin Chen {21, 3} 180f520bb22SYouMin Chen }; 181f520bb22SYouMin Chen 182f520bb22SYouMin Chen u32 addrmap[23][9] = { 183f520bb22SYouMin Chen {24, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808, 184f520bb22SYouMin Chen 0x08080808, 0x00000f0f, 0x3f3f}, /* 0 */ 185f520bb22SYouMin Chen {23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707, 186f520bb22SYouMin Chen 0x07070707, 0x00000f0f, 0x3f3f}, /* 1 */ 187f520bb22SYouMin Chen {23, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808, 188f520bb22SYouMin Chen 0x0f080808, 0x00000f0f, 0x3f3f}, /* 2 */ 189f520bb22SYouMin Chen {22, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606, 190f520bb22SYouMin Chen 0x06060606, 0x00000f0f, 0x3f3f}, /* 3 */ 191f520bb22SYouMin Chen {24, 0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909, 192f520bb22SYouMin Chen 0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */ 193f520bb22SYouMin Chen {6, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x07070707, 194f520bb22SYouMin Chen 0x07070707, 0x00000f0f, 0x3f3f}, /* 5 */ 195f520bb22SYouMin Chen {7, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x08080808, 196f520bb22SYouMin Chen 0x08080808, 0x00000f0f, 0x3f3f}, /* 6 */ 197f520bb22SYouMin Chen {8, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x09090909, 198f520bb22SYouMin Chen 0x0f090909, 0x00000f0f, 0x3f3f}, /* 7 */ 199f520bb22SYouMin Chen {22, 0x001f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606, 200f520bb22SYouMin Chen 0x06060606, 0x00000f0f, 0x3f3f}, /* 8 */ 201f520bb22SYouMin Chen {23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707, 202f520bb22SYouMin Chen 0x0f070707, 0x00000f0f, 0x3f3f}, /* 9 */ 203f520bb22SYouMin Chen 204f520bb22SYouMin Chen {24, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808, 205f520bb22SYouMin Chen 0x08080808, 0x00000f0f, 0x0801}, /* 10 */ 206f520bb22SYouMin Chen {23, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808, 207f520bb22SYouMin Chen 0x0f080808, 0x00000f0f, 0x0801}, /* 11 */ 208f520bb22SYouMin Chen {24, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707, 209f520bb22SYouMin Chen 0x07070707, 0x00000f07, 0x0700}, /* 12 */ 210f520bb22SYouMin Chen {23, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707, 211f520bb22SYouMin Chen 0x07070707, 0x00000f0f, 0x0700}, /* 13 */ 212f520bb22SYouMin Chen {24, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707, 213f520bb22SYouMin Chen 0x07070707, 0x00000f07, 0x3f01}, /* 14 */ 214f520bb22SYouMin Chen {23, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707, 215f520bb22SYouMin Chen 0x07070707, 0x00000f0f, 0x3f01}, /* 15 */ 216f520bb22SYouMin Chen {23, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606, 217f520bb22SYouMin Chen 0x06060606, 0x00000f06, 0x3f00}, /* 16 */ 218f520bb22SYouMin Chen {8, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x09090909, 219f520bb22SYouMin Chen 0x0f090909, 0x00000f0f, 0x0801}, /* 17 */ 220f520bb22SYouMin Chen {7, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x08080808, 221f520bb22SYouMin Chen 0x08080808, 0x00000f0f, 0x0700}, /* 18 */ 222f520bb22SYouMin Chen {7, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808, 223f520bb22SYouMin Chen 0x08080808, 0x00000f0f, 0x3f01}, /* 19 */ 224f520bb22SYouMin Chen 225f520bb22SYouMin Chen {6, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707, 226f520bb22SYouMin Chen 0x07070707, 0x00000f07, 0x3f00}, /* 20 */ 227f520bb22SYouMin Chen {23, 0x003f0909, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606, 228f520bb22SYouMin Chen 0x06060606, 0x00000f06, 0x0600}, /* 21 */ 229f520bb22SYouMin Chen {21, 0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505, 230f520bb22SYouMin Chen 0x05050505, 0x00000f0f, 0x3f3f} /* 22 */ 231f520bb22SYouMin Chen }; 232f520bb22SYouMin Chen 233f520bb22SYouMin Chen static u8 dq_sel[22][3] = { 234f520bb22SYouMin Chen {0x0, 0x17, 0x22}, 235f520bb22SYouMin Chen {0x1, 0x18, 0x23}, 236f520bb22SYouMin Chen {0x2, 0x19, 0x24}, 237f520bb22SYouMin Chen {0x3, 0x1a, 0x25}, 238f520bb22SYouMin Chen {0x4, 0x1b, 0x26}, 239f520bb22SYouMin Chen {0x5, 0x1c, 0x27}, 240f520bb22SYouMin Chen {0x6, 0x1d, 0x28}, 241f520bb22SYouMin Chen {0x7, 0x1e, 0x29}, 242f520bb22SYouMin Chen {0x8, 0x16, 0x21}, 243f520bb22SYouMin Chen {0x9, 0x1f, 0x2a}, 244f520bb22SYouMin Chen {0xa, 0x20, 0x2b}, 245f520bb22SYouMin Chen {0x10, 0x1, 0xc}, 246f520bb22SYouMin Chen {0x11, 0x2, 0xd}, 247f520bb22SYouMin Chen {0x12, 0x3, 0xe}, 248f520bb22SYouMin Chen {0x13, 0x4, 0xf}, 249f520bb22SYouMin Chen {0x14, 0x5, 0x10}, 250f520bb22SYouMin Chen {0x15, 0x6, 0x11}, 251f520bb22SYouMin Chen {0x16, 0x7, 0x12}, 252f520bb22SYouMin Chen {0x17, 0x8, 0x13}, 253f520bb22SYouMin Chen {0x18, 0x0, 0xb}, 254f520bb22SYouMin Chen {0x19, 0x9, 0x14}, 255f520bb22SYouMin Chen {0x1a, 0xa, 0x15} 256f520bb22SYouMin Chen }; 257f520bb22SYouMin Chen 258f520bb22SYouMin Chen static u16 grp_addr[4] = { 259f520bb22SYouMin Chen ADD_GROUP_CS0_A, 260f520bb22SYouMin Chen ADD_GROUP_CS0_B, 261f520bb22SYouMin Chen ADD_GROUP_CS1_A, 262f520bb22SYouMin Chen ADD_GROUP_CS1_B 263f520bb22SYouMin Chen }; 264f520bb22SYouMin Chen 265f520bb22SYouMin Chen static u8 wrlvl_result_offset[2][4] = { 266f520bb22SYouMin Chen {0xa0 + 0x26, 0xa0 + 0x27, 0xd0 + 0x26, 0xd0 + 0x27}, 267f520bb22SYouMin Chen {0xa0 + 0x28, 0xa0 + 0x29, 0xd0 + 0x28, 0xd0 + 0x29}, 268f520bb22SYouMin Chen }; 269f520bb22SYouMin Chen 270f520bb22SYouMin Chen static u16 dqs_dq_skew_adr[16] = { 271f520bb22SYouMin Chen 0x170 + 0, /* SKEW_UPDATE_RX_CS0_DQS0 */ 272f520bb22SYouMin Chen 0x170 + 0xb, /* SKEW_UPDATE_RX_CS0_DQS1 */ 273f520bb22SYouMin Chen 0x1d0 + 0, /* SKEW_UPDATE_RX_CS0_DQS2 */ 274f520bb22SYouMin Chen 0x1d0 + 0xb, /* SKEW_UPDATE_RX_CS0_DQS3 */ 275f520bb22SYouMin Chen 0x1a0 + 0, /* SKEW_UPDATE_RX_CS1_DQS0 */ 276f520bb22SYouMin Chen 0x1a0 + 0xb, /* SKEW_UPDATE_RX_CS1_DQS1 */ 277f520bb22SYouMin Chen 0x200 + 0, /* SKEW_UPDATE_RX_CS1_DQS2 */ 278f520bb22SYouMin Chen 0x200 + 0xb, /* SKEW_UPDATE_RX_CS1_DQS3 */ 279f520bb22SYouMin Chen 0x170 + 0x16, /* SKEW_UPDATE_TX_CS0_DQS0 */ 280f520bb22SYouMin Chen 0x170 + 0x21, /* SKEW_UPDATE_TX_CS0_DQS1 */ 281f520bb22SYouMin Chen 0x1d0 + 0x16, /* SKEW_UPDATE_TX_CS0_DQS2 */ 282f520bb22SYouMin Chen 0x1d0 + 0x21, /* SKEW_UPDATE_TX_CS0_DQS3 */ 283f520bb22SYouMin Chen 0x1a0 + 0x16, /* SKEW_UPDATE_TX_CS1_DQS0 */ 284f520bb22SYouMin Chen 0x1a0 + 0x21, /* SKEW_UPDATE_TX_CS1_DQS1 */ 285f520bb22SYouMin Chen 0x200 + 0x16, /* SKEW_UPDATE_TX_CS1_DQS2 */ 286f520bb22SYouMin Chen 0x200 + 0x21, /* SKEW_UPDATE_TX_CS1_DQS3 */ 287f520bb22SYouMin Chen }; 288f520bb22SYouMin Chen 289f520bb22SYouMin Chen static void rkclk_ddr_reset(struct dram_info *dram, 290f520bb22SYouMin Chen u32 ctl_srstn, u32 ctl_psrstn, 291f520bb22SYouMin Chen u32 phy_srstn, u32 phy_psrstn) 292f520bb22SYouMin Chen { 293f520bb22SYouMin Chen writel(UPCTL2_SRSTN_REQ(ctl_srstn) | UPCTL2_PSRSTN_REQ(ctl_psrstn) | 294f520bb22SYouMin Chen UPCTL2_ASRSTN_REQ(ctl_srstn), 295f520bb22SYouMin Chen BUS_SGRF_BASE_ADDR + SGRF_SOC_CON13); 296f520bb22SYouMin Chen 297f520bb22SYouMin Chen writel(DDRPHY_SRSTN_REQ(phy_srstn) | DDRPHY_PSRSTN_REQ(phy_psrstn), 298f520bb22SYouMin Chen &dram->cru->softrst_con[12]); 299f520bb22SYouMin Chen } 300f520bb22SYouMin Chen 301f520bb22SYouMin Chen static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz) 302f520bb22SYouMin Chen { 303f520bb22SYouMin Chen unsigned int refdiv, postdiv1, postdiv2, fbdiv; 304f520bb22SYouMin Chen int delay = 1000; 305f520bb22SYouMin Chen u32 mhz = hz / MHz; 306*0367dfefSZhihuan He struct global_info *gbl_info; 307*0367dfefSZhihuan He struct sdram_head_info_index_v2 *index = 308*0367dfefSZhihuan He (struct sdram_head_info_index_v2 *)common_info; 309*0367dfefSZhihuan He u32 ssmod_info; 310*0367dfefSZhihuan He u32 dsmpd = 1; 311f520bb22SYouMin Chen 312*0367dfefSZhihuan He gbl_info = (struct global_info *)((void *)common_info + 313*0367dfefSZhihuan He index->global_index.offset * 4); 314*0367dfefSZhihuan He ssmod_info = gbl_info->info_2t; 315f520bb22SYouMin Chen refdiv = 1; 316f520bb22SYouMin Chen if (mhz <= 100) { 317f520bb22SYouMin Chen postdiv1 = 6; 318f520bb22SYouMin Chen postdiv2 = 4; 319f520bb22SYouMin Chen } else if (mhz <= 150) { 320f520bb22SYouMin Chen postdiv1 = 4; 321f520bb22SYouMin Chen postdiv2 = 4; 322f520bb22SYouMin Chen } else if (mhz <= 200) { 323f520bb22SYouMin Chen postdiv1 = 6; 324f520bb22SYouMin Chen postdiv2 = 2; 325f520bb22SYouMin Chen } else if (mhz <= 300) { 326f520bb22SYouMin Chen postdiv1 = 4; 327f520bb22SYouMin Chen postdiv2 = 2; 328f520bb22SYouMin Chen } else if (mhz <= 400) { 329f520bb22SYouMin Chen postdiv1 = 6; 330f520bb22SYouMin Chen postdiv2 = 1; 331f520bb22SYouMin Chen } else { 332f520bb22SYouMin Chen postdiv1 = 4; 333f520bb22SYouMin Chen postdiv2 = 1; 334f520bb22SYouMin Chen } 335f520bb22SYouMin Chen fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24; 336f520bb22SYouMin Chen 337f520bb22SYouMin Chen writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode); 338f520bb22SYouMin Chen 339f520bb22SYouMin Chen writel(0x1f000000, &dram->cru->clksel_con[64]); 340f520bb22SYouMin Chen writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0); 341*0367dfefSZhihuan He /* enable ssmod */ 342*0367dfefSZhihuan He if (PLL_SSMOD_SPREAD(ssmod_info)) { 343*0367dfefSZhihuan He dsmpd = 0; 344*0367dfefSZhihuan He clrsetbits_le32(&dram->cru->pll[1].con2, 345*0367dfefSZhihuan He 0xffffff << 0, 0x0 << 0); 346*0367dfefSZhihuan He writel(SSMOD_SPREAD(PLL_SSMOD_SPREAD(ssmod_info)) | 347*0367dfefSZhihuan He SSMOD_DIVVAL(PLL_SSMOD_DIV(ssmod_info)) | 348*0367dfefSZhihuan He SSMOD_DOWNSPREAD(PLL_SSMOD_DOWNSPREAD(ssmod_info)) | 349*0367dfefSZhihuan He SSMOD_RESET(0) | 350*0367dfefSZhihuan He SSMOD_DIS_SSCG(0) | 351*0367dfefSZhihuan He SSMOD_BP(0), 352*0367dfefSZhihuan He &dram->cru->pll[1].con3); 353*0367dfefSZhihuan He } 354*0367dfefSZhihuan He writel(DSMPD(dsmpd) | POSTDIV2(postdiv2) | REFDIV(refdiv), 355f520bb22SYouMin Chen &dram->cru->pll[1].con1); 356f520bb22SYouMin Chen 357f520bb22SYouMin Chen while (delay > 0) { 358f520bb22SYouMin Chen udelay(1); 359f520bb22SYouMin Chen if (LOCK(readl(&dram->cru->pll[1].con1))) 360f520bb22SYouMin Chen break; 361f520bb22SYouMin Chen delay--; 362f520bb22SYouMin Chen } 363f520bb22SYouMin Chen 364f520bb22SYouMin Chen writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode); 365f520bb22SYouMin Chen } 366f520bb22SYouMin Chen 367f520bb22SYouMin Chen static void rkclk_configure_ddr(struct dram_info *dram, 368f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 369f520bb22SYouMin Chen { 370f520bb22SYouMin Chen /* for inno ddr phy need freq / 2 */ 371f520bb22SYouMin Chen rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHZ / 2); 372f520bb22SYouMin Chen } 373f520bb22SYouMin Chen 374f520bb22SYouMin Chen static unsigned int 375f520bb22SYouMin Chen calculate_ddrconfig(struct rv1126_sdram_params *sdram_params) 376f520bb22SYouMin Chen { 377f520bb22SYouMin Chen struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info; 378f520bb22SYouMin Chen u32 cs, bw, die_bw, col, row, bank; 379f520bb22SYouMin Chen u32 cs1_row; 380f520bb22SYouMin Chen u32 i, tmp; 381f520bb22SYouMin Chen u32 ddrconf = -1; 382f520bb22SYouMin Chen u32 row_3_4; 383f520bb22SYouMin Chen 384f520bb22SYouMin Chen cs = cap_info->rank; 385f520bb22SYouMin Chen bw = cap_info->bw; 386f520bb22SYouMin Chen die_bw = cap_info->dbw; 387f520bb22SYouMin Chen col = cap_info->col; 388f520bb22SYouMin Chen row = cap_info->cs0_row; 389f520bb22SYouMin Chen cs1_row = cap_info->cs1_row; 390f520bb22SYouMin Chen bank = cap_info->bk; 391f520bb22SYouMin Chen row_3_4 = cap_info->row_3_4; 392f520bb22SYouMin Chen 393f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR4) { 394f520bb22SYouMin Chen if (cs == 2 && row == cs1_row && !row_3_4) { 395f520bb22SYouMin Chen tmp = ((row - 13) << 4) | (1 << 3) | (bw << 1) | 396f520bb22SYouMin Chen die_bw; 397f520bb22SYouMin Chen for (i = 17; i < 21; i++) { 398f520bb22SYouMin Chen if (((tmp & 0xf) == 399f520bb22SYouMin Chen (ddr4_cfg_2_rbc[i - 10] & 0xf)) && 400f520bb22SYouMin Chen ((tmp & 0x70) <= 401f520bb22SYouMin Chen (ddr4_cfg_2_rbc[i - 10] & 0x70))) { 402f520bb22SYouMin Chen ddrconf = i; 403f520bb22SYouMin Chen goto out; 404f520bb22SYouMin Chen } 405f520bb22SYouMin Chen } 406f520bb22SYouMin Chen } 407f520bb22SYouMin Chen 408f520bb22SYouMin Chen tmp = ((cs - 1) << 7) | ((row - 13) << 4) | (bw << 1) | die_bw; 409f520bb22SYouMin Chen for (i = 10; i < 21; i++) { 410f520bb22SYouMin Chen if (((tmp & 0xf) == (ddr4_cfg_2_rbc[i - 10] & 0xf)) && 411f520bb22SYouMin Chen ((tmp & 0x70) <= (ddr4_cfg_2_rbc[i - 10] & 0x70)) && 412f520bb22SYouMin Chen ((tmp & 0x80) <= (ddr4_cfg_2_rbc[i - 10] & 0x80))) { 413f520bb22SYouMin Chen ddrconf = i; 414f520bb22SYouMin Chen goto out; 415f520bb22SYouMin Chen } 416f520bb22SYouMin Chen } 417f520bb22SYouMin Chen } else { 418f520bb22SYouMin Chen if (cs == 2 && row == cs1_row && bank == 3) { 419f520bb22SYouMin Chen for (i = 5; i < 8; i++) { 420f520bb22SYouMin Chen if (((bw + col - 10) == (ddr_cfg_2_rbc[i] & 421f520bb22SYouMin Chen 0x7)) && 422f520bb22SYouMin Chen ((row - 13) << 5) <= (ddr_cfg_2_rbc[i] & 423f520bb22SYouMin Chen (0x7 << 5))) { 424f520bb22SYouMin Chen ddrconf = i; 425f520bb22SYouMin Chen goto out; 426f520bb22SYouMin Chen } 427f520bb22SYouMin Chen } 428f520bb22SYouMin Chen } 429f520bb22SYouMin Chen 430f520bb22SYouMin Chen tmp = ((cs - 1) << 8) | ((row - 13) << 5) | 431f520bb22SYouMin Chen ((bw + col - 10) << 0); 432f520bb22SYouMin Chen if (bank == 3) 433f520bb22SYouMin Chen tmp |= (1 << 3); 434f520bb22SYouMin Chen 435f520bb22SYouMin Chen for (i = 0; i < 9; i++) 436f520bb22SYouMin Chen if (((tmp & 0x1f) == (ddr_cfg_2_rbc[i] & 0x1f)) && 437f520bb22SYouMin Chen ((tmp & (7 << 5)) <= 438f520bb22SYouMin Chen (ddr_cfg_2_rbc[i] & (7 << 5))) && 439f520bb22SYouMin Chen ((tmp & (1 << 8)) <= 440f520bb22SYouMin Chen (ddr_cfg_2_rbc[i] & (1 << 8)))) { 441f520bb22SYouMin Chen ddrconf = i; 442f520bb22SYouMin Chen goto out; 443f520bb22SYouMin Chen } 4449d5c314bSWesley Yao 4459d5c314bSWesley Yao for (i = 0; i < 7; i++) 4469d5c314bSWesley Yao if (((tmp & 0x1f) == (ddr_cfg_2_rbc_p2[i] & 0x1f)) && 4479d5c314bSWesley Yao ((tmp & (7 << 5)) <= 4489d5c314bSWesley Yao (ddr_cfg_2_rbc_p2[i] & (7 << 5))) && 4499d5c314bSWesley Yao ((tmp & (1 << 8)) <= 4509d5c314bSWesley Yao (ddr_cfg_2_rbc_p2[i] & (1 << 8)))) { 4519d5c314bSWesley Yao ddrconf = i + 22; 4529d5c314bSWesley Yao goto out; 4539d5c314bSWesley Yao } 4549d5c314bSWesley Yao 455f520bb22SYouMin Chen if (cs == 1 && bank == 3 && row <= 17 && 456f520bb22SYouMin Chen (col + bw) == 12) 457f520bb22SYouMin Chen ddrconf = 23; 458f520bb22SYouMin Chen } 459f520bb22SYouMin Chen 460f520bb22SYouMin Chen out: 461f520bb22SYouMin Chen if (ddrconf > 28) 462f520bb22SYouMin Chen printascii("calculate ddrconfig error\n"); 463f520bb22SYouMin Chen 464f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR4) { 465f520bb22SYouMin Chen for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) { 466f520bb22SYouMin Chen if (ddrconf == d4_rbc_2_d3_rbc[i][0]) { 467f520bb22SYouMin Chen if (ddrconf == 21 && row > 16) 468f520bb22SYouMin Chen printascii("warn:ddrconf21 row > 16\n"); 469f520bb22SYouMin Chen else 470f520bb22SYouMin Chen ddrconf = d4_rbc_2_d3_rbc[i][1]; 471f520bb22SYouMin Chen break; 472f520bb22SYouMin Chen } 473f520bb22SYouMin Chen } 474f520bb22SYouMin Chen } 475f520bb22SYouMin Chen 476f520bb22SYouMin Chen return ddrconf; 477f520bb22SYouMin Chen } 478f520bb22SYouMin Chen 479f520bb22SYouMin Chen static void sw_set_req(struct dram_info *dram) 480f520bb22SYouMin Chen { 481f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 482f520bb22SYouMin Chen 483f520bb22SYouMin Chen /* clear sw_done=0 */ 484f520bb22SYouMin Chen writel(PCTL2_SW_DONE_CLEAR, pctl_base + DDR_PCTL2_SWCTL); 485f520bb22SYouMin Chen } 486f520bb22SYouMin Chen 487f520bb22SYouMin Chen static void sw_set_ack(struct dram_info *dram) 488f520bb22SYouMin Chen { 489f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 490f520bb22SYouMin Chen 491f520bb22SYouMin Chen /* set sw_done=1 */ 492f520bb22SYouMin Chen writel(PCTL2_SW_DONE, pctl_base + DDR_PCTL2_SWCTL); 493f520bb22SYouMin Chen while (1) { 494f520bb22SYouMin Chen /* wait programming done */ 495f520bb22SYouMin Chen if (readl(pctl_base + DDR_PCTL2_SWSTAT) & 496f520bb22SYouMin Chen PCTL2_SW_DONE_ACK) 497f520bb22SYouMin Chen break; 498f520bb22SYouMin Chen } 499f520bb22SYouMin Chen } 500f520bb22SYouMin Chen 501f520bb22SYouMin Chen static void set_ctl_address_map(struct dram_info *dram, 502f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 503f520bb22SYouMin Chen { 504f520bb22SYouMin Chen struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info; 505f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 506f520bb22SYouMin Chen u32 ddrconf = cap_info->ddrconfig; 507f520bb22SYouMin Chen u32 i, row; 508f520bb22SYouMin Chen 509f520bb22SYouMin Chen row = cap_info->cs0_row; 510f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR4) { 511f520bb22SYouMin Chen for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) { 512f520bb22SYouMin Chen if (ddrconf == d4_rbc_2_d3_rbc[i][1]) { 513f520bb22SYouMin Chen ddrconf = d4_rbc_2_d3_rbc[i][0]; 514f520bb22SYouMin Chen break; 515f520bb22SYouMin Chen } 516f520bb22SYouMin Chen } 517f520bb22SYouMin Chen } 518f520bb22SYouMin Chen 519f520bb22SYouMin Chen if (ddrconf > ARRAY_SIZE(addrmap)) { 520f520bb22SYouMin Chen printascii("set ctl address map fail\n"); 521f520bb22SYouMin Chen return; 522f520bb22SYouMin Chen } 523f520bb22SYouMin Chen 524f520bb22SYouMin Chen sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0), 525f520bb22SYouMin Chen &addrmap[ddrconf][0], 9 * 4); 526f520bb22SYouMin Chen 527f520bb22SYouMin Chen /* unused row set to 0xf */ 528f520bb22SYouMin Chen for (i = 17; i >= row; i--) 529f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 + 530f520bb22SYouMin Chen ((i - 12) * 8 / 32) * 4, 531f520bb22SYouMin Chen 0xf << ((i - 12) * 8 % 32)); 532f520bb22SYouMin Chen 533f520bb22SYouMin Chen if (sdram_params->base.dramtype == LPDDR3 && cap_info->row_3_4) 534f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31); 535f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR4 && cap_info->bw == 0x1) 536f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8); 537f520bb22SYouMin Chen 538f520bb22SYouMin Chen if (cap_info->rank == 1) 539f520bb22SYouMin Chen clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f); 540f520bb22SYouMin Chen } 541f520bb22SYouMin Chen 542f520bb22SYouMin Chen static void phy_pll_set(struct dram_info *dram, u32 freq, u32 wait) 543f520bb22SYouMin Chen { 544f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 545f520bb22SYouMin Chen u32 fbdiv, prediv, postdiv, postdiv_en; 546f520bb22SYouMin Chen 547f520bb22SYouMin Chen if (wait) { 548f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x53), PHY_PD_DISB); 549f520bb22SYouMin Chen while (!(readl(PHY_REG(phy_base, 0x90)) & PHY_PLL_LOCK)) 550f520bb22SYouMin Chen continue; 551f520bb22SYouMin Chen } else { 552f520bb22SYouMin Chen freq /= MHz; 553f520bb22SYouMin Chen prediv = 1; 554f520bb22SYouMin Chen if (freq <= 200) { 555f520bb22SYouMin Chen fbdiv = 16; 556f520bb22SYouMin Chen postdiv = 2; 557f520bb22SYouMin Chen postdiv_en = 1; 558f520bb22SYouMin Chen } else if (freq <= 456) { 559f520bb22SYouMin Chen fbdiv = 8; 560f520bb22SYouMin Chen postdiv = 1; 561f520bb22SYouMin Chen postdiv_en = 1; 562f520bb22SYouMin Chen } else { 563f520bb22SYouMin Chen fbdiv = 4; 564f520bb22SYouMin Chen postdiv = 0; 565f520bb22SYouMin Chen postdiv_en = 0; 566f520bb22SYouMin Chen } 567f520bb22SYouMin Chen writel(fbdiv & 0xff, PHY_REG(phy_base, 0x50)); 568f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_PBDIV_BIT9_MASK, 569f520bb22SYouMin Chen (fbdiv >> 8) & 1); 570f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_POSTDIV_EN_MASK, 571f520bb22SYouMin Chen postdiv_en << PHY_POSTDIV_EN_SHIFT); 572f520bb22SYouMin Chen 573f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x52), 574f520bb22SYouMin Chen PHY_PREDIV_MASK << PHY_PREDIV_SHIFT, prediv); 575f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x53), 576f520bb22SYouMin Chen PHY_POSTDIV_MASK << PHY_POSTDIV_SHIFT, 577f520bb22SYouMin Chen postdiv << PHY_POSTDIV_SHIFT); 578f520bb22SYouMin Chen } 579f520bb22SYouMin Chen } 580f520bb22SYouMin Chen 581f520bb22SYouMin Chen static const u16 d3_phy_drv_2_ohm[][2] = { 58270fee8b3STang Yun ping {PHY_DDR3_RON_455ohm, 455}, 58370fee8b3STang Yun ping {PHY_DDR3_RON_230ohm, 230}, 58470fee8b3STang Yun ping {PHY_DDR3_RON_153ohm, 153}, 58570fee8b3STang Yun ping {PHY_DDR3_RON_115ohm, 115}, 58670fee8b3STang Yun ping {PHY_DDR3_RON_91ohm, 91}, 58770fee8b3STang Yun ping {PHY_DDR3_RON_76ohm, 76}, 58870fee8b3STang Yun ping {PHY_DDR3_RON_65ohm, 65}, 58970fee8b3STang Yun ping {PHY_DDR3_RON_57ohm, 57}, 590f520bb22SYouMin Chen {PHY_DDR3_RON_51ohm, 51}, 591f520bb22SYouMin Chen {PHY_DDR3_RON_46ohm, 46}, 59270fee8b3STang Yun ping {PHY_DDR3_RON_41ohm, 41}, 59370fee8b3STang Yun ping {PHY_DDR3_RON_38ohm, 38}, 59470fee8b3STang Yun ping {PHY_DDR3_RON_35ohm, 35}, 595f520bb22SYouMin Chen {PHY_DDR3_RON_32ohm, 32}, 596f520bb22SYouMin Chen {PHY_DDR3_RON_30ohm, 30}, 597f520bb22SYouMin Chen {PHY_DDR3_RON_28ohm, 28}, 598f520bb22SYouMin Chen {PHY_DDR3_RON_27ohm, 27}, 599f520bb22SYouMin Chen {PHY_DDR3_RON_25ohm, 25}, 600f520bb22SYouMin Chen {PHY_DDR3_RON_24ohm, 24}, 601f520bb22SYouMin Chen {PHY_DDR3_RON_23ohm, 23}, 60270fee8b3STang Yun ping {PHY_DDR3_RON_22ohm, 22}, 60370fee8b3STang Yun ping {PHY_DDR3_RON_21ohm, 21}, 60470fee8b3STang Yun ping {PHY_DDR3_RON_20ohm, 20} 605f520bb22SYouMin Chen }; 606f520bb22SYouMin Chen 607f520bb22SYouMin Chen static u16 d3_phy_odt_2_ohm[][2] = { 608f520bb22SYouMin Chen {PHY_DDR3_RTT_DISABLE, 0}, 60970fee8b3STang Yun ping {PHY_DDR3_RTT_561ohm, 561}, 61070fee8b3STang Yun ping {PHY_DDR3_RTT_282ohm, 282}, 61170fee8b3STang Yun ping {PHY_DDR3_RTT_188ohm, 188}, 61270fee8b3STang Yun ping {PHY_DDR3_RTT_141ohm, 141}, 61370fee8b3STang Yun ping {PHY_DDR3_RTT_113ohm, 113}, 61470fee8b3STang Yun ping {PHY_DDR3_RTT_94ohm, 94}, 61570fee8b3STang Yun ping {PHY_DDR3_RTT_81ohm, 81}, 61670fee8b3STang Yun ping {PHY_DDR3_RTT_72ohm, 72}, 617f520bb22SYouMin Chen {PHY_DDR3_RTT_64ohm, 64}, 61870fee8b3STang Yun ping {PHY_DDR3_RTT_58ohm, 58}, 61970fee8b3STang Yun ping {PHY_DDR3_RTT_52ohm, 52}, 620f520bb22SYouMin Chen {PHY_DDR3_RTT_48ohm, 48}, 621f520bb22SYouMin Chen {PHY_DDR3_RTT_44ohm, 44}, 62270fee8b3STang Yun ping {PHY_DDR3_RTT_41ohm, 41}, 62370fee8b3STang Yun ping {PHY_DDR3_RTT_38ohm, 38}, 62470fee8b3STang Yun ping {PHY_DDR3_RTT_37ohm, 37}, 62570fee8b3STang Yun ping {PHY_DDR3_RTT_34ohm, 34}, 62670fee8b3STang Yun ping {PHY_DDR3_RTT_32ohm, 32}, 62770fee8b3STang Yun ping {PHY_DDR3_RTT_31ohm, 31}, 62870fee8b3STang Yun ping {PHY_DDR3_RTT_29ohm, 29}, 62970fee8b3STang Yun ping {PHY_DDR3_RTT_28ohm, 28}, 63070fee8b3STang Yun ping {PHY_DDR3_RTT_27ohm, 27}, 63170fee8b3STang Yun ping {PHY_DDR3_RTT_25ohm, 25} 632f520bb22SYouMin Chen }; 633f520bb22SYouMin Chen 634f520bb22SYouMin Chen static u16 d4lp3_phy_drv_2_ohm[][2] = { 63570fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_482ohm, 482}, 63670fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_244ohm, 244}, 63770fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_162ohm, 162}, 63870fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_122ohm, 122}, 63970fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_97ohm, 97}, 640f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RON_81ohm, 81}, 64170fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_69ohm, 69}, 64270fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_61ohm, 61}, 64370fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_54ohm, 54}, 64470fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_48ohm, 48}, 645f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RON_44ohm, 44}, 64670fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_40ohm, 40}, 64770fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_37ohm, 37}, 648f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RON_34ohm, 34}, 649f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RON_32ohm, 32}, 650f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RON_30ohm, 30}, 651f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RON_28ohm, 28}, 652f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RON_27ohm, 27}, 65370fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_25ohm, 25}, 65470fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_24ohm, 24}, 65570fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_23ohm, 23}, 65670fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_22ohm, 22}, 65770fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RON_21ohm, 21} 658f520bb22SYouMin Chen }; 659f520bb22SYouMin Chen 660f520bb22SYouMin Chen static u16 d4lp3_phy_odt_2_ohm[][2] = { 661f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RTT_DISABLE, 0}, 66270fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_586ohm, 586}, 66370fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_294ohm, 294}, 66470fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_196ohm, 196}, 66570fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_148ohm, 148}, 66670fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_118ohm, 118}, 667f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RTT_99ohm, 99}, 66870fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_85ohm, 58}, 669f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RTT_76ohm, 76}, 67070fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_67ohm, 67}, 67170fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_60ohm, 60}, 672f520bb22SYouMin Chen {PHY_DDR4_LPDDR3_RTT_55ohm, 55}, 67370fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_50ohm, 50}, 67470fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_46ohm, 46}, 67570fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_43ohm, 43}, 67670fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_40ohm, 40}, 67770fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_38ohm, 38}, 67870fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_36ohm, 36}, 67970fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_34ohm, 34}, 68070fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_32ohm, 32}, 68170fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_31ohm, 31}, 68270fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_29ohm, 29}, 68370fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_28ohm, 28}, 68470fee8b3STang Yun ping {PHY_DDR4_LPDDR3_RTT_27ohm, 27} 685f520bb22SYouMin Chen }; 686f520bb22SYouMin Chen 687f520bb22SYouMin Chen static u16 lp4_phy_drv_2_ohm[][2] = { 68870fee8b3STang Yun ping {PHY_LPDDR4_RON_501ohm, 501}, 68970fee8b3STang Yun ping {PHY_LPDDR4_RON_253ohm, 253}, 69070fee8b3STang Yun ping {PHY_LPDDR4_RON_168ohm, 168}, 69170fee8b3STang Yun ping {PHY_LPDDR4_RON_126ohm, 126}, 692f520bb22SYouMin Chen {PHY_LPDDR4_RON_101ohm, 101}, 69370fee8b3STang Yun ping {PHY_LPDDR4_RON_84ohm, 84}, 69470fee8b3STang Yun ping {PHY_LPDDR4_RON_72ohm, 72}, 69570fee8b3STang Yun ping {PHY_LPDDR4_RON_63ohm, 63}, 69670fee8b3STang Yun ping {PHY_LPDDR4_RON_56ohm, 56}, 69770fee8b3STang Yun ping {PHY_LPDDR4_RON_50ohm, 50}, 69870fee8b3STang Yun ping {PHY_LPDDR4_RON_46ohm, 46}, 69970fee8b3STang Yun ping {PHY_LPDDR4_RON_42ohm, 42}, 700f520bb22SYouMin Chen {PHY_LPDDR4_RON_38ohm, 38}, 701f520bb22SYouMin Chen {PHY_LPDDR4_RON_36ohm, 36}, 70270fee8b3STang Yun ping {PHY_LPDDR4_RON_33ohm, 33}, 70370fee8b3STang Yun ping {PHY_LPDDR4_RON_31ohm, 31}, 704f520bb22SYouMin Chen {PHY_LPDDR4_RON_29ohm, 29}, 705f520bb22SYouMin Chen {PHY_LPDDR4_RON_28ohm, 28}, 70670fee8b3STang Yun ping {PHY_LPDDR4_RON_26ohm, 26}, 70770fee8b3STang Yun ping {PHY_LPDDR4_RON_25ohm, 25}, 70870fee8b3STang Yun ping {PHY_LPDDR4_RON_24ohm, 24}, 70970fee8b3STang Yun ping {PHY_LPDDR4_RON_23ohm, 23}, 71070fee8b3STang Yun ping {PHY_LPDDR4_RON_22ohm, 22} 711f520bb22SYouMin Chen }; 712f520bb22SYouMin Chen 713f520bb22SYouMin Chen static u16 lp4_phy_odt_2_ohm[][2] = { 714f520bb22SYouMin Chen {PHY_LPDDR4_RTT_DISABLE, 0}, 71570fee8b3STang Yun ping {PHY_LPDDR4_RTT_604ohm, 604}, 71670fee8b3STang Yun ping {PHY_LPDDR4_RTT_303ohm, 303}, 717f520bb22SYouMin Chen {PHY_LPDDR4_RTT_202ohm, 202}, 71870fee8b3STang Yun ping {PHY_LPDDR4_RTT_152ohm, 152}, 71970fee8b3STang Yun ping {PHY_LPDDR4_RTT_122ohm, 122}, 720f520bb22SYouMin Chen {PHY_LPDDR4_RTT_101ohm, 101}, 72170fee8b3STang Yun ping {PHY_LPDDR4_RTT_87ohm, 87}, 722f520bb22SYouMin Chen {PHY_LPDDR4_RTT_78ohm, 78}, 72370fee8b3STang Yun ping {PHY_LPDDR4_RTT_69ohm, 69}, 72470fee8b3STang Yun ping {PHY_LPDDR4_RTT_62ohm, 62}, 725f520bb22SYouMin Chen {PHY_LPDDR4_RTT_56ohm, 56}, 72670fee8b3STang Yun ping {PHY_LPDDR4_RTT_52ohm, 52}, 727f520bb22SYouMin Chen {PHY_LPDDR4_RTT_48ohm, 48}, 72870fee8b3STang Yun ping {PHY_LPDDR4_RTT_44ohm, 44}, 72970fee8b3STang Yun ping {PHY_LPDDR4_RTT_41ohm, 41}, 73070fee8b3STang Yun ping {PHY_LPDDR4_RTT_39ohm, 39}, 73170fee8b3STang Yun ping {PHY_LPDDR4_RTT_37ohm, 37}, 73270fee8b3STang Yun ping {PHY_LPDDR4_RTT_35ohm, 35}, 73370fee8b3STang Yun ping {PHY_LPDDR4_RTT_33ohm, 33}, 73470fee8b3STang Yun ping {PHY_LPDDR4_RTT_32ohm, 32}, 73570fee8b3STang Yun ping {PHY_LPDDR4_RTT_30ohm, 30}, 73670fee8b3STang Yun ping {PHY_LPDDR4_RTT_29ohm, 29}, 73770fee8b3STang Yun ping {PHY_LPDDR4_RTT_27ohm, 27} 738f520bb22SYouMin Chen }; 739f520bb22SYouMin Chen 740f520bb22SYouMin Chen static u32 lp4_odt_calc(u32 odt_ohm) 741f520bb22SYouMin Chen { 742f520bb22SYouMin Chen u32 odt; 743f520bb22SYouMin Chen 744f520bb22SYouMin Chen if (odt_ohm == 0) 745f520bb22SYouMin Chen odt = LPDDR4_DQODT_DIS; 746f520bb22SYouMin Chen else if (odt_ohm <= 40) 747f520bb22SYouMin Chen odt = LPDDR4_DQODT_40; 748f520bb22SYouMin Chen else if (odt_ohm <= 48) 749f520bb22SYouMin Chen odt = LPDDR4_DQODT_48; 750f520bb22SYouMin Chen else if (odt_ohm <= 60) 751f520bb22SYouMin Chen odt = LPDDR4_DQODT_60; 752f520bb22SYouMin Chen else if (odt_ohm <= 80) 753f520bb22SYouMin Chen odt = LPDDR4_DQODT_80; 754f520bb22SYouMin Chen else if (odt_ohm <= 120) 755f520bb22SYouMin Chen odt = LPDDR4_DQODT_120; 756f520bb22SYouMin Chen else 757f520bb22SYouMin Chen odt = LPDDR4_DQODT_240; 758f520bb22SYouMin Chen 759f520bb22SYouMin Chen return odt; 760f520bb22SYouMin Chen } 761f520bb22SYouMin Chen 762f520bb22SYouMin Chen static void *get_ddr_drv_odt_info(u32 dramtype) 763f520bb22SYouMin Chen { 764f520bb22SYouMin Chen struct sdram_head_info_index_v2 *index = 765f520bb22SYouMin Chen (struct sdram_head_info_index_v2 *)common_info; 766f520bb22SYouMin Chen void *ddr_info = 0; 767f520bb22SYouMin Chen 768f520bb22SYouMin Chen if (dramtype == DDR4) 769f520bb22SYouMin Chen ddr_info = (void *)common_info + index->ddr4_index.offset * 4; 770f520bb22SYouMin Chen else if (dramtype == DDR3) 771f520bb22SYouMin Chen ddr_info = (void *)common_info + index->ddr3_index.offset * 4; 772f520bb22SYouMin Chen else if (dramtype == LPDDR3) 773f520bb22SYouMin Chen ddr_info = (void *)common_info + index->lp3_index.offset * 4; 774f520bb22SYouMin Chen else if (dramtype == LPDDR4) 775f520bb22SYouMin Chen ddr_info = (void *)common_info + index->lp4_index.offset * 4; 776f520bb22SYouMin Chen else 777f520bb22SYouMin Chen printascii("unsupported dram type\n"); 778f520bb22SYouMin Chen return ddr_info; 779f520bb22SYouMin Chen } 780f520bb22SYouMin Chen 781f520bb22SYouMin Chen static void set_lp4_vref(struct dram_info *dram, struct lp4_info *lp4_info, 782f520bb22SYouMin Chen u32 freq_mhz, u32 dst_fsp) 783f520bb22SYouMin Chen { 784f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 785f520bb22SYouMin Chen u32 ca_vref, dq_vref; 786f520bb22SYouMin Chen 787f520bb22SYouMin Chen if (freq_mhz <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq)) 788f520bb22SYouMin Chen ca_vref = LP4_CA_VREF(lp4_info->vref_when_odtoff); 789f520bb22SYouMin Chen else 790f520bb22SYouMin Chen ca_vref = LP4_CA_VREF(lp4_info->vref_when_odten); 791f520bb22SYouMin Chen 792f520bb22SYouMin Chen if (freq_mhz <= LP4_DQ_ODT_EN_FREQ(lp4_info->dq_odten_freq)) 793f520bb22SYouMin Chen dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odtoff); 794f520bb22SYouMin Chen else 795f520bb22SYouMin Chen dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odten); 796f520bb22SYouMin Chen 797f520bb22SYouMin Chen if (ca_vref < 100) 798f520bb22SYouMin Chen ca_vref = 100; 799f520bb22SYouMin Chen if (ca_vref > 420) 800f520bb22SYouMin Chen ca_vref = 420; 801f520bb22SYouMin Chen 802f520bb22SYouMin Chen if (ca_vref <= 300) 803f520bb22SYouMin Chen ca_vref = (0 << 6) | (ca_vref - 100) / 4; 804f520bb22SYouMin Chen else 805f520bb22SYouMin Chen ca_vref = (1 << 6) | (ca_vref - 220) / 4; 806f520bb22SYouMin Chen 807f520bb22SYouMin Chen if (dq_vref < 100) 808f520bb22SYouMin Chen dq_vref = 100; 809f520bb22SYouMin Chen if (dq_vref > 420) 810f520bb22SYouMin Chen dq_vref = 420; 811f520bb22SYouMin Chen 812f520bb22SYouMin Chen if (dq_vref <= 300) 813f520bb22SYouMin Chen dq_vref = (0 << 6) | (dq_vref - 100) / 4; 814f520bb22SYouMin Chen else 815f520bb22SYouMin Chen dq_vref = (1 << 6) | (dq_vref - 220) / 4; 816f520bb22SYouMin Chen 817f520bb22SYouMin Chen sw_set_req(dram); 818f520bb22SYouMin Chen clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 819f520bb22SYouMin Chen DDR_PCTL2_INIT6, 820f520bb22SYouMin Chen PCTL2_MR_MASK << PCTL2_LPDDR4_MR12_SHIFT, 821f520bb22SYouMin Chen ca_vref << PCTL2_LPDDR4_MR12_SHIFT); 822f520bb22SYouMin Chen 823f520bb22SYouMin Chen clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 824f520bb22SYouMin Chen DDR_PCTL2_INIT7, 825f520bb22SYouMin Chen PCTL2_MR_MASK << PCTL2_LPDDR4_MR14_SHIFT, 826f520bb22SYouMin Chen dq_vref << PCTL2_LPDDR4_MR14_SHIFT); 827f520bb22SYouMin Chen sw_set_ack(dram); 828f520bb22SYouMin Chen } 829f520bb22SYouMin Chen 830f520bb22SYouMin Chen static void set_ds_odt(struct dram_info *dram, 831f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params, u32 dst_fsp) 832f520bb22SYouMin Chen { 833f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 834f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 835f520bb22SYouMin Chen u32 dramtype = sdram_params->base.dramtype; 836f520bb22SYouMin Chen struct ddr2_3_4_lp2_3_info *ddr_info; 837f520bb22SYouMin Chen struct lp4_info *lp4_info; 838f520bb22SYouMin Chen u32 i, j, tmp; 839f520bb22SYouMin Chen const u16 (*p_drv)[2]; 840f520bb22SYouMin Chen const u16 (*p_odt)[2]; 841f520bb22SYouMin Chen u32 drv_info, sr_info; 842f520bb22SYouMin Chen u32 phy_dq_drv_ohm, phy_clk_drv_ohm, phy_ca_drv_ohm, dram_drv_ohm; 843f520bb22SYouMin Chen u32 phy_odt_ohm, dram_odt_ohm; 844f520bb22SYouMin Chen u32 lp4_pu_cal, phy_lp4_drv_pd_en; 845f520bb22SYouMin Chen u32 phy_odt_up_en, phy_odt_dn_en; 846f520bb22SYouMin Chen u32 sr_dq, sr_clk; 847f520bb22SYouMin Chen u32 freq = sdram_params->base.ddr_freq; 848f520bb22SYouMin Chen u32 mr1_mr3, mr11, mr22, vref_out, vref_inner; 849f520bb22SYouMin Chen u32 phy_clk_drv = 0, phy_odt = 0, phy_ca_drv = 0, dram_caodt_ohm = 0; 850f520bb22SYouMin Chen u32 phy_dq_drv = 0; 851f520bb22SYouMin Chen u32 phy_odt_up = 0, phy_odt_dn = 0; 852f520bb22SYouMin Chen 853f520bb22SYouMin Chen ddr_info = get_ddr_drv_odt_info(dramtype); 854f520bb22SYouMin Chen lp4_info = (void *)ddr_info; 855f520bb22SYouMin Chen 856f520bb22SYouMin Chen if (!ddr_info) 857f520bb22SYouMin Chen return; 858f520bb22SYouMin Chen 859f520bb22SYouMin Chen /* dram odt en freq control phy drv, dram odt and phy sr */ 860f520bb22SYouMin Chen if (freq <= DRAMODT_EN_FREQ(ddr_info->odten_freq)) { 861f520bb22SYouMin Chen drv_info = ddr_info->drv_when_odtoff; 862f520bb22SYouMin Chen dram_odt_ohm = 0; 863f520bb22SYouMin Chen sr_info = ddr_info->sr_when_odtoff; 864f520bb22SYouMin Chen phy_lp4_drv_pd_en = 865f520bb22SYouMin Chen PHY_LP4_DRV_PULLDOWN_EN_ODTOFF(lp4_info->odt_info); 866f520bb22SYouMin Chen } else { 867f520bb22SYouMin Chen drv_info = ddr_info->drv_when_odten; 868f520bb22SYouMin Chen dram_odt_ohm = ODT_INFO_DRAM_ODT(ddr_info->odt_info); 869f520bb22SYouMin Chen sr_info = ddr_info->sr_when_odten; 870f520bb22SYouMin Chen phy_lp4_drv_pd_en = 871f520bb22SYouMin Chen PHY_LP4_DRV_PULLDOWN_EN_ODTEN(lp4_info->odt_info); 872f520bb22SYouMin Chen } 873f520bb22SYouMin Chen phy_dq_drv_ohm = 874f520bb22SYouMin Chen DRV_INFO_PHY_DQ_DRV(drv_info); 875f520bb22SYouMin Chen phy_clk_drv_ohm = 876f520bb22SYouMin Chen DRV_INFO_PHY_CLK_DRV(drv_info); 877f520bb22SYouMin Chen phy_ca_drv_ohm = 878f520bb22SYouMin Chen DRV_INFO_PHY_CA_DRV(drv_info); 879f520bb22SYouMin Chen 880f520bb22SYouMin Chen sr_dq = DQ_SR_INFO(sr_info); 881f520bb22SYouMin Chen sr_clk = CLK_SR_INFO(sr_info); 882f520bb22SYouMin Chen 883f520bb22SYouMin Chen /* phy odt en freq control dram drv and phy odt */ 884f520bb22SYouMin Chen if (freq <= PHYODT_EN_FREQ(ddr_info->odten_freq)) { 885f520bb22SYouMin Chen dram_drv_ohm = DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odtoff); 886f520bb22SYouMin Chen lp4_pu_cal = LP4_DRV_PU_CAL_ODTOFF(lp4_info->odt_info); 887f520bb22SYouMin Chen phy_odt_ohm = 0; 888f520bb22SYouMin Chen phy_odt_up_en = 0; 889f520bb22SYouMin Chen phy_odt_dn_en = 0; 890f520bb22SYouMin Chen } else { 891f520bb22SYouMin Chen dram_drv_ohm = 892f520bb22SYouMin Chen DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odten); 893f520bb22SYouMin Chen phy_odt_ohm = ODT_INFO_PHY_ODT(ddr_info->odt_info); 894f520bb22SYouMin Chen phy_odt_up_en = 895f520bb22SYouMin Chen ODT_INFO_PULLUP_EN(ddr_info->odt_info); 896f520bb22SYouMin Chen phy_odt_dn_en = 897f520bb22SYouMin Chen ODT_INFO_PULLDOWN_EN(ddr_info->odt_info); 898f520bb22SYouMin Chen lp4_pu_cal = LP4_DRV_PU_CAL_ODTEN(lp4_info->odt_info); 899f520bb22SYouMin Chen } 900f520bb22SYouMin Chen 901f520bb22SYouMin Chen if (dramtype == LPDDR4) { 902f520bb22SYouMin Chen if (phy_odt_ohm) { 903f520bb22SYouMin Chen phy_odt_up_en = 0; 904f520bb22SYouMin Chen phy_odt_dn_en = 1; 905f520bb22SYouMin Chen } 906f520bb22SYouMin Chen if (freq <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq)) 907f520bb22SYouMin Chen dram_caodt_ohm = 0; 908f520bb22SYouMin Chen else 909f520bb22SYouMin Chen dram_caodt_ohm = 910f520bb22SYouMin Chen ODT_INFO_LP4_CA_ODT(lp4_info->odt_info); 911f520bb22SYouMin Chen } 912f520bb22SYouMin Chen 913f520bb22SYouMin Chen if (dramtype == DDR3) { 914f520bb22SYouMin Chen p_drv = d3_phy_drv_2_ohm; 915f520bb22SYouMin Chen p_odt = d3_phy_odt_2_ohm; 916f520bb22SYouMin Chen } else if (dramtype == LPDDR4) { 917f520bb22SYouMin Chen p_drv = lp4_phy_drv_2_ohm; 918f520bb22SYouMin Chen p_odt = lp4_phy_odt_2_ohm; 919f520bb22SYouMin Chen } else { 920f520bb22SYouMin Chen p_drv = d4lp3_phy_drv_2_ohm; 921f520bb22SYouMin Chen p_odt = d4lp3_phy_odt_2_ohm; 922f520bb22SYouMin Chen } 923f520bb22SYouMin Chen 924f520bb22SYouMin Chen for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) { 925f520bb22SYouMin Chen if (phy_dq_drv_ohm <= *(*(p_drv + i) + 1)) { 926f520bb22SYouMin Chen phy_dq_drv = **(p_drv + i); 927f520bb22SYouMin Chen break; 928f520bb22SYouMin Chen } 929f520bb22SYouMin Chen if (i == 0) 930f520bb22SYouMin Chen break; 931f520bb22SYouMin Chen } 932f520bb22SYouMin Chen for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) { 933f520bb22SYouMin Chen if (phy_clk_drv_ohm <= *(*(p_drv + i) + 1)) { 934f520bb22SYouMin Chen phy_clk_drv = **(p_drv + i); 935f520bb22SYouMin Chen break; 936f520bb22SYouMin Chen } 937f520bb22SYouMin Chen if (i == 0) 938f520bb22SYouMin Chen break; 939f520bb22SYouMin Chen } 940f520bb22SYouMin Chen for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) { 941f520bb22SYouMin Chen if (phy_ca_drv_ohm <= *(*(p_drv + i) + 1)) { 942f520bb22SYouMin Chen phy_ca_drv = **(p_drv + i); 943f520bb22SYouMin Chen break; 944f520bb22SYouMin Chen } 945f520bb22SYouMin Chen if (i == 0) 946f520bb22SYouMin Chen break; 947f520bb22SYouMin Chen } 948f520bb22SYouMin Chen if (!phy_odt_ohm) 949f520bb22SYouMin Chen phy_odt = 0; 950f520bb22SYouMin Chen else 951f520bb22SYouMin Chen for (i = ARRAY_SIZE(d4lp3_phy_odt_2_ohm) - 1; ; i--) { 952f520bb22SYouMin Chen if (phy_odt_ohm <= *(*(p_odt + i) + 1)) { 953f520bb22SYouMin Chen phy_odt = **(p_odt + i); 954f520bb22SYouMin Chen break; 955f520bb22SYouMin Chen } 956f520bb22SYouMin Chen if (i == 0) 957f520bb22SYouMin Chen break; 958f520bb22SYouMin Chen } 959f520bb22SYouMin Chen 960f520bb22SYouMin Chen if (dramtype != LPDDR4) { 961f520bb22SYouMin Chen if (!phy_odt_ohm || (phy_odt_up_en && phy_odt_dn_en)) 962f520bb22SYouMin Chen vref_inner = 0x80; 963f520bb22SYouMin Chen else if (phy_odt_up_en) 964f520bb22SYouMin Chen vref_inner = (2 * dram_drv_ohm + phy_odt_ohm) * 128 / 965f520bb22SYouMin Chen (dram_drv_ohm + phy_odt_ohm); 966f520bb22SYouMin Chen else 967f520bb22SYouMin Chen vref_inner = phy_odt_ohm * 128 / 968f520bb22SYouMin Chen (phy_odt_ohm + dram_drv_ohm); 969f520bb22SYouMin Chen 970f520bb22SYouMin Chen if (dramtype != DDR3 && dram_odt_ohm) 971f520bb22SYouMin Chen vref_out = (2 * phy_dq_drv_ohm + dram_odt_ohm) * 128 / 972f520bb22SYouMin Chen (phy_dq_drv_ohm + dram_odt_ohm); 973f520bb22SYouMin Chen else 974f520bb22SYouMin Chen vref_out = 0x80; 975f520bb22SYouMin Chen } else { 976f520bb22SYouMin Chen /* for lp4 */ 977f520bb22SYouMin Chen if (phy_odt_ohm) 978f520bb22SYouMin Chen vref_inner = 979f520bb22SYouMin Chen (PHY_LP4_DQ_VREF(lp4_info->vref_when_odten) * 980f520bb22SYouMin Chen 256) / 1000; 981f520bb22SYouMin Chen else 982f520bb22SYouMin Chen vref_inner = 983f520bb22SYouMin Chen (PHY_LP4_DQ_VREF(lp4_info->vref_when_odtoff) * 984f520bb22SYouMin Chen 256) / 1000; 985f520bb22SYouMin Chen 986f520bb22SYouMin Chen vref_out = 0x80; 987f520bb22SYouMin Chen } 988f520bb22SYouMin Chen 989f520bb22SYouMin Chen /* default ZQCALIB bypass mode */ 990f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x100), 0x1f, phy_ca_drv); 991f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x101), 0x1f, phy_ca_drv); 992f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x102), 0x1f, phy_clk_drv); 993f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x103), 0x1f, phy_clk_drv); 994a5033de0STang Yun ping if (dramtype == LPDDR4) { 995a5033de0STang Yun ping clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_clk_drv); 996a5033de0STang Yun ping clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_clk_drv); 997a5033de0STang Yun ping } else { 998a5033de0STang Yun ping clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_ca_drv); 999a5033de0STang Yun ping clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_ca_drv); 1000a5033de0STang Yun ping } 1001f520bb22SYouMin Chen /* clk / cmd slew rate */ 1002f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x106), 0x1f, sr_clk); 1003f520bb22SYouMin Chen 1004f520bb22SYouMin Chen phy_lp4_drv_pd_en = (~phy_lp4_drv_pd_en) & 1; 1005f520bb22SYouMin Chen if (phy_odt_up_en) 1006f520bb22SYouMin Chen phy_odt_up = phy_odt; 1007f520bb22SYouMin Chen if (phy_odt_dn_en) 1008f520bb22SYouMin Chen phy_odt_dn = phy_odt; 1009f520bb22SYouMin Chen 1010f520bb22SYouMin Chen for (i = 0; i < 4; i++) { 1011f520bb22SYouMin Chen j = 0x110 + i * 0x10; 1012f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, j + 1), 0x1f, phy_odt_up); 1013f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, j), 0x1f, phy_odt_dn); 1014f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, j + 2), 0x1f, phy_dq_drv); 1015f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, j + 3), 0x1f, phy_dq_drv); 1016f520bb22SYouMin Chen writel(vref_inner, PHY_REG(phy_base, 0x118 + i * 0x10)); 1017f520bb22SYouMin Chen 1018f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10), 1019f520bb22SYouMin Chen 1 << 3, phy_lp4_drv_pd_en << 3); 1020f520bb22SYouMin Chen /* dq slew rate */ 1021f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x117 + i * 0x10), 1022f520bb22SYouMin Chen 0x1f, sr_dq); 1023f520bb22SYouMin Chen } 1024f520bb22SYouMin Chen 1025f520bb22SYouMin Chen /* reg_rx_vref_value_update */ 1026f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5); 1027f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5); 1028f520bb22SYouMin Chen 1029f520bb22SYouMin Chen /* RAM VREF */ 1030f520bb22SYouMin Chen writel(vref_out, PHY_REG(phy_base, 0x105)); 1031d3f5f12cSTang Yun ping if (dramtype == LPDDR3) 1032d3f5f12cSTang Yun ping udelay(100); 1033f520bb22SYouMin Chen 1034f520bb22SYouMin Chen if (dramtype == LPDDR4) 1035f520bb22SYouMin Chen set_lp4_vref(dram, lp4_info, freq, dst_fsp); 1036f520bb22SYouMin Chen 1037f520bb22SYouMin Chen if (dramtype == DDR3 || dramtype == DDR4) { 1038f520bb22SYouMin Chen mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 1039f520bb22SYouMin Chen DDR_PCTL2_INIT3); 1040f520bb22SYouMin Chen mr1_mr3 = mr1_mr3 >> PCTL2_DDR34_MR1_SHIFT & PCTL2_MR_MASK; 1041f520bb22SYouMin Chen } else { 1042f520bb22SYouMin Chen mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 1043f520bb22SYouMin Chen DDR_PCTL2_INIT4); 1044f520bb22SYouMin Chen mr1_mr3 = mr1_mr3 >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK; 1045f520bb22SYouMin Chen } 1046f520bb22SYouMin Chen 1047f520bb22SYouMin Chen if (dramtype == DDR3) { 1048f520bb22SYouMin Chen mr1_mr3 &= ~(DDR3_DS_MASK | DDR3_RTT_NOM_MASK); 1049f520bb22SYouMin Chen if (dram_drv_ohm == 34) 1050f520bb22SYouMin Chen mr1_mr3 |= DDR3_DS_34; 1051f520bb22SYouMin Chen 1052f520bb22SYouMin Chen if (dram_odt_ohm == 0) 1053f520bb22SYouMin Chen mr1_mr3 |= DDR3_RTT_NOM_DIS; 1054f520bb22SYouMin Chen else if (dram_odt_ohm <= 40) 1055f520bb22SYouMin Chen mr1_mr3 |= DDR3_RTT_NOM_40; 1056f520bb22SYouMin Chen else if (dram_odt_ohm <= 60) 1057f520bb22SYouMin Chen mr1_mr3 |= DDR3_RTT_NOM_60; 1058f520bb22SYouMin Chen else 1059f520bb22SYouMin Chen mr1_mr3 |= DDR3_RTT_NOM_120; 1060f520bb22SYouMin Chen 1061f520bb22SYouMin Chen } else if (dramtype == DDR4) { 1062f520bb22SYouMin Chen mr1_mr3 &= ~(DDR4_DS_MASK | DDR4_RTT_NOM_MASK); 1063f520bb22SYouMin Chen if (dram_drv_ohm == 48) 1064f520bb22SYouMin Chen mr1_mr3 |= DDR4_DS_48; 1065f520bb22SYouMin Chen 1066f520bb22SYouMin Chen if (dram_odt_ohm == 0) 1067f520bb22SYouMin Chen mr1_mr3 |= DDR4_RTT_NOM_DIS; 1068f520bb22SYouMin Chen else if (dram_odt_ohm <= 34) 1069f520bb22SYouMin Chen mr1_mr3 |= DDR4_RTT_NOM_34; 1070f520bb22SYouMin Chen else if (dram_odt_ohm <= 40) 1071f520bb22SYouMin Chen mr1_mr3 |= DDR4_RTT_NOM_40; 1072f520bb22SYouMin Chen else if (dram_odt_ohm <= 48) 1073f520bb22SYouMin Chen mr1_mr3 |= DDR4_RTT_NOM_48; 1074f520bb22SYouMin Chen else if (dram_odt_ohm <= 60) 1075f520bb22SYouMin Chen mr1_mr3 |= DDR4_RTT_NOM_60; 1076f520bb22SYouMin Chen else 1077f520bb22SYouMin Chen mr1_mr3 |= DDR4_RTT_NOM_120; 1078f520bb22SYouMin Chen 1079f520bb22SYouMin Chen } else if (dramtype == LPDDR3) { 1080f520bb22SYouMin Chen if (dram_drv_ohm <= 34) 1081f520bb22SYouMin Chen mr1_mr3 |= LPDDR3_DS_34; 1082f520bb22SYouMin Chen else if (dram_drv_ohm <= 40) 1083f520bb22SYouMin Chen mr1_mr3 |= LPDDR3_DS_40; 1084f520bb22SYouMin Chen else if (dram_drv_ohm <= 48) 1085f520bb22SYouMin Chen mr1_mr3 |= LPDDR3_DS_48; 1086f520bb22SYouMin Chen else if (dram_drv_ohm <= 60) 1087f520bb22SYouMin Chen mr1_mr3 |= LPDDR3_DS_60; 1088f520bb22SYouMin Chen else if (dram_drv_ohm <= 80) 1089f520bb22SYouMin Chen mr1_mr3 |= LPDDR3_DS_80; 1090f520bb22SYouMin Chen 1091f520bb22SYouMin Chen if (dram_odt_ohm == 0) 1092f520bb22SYouMin Chen lp3_odt_value = LPDDR3_ODT_DIS; 1093f520bb22SYouMin Chen else if (dram_odt_ohm <= 60) 1094f520bb22SYouMin Chen lp3_odt_value = LPDDR3_ODT_60; 1095f520bb22SYouMin Chen else if (dram_odt_ohm <= 120) 1096f520bb22SYouMin Chen lp3_odt_value = LPDDR3_ODT_120; 1097f520bb22SYouMin Chen else 1098f520bb22SYouMin Chen lp3_odt_value = LPDDR3_ODT_240; 1099f520bb22SYouMin Chen } else {/* for lpddr4 */ 1100f520bb22SYouMin Chen /* MR3 for lp4 PU-CAL and PDDS */ 1101f520bb22SYouMin Chen mr1_mr3 &= ~(LPDDR4_PDDS_MASK | LPDDR4_PU_CAL_MASK); 1102f520bb22SYouMin Chen mr1_mr3 |= lp4_pu_cal; 1103f520bb22SYouMin Chen 1104f520bb22SYouMin Chen tmp = lp4_odt_calc(dram_drv_ohm); 1105f520bb22SYouMin Chen if (!tmp) 1106f520bb22SYouMin Chen tmp = LPDDR4_PDDS_240; 1107f520bb22SYouMin Chen mr1_mr3 |= (tmp << LPDDR4_PDDS_SHIFT); 1108f520bb22SYouMin Chen 1109f520bb22SYouMin Chen /* MR11 for lp4 ca odt, dq odt set */ 1110f520bb22SYouMin Chen mr11 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 1111f520bb22SYouMin Chen DDR_PCTL2_INIT6); 1112f520bb22SYouMin Chen mr11 = mr11 >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK; 1113f520bb22SYouMin Chen 1114f520bb22SYouMin Chen mr11 &= ~(LPDDR4_DQODT_MASK | LPDDR4_CAODT_MASK); 1115f520bb22SYouMin Chen 1116f520bb22SYouMin Chen tmp = lp4_odt_calc(dram_odt_ohm); 1117f520bb22SYouMin Chen mr11 |= (tmp << LPDDR4_DQODT_SHIFT); 1118f520bb22SYouMin Chen 1119f520bb22SYouMin Chen tmp = lp4_odt_calc(dram_caodt_ohm); 1120f520bb22SYouMin Chen mr11 |= (tmp << LPDDR4_CAODT_SHIFT); 1121f520bb22SYouMin Chen sw_set_req(dram); 1122f520bb22SYouMin Chen clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 1123f520bb22SYouMin Chen DDR_PCTL2_INIT6, 1124f520bb22SYouMin Chen PCTL2_MR_MASK << PCTL2_LPDDR4_MR11_SHIFT, 1125f520bb22SYouMin Chen mr11 << PCTL2_LPDDR4_MR11_SHIFT); 1126f520bb22SYouMin Chen sw_set_ack(dram); 1127f520bb22SYouMin Chen 1128f520bb22SYouMin Chen /* MR22 for soc odt/odt-ck/odt-cs/odt-ca */ 1129f520bb22SYouMin Chen mr22 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 1130f520bb22SYouMin Chen DDR_PCTL2_INIT7); 1131f520bb22SYouMin Chen mr22 = mr22 >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK; 1132f520bb22SYouMin Chen mr22 &= ~LPDDR4_SOC_ODT_MASK; 1133f520bb22SYouMin Chen 1134f520bb22SYouMin Chen tmp = lp4_odt_calc(phy_odt_ohm); 1135f520bb22SYouMin Chen mr22 |= tmp; 1136f520bb22SYouMin Chen mr22 = mr22 | 1137f520bb22SYouMin Chen (LP4_ODTE_CK_EN(lp4_info->cs_drv_ca_odt_info) << 1138f520bb22SYouMin Chen LPDDR4_ODTE_CK_SHIFT) | 1139f520bb22SYouMin Chen (LP4_ODTE_CS_EN(lp4_info->cs_drv_ca_odt_info) << 1140f520bb22SYouMin Chen LPDDR4_ODTE_CS_SHIFT) | 1141f520bb22SYouMin Chen (LP4_ODTD_CA_EN(lp4_info->cs_drv_ca_odt_info) << 1142f520bb22SYouMin Chen LPDDR4_ODTD_CA_SHIFT); 1143f520bb22SYouMin Chen 1144f520bb22SYouMin Chen sw_set_req(dram); 1145f520bb22SYouMin Chen clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 1146f520bb22SYouMin Chen DDR_PCTL2_INIT7, 1147f520bb22SYouMin Chen PCTL2_MR_MASK << PCTL2_LPDDR4_MR22_SHIFT, 1148f520bb22SYouMin Chen mr22 << PCTL2_LPDDR4_MR22_SHIFT); 1149f520bb22SYouMin Chen sw_set_ack(dram); 1150f520bb22SYouMin Chen } 1151f520bb22SYouMin Chen 1152f520bb22SYouMin Chen if (dramtype == DDR4 || dramtype == DDR3) { 1153f520bb22SYouMin Chen sw_set_req(dram); 1154f520bb22SYouMin Chen clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 1155f520bb22SYouMin Chen DDR_PCTL2_INIT3, 1156f520bb22SYouMin Chen PCTL2_MR_MASK << PCTL2_DDR34_MR1_SHIFT, 1157f520bb22SYouMin Chen mr1_mr3 << PCTL2_DDR34_MR1_SHIFT); 1158f520bb22SYouMin Chen sw_set_ack(dram); 1159f520bb22SYouMin Chen } else { 1160f520bb22SYouMin Chen sw_set_req(dram); 1161f520bb22SYouMin Chen clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 1162f520bb22SYouMin Chen DDR_PCTL2_INIT4, 1163f520bb22SYouMin Chen PCTL2_MR_MASK << PCTL2_LPDDR234_MR3_SHIFT, 1164f520bb22SYouMin Chen mr1_mr3 << PCTL2_LPDDR234_MR3_SHIFT); 1165f520bb22SYouMin Chen sw_set_ack(dram); 1166f520bb22SYouMin Chen } 1167f520bb22SYouMin Chen } 1168f520bb22SYouMin Chen 1169f520bb22SYouMin Chen static int sdram_cmd_dq_path_remap(struct dram_info *dram, 1170f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 1171f520bb22SYouMin Chen { 1172f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1173f520bb22SYouMin Chen u32 dramtype = sdram_params->base.dramtype; 1174f520bb22SYouMin Chen struct sdram_head_info_index_v2 *index = 1175f520bb22SYouMin Chen (struct sdram_head_info_index_v2 *)common_info; 1176f520bb22SYouMin Chen struct dq_map_info *map_info; 1177f520bb22SYouMin Chen 1178f520bb22SYouMin Chen map_info = (struct dq_map_info *)((void *)common_info + 1179f520bb22SYouMin Chen index->dq_map_index.offset * 4); 1180f520bb22SYouMin Chen 1181f520bb22SYouMin Chen if (dramtype <= LPDDR4) 1182f520bb22SYouMin Chen writel((map_info->byte_map[dramtype / 4] >> 1183f520bb22SYouMin Chen ((dramtype % 4) * 8)) & 0xff, 1184f520bb22SYouMin Chen PHY_REG(phy_base, 0x4f)); 1185f520bb22SYouMin Chen 1186f520bb22SYouMin Chen return 0; 1187f520bb22SYouMin Chen } 1188f520bb22SYouMin Chen 1189f520bb22SYouMin Chen static void phy_cfg(struct dram_info *dram, 1190f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 1191f520bb22SYouMin Chen { 1192f520bb22SYouMin Chen struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info; 1193f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1194f520bb22SYouMin Chen u32 i, dq_map, tmp; 1195f520bb22SYouMin Chen u32 byte1 = 0, byte0 = 0; 1196f520bb22SYouMin Chen 1197f520bb22SYouMin Chen sdram_cmd_dq_path_remap(dram, sdram_params); 1198f520bb22SYouMin Chen 1199f520bb22SYouMin Chen phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 0); 1200f520bb22SYouMin Chen for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) { 1201f520bb22SYouMin Chen writel(sdram_params->phy_regs.phy[i][1], 1202f520bb22SYouMin Chen phy_base + sdram_params->phy_regs.phy[i][0]); 1203f520bb22SYouMin Chen } 1204f520bb22SYouMin Chen 1205f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x62), BIT(5)); 1206f520bb22SYouMin Chen dq_map = readl(PHY_REG(phy_base, 0x4f)); 1207f520bb22SYouMin Chen for (i = 0; i < 4; i++) { 1208f520bb22SYouMin Chen if (((dq_map >> (i * 2)) & 0x3) == 0) 1209f520bb22SYouMin Chen byte0 = i; 1210f520bb22SYouMin Chen if (((dq_map >> (i * 2)) & 0x3) == 1) 1211f520bb22SYouMin Chen byte1 = i; 1212f520bb22SYouMin Chen } 1213f520bb22SYouMin Chen 1214f520bb22SYouMin Chen tmp = readl(PHY_REG(phy_base, 0xf)) & (~PHY_DQ_WIDTH_MASK); 1215f520bb22SYouMin Chen if (cap_info->bw == 2) 1216f520bb22SYouMin Chen tmp |= 0xf; 1217f520bb22SYouMin Chen else if (cap_info->bw == 1) 1218f520bb22SYouMin Chen tmp |= ((1 << byte0) | (1 << byte1)); 1219f520bb22SYouMin Chen else 1220f520bb22SYouMin Chen tmp |= (1 << byte0); 1221f520bb22SYouMin Chen 1222f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, 0xf)); 1223f520bb22SYouMin Chen 1224f520bb22SYouMin Chen /* lpddr4 odt control by phy, enable cs0 odt */ 1225f520bb22SYouMin Chen if (sdram_params->base.dramtype == LPDDR4) 1226f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x20), 0x7 << 4, 1227f520bb22SYouMin Chen (1 << 6) | (1 << 4)); 1228f520bb22SYouMin Chen /* for ca training ca vref choose range1 */ 1229f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x1e), BIT(6)); 1230f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x1f), BIT(6)); 1231f520bb22SYouMin Chen /* for wr training PHY_0x7c[5], choose range0 */ 1232f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x7c), BIT(5)); 1233f520bb22SYouMin Chen } 1234f520bb22SYouMin Chen 1235f520bb22SYouMin Chen static int update_refresh_reg(struct dram_info *dram) 1236f520bb22SYouMin Chen { 1237f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 1238f520bb22SYouMin Chen u32 ret; 1239f520bb22SYouMin Chen 1240f520bb22SYouMin Chen ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1); 1241f520bb22SYouMin Chen writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3); 1242f520bb22SYouMin Chen 1243f520bb22SYouMin Chen return 0; 1244f520bb22SYouMin Chen } 1245f520bb22SYouMin Chen 1246f520bb22SYouMin Chen /* 1247f520bb22SYouMin Chen * rank = 1: cs0 1248f520bb22SYouMin Chen * rank = 2: cs1 1249f520bb22SYouMin Chen */ 1250f520bb22SYouMin Chen int read_mr(struct dram_info *dram, u32 rank, u32 mr_num, u32 dramtype) 1251f520bb22SYouMin Chen { 1252f520bb22SYouMin Chen u32 ret; 1253f520bb22SYouMin Chen u32 i, temp; 1254f520bb22SYouMin Chen u32 dqmap; 1255f520bb22SYouMin Chen 1256f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 1257f520bb22SYouMin Chen struct sdram_head_info_index_v2 *index = 1258f520bb22SYouMin Chen (struct sdram_head_info_index_v2 *)common_info; 1259f520bb22SYouMin Chen struct dq_map_info *map_info; 1260f520bb22SYouMin Chen 1261f520bb22SYouMin Chen map_info = (struct dq_map_info *)((void *)common_info + 1262f520bb22SYouMin Chen index->dq_map_index.offset * 4); 1263f520bb22SYouMin Chen 1264f520bb22SYouMin Chen if (dramtype == LPDDR2) 1265f520bb22SYouMin Chen dqmap = map_info->lp2_dq0_7_map; 1266f520bb22SYouMin Chen else 1267f520bb22SYouMin Chen dqmap = map_info->lp3_dq0_7_map; 1268f520bb22SYouMin Chen 1269f520bb22SYouMin Chen pctl_read_mr(pctl_base, rank, mr_num); 1270f520bb22SYouMin Chen 1271f520bb22SYouMin Chen ret = (readl(&dram->ddrgrf->ddr_grf_status[0]) & 0xff); 1272f520bb22SYouMin Chen 1273f520bb22SYouMin Chen if (dramtype != LPDDR4) { 1274f520bb22SYouMin Chen temp = 0; 1275f520bb22SYouMin Chen for (i = 0; i < 8; i++) { 1276f520bb22SYouMin Chen temp = temp | (((ret >> i) & 0x1) << 1277f520bb22SYouMin Chen ((dqmap >> (i * 4)) & 0xf)); 1278f520bb22SYouMin Chen } 1279f520bb22SYouMin Chen } else { 1280330cd12fSWesley Yao temp = (readl(&dram->ddrgrf->ddr_grf_status[1]) & 0xff); 1281f520bb22SYouMin Chen } 1282f520bb22SYouMin Chen 1283330cd12fSWesley Yao return temp; 1284f520bb22SYouMin Chen } 1285f520bb22SYouMin Chen 1286f520bb22SYouMin Chen /* before call this function autorefresh should be disabled */ 1287f520bb22SYouMin Chen void send_a_refresh(struct dram_info *dram) 1288f520bb22SYouMin Chen { 1289f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 1290f520bb22SYouMin Chen 1291f520bb22SYouMin Chen while (readl(pctl_base + DDR_PCTL2_DBGSTAT) & 0x3) 1292f520bb22SYouMin Chen continue; 1293f520bb22SYouMin Chen writel(0x3, pctl_base + DDR_PCTL2_DBGCMD); 1294f520bb22SYouMin Chen } 1295f520bb22SYouMin Chen 1296f4f57f8eSTang Yun ping static void enter_sr(struct dram_info *dram, u32 en) 1297f4f57f8eSTang Yun ping { 1298f4f57f8eSTang Yun ping void __iomem *pctl_base = dram->pctl; 1299f4f57f8eSTang Yun ping 1300f4f57f8eSTang Yun ping if (en) { 1301f4f57f8eSTang Yun ping setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW); 1302f4f57f8eSTang Yun ping while (1) { 1303f4f57f8eSTang Yun ping if (((readl(pctl_base + DDR_PCTL2_STAT) & 1304f4f57f8eSTang Yun ping PCTL2_SELFREF_TYPE_MASK) == 1305f4f57f8eSTang Yun ping PCTL2_SELFREF_TYPE_SR_NOT_AUTO) && 1306f4f57f8eSTang Yun ping ((readl(pctl_base + DDR_PCTL2_STAT) & 1307f4f57f8eSTang Yun ping PCTL2_OPERATING_MODE_MASK) == 1308f4f57f8eSTang Yun ping PCTL2_OPERATING_MODE_SR)) 1309f4f57f8eSTang Yun ping break; 1310f4f57f8eSTang Yun ping } 1311f4f57f8eSTang Yun ping } else { 1312f4f57f8eSTang Yun ping clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW); 1313f4f57f8eSTang Yun ping while ((readl(pctl_base + DDR_PCTL2_STAT) & 1314f4f57f8eSTang Yun ping PCTL2_OPERATING_MODE_MASK) == PCTL2_OPERATING_MODE_SR) 1315f4f57f8eSTang Yun ping continue; 1316f4f57f8eSTang Yun ping } 1317f4f57f8eSTang Yun ping } 1318f4f57f8eSTang Yun ping 1319f520bb22SYouMin Chen void record_dq_prebit(struct dram_info *dram) 1320f520bb22SYouMin Chen { 1321f520bb22SYouMin Chen u32 group, i, tmp; 1322f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1323f520bb22SYouMin Chen 1324f520bb22SYouMin Chen for (group = 0; group < 4; group++) { 1325f520bb22SYouMin Chen for (i = 0; i < ARRAY_SIZE(dq_sel); i++) { 1326f520bb22SYouMin Chen /* l_loop_invdelaysel */ 1327f520bb22SYouMin Chen writel(dq_sel[i][0], PHY_REG(phy_base, 1328f520bb22SYouMin Chen grp_addr[group] + 0x2c)); 1329f520bb22SYouMin Chen tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2e)); 1330f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, 1331f520bb22SYouMin Chen grp_addr[group] + dq_sel[i][1])); 1332f520bb22SYouMin Chen 1333f520bb22SYouMin Chen /* r_loop_invdelaysel */ 1334f520bb22SYouMin Chen writel(dq_sel[i][0], PHY_REG(phy_base, 1335f520bb22SYouMin Chen grp_addr[group] + 0x2d)); 1336f520bb22SYouMin Chen tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2f)); 1337f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, 1338f520bb22SYouMin Chen grp_addr[group] + dq_sel[i][2])); 1339f520bb22SYouMin Chen } 1340f520bb22SYouMin Chen } 1341f520bb22SYouMin Chen } 1342f520bb22SYouMin Chen 1343f520bb22SYouMin Chen static void update_dq_rx_prebit(struct dram_info *dram) 1344f520bb22SYouMin Chen { 1345f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1346f520bb22SYouMin Chen 1347f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x70), BIT(1) | BIT(6) | BIT(4), 1348f520bb22SYouMin Chen BIT(4)); 1349f520bb22SYouMin Chen udelay(1); 1350f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x70), BIT(4)); 1351f520bb22SYouMin Chen } 1352f520bb22SYouMin Chen 1353f520bb22SYouMin Chen static void update_dq_tx_prebit(struct dram_info *dram) 1354f520bb22SYouMin Chen { 1355f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1356f520bb22SYouMin Chen 1357f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1)); 1358f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x2), BIT(3)); 1359f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0xc), BIT(6)); 1360f520bb22SYouMin Chen udelay(1); 1361f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0xc), BIT(6)); 1362f520bb22SYouMin Chen } 1363f520bb22SYouMin Chen 1364f520bb22SYouMin Chen static void update_ca_prebit(struct dram_info *dram) 1365f520bb22SYouMin Chen { 1366f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1367f520bb22SYouMin Chen 1368f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x25), BIT(2)); 1369f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x22), BIT(6)); 1370f520bb22SYouMin Chen udelay(1); 1371f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x22), BIT(6)); 1372f520bb22SYouMin Chen } 1373f520bb22SYouMin Chen 1374f520bb22SYouMin Chen /* 1375f520bb22SYouMin Chen * dir: 0: de-skew = delta_* 1376f520bb22SYouMin Chen * 1: de-skew = reg val - delta_* 1377f520bb22SYouMin Chen * delta_dir: value for differential signal: clk/ 1378f520bb22SYouMin Chen * delta_sig: value for single signal: ca/cmd 1379f520bb22SYouMin Chen */ 1380f520bb22SYouMin Chen static void modify_ca_deskew(struct dram_info *dram, u32 dir, int delta_dif, 1381f520bb22SYouMin Chen int delta_sig, u32 cs, u32 dramtype) 1382f520bb22SYouMin Chen { 1383f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1384f520bb22SYouMin Chen u32 i, cs_en, tmp; 1385f4f57f8eSTang Yun ping u32 dfi_lp_stat = 0; 1386f520bb22SYouMin Chen 1387f520bb22SYouMin Chen if (cs == 0) 1388f520bb22SYouMin Chen cs_en = 1; 1389f520bb22SYouMin Chen else if (cs == 2) 1390f520bb22SYouMin Chen cs_en = 2; 1391f520bb22SYouMin Chen else 1392f520bb22SYouMin Chen cs_en = 3; 1393f520bb22SYouMin Chen 1394f4f57f8eSTang Yun ping if (dramtype == LPDDR4 && 1395f4f57f8eSTang Yun ping ((readl(PHY_REG(phy_base, 0x60)) & BIT(5)) == 0)) { 1396f4f57f8eSTang Yun ping dfi_lp_stat = 1; 1397f4f57f8eSTang Yun ping setbits_le32(PHY_REG(phy_base, 0x60), BIT(5)); 1398f4f57f8eSTang Yun ping } 1399f4f57f8eSTang Yun ping enter_sr(dram, 1); 1400f4f57f8eSTang Yun ping 1401f520bb22SYouMin Chen for (i = 0; i < 0x20; i++) { 1402f520bb22SYouMin Chen if (dir == DESKEW_MDF_ABS_VAL) 1403f520bb22SYouMin Chen tmp = delta_sig; 1404f520bb22SYouMin Chen else 1405f520bb22SYouMin Chen tmp = readl(PHY_REG(phy_base, 0x150 + i)) + 1406f520bb22SYouMin Chen delta_sig; 1407f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, 0x150 + i)); 1408f520bb22SYouMin Chen } 1409f520bb22SYouMin Chen 1410f520bb22SYouMin Chen if (dir == DESKEW_MDF_ABS_VAL) 1411f520bb22SYouMin Chen tmp = delta_dif; 1412f520bb22SYouMin Chen else 1413f520bb22SYouMin Chen tmp = readl(PHY_REG(phy_base, 0x150 + 0x17)) - 1414f520bb22SYouMin Chen delta_sig + delta_dif; 1415f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, 0x150 + 0x17)); 1416f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, 0x150 + 0x18)); 1417f520bb22SYouMin Chen if (dramtype == LPDDR4) { 1418f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, 0x150 + 0x4)); 1419f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, 0x150 + 0xa)); 1420f520bb22SYouMin Chen 1421f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x10), cs_en << 6); 1422f520bb22SYouMin Chen update_ca_prebit(dram); 1423f520bb22SYouMin Chen } 1424f4f57f8eSTang Yun ping enter_sr(dram, 0); 1425f4f57f8eSTang Yun ping 1426f4f57f8eSTang Yun ping if (dfi_lp_stat) 1427f4f57f8eSTang Yun ping clrbits_le32(PHY_REG(phy_base, 0x60), BIT(5)); 1428f4f57f8eSTang Yun ping 1429f520bb22SYouMin Chen } 1430f520bb22SYouMin Chen 1431f520bb22SYouMin Chen static u32 get_min_value(struct dram_info *dram, u32 signal, u32 rank) 1432f520bb22SYouMin Chen { 1433f520bb22SYouMin Chen u32 i, j, offset = 0; 1434f520bb22SYouMin Chen u32 min = 0x3f; 1435f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1436f520bb22SYouMin Chen u32 byte_en; 1437f520bb22SYouMin Chen 1438f520bb22SYouMin Chen if (signal == SKEW_TX_SIGNAL) 1439f520bb22SYouMin Chen offset = 8; 1440f520bb22SYouMin Chen 1441f520bb22SYouMin Chen if (signal == SKEW_CA_SIGNAL) { 1442f520bb22SYouMin Chen for (i = 0; i < 0x20; i++) 1443f520bb22SYouMin Chen min = MIN(min, readl(PHY_REG(phy_base, 0x150 + i))); 1444f520bb22SYouMin Chen } else { 1445f520bb22SYouMin Chen byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf; 1446f520bb22SYouMin Chen for (j = offset; j < offset + rank * 4; j++) { 1447f520bb22SYouMin Chen if (!((byte_en >> (j % 4)) & 1)) 1448f520bb22SYouMin Chen continue; 1449f520bb22SYouMin Chen for (i = 0; i < 11; i++) 1450f520bb22SYouMin Chen min = MIN(min, 1451f520bb22SYouMin Chen readl(PHY_REG(phy_base, 1452f520bb22SYouMin Chen dqs_dq_skew_adr[j] + 1453f520bb22SYouMin Chen i))); 1454f520bb22SYouMin Chen } 1455f520bb22SYouMin Chen } 1456f520bb22SYouMin Chen 1457f520bb22SYouMin Chen return min; 1458f520bb22SYouMin Chen } 1459f520bb22SYouMin Chen 1460f520bb22SYouMin Chen static u32 low_power_update(struct dram_info *dram, u32 en) 1461f520bb22SYouMin Chen { 1462f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 1463f520bb22SYouMin Chen u32 lp_stat = 0; 1464f520bb22SYouMin Chen 1465f520bb22SYouMin Chen if (en) { 1466f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, en & 0xf); 1467f520bb22SYouMin Chen } else { 1468f520bb22SYouMin Chen lp_stat = readl(pctl_base + DDR_PCTL2_PWRCTL) & 0xf; 1469f520bb22SYouMin Chen clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 0xf); 1470f520bb22SYouMin Chen } 1471f520bb22SYouMin Chen 1472f520bb22SYouMin Chen return lp_stat; 1473f520bb22SYouMin Chen } 1474f520bb22SYouMin Chen 1475f520bb22SYouMin Chen /* 1476f520bb22SYouMin Chen * signal: 1477f520bb22SYouMin Chen * dir: 0: de-skew = delta_* 1478f520bb22SYouMin Chen * 1: de-skew = reg val - delta_* 1479f520bb22SYouMin Chen * delta_dir: value for differential signal: dqs 1480f520bb22SYouMin Chen * delta_sig: value for single signal: dq/dm 1481f520bb22SYouMin Chen */ 1482f520bb22SYouMin Chen static void modify_dq_deskew(struct dram_info *dram, u32 signal, u32 dir, 1483f520bb22SYouMin Chen int delta_dif, int delta_sig, u32 rank) 1484f520bb22SYouMin Chen { 1485f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1486f520bb22SYouMin Chen u32 i, j, tmp, offset; 1487f520bb22SYouMin Chen u32 byte_en; 1488f520bb22SYouMin Chen 1489f520bb22SYouMin Chen byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf; 1490f520bb22SYouMin Chen 1491f520bb22SYouMin Chen if (signal == SKEW_RX_SIGNAL) 1492f520bb22SYouMin Chen offset = 0; 1493f520bb22SYouMin Chen else 1494f520bb22SYouMin Chen offset = 8; 1495f520bb22SYouMin Chen 1496f520bb22SYouMin Chen for (j = offset; j < (offset + rank * 4); j++) { 1497f520bb22SYouMin Chen if (!((byte_en >> (j % 4)) & 1)) 1498f520bb22SYouMin Chen continue; 1499f520bb22SYouMin Chen for (i = 0; i < 0x9; i++) { 1500f520bb22SYouMin Chen if (dir == DESKEW_MDF_ABS_VAL) 1501f520bb22SYouMin Chen tmp = delta_sig; 1502f520bb22SYouMin Chen else 1503f520bb22SYouMin Chen tmp = delta_sig + readl(PHY_REG(phy_base, 1504f520bb22SYouMin Chen dqs_dq_skew_adr[j] + 1505f520bb22SYouMin Chen i)); 1506f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + i)); 1507f520bb22SYouMin Chen } 1508f520bb22SYouMin Chen if (dir == DESKEW_MDF_ABS_VAL) 1509f520bb22SYouMin Chen tmp = delta_dif; 1510f520bb22SYouMin Chen else 1511f520bb22SYouMin Chen tmp = delta_dif + readl(PHY_REG(phy_base, 1512f520bb22SYouMin Chen dqs_dq_skew_adr[j] + 9)); 1513f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 9)); 1514f520bb22SYouMin Chen writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 0xa)); 1515f520bb22SYouMin Chen } 1516f520bb22SYouMin Chen if (signal == SKEW_RX_SIGNAL) 1517f520bb22SYouMin Chen update_dq_rx_prebit(dram); 1518f520bb22SYouMin Chen else 1519f520bb22SYouMin Chen update_dq_tx_prebit(dram); 1520f520bb22SYouMin Chen } 1521f520bb22SYouMin Chen 1522f520bb22SYouMin Chen static int data_training_rg(struct dram_info *dram, u32 cs, u32 dramtype) 1523f520bb22SYouMin Chen { 1524f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1525f520bb22SYouMin Chen u32 ret; 1526f520bb22SYouMin Chen u32 dis_auto_zq = 0; 1527f520bb22SYouMin Chen u32 odt_val_up, odt_val_dn; 1528f520bb22SYouMin Chen u32 i, j; 1529f520bb22SYouMin Chen 1530f520bb22SYouMin Chen odt_val_dn = readl(PHY_REG(phy_base, 0x110)); 1531f520bb22SYouMin Chen odt_val_up = readl(PHY_REG(phy_base, 0x111)); 1532f520bb22SYouMin Chen 1533f520bb22SYouMin Chen if (dramtype != LPDDR4) { 1534f520bb22SYouMin Chen for (i = 0; i < 4; i++) { 1535f520bb22SYouMin Chen j = 0x110 + i * 0x10; 153670fee8b3STang Yun ping writel(PHY_DDR4_LPDDR3_RTT_294ohm, 1537f520bb22SYouMin Chen PHY_REG(phy_base, j)); 1538f520bb22SYouMin Chen writel(PHY_DDR4_LPDDR3_RTT_DISABLE, 1539f520bb22SYouMin Chen PHY_REG(phy_base, j + 0x1)); 1540f520bb22SYouMin Chen } 1541f520bb22SYouMin Chen } 1542f520bb22SYouMin Chen dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl); 1543f520bb22SYouMin Chen /* use normal read mode for data training */ 1544f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0xc), BIT(1)); 1545f520bb22SYouMin Chen 15462c5208e2STang Yun ping if (dramtype == DDR4) 15472c5208e2STang Yun ping setbits_le32(PHY_REG(phy_base, 0xc), BIT(1)); 1548f520bb22SYouMin Chen 1549f520bb22SYouMin Chen /* choose training cs */ 1550f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs)); 1551f520bb22SYouMin Chen /* enable gate training */ 1552f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1); 1553f520bb22SYouMin Chen udelay(50); 1554f520bb22SYouMin Chen ret = readl(PHY_REG(phy_base, 0x91)); 1555f520bb22SYouMin Chen /* disable gate training */ 1556f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0); 1557f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 2), 0x30); 1558f520bb22SYouMin Chen pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq); 1559f520bb22SYouMin Chen 1560f520bb22SYouMin Chen if (ret & 0x20) 1561f520bb22SYouMin Chen ret = -1; 1562f520bb22SYouMin Chen else 1563f520bb22SYouMin Chen ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0xf)) & 0xf); 1564f520bb22SYouMin Chen 1565f520bb22SYouMin Chen if (dramtype != LPDDR4) { 1566f520bb22SYouMin Chen for (i = 0; i < 4; i++) { 1567f520bb22SYouMin Chen j = 0x110 + i * 0x10; 1568f520bb22SYouMin Chen writel(odt_val_dn, PHY_REG(phy_base, j)); 1569f520bb22SYouMin Chen writel(odt_val_up, PHY_REG(phy_base, j + 0x1)); 1570f520bb22SYouMin Chen } 1571f520bb22SYouMin Chen } 1572f520bb22SYouMin Chen return ret; 1573f520bb22SYouMin Chen } 1574f520bb22SYouMin Chen 1575f520bb22SYouMin Chen static int data_training_wl(struct dram_info *dram, u32 cs, u32 dramtype, 1576f520bb22SYouMin Chen u32 rank) 1577f520bb22SYouMin Chen { 1578f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 1579f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1580f520bb22SYouMin Chen u32 dis_auto_zq = 0; 1581f520bb22SYouMin Chen u32 tmp; 1582f520bb22SYouMin Chen u32 cur_fsp; 1583f520bb22SYouMin Chen u32 timeout_us = 1000; 1584f520bb22SYouMin Chen 1585f520bb22SYouMin Chen dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl); 1586f520bb22SYouMin Chen 1587f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x7a), 0x1); 1588f520bb22SYouMin Chen 1589f520bb22SYouMin Chen cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3; 1590f520bb22SYouMin Chen tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_INIT3) & 1591f520bb22SYouMin Chen 0xffff; 1592f520bb22SYouMin Chen writel(tmp & 0xff, PHY_REG(phy_base, 0x3)); 1593f520bb22SYouMin Chen 1594f520bb22SYouMin Chen /* disable another cs's output */ 1595f520bb22SYouMin Chen if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2) 1596f520bb22SYouMin Chen pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp | (1 << 12), 1597f520bb22SYouMin Chen dramtype); 1598f520bb22SYouMin Chen if (dramtype == DDR3 || dramtype == DDR4) 1599f520bb22SYouMin Chen writel(0x40 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4)); 1600f520bb22SYouMin Chen else 1601f520bb22SYouMin Chen writel(0x80 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4)); 1602f520bb22SYouMin Chen 1603f520bb22SYouMin Chen /* choose cs */ 1604f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2), 1605f520bb22SYouMin Chen ((0x2 >> cs) << 6) | (0 << 2)); 1606f520bb22SYouMin Chen /* enable write leveling */ 1607f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2), 1608f520bb22SYouMin Chen ((0x2 >> cs) << 6) | (1 << 2)); 1609f520bb22SYouMin Chen 1610f520bb22SYouMin Chen while (1) { 1611f520bb22SYouMin Chen if ((readl(PHY_REG(phy_base, 0x92)) & 0xf) == 1612f520bb22SYouMin Chen (readl(PHY_REG(phy_base, 0xf)) & 0xf)) 1613f520bb22SYouMin Chen break; 1614f520bb22SYouMin Chen 1615f520bb22SYouMin Chen udelay(1); 1616f520bb22SYouMin Chen if (timeout_us-- == 0) { 1617f520bb22SYouMin Chen printascii("error: write leveling timeout\n"); 1618f520bb22SYouMin Chen while (1) 1619f520bb22SYouMin Chen ; 1620f520bb22SYouMin Chen } 1621f520bb22SYouMin Chen } 1622f520bb22SYouMin Chen 1623f520bb22SYouMin Chen /* disable write leveling */ 1624f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2), 1625f520bb22SYouMin Chen ((0x2 >> cs) << 6) | (0 << 2)); 1626f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), 0x3 << 6, 0 << 6); 1627f520bb22SYouMin Chen 1628f520bb22SYouMin Chen /* enable another cs's output */ 1629f520bb22SYouMin Chen if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2) 1630f520bb22SYouMin Chen pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp & ~(1 << 12), 1631f520bb22SYouMin Chen dramtype); 1632f520bb22SYouMin Chen 1633f520bb22SYouMin Chen pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq); 1634f520bb22SYouMin Chen 1635f520bb22SYouMin Chen return 0; 1636f520bb22SYouMin Chen } 1637f520bb22SYouMin Chen 1638f520bb22SYouMin Chen char pattern[32] = { 1639f520bb22SYouMin Chen 0xaa, 0x55, 0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa, 1640f520bb22SYouMin Chen 0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xaa, 0x55, 1641f520bb22SYouMin Chen 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 1642f520bb22SYouMin Chen 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa 1643f520bb22SYouMin Chen }; 1644f520bb22SYouMin Chen 1645f520bb22SYouMin Chen static int data_training_rd(struct dram_info *dram, u32 cs, u32 dramtype, 1646f520bb22SYouMin Chen u32 mhz) 1647f520bb22SYouMin Chen { 1648f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 1649f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1650f520bb22SYouMin Chen u32 trefi_1x, trfc_1x; 1651f520bb22SYouMin Chen u32 dis_auto_zq = 0; 1652f520bb22SYouMin Chen u32 timeout_us = 1000; 1653f520bb22SYouMin Chen u32 dqs_default; 1654f520bb22SYouMin Chen u32 cur_fsp; 165548c0a787SYouMin Chen u32 vref_inner; 1656f520bb22SYouMin Chen u32 i; 1657f520bb22SYouMin Chen struct sdram_head_info_index_v2 *index = 1658f520bb22SYouMin Chen (struct sdram_head_info_index_v2 *)common_info; 1659f520bb22SYouMin Chen struct dq_map_info *map_info; 1660f520bb22SYouMin Chen 166148c0a787SYouMin Chen vref_inner = readl(PHY_REG(phy_base, 0x128)) & 0xff; 166248c0a787SYouMin Chen if (dramtype == DDR3 && vref_inner == 0x80) { 166348c0a787SYouMin Chen for (i = 0; i < 4; i++) 166448c0a787SYouMin Chen writel(vref_inner - 0xa, 166548c0a787SYouMin Chen PHY_REG(phy_base, 0x118 + i * 0x10)); 166648c0a787SYouMin Chen 166748c0a787SYouMin Chen /* reg_rx_vref_value_update */ 166848c0a787SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5); 166948c0a787SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5); 167048c0a787SYouMin Chen } 167148c0a787SYouMin Chen 1672f520bb22SYouMin Chen map_info = (struct dq_map_info *)((void *)common_info + 1673f520bb22SYouMin Chen index->dq_map_index.offset * 4); 1674f520bb22SYouMin Chen /* only 1cs a time, 0:cs0 1 cs1 */ 1675f520bb22SYouMin Chen if (cs > 1) 1676f520bb22SYouMin Chen return -1; 1677f520bb22SYouMin Chen 1678f520bb22SYouMin Chen dqs_default = 0xf; 1679f520bb22SYouMin Chen dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl); 1680f520bb22SYouMin Chen 1681f520bb22SYouMin Chen cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3; 1682f520bb22SYouMin Chen /* config refresh timing */ 1683f520bb22SYouMin Chen trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + 1684f520bb22SYouMin Chen DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32; 1685f520bb22SYouMin Chen trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + 1686f520bb22SYouMin Chen DDR_PCTL2_RFSHTMG) & 0x3ff; 1687f520bb22SYouMin Chen /* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */ 1688f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff); 1689f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f); 1690f520bb22SYouMin Chen /* reg_phy_trfc */ 1691f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x); 1692f520bb22SYouMin Chen /* reg_max_refi_cnt */ 1693f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4); 1694f520bb22SYouMin Chen 1695f520bb22SYouMin Chen /* choose training cs */ 1696f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x71), 0x3 << 6, (0x2 >> cs) << 6); 1697f520bb22SYouMin Chen 1698f520bb22SYouMin Chen /* set dq map for ddr4 */ 1699f520bb22SYouMin Chen if (dramtype == DDR4) { 1700f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x70), BIT(7)); 1701f520bb22SYouMin Chen for (i = 0; i < 4; i++) { 1702f520bb22SYouMin Chen writel((map_info->ddr4_dq_map[cs * 2] >> 1703f520bb22SYouMin Chen ((i % 4) * 8)) & 0xff, 1704f520bb22SYouMin Chen PHY_REG(phy_base, 0x238 + i)); 1705f520bb22SYouMin Chen writel((map_info->ddr4_dq_map[cs * 2 + 1] >> 1706f520bb22SYouMin Chen ((i % 4) * 8)) & 0xff, 1707f520bb22SYouMin Chen PHY_REG(phy_base, 0x2b8 + i)); 1708f520bb22SYouMin Chen } 1709f520bb22SYouMin Chen } 1710f520bb22SYouMin Chen 1711f520bb22SYouMin Chen /* cha_l reg_l_rd_train_dqs_default[5:0] */ 1712f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x230), 0x3f, dqs_default); 1713f520bb22SYouMin Chen /* cha_h reg_h_rd_train_dqs_default[5:0] */ 1714f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x234), 0x3f, dqs_default); 1715f520bb22SYouMin Chen /* chb_l reg_l_rd_train_dqs_default[5:0] */ 1716f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x2b0), 0x3f, dqs_default); 1717f520bb22SYouMin Chen /* chb_h reg_h_rd_train_dqs_default[5:0] */ 1718f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x2b4), 0x3f, dqs_default); 1719f520bb22SYouMin Chen 1720f520bb22SYouMin Chen /* Choose the read train auto mode */ 1721f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x1); 1722f520bb22SYouMin Chen /* Enable the auto train of the read train */ 1723f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x3); 1724f520bb22SYouMin Chen 1725f520bb22SYouMin Chen /* Wait the train done. */ 1726f520bb22SYouMin Chen while (1) { 1727f520bb22SYouMin Chen if ((readl(PHY_REG(phy_base, 0x93)) >> 7) & 0x1) 1728f520bb22SYouMin Chen break; 1729f520bb22SYouMin Chen 1730f520bb22SYouMin Chen udelay(1); 1731f520bb22SYouMin Chen if (timeout_us-- == 0) { 1732f520bb22SYouMin Chen printascii("error: read training timeout\n"); 1733f520bb22SYouMin Chen return -1; 1734f520bb22SYouMin Chen } 1735f520bb22SYouMin Chen } 1736f520bb22SYouMin Chen 1737f520bb22SYouMin Chen /* Check the read train state */ 1738f520bb22SYouMin Chen if ((readl(PHY_REG(phy_base, 0x240)) & 0x3) || 1739f520bb22SYouMin Chen (readl(PHY_REG(phy_base, 0x2c0)) & 0x3)) { 1740f520bb22SYouMin Chen printascii("error: read training error\n"); 1741f520bb22SYouMin Chen return -1; 1742f520bb22SYouMin Chen } 1743f520bb22SYouMin Chen 1744f520bb22SYouMin Chen /* Exit the Read Training by setting */ 1745f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x70), BIT(1)); 1746f520bb22SYouMin Chen 1747f520bb22SYouMin Chen pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq); 1748f520bb22SYouMin Chen 174948c0a787SYouMin Chen if (dramtype == DDR3 && vref_inner == 0x80) { 175048c0a787SYouMin Chen for (i = 0; i < 4; i++) 175148c0a787SYouMin Chen writel(vref_inner, 175248c0a787SYouMin Chen PHY_REG(phy_base, 0x118 + i * 0x10)); 175348c0a787SYouMin Chen 175448c0a787SYouMin Chen /* reg_rx_vref_value_update */ 175548c0a787SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5); 175648c0a787SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5); 175748c0a787SYouMin Chen } 175848c0a787SYouMin Chen 1759f520bb22SYouMin Chen return 0; 1760f520bb22SYouMin Chen } 1761f520bb22SYouMin Chen 1762f520bb22SYouMin Chen static int data_training_wr(struct dram_info *dram, u32 cs, u32 dramtype, 1763f520bb22SYouMin Chen u32 mhz, u32 dst_fsp) 1764f520bb22SYouMin Chen { 1765f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 1766f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1767f520bb22SYouMin Chen u32 trefi_1x, trfc_1x; 1768f520bb22SYouMin Chen u32 dis_auto_zq = 0; 1769f520bb22SYouMin Chen u32 timeout_us = 1000; 1770f520bb22SYouMin Chen u32 cur_fsp; 1771f520bb22SYouMin Chen u32 mr_tmp, cl, cwl, phy_fsp, offset = 0; 1772f520bb22SYouMin Chen 1773f520bb22SYouMin Chen if (dramtype == LPDDR3 && mhz <= 400) { 1774f520bb22SYouMin Chen phy_fsp = (readl(PHY_REG(phy_base, 0xc)) >> 0x2) & 0x3; 1775f520bb22SYouMin Chen offset = (phy_fsp == 0) ? 0x5 : 0x387 + (phy_fsp - 1) * 3; 1776f520bb22SYouMin Chen cl = readl(PHY_REG(phy_base, offset)); 1777f520bb22SYouMin Chen cwl = readl(PHY_REG(phy_base, offset + 2)); 1778f520bb22SYouMin Chen 1779f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, 0x8); 1780f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, 0x4); 1781f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 2, 0x6, dramtype); 1782f520bb22SYouMin Chen } 1783f520bb22SYouMin Chen 1784f520bb22SYouMin Chen dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl); 1785f520bb22SYouMin Chen 1786f520bb22SYouMin Chen /* PHY_0x7b[7:0] reg_train_col_addr[7:0] */ 1787f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x7b), 0xff, 0x0); 1788f520bb22SYouMin Chen /* PHY_0x7c[4:2] reg_train_ba_addr[2:0] */ 1789f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x7 << 2, 0x0 << 2); 1790f520bb22SYouMin Chen /* PHY_0x7c[1:0] reg_train_col_addr[9:8] */ 1791f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3, 0x0); 1792f520bb22SYouMin Chen /* PHY_0x7d[7:0] reg_train_row_addr[7:0] */ 1793f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x7d), 0xff, 0x0); 1794f520bb22SYouMin Chen /* PHY_0x7e[7:0] reg_train_row_addr[15:8] */ 1795f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x7e), 0xff, 0x0); 1796f520bb22SYouMin Chen 1797f520bb22SYouMin Chen /* PHY_0x71[3] wrtrain_check_data_value_random_gen */ 1798f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x71), BIT(3)); 1799f520bb22SYouMin Chen 1800f520bb22SYouMin Chen /* config refresh timing */ 1801f520bb22SYouMin Chen cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3; 1802f520bb22SYouMin Chen trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + 1803f520bb22SYouMin Chen DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32; 1804f520bb22SYouMin Chen trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + 1805f520bb22SYouMin Chen DDR_PCTL2_RFSHTMG) & 0x3ff; 1806f520bb22SYouMin Chen /* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */ 1807f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff); 1808f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f); 1809f520bb22SYouMin Chen /* reg_phy_trfc */ 1810f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x); 1811f520bb22SYouMin Chen /* reg_max_refi_cnt */ 1812f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4); 1813f520bb22SYouMin Chen 1814f520bb22SYouMin Chen /* choose training cs */ 1815f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3 << 6, (0x2 >> cs) << 6); 1816f520bb22SYouMin Chen 1817f520bb22SYouMin Chen /* PHY_0x7a [4] reg_wr_train_dqs_default_bypass */ 1818f520bb22SYouMin Chen /* 0: Use the write-leveling value. */ 1819f520bb22SYouMin Chen /* 1: use reg0x233 0x237 0x2b3 0x2b7 */ 1820f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x7a), BIT(4)); 1821f520bb22SYouMin Chen 1822f520bb22SYouMin Chen /* PHY_0x7a [0] reg_dq_wr_train_auto */ 1823f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x7a), 0x1); 1824f520bb22SYouMin Chen 1825f520bb22SYouMin Chen /* PHY_0x7a [1] reg_dq_wr_train_en */ 1826f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x7a), BIT(1)); 1827f520bb22SYouMin Chen 1828f520bb22SYouMin Chen send_a_refresh(dram); 1829f520bb22SYouMin Chen 1830f520bb22SYouMin Chen while (1) { 1831f520bb22SYouMin Chen if ((readl(PHY_REG(phy_base, 0x92)) >> 7) & 0x1) 1832f520bb22SYouMin Chen break; 1833f520bb22SYouMin Chen 1834f520bb22SYouMin Chen udelay(1); 1835f520bb22SYouMin Chen if (timeout_us-- == 0) { 1836f520bb22SYouMin Chen printascii("error: write training timeout\n"); 1837f520bb22SYouMin Chen while (1) 1838f520bb22SYouMin Chen ; 1839f520bb22SYouMin Chen } 1840f520bb22SYouMin Chen } 1841f520bb22SYouMin Chen 1842f520bb22SYouMin Chen /* Check the write train state */ 1843f520bb22SYouMin Chen if ((readl(PHY_REG(phy_base, 0x90)) >> 5) & 0x7) { 1844f520bb22SYouMin Chen printascii("error: write training error\n"); 1845f520bb22SYouMin Chen return -1; 1846f520bb22SYouMin Chen } 1847f520bb22SYouMin Chen 1848f520bb22SYouMin Chen /* PHY_0x7a [1] reg_dq_wr_train_en */ 1849f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1)); 1850f520bb22SYouMin Chen 1851f520bb22SYouMin Chen pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq); 1852f520bb22SYouMin Chen 1853f520bb22SYouMin Chen /* save LPDDR4 write vref to fsp_param for dfs */ 1854f520bb22SYouMin Chen if (dramtype == LPDDR4) { 1855f520bb22SYouMin Chen fsp_param[dst_fsp].vref_dq[cs] = 1856f520bb22SYouMin Chen ((readl(PHY_REG(phy_base, 0x384)) & 0x3f) + 1857f520bb22SYouMin Chen (readl(PHY_REG(phy_base, 0x385)) & 0x3f)) / 2; 1858f520bb22SYouMin Chen /* add range info */ 1859f520bb22SYouMin Chen fsp_param[dst_fsp].vref_dq[cs] |= 1860f520bb22SYouMin Chen ((readl(PHY_REG(phy_base, 0x7c)) & BIT(5)) << 1); 1861f520bb22SYouMin Chen } 1862f520bb22SYouMin Chen 1863f520bb22SYouMin Chen if (dramtype == LPDDR3 && mhz <= 400) { 1864f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, cl); 1865f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, cwl); 1866f520bb22SYouMin Chen mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + 1867f520bb22SYouMin Chen DDR_PCTL2_INIT3); 1868f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK, 1869f520bb22SYouMin Chen dramtype); 1870f520bb22SYouMin Chen } 1871f520bb22SYouMin Chen 1872f520bb22SYouMin Chen return 0; 1873f520bb22SYouMin Chen } 1874f520bb22SYouMin Chen 1875f520bb22SYouMin Chen static int data_training(struct dram_info *dram, u32 cs, 1876f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params, u32 dst_fsp, 1877f520bb22SYouMin Chen u32 training_flag) 1878f520bb22SYouMin Chen { 1879f520bb22SYouMin Chen u32 ret = 0; 1880f520bb22SYouMin Chen 1881f520bb22SYouMin Chen if (training_flag == FULL_TRAINING) 1882f520bb22SYouMin Chen training_flag = READ_GATE_TRAINING | WRITE_LEVELING | 1883f520bb22SYouMin Chen WRITE_TRAINING | READ_TRAINING; 1884f520bb22SYouMin Chen 1885f520bb22SYouMin Chen if ((training_flag & WRITE_LEVELING) == WRITE_LEVELING) { 1886f520bb22SYouMin Chen ret = data_training_wl(dram, cs, 1887f520bb22SYouMin Chen sdram_params->base.dramtype, 1888f520bb22SYouMin Chen sdram_params->ch.cap_info.rank); 1889f520bb22SYouMin Chen if (ret != 0) 1890f520bb22SYouMin Chen goto out; 1891f520bb22SYouMin Chen } 1892f520bb22SYouMin Chen 1893f520bb22SYouMin Chen if ((training_flag & READ_GATE_TRAINING) == READ_GATE_TRAINING) { 1894f520bb22SYouMin Chen ret = data_training_rg(dram, cs, 1895f520bb22SYouMin Chen sdram_params->base.dramtype); 1896f520bb22SYouMin Chen if (ret != 0) 1897f520bb22SYouMin Chen goto out; 1898f520bb22SYouMin Chen } 1899f520bb22SYouMin Chen 1900f520bb22SYouMin Chen if ((training_flag & READ_TRAINING) == READ_TRAINING) { 1901f520bb22SYouMin Chen ret = data_training_rd(dram, cs, 1902f520bb22SYouMin Chen sdram_params->base.dramtype, 1903f520bb22SYouMin Chen sdram_params->base.ddr_freq); 1904f520bb22SYouMin Chen if (ret != 0) 1905f520bb22SYouMin Chen goto out; 1906f520bb22SYouMin Chen } 1907f520bb22SYouMin Chen 1908f520bb22SYouMin Chen if ((training_flag & WRITE_TRAINING) == WRITE_TRAINING) { 1909f520bb22SYouMin Chen ret = data_training_wr(dram, cs, 1910f520bb22SYouMin Chen sdram_params->base.dramtype, 1911f520bb22SYouMin Chen sdram_params->base.ddr_freq, dst_fsp); 1912f520bb22SYouMin Chen if (ret != 0) 1913f520bb22SYouMin Chen goto out; 1914f520bb22SYouMin Chen } 1915f520bb22SYouMin Chen 1916f520bb22SYouMin Chen out: 1917f520bb22SYouMin Chen return ret; 1918f520bb22SYouMin Chen } 1919f520bb22SYouMin Chen 1920f520bb22SYouMin Chen static int get_wrlvl_val(struct dram_info *dram, 1921f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 1922f520bb22SYouMin Chen { 1923f520bb22SYouMin Chen u32 i, j, clk_skew; 1924f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 1925f520bb22SYouMin Chen u32 lp_stat; 1926f520bb22SYouMin Chen int ret; 1927f520bb22SYouMin Chen 1928f520bb22SYouMin Chen lp_stat = low_power_update(dram, 0); 1929f520bb22SYouMin Chen 1930d5bb9a92STang Yun ping clk_skew = 0x1f; 1931d5bb9a92STang Yun ping modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, clk_skew, 3, 1932d5bb9a92STang Yun ping sdram_params->base.dramtype); 1933f520bb22SYouMin Chen 1934f520bb22SYouMin Chen ret = data_training(dram, 0, sdram_params, 0, WRITE_LEVELING); 1935f520bb22SYouMin Chen if (sdram_params->ch.cap_info.rank == 2) 1936f520bb22SYouMin Chen ret |= data_training(dram, 1, sdram_params, 0, WRITE_LEVELING); 1937f520bb22SYouMin Chen 1938f520bb22SYouMin Chen for (j = 0; j < 2; j++) 1939f520bb22SYouMin Chen for (i = 0; i < 4; i++) 1940f520bb22SYouMin Chen wrlvl_result[j][i] = 1941f520bb22SYouMin Chen readl(PHY_REG(phy_base, 1942f520bb22SYouMin Chen wrlvl_result_offset[j][i])) - 1943f520bb22SYouMin Chen clk_skew; 1944f520bb22SYouMin Chen 1945f520bb22SYouMin Chen low_power_update(dram, lp_stat); 1946f520bb22SYouMin Chen 1947f520bb22SYouMin Chen return ret; 1948f520bb22SYouMin Chen } 1949f520bb22SYouMin Chen 1950c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL) 1951c71eeac4SWesley Yao static void init_rw_trn_result_struct(struct rw_trn_result *result, 1952c71eeac4SWesley Yao void __iomem *phy_base, u8 cs_num) 1953c71eeac4SWesley Yao { 1954c71eeac4SWesley Yao int i; 1955c71eeac4SWesley Yao 1956c71eeac4SWesley Yao result->cs_num = cs_num; 1957c71eeac4SWesley Yao result->byte_en = readb(PHY_REG(dram_info.phy, 0xf)) & 1958c71eeac4SWesley Yao PHY_DQ_WIDTH_MASK; 1959c71eeac4SWesley Yao for (i = 0; i < FSP_NUM; i++) 1960c71eeac4SWesley Yao result->fsp_mhz[i] = 0; 1961c71eeac4SWesley Yao } 1962c71eeac4SWesley Yao 1963c71eeac4SWesley Yao static void save_rw_trn_min_max(void __iomem *phy_base, 1964c71eeac4SWesley Yao struct cs_rw_trn_result *rd_result, 1965c71eeac4SWesley Yao struct cs_rw_trn_result *wr_result, 1966c71eeac4SWesley Yao u8 byte_en) 1967c71eeac4SWesley Yao { 1968c71eeac4SWesley Yao u16 phy_ofs; 1969c71eeac4SWesley Yao u8 dqs; 1970c71eeac4SWesley Yao u8 dq; 1971c71eeac4SWesley Yao 19728889aef0SWesley Yao for (dqs = 0; dqs < BYTE_NUM; dqs++) { 19738889aef0SWesley Yao if ((byte_en & BIT(dqs)) == 0) 19748889aef0SWesley Yao continue; 19758889aef0SWesley Yao 1976c71eeac4SWesley Yao /* Channel A or B (low or high 16 bit) */ 1977c71eeac4SWesley Yao phy_ofs = dqs < 2 ? 0x230 : 0x2b0; 1978c71eeac4SWesley Yao /* low or high 8 bit */ 1979c71eeac4SWesley Yao phy_ofs += (dqs & 0x1) == 0 ? 0 : 0x9; 1980c71eeac4SWesley Yao for (dq = 0; dq < 8; dq++) { 1981c71eeac4SWesley Yao rd_result->dqs[dqs].dq_min[dq] = 1982c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0x15 + dq)); 1983c71eeac4SWesley Yao rd_result->dqs[dqs].dq_max[dq] = 1984c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0x27 + dq)); 1985c71eeac4SWesley Yao wr_result->dqs[dqs].dq_min[dq] = 1986c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0x3d + dq)); 1987c71eeac4SWesley Yao wr_result->dqs[dqs].dq_max[dq] = 1988c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0x4f + dq)); 1989c71eeac4SWesley Yao } 1990c71eeac4SWesley Yao } 1991c71eeac4SWesley Yao } 1992c71eeac4SWesley Yao 1993c71eeac4SWesley Yao static void save_rw_trn_deskew(void __iomem *phy_base, 1994c71eeac4SWesley Yao struct fsp_rw_trn_result *result, u8 cs_num, 1995c71eeac4SWesley Yao int min_val, bool rw) 1996c71eeac4SWesley Yao { 1997c71eeac4SWesley Yao u16 phy_ofs; 1998c71eeac4SWesley Yao u8 cs; 1999c71eeac4SWesley Yao u8 dq; 2000c71eeac4SWesley Yao 2001c71eeac4SWesley Yao result->min_val = min_val; 2002c71eeac4SWesley Yao 2003c71eeac4SWesley Yao for (cs = 0; cs < cs_num; cs++) { 2004c71eeac4SWesley Yao phy_ofs = cs == 0 ? 0x170 : 0x1a0; 2005c71eeac4SWesley Yao phy_ofs += rw == SKEW_RX_SIGNAL ? 0x1 : 0x17; 2006c71eeac4SWesley Yao for (dq = 0; dq < 8; dq++) { 2007c71eeac4SWesley Yao result->cs[cs].dqs[0].dq_deskew[dq] = 2008c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + dq)); 2009c71eeac4SWesley Yao result->cs[cs].dqs[1].dq_deskew[dq] = 2010c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0xb + dq)); 2011c71eeac4SWesley Yao result->cs[cs].dqs[2].dq_deskew[dq] = 2012c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0x60 + dq)); 2013c71eeac4SWesley Yao result->cs[cs].dqs[3].dq_deskew[dq] = 2014c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + dq)); 2015c71eeac4SWesley Yao } 2016c71eeac4SWesley Yao 2017c71eeac4SWesley Yao result->cs[cs].dqs[0].dqs_deskew = 2018c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0x8)); 2019c71eeac4SWesley Yao result->cs[cs].dqs[1].dqs_deskew = 2020c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0xb + 0x8)); 2021c71eeac4SWesley Yao result->cs[cs].dqs[2].dqs_deskew = 2022c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0x8)); 2023c71eeac4SWesley Yao result->cs[cs].dqs[3].dqs_deskew = 2024c71eeac4SWesley Yao readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + 0x8)); 2025c71eeac4SWesley Yao } 2026c71eeac4SWesley Yao } 2027c71eeac4SWesley Yao 2028c71eeac4SWesley Yao static void save_rw_trn_result_to_ddr(struct rw_trn_result *result) 2029c71eeac4SWesley Yao { 20307a110f3aSWesley Yao result->flag = DDR_DQ_EYE_FLAG; 2031c71eeac4SWesley Yao memcpy((void *)(RW_TRN_RESULT_ADDR), result, sizeof(*result)); 2032c71eeac4SWesley Yao } 2033c71eeac4SWesley Yao #endif 2034c71eeac4SWesley Yao 2035f520bb22SYouMin Chen static int high_freq_training(struct dram_info *dram, 2036f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params, 2037f520bb22SYouMin Chen u32 fsp) 2038f520bb22SYouMin Chen { 2039f520bb22SYouMin Chen u32 i, j; 2040f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 2041f520bb22SYouMin Chen u32 dramtype = sdram_params->base.dramtype; 2042f520bb22SYouMin Chen int min_val; 2043d5bb9a92STang Yun ping int dqs_skew, clk_skew, ca_skew; 204482ad70b5SWesley Yao u8 byte_en; 2045f520bb22SYouMin Chen int ret; 2046f520bb22SYouMin Chen 204782ad70b5SWesley Yao byte_en = readl(PHY_REG(phy_base, 0xf)) & PHY_DQ_WIDTH_MASK; 2048f520bb22SYouMin Chen dqs_skew = 0; 204982ad70b5SWesley Yao for (j = 0; j < sdram_params->ch.cap_info.rank; j++) { 205082ad70b5SWesley Yao for (i = 0; i < ARRAY_SIZE(wrlvl_result[0]); i++) { 205182ad70b5SWesley Yao if ((byte_en & BIT(i)) != 0) 2052f520bb22SYouMin Chen dqs_skew += wrlvl_result[j][i]; 205382ad70b5SWesley Yao } 205482ad70b5SWesley Yao } 2055f520bb22SYouMin Chen dqs_skew = dqs_skew / (sdram_params->ch.cap_info.rank * 205682ad70b5SWesley Yao (1 << sdram_params->ch.cap_info.bw)); 2057f520bb22SYouMin Chen 2058f520bb22SYouMin Chen clk_skew = 0x20 - dqs_skew; 2059f520bb22SYouMin Chen dqs_skew = 0x20; 2060f520bb22SYouMin Chen 2061f520bb22SYouMin Chen if (dramtype == LPDDR4) { 2062f520bb22SYouMin Chen clk_skew = 0; 2063f520bb22SYouMin Chen ca_skew = 0; 2064f520bb22SYouMin Chen } else if (dramtype == LPDDR3) { 2065f520bb22SYouMin Chen ca_skew = clk_skew - 4; 2066f520bb22SYouMin Chen } else { 2067f520bb22SYouMin Chen ca_skew = clk_skew; 2068f520bb22SYouMin Chen } 2069f520bb22SYouMin Chen modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, ca_skew, 3, 2070f520bb22SYouMin Chen dramtype); 2071f520bb22SYouMin Chen 2072f520bb22SYouMin Chen writel(wrlvl_result[0][0] + clk_skew, PHY_REG(phy_base, 0x233)); 2073f520bb22SYouMin Chen writel(wrlvl_result[0][1] + clk_skew, PHY_REG(phy_base, 0x237)); 2074f520bb22SYouMin Chen writel(wrlvl_result[0][2] + clk_skew, PHY_REG(phy_base, 0x2b3)); 2075f520bb22SYouMin Chen writel(wrlvl_result[0][3] + clk_skew, PHY_REG(phy_base, 0x2b7)); 2076f520bb22SYouMin Chen ret = data_training(dram, 0, sdram_params, fsp, READ_GATE_TRAINING | 2077f520bb22SYouMin Chen READ_TRAINING | WRITE_TRAINING); 2078c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL) 2079c71eeac4SWesley Yao rw_trn_result.fsp_mhz[fsp] = (u16)sdram_params->base.ddr_freq; 2080c71eeac4SWesley Yao save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[0], 2081c71eeac4SWesley Yao &rw_trn_result.wr_fsp[fsp].cs[0], 2082c71eeac4SWesley Yao rw_trn_result.byte_en); 2083c71eeac4SWesley Yao #endif 2084f520bb22SYouMin Chen if (sdram_params->ch.cap_info.rank == 2) { 2085f520bb22SYouMin Chen writel(wrlvl_result[1][0] + clk_skew, PHY_REG(phy_base, 0x233)); 2086f520bb22SYouMin Chen writel(wrlvl_result[1][1] + clk_skew, PHY_REG(phy_base, 0x237)); 2087f520bb22SYouMin Chen writel(wrlvl_result[1][2] + clk_skew, PHY_REG(phy_base, 0x2b3)); 2088f520bb22SYouMin Chen writel(wrlvl_result[1][3] + clk_skew, PHY_REG(phy_base, 0x2b7)); 2089f520bb22SYouMin Chen ret |= data_training(dram, 1, sdram_params, fsp, 2090f520bb22SYouMin Chen READ_GATE_TRAINING | READ_TRAINING | 2091f520bb22SYouMin Chen WRITE_TRAINING); 2092c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL) 2093c71eeac4SWesley Yao save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[1], 2094c71eeac4SWesley Yao &rw_trn_result.wr_fsp[fsp].cs[1], 2095c71eeac4SWesley Yao rw_trn_result.byte_en); 2096c71eeac4SWesley Yao #endif 2097f520bb22SYouMin Chen } 2098f520bb22SYouMin Chen if (ret) 2099f520bb22SYouMin Chen goto out; 2100f520bb22SYouMin Chen 2101f520bb22SYouMin Chen record_dq_prebit(dram); 2102f520bb22SYouMin Chen 2103f520bb22SYouMin Chen min_val = get_min_value(dram, SKEW_RX_SIGNAL, 2104f520bb22SYouMin Chen sdram_params->ch.cap_info.rank) * -1; 2105f520bb22SYouMin Chen modify_dq_deskew(dram, SKEW_RX_SIGNAL, DESKEW_MDF_DIFF_VAL, 2106f520bb22SYouMin Chen min_val, min_val, sdram_params->ch.cap_info.rank); 2107c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL) 2108c71eeac4SWesley Yao save_rw_trn_deskew(phy_base, &rw_trn_result.rd_fsp[fsp], 2109c71eeac4SWesley Yao rw_trn_result.cs_num, (u8)(min_val * (-1)), 2110c71eeac4SWesley Yao SKEW_RX_SIGNAL); 2111c71eeac4SWesley Yao #endif 2112f520bb22SYouMin Chen 2113f520bb22SYouMin Chen min_val = MIN(get_min_value(dram, SKEW_TX_SIGNAL, 2114f520bb22SYouMin Chen sdram_params->ch.cap_info.rank), 2115f520bb22SYouMin Chen get_min_value(dram, SKEW_CA_SIGNAL, 2116f520bb22SYouMin Chen sdram_params->ch.cap_info.rank)) * -1; 2117f520bb22SYouMin Chen 2118f520bb22SYouMin Chen /* clk = 0, rx all skew -7, tx - min_value */ 2119f520bb22SYouMin Chen modify_ca_deskew(dram, DESKEW_MDF_DIFF_VAL, min_val, min_val, 3, 2120f520bb22SYouMin Chen dramtype); 2121f520bb22SYouMin Chen 2122f520bb22SYouMin Chen modify_dq_deskew(dram, SKEW_TX_SIGNAL, DESKEW_MDF_DIFF_VAL, 2123f520bb22SYouMin Chen min_val, min_val, sdram_params->ch.cap_info.rank); 2124c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL) 2125c71eeac4SWesley Yao save_rw_trn_deskew(phy_base, &rw_trn_result.wr_fsp[fsp], 2126c71eeac4SWesley Yao rw_trn_result.cs_num, (u8)(min_val * (-1)), 2127c71eeac4SWesley Yao SKEW_TX_SIGNAL); 2128c71eeac4SWesley Yao #endif 2129f520bb22SYouMin Chen 2130f520bb22SYouMin Chen ret = data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING); 2131f520bb22SYouMin Chen if (sdram_params->ch.cap_info.rank == 2) 2132f520bb22SYouMin Chen ret |= data_training(dram, 1, sdram_params, 0, 2133f520bb22SYouMin Chen READ_GATE_TRAINING); 2134f520bb22SYouMin Chen out: 2135f520bb22SYouMin Chen return ret; 2136f520bb22SYouMin Chen } 2137f520bb22SYouMin Chen 2138f520bb22SYouMin Chen static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig) 2139f520bb22SYouMin Chen { 2140f520bb22SYouMin Chen writel(ddrconfig, &dram->msch->deviceconf); 2141f520bb22SYouMin Chen clrsetbits_le32(&dram->grf->noc_con0, 0x3 << 0, 0 << 0); 2142f520bb22SYouMin Chen } 2143f520bb22SYouMin Chen 2144f520bb22SYouMin Chen static void update_noc_timing(struct dram_info *dram, 2145f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 2146f520bb22SYouMin Chen { 214738b16f08SYouMin Chen void __iomem *pctl_base = dram->pctl; 214838b16f08SYouMin Chen u32 bw, bl; 214938b16f08SYouMin Chen 215038b16f08SYouMin Chen bw = 8 << sdram_params->ch.cap_info.bw; 215138b16f08SYouMin Chen bl = ((readl(pctl_base + DDR_PCTL2_MSTR) >> 16) & 0xf) * 2; 215238b16f08SYouMin Chen 215338b16f08SYouMin Chen /* update the noc timing related to data bus width */ 21549d5c314bSWesley Yao if ((bw / 8 * bl) <= 16) 215538b16f08SYouMin Chen sdram_params->ch.noc_timings.ddrmode.b.burstsize = 0; 215638b16f08SYouMin Chen else if ((bw / 8 * bl) == 32) 215738b16f08SYouMin Chen sdram_params->ch.noc_timings.ddrmode.b.burstsize = 1; 215838b16f08SYouMin Chen else if ((bw / 8 * bl) == 64) 215938b16f08SYouMin Chen sdram_params->ch.noc_timings.ddrmode.b.burstsize = 2; 216038b16f08SYouMin Chen else 216138b16f08SYouMin Chen sdram_params->ch.noc_timings.ddrmode.b.burstsize = 3; 216238b16f08SYouMin Chen 216338b16f08SYouMin Chen sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty = 2164da1862e9SYouMin Chen (bl * bw / 8) > 16 ? (bl / 4) : (16 / (bl * bw / 8)) * bl / 4; 216538b16f08SYouMin Chen 216638b16f08SYouMin Chen if (sdram_params->base.dramtype == LPDDR4) { 216738b16f08SYouMin Chen sdram_params->ch.noc_timings.ddrmode.b.mwrsize = 216838b16f08SYouMin Chen (bw == 16) ? 0x1 : 0x2; 216938b16f08SYouMin Chen sdram_params->ch.noc_timings.ddrtimingc0.b.wrtomwr = 217038b16f08SYouMin Chen 3 * sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty; 217138b16f08SYouMin Chen } 217238b16f08SYouMin Chen 2173f520bb22SYouMin Chen writel(sdram_params->ch.noc_timings.ddrtiminga0.d32, 2174f520bb22SYouMin Chen &dram->msch->ddrtiminga0); 2175f520bb22SYouMin Chen writel(sdram_params->ch.noc_timings.ddrtimingb0.d32, 2176f520bb22SYouMin Chen &dram->msch->ddrtimingb0); 2177f520bb22SYouMin Chen writel(sdram_params->ch.noc_timings.ddrtimingc0.d32, 2178f520bb22SYouMin Chen &dram->msch->ddrtimingc0); 2179f520bb22SYouMin Chen writel(sdram_params->ch.noc_timings.devtodev0.d32, 2180f520bb22SYouMin Chen &dram->msch->devtodev0); 2181f520bb22SYouMin Chen writel(sdram_params->ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode); 2182f520bb22SYouMin Chen writel(sdram_params->ch.noc_timings.ddr4timing.d32, 2183f520bb22SYouMin Chen &dram->msch->ddr4timing); 2184f520bb22SYouMin Chen } 2185f520bb22SYouMin Chen 2186f520bb22SYouMin Chen static void dram_all_config(struct dram_info *dram, 2187f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 2188f520bb22SYouMin Chen { 2189f520bb22SYouMin Chen struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info; 2190f520bb22SYouMin Chen u32 dram_type = sdram_params->base.dramtype; 2191f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 2192f520bb22SYouMin Chen u32 sys_reg2 = 0; 2193f520bb22SYouMin Chen u32 sys_reg3 = 0; 2194f520bb22SYouMin Chen u64 cs_cap[2]; 2195f520bb22SYouMin Chen u32 cs_pst; 2196f520bb22SYouMin Chen 2197f520bb22SYouMin Chen set_ddrconfig(dram, cap_info->ddrconfig); 2198f520bb22SYouMin Chen sdram_org_config(cap_info, &sdram_params->base, &sys_reg2, 2199f520bb22SYouMin Chen &sys_reg3, 0); 2200f520bb22SYouMin Chen writel(sys_reg2, &dram->pmugrf->os_reg[2]); 2201f520bb22SYouMin Chen writel(sys_reg3, &dram->pmugrf->os_reg[3]); 2202f520bb22SYouMin Chen 2203f520bb22SYouMin Chen cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type); 2204f520bb22SYouMin Chen cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type); 2205f520bb22SYouMin Chen 2206f520bb22SYouMin Chen if (cap_info->rank == 2) { 2207f520bb22SYouMin Chen cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) + 2208f520bb22SYouMin Chen 6 + 2; 2209f520bb22SYouMin Chen if (cs_pst > 28) 2210bf922fc8SWesley Yao cs_cap[0] = 1llu << cs_pst; 2211f520bb22SYouMin Chen } 2212f520bb22SYouMin Chen 2213f520bb22SYouMin Chen writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) | 2214f520bb22SYouMin Chen (((cs_cap[0] >> 20) / 64) & 0xff), 2215f520bb22SYouMin Chen &dram->msch->devicesize); 2216f520bb22SYouMin Chen update_noc_timing(dram, sdram_params); 2217f520bb22SYouMin Chen } 2218f520bb22SYouMin Chen 2219f520bb22SYouMin Chen static void enable_low_power(struct dram_info *dram, 2220f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 2221f520bb22SYouMin Chen { 2222f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 2223f520bb22SYouMin Chen u32 grf_lp_con; 2224f520bb22SYouMin Chen 2225f520bb22SYouMin Chen writel(0x1f1f0617, &dram->ddrgrf->ddr_grf_con[1]); 2226f520bb22SYouMin Chen 2227f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR4) 2228f520bb22SYouMin Chen grf_lp_con = (0x7 << 16) | (1 << 1); 2229f520bb22SYouMin Chen else if (sdram_params->base.dramtype == DDR3) 2230f520bb22SYouMin Chen grf_lp_con = (0x7 << 16) | (1 << 0); 2231f520bb22SYouMin Chen else 2232f520bb22SYouMin Chen grf_lp_con = (0x7 << 16) | (1 << 2); 2233f520bb22SYouMin Chen 2234f520bb22SYouMin Chen /* en lpckdis_en */ 2235f520bb22SYouMin Chen grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9); 2236f520bb22SYouMin Chen writel(grf_lp_con, &dram->ddrgrf->ddr_grf_lp_con); 2237f520bb22SYouMin Chen 2238f520bb22SYouMin Chen /* enable sr, pd */ 2239f520bb22SYouMin Chen if (dram->pd_idle == 0) 2240f520bb22SYouMin Chen clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1)); 2241f520bb22SYouMin Chen else 2242f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1)); 2243f520bb22SYouMin Chen if (dram->sr_idle == 0) 2244f520bb22SYouMin Chen clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1); 2245f520bb22SYouMin Chen else 2246f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1); 2247f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3)); 2248f520bb22SYouMin Chen } 2249f520bb22SYouMin Chen 2250f520bb22SYouMin Chen static void ddr_set_atags(struct dram_info *dram, 2251f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 2252f520bb22SYouMin Chen { 2253f520bb22SYouMin Chen struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info; 2254f520bb22SYouMin Chen u32 dram_type = sdram_params->base.dramtype; 2255f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 2256f520bb22SYouMin Chen struct tag_serial t_serial; 2257f520bb22SYouMin Chen struct tag_ddr_mem t_ddrmem; 2258f520bb22SYouMin Chen struct tag_soc_info t_socinfo; 2259f520bb22SYouMin Chen u64 cs_cap[2]; 2260f520bb22SYouMin Chen u32 cs_pst = 0; 2261f520bb22SYouMin Chen 2262f520bb22SYouMin Chen cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type); 2263f520bb22SYouMin Chen cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type); 2264f520bb22SYouMin Chen 2265f520bb22SYouMin Chen memset(&t_serial, 0, sizeof(struct tag_serial)); 2266f520bb22SYouMin Chen 2267f520bb22SYouMin Chen t_serial.version = 0; 2268f520bb22SYouMin Chen t_serial.enable = 1; 2269f520bb22SYouMin Chen t_serial.addr = CONFIG_DEBUG_UART_BASE; 2270f520bb22SYouMin Chen t_serial.baudrate = CONFIG_BAUDRATE; 2271f520bb22SYouMin Chen t_serial.m_mode = SERIAL_M_MODE_M0; 2272f520bb22SYouMin Chen t_serial.id = 2; 2273f520bb22SYouMin Chen 2274f520bb22SYouMin Chen atags_destroy(); 2275f520bb22SYouMin Chen atags_set_tag(ATAG_SERIAL, &t_serial); 2276f520bb22SYouMin Chen 2277f520bb22SYouMin Chen memset(&t_ddrmem, 0, sizeof(struct tag_ddr_mem)); 2278f520bb22SYouMin Chen if (cap_info->row_3_4) { 2279f520bb22SYouMin Chen cs_cap[0] = cs_cap[0] * 3 / 4; 2280f520bb22SYouMin Chen cs_cap[1] = cs_cap[1] * 3 / 4; 2281f520bb22SYouMin Chen } 2282f520bb22SYouMin Chen t_ddrmem.version = 0; 2283f520bb22SYouMin Chen t_ddrmem.bank[0] = CONFIG_SYS_SDRAM_BASE; 2284f520bb22SYouMin Chen if (cs_cap[1]) { 2285f520bb22SYouMin Chen cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) + 2286f520bb22SYouMin Chen 6 + 2; 2287f520bb22SYouMin Chen } 2288f520bb22SYouMin Chen 2289f520bb22SYouMin Chen if (cs_cap[1] && cs_pst > 27) { 2290f520bb22SYouMin Chen t_ddrmem.count = 2; 2291f520bb22SYouMin Chen t_ddrmem.bank[1] = 1 << cs_pst; 2292f520bb22SYouMin Chen t_ddrmem.bank[2] = cs_cap[0]; 2293f520bb22SYouMin Chen t_ddrmem.bank[3] = cs_cap[1]; 2294f520bb22SYouMin Chen } else { 2295f520bb22SYouMin Chen t_ddrmem.count = 1; 2296f520bb22SYouMin Chen t_ddrmem.bank[1] = (u64)cs_cap[0] + (u64)cs_cap[1]; 2297f520bb22SYouMin Chen } 2298f520bb22SYouMin Chen 2299f520bb22SYouMin Chen atags_set_tag(ATAG_DDR_MEM, &t_ddrmem); 2300f520bb22SYouMin Chen 2301f520bb22SYouMin Chen memset(&t_socinfo, 0, sizeof(struct tag_soc_info)); 2302f520bb22SYouMin Chen t_socinfo.version = 0; 2303f520bb22SYouMin Chen t_socinfo.name = 0x1126; 2304f520bb22SYouMin Chen } 2305f520bb22SYouMin Chen 2306f520bb22SYouMin Chen static void print_ddr_info(struct rv1126_sdram_params *sdram_params) 2307f520bb22SYouMin Chen { 2308f520bb22SYouMin Chen u32 split; 2309f520bb22SYouMin Chen 2310f520bb22SYouMin Chen if ((readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) & 2311f520bb22SYouMin Chen (1 << SPLIT_BYPASS_OFFSET)) != 0) 2312f520bb22SYouMin Chen split = 0; 2313f520bb22SYouMin Chen else 2314f520bb22SYouMin Chen split = readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) & 2315f520bb22SYouMin Chen SPLIT_SIZE_MASK; 2316f520bb22SYouMin Chen 2317f520bb22SYouMin Chen sdram_print_ddr_info(&sdram_params->ch.cap_info, 2318f520bb22SYouMin Chen &sdram_params->base, split); 2319f520bb22SYouMin Chen } 2320f520bb22SYouMin Chen 2321f520bb22SYouMin Chen static int sdram_init_(struct dram_info *dram, 2322f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params, u32 post_init) 2323f520bb22SYouMin Chen { 2324f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 2325f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 2326f520bb22SYouMin Chen u32 ddr4_vref; 2327f520bb22SYouMin Chen u32 mr_tmp; 2328f520bb22SYouMin Chen 2329f520bb22SYouMin Chen rkclk_configure_ddr(dram, sdram_params); 2330f520bb22SYouMin Chen 2331f520bb22SYouMin Chen rkclk_ddr_reset(dram, 1, 1, 1, 1); 2332f520bb22SYouMin Chen udelay(10); 2333f520bb22SYouMin Chen 2334f520bb22SYouMin Chen rkclk_ddr_reset(dram, 1, 1, 1, 0); 2335f520bb22SYouMin Chen phy_cfg(dram, sdram_params); 2336f520bb22SYouMin Chen 2337f520bb22SYouMin Chen rkclk_ddr_reset(dram, 1, 1, 0, 0); 2338f520bb22SYouMin Chen phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 1); 2339f520bb22SYouMin Chen 2340f520bb22SYouMin Chen rkclk_ddr_reset(dram, 1, 0, 0, 0); 2341f520bb22SYouMin Chen pctl_cfg(dram->pctl, &sdram_params->pctl_regs, 2342f520bb22SYouMin Chen dram->sr_idle, dram->pd_idle); 2343f520bb22SYouMin Chen 234422b43223SZhihuan He if (sdram_params->ch.cap_info.bw == 2) { 2345e8885e24SCanYang He /* 32bit interface use pageclose */ 2346e8885e24SCanYang He setbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2); 234722b43223SZhihuan He /* pageclose = 1, pageclose_timer = 0 will err in lp4 328MHz */ 234822b43223SZhihuan He clrsetbits_le32(pctl_base + DDR_PCTL2_SCHED1, 0xff, 0x1 << 0); 234922b43223SZhihuan He } else { 2350e8885e24SCanYang He clrbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2); 235122b43223SZhihuan He } 2352e8885e24SCanYang He 2353ee5f0829STang Yun ping #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT 2354ee5f0829STang Yun ping u32 tmp, trefi; 2355ee5f0829STang Yun ping 2356ee5f0829STang Yun ping tmp = readl(pctl_base + DDR_PCTL2_RFSHTMG); 2357ee5f0829STang Yun ping trefi = (tmp >> 16) & 0xfff; 2358ee5f0829STang Yun ping writel((tmp & 0xf000ffff) | (trefi / 2) << 16, 2359ee5f0829STang Yun ping pctl_base + DDR_PCTL2_RFSHTMG); 2360ee5f0829STang Yun ping #endif 2361ee5f0829STang Yun ping 2362f520bb22SYouMin Chen /* set frequency_mode */ 2363f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29); 2364f520bb22SYouMin Chen /* set target_frequency to Frequency 0 */ 2365f520bb22SYouMin Chen clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, 0); 2366f520bb22SYouMin Chen 2367f520bb22SYouMin Chen set_ds_odt(dram, sdram_params, 0); 2368f520bb22SYouMin Chen sdram_params->ch.cap_info.ddrconfig = calculate_ddrconfig(sdram_params); 2369f520bb22SYouMin Chen set_ctl_address_map(dram, sdram_params); 2370f520bb22SYouMin Chen 2371f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4)); 2372f520bb22SYouMin Chen 2373f520bb22SYouMin Chen rkclk_ddr_reset(dram, 0, 0, 0, 0); 2374f520bb22SYouMin Chen 2375f520bb22SYouMin Chen while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0) 2376f520bb22SYouMin Chen continue; 2377f520bb22SYouMin Chen 2378f520bb22SYouMin Chen if (sdram_params->base.dramtype == LPDDR3) { 2379f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, LPDDR3); 2380f520bb22SYouMin Chen } else if (sdram_params->base.dramtype == LPDDR4) { 2381f520bb22SYouMin Chen mr_tmp = readl(pctl_base + DDR_PCTL2_INIT6); 2382f520bb22SYouMin Chen /* MR11 */ 2383f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 11, 2384f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK, 2385f520bb22SYouMin Chen LPDDR4); 2386f520bb22SYouMin Chen /* MR12 */ 2387f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 12, 2388f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK, 2389f520bb22SYouMin Chen LPDDR4); 2390f520bb22SYouMin Chen 2391f520bb22SYouMin Chen mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7); 2392f520bb22SYouMin Chen /* MR22 */ 2393f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 22, 2394f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK, 2395f520bb22SYouMin Chen LPDDR4); 2396f520bb22SYouMin Chen /* MR14 */ 2397f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 14, 2398f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK, 2399f520bb22SYouMin Chen LPDDR4); 2400f520bb22SYouMin Chen } 2401f520bb22SYouMin Chen 2402f520bb22SYouMin Chen if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) != 0) { 2403f520bb22SYouMin Chen if (post_init != 0) 2404f520bb22SYouMin Chen printascii("DTT cs0 error\n"); 2405f520bb22SYouMin Chen return -1; 2406f520bb22SYouMin Chen } 2407f520bb22SYouMin Chen 2408f520bb22SYouMin Chen if (post_init != 0 && sdram_params->ch.cap_info.rank == 2) { 2409f520bb22SYouMin Chen if (data_training(dram, 1, sdram_params, 0, 2410f520bb22SYouMin Chen READ_GATE_TRAINING) != 0) { 2411f520bb22SYouMin Chen printascii("DTT cs1 error\n"); 2412f520bb22SYouMin Chen return -1; 2413f520bb22SYouMin Chen } 2414f520bb22SYouMin Chen } 2415f520bb22SYouMin Chen 2416f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR4) { 2417f520bb22SYouMin Chen ddr4_vref = readl(PHY_REG(phy_base, 0x105)) * 39; 2418f520bb22SYouMin Chen pctl_write_vrefdq(dram->pctl, 0x3, ddr4_vref, 2419f520bb22SYouMin Chen sdram_params->base.dramtype); 2420f520bb22SYouMin Chen } 2421f520bb22SYouMin Chen 2422f520bb22SYouMin Chen dram_all_config(dram, sdram_params); 2423f520bb22SYouMin Chen enable_low_power(dram, sdram_params); 2424f520bb22SYouMin Chen 2425f520bb22SYouMin Chen return 0; 2426f520bb22SYouMin Chen } 2427f520bb22SYouMin Chen 2428f520bb22SYouMin Chen static u64 dram_detect_cap(struct dram_info *dram, 2429f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params, 2430f520bb22SYouMin Chen unsigned char channel) 2431f520bb22SYouMin Chen { 2432f520bb22SYouMin Chen struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info; 2433f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 2434f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 2435f520bb22SYouMin Chen u32 mr8; 2436f520bb22SYouMin Chen 2437f520bb22SYouMin Chen u32 bktmp; 2438f520bb22SYouMin Chen u32 coltmp; 2439f520bb22SYouMin Chen u32 rowtmp; 2440f520bb22SYouMin Chen u32 cs; 2441f520bb22SYouMin Chen u32 dram_type = sdram_params->base.dramtype; 2442f520bb22SYouMin Chen u32 pwrctl; 24439d5c314bSWesley Yao u32 i, dq_map; 24449d5c314bSWesley Yao u32 byte1 = 0, byte0 = 0; 2445f520bb22SYouMin Chen 24469d5c314bSWesley Yao cap_info->bw = dram_type == DDR3 ? 0 : 1; 2447f520bb22SYouMin Chen if (dram_type != LPDDR4) { 2448f520bb22SYouMin Chen if (dram_type != DDR4) { 2449f520bb22SYouMin Chen coltmp = 12; 2450f520bb22SYouMin Chen bktmp = 3; 2451f520bb22SYouMin Chen if (dram_type == LPDDR2) 2452f520bb22SYouMin Chen rowtmp = 15; 2453f520bb22SYouMin Chen else 2454f520bb22SYouMin Chen rowtmp = 16; 2455f520bb22SYouMin Chen 2456f520bb22SYouMin Chen if (sdram_detect_col(cap_info, coltmp) != 0) 2457f520bb22SYouMin Chen goto cap_err; 2458f520bb22SYouMin Chen 2459f520bb22SYouMin Chen sdram_detect_bank(cap_info, coltmp, bktmp); 2460f520bb22SYouMin Chen sdram_detect_dbw(cap_info, dram_type); 2461f520bb22SYouMin Chen } else { 2462f520bb22SYouMin Chen coltmp = 10; 2463f520bb22SYouMin Chen bktmp = 4; 2464f520bb22SYouMin Chen rowtmp = 17; 2465f520bb22SYouMin Chen 2466f520bb22SYouMin Chen cap_info->col = 10; 2467f520bb22SYouMin Chen cap_info->bk = 2; 2468f520bb22SYouMin Chen sdram_detect_bg(cap_info, coltmp); 2469f520bb22SYouMin Chen } 2470f520bb22SYouMin Chen 2471f520bb22SYouMin Chen if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0) 2472f520bb22SYouMin Chen goto cap_err; 2473f520bb22SYouMin Chen 2474f520bb22SYouMin Chen sdram_detect_row_3_4(cap_info, coltmp, bktmp); 2475f520bb22SYouMin Chen } else { 2476f520bb22SYouMin Chen mr8 = (read_mr(dram, 1, 8, dram_type) >> 2) & 0xf; 2477f520bb22SYouMin Chen cap_info->col = 10; 2478f520bb22SYouMin Chen cap_info->bk = 3; 2479f520bb22SYouMin Chen cap_info->cs0_row = 14 + (mr8 + 1) / 2; 2480f520bb22SYouMin Chen if (mr8 % 2) 2481f520bb22SYouMin Chen cap_info->row_3_4 = 1; 2482f520bb22SYouMin Chen else 2483f520bb22SYouMin Chen cap_info->row_3_4 = 0; 2484f520bb22SYouMin Chen cap_info->dbw = 1; 2485f520bb22SYouMin Chen cap_info->bw = 2; 2486f520bb22SYouMin Chen } 2487f520bb22SYouMin Chen 2488f520bb22SYouMin Chen pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL); 2489f520bb22SYouMin Chen writel(0, pctl_base + DDR_PCTL2_PWRCTL); 2490f520bb22SYouMin Chen 2491f520bb22SYouMin Chen if (data_training(dram, 1, sdram_params, 0, READ_GATE_TRAINING) == 0) 2492f520bb22SYouMin Chen cs = 1; 2493f520bb22SYouMin Chen else 2494f520bb22SYouMin Chen cs = 0; 2495f520bb22SYouMin Chen cap_info->rank = cs + 1; 2496f520bb22SYouMin Chen 2497f520bb22SYouMin Chen if (dram_type != LPDDR4) { 2498f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0xf), 0xf); 2499f520bb22SYouMin Chen 2500f520bb22SYouMin Chen if (data_training(dram, 0, sdram_params, 0, 25019d5c314bSWesley Yao READ_GATE_TRAINING) == 0) { 2502f520bb22SYouMin Chen cap_info->bw = 2; 25039d5c314bSWesley Yao } else { 25049d5c314bSWesley Yao dq_map = readl(PHY_REG(phy_base, 0x4f)); 25059d5c314bSWesley Yao for (i = 0; i < 4; i++) { 25069d5c314bSWesley Yao if (((dq_map >> (i * 2)) & 0x3) == 0) 25079d5c314bSWesley Yao byte0 = i; 25089d5c314bSWesley Yao if (((dq_map >> (i * 2)) & 0x3) == 1) 25099d5c314bSWesley Yao byte1 = i; 25109d5c314bSWesley Yao } 25119d5c314bSWesley Yao clrsetbits_le32(PHY_REG(phy_base, 0xf), PHY_DQ_WIDTH_MASK, 25129d5c314bSWesley Yao BIT(byte0) | BIT(byte1)); 25139d5c314bSWesley Yao if (data_training(dram, 0, sdram_params, 0, 25149d5c314bSWesley Yao READ_GATE_TRAINING) == 0) 2515f520bb22SYouMin Chen cap_info->bw = 1; 25169d5c314bSWesley Yao else 25179d5c314bSWesley Yao cap_info->bw = 0; 25189d5c314bSWesley Yao } 25193993b0c7SWesley Yao if (cap_info->bw > 0) 25203993b0c7SWesley Yao cap_info->dbw = 1; 2521f520bb22SYouMin Chen } 2522f520bb22SYouMin Chen 2523f520bb22SYouMin Chen writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL); 2524f520bb22SYouMin Chen 2525f520bb22SYouMin Chen cap_info->cs0_high16bit_row = cap_info->cs0_row; 2526f520bb22SYouMin Chen if (cs) { 2527f520bb22SYouMin Chen cap_info->cs1_row = cap_info->cs0_row; 2528f520bb22SYouMin Chen cap_info->cs1_high16bit_row = cap_info->cs0_row; 2529f520bb22SYouMin Chen } else { 2530f520bb22SYouMin Chen cap_info->cs1_row = 0; 2531f520bb22SYouMin Chen cap_info->cs1_high16bit_row = 0; 2532f520bb22SYouMin Chen } 2533f520bb22SYouMin Chen 2534f520bb22SYouMin Chen return 0; 2535f520bb22SYouMin Chen cap_err: 2536f520bb22SYouMin Chen return -1; 2537f520bb22SYouMin Chen } 2538f520bb22SYouMin Chen 2539f520bb22SYouMin Chen static int dram_detect_cs1_row(struct dram_info *dram, 2540f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params, 2541f520bb22SYouMin Chen unsigned char channel) 2542f520bb22SYouMin Chen { 2543f520bb22SYouMin Chen struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info; 2544f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 2545f520bb22SYouMin Chen u32 ret = 0; 2546f520bb22SYouMin Chen void __iomem *test_addr; 2547f520bb22SYouMin Chen u32 row, bktmp, coltmp, bw; 2548f520bb22SYouMin Chen u64 cs0_cap; 2549f520bb22SYouMin Chen u32 byte_mask; 2550f520bb22SYouMin Chen u32 cs_pst; 2551f520bb22SYouMin Chen u32 cs_add = 0; 2552f520bb22SYouMin Chen u32 max_row; 2553f520bb22SYouMin Chen 2554f520bb22SYouMin Chen if (cap_info->rank == 2) { 2555f520bb22SYouMin Chen cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) + 2556f520bb22SYouMin Chen 6 + 2; 2557f520bb22SYouMin Chen if (cs_pst < 28) 2558f520bb22SYouMin Chen cs_add = 1; 2559f520bb22SYouMin Chen 2560f520bb22SYouMin Chen cs0_cap = 1 << cs_pst; 2561f520bb22SYouMin Chen 2562f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR4) { 2563f520bb22SYouMin Chen if (cap_info->dbw == 0) 2564f520bb22SYouMin Chen bktmp = cap_info->bk + 2; 2565f520bb22SYouMin Chen else 2566f520bb22SYouMin Chen bktmp = cap_info->bk + 1; 2567f520bb22SYouMin Chen } else { 2568f520bb22SYouMin Chen bktmp = cap_info->bk; 2569f520bb22SYouMin Chen } 2570f520bb22SYouMin Chen bw = cap_info->bw; 2571f520bb22SYouMin Chen coltmp = cap_info->col; 2572f520bb22SYouMin Chen 2573f520bb22SYouMin Chen if (bw == 2) 2574f520bb22SYouMin Chen byte_mask = 0xFFFF; 2575f520bb22SYouMin Chen else 2576f520bb22SYouMin Chen byte_mask = 0xFF; 2577f520bb22SYouMin Chen 2578f520bb22SYouMin Chen max_row = (cs_pst == 31) ? 30 : 31; 2579f520bb22SYouMin Chen 2580f520bb22SYouMin Chen max_row = max_row - bktmp - coltmp - bw - cs_add + 1; 2581f520bb22SYouMin Chen 2582f520bb22SYouMin Chen row = (cap_info->cs0_row > max_row) ? max_row : 2583f520bb22SYouMin Chen cap_info->cs0_row; 2584f520bb22SYouMin Chen 2585f520bb22SYouMin Chen for (; row > 12; row--) { 2586f520bb22SYouMin Chen test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE + 2587f520bb22SYouMin Chen (u32)cs0_cap + 2588f520bb22SYouMin Chen (1ul << (row + bktmp + coltmp + 2589f520bb22SYouMin Chen cs_add + bw - 1ul))); 2590f520bb22SYouMin Chen 2591f520bb22SYouMin Chen writel(0, CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap); 2592f520bb22SYouMin Chen writel(PATTERN, test_addr); 2593f520bb22SYouMin Chen 2594f520bb22SYouMin Chen if (((readl(test_addr) & byte_mask) == 2595f520bb22SYouMin Chen (PATTERN & byte_mask)) && 2596f520bb22SYouMin Chen ((readl(CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap) & 2597f520bb22SYouMin Chen byte_mask) == 0)) { 2598f520bb22SYouMin Chen ret = row; 2599f520bb22SYouMin Chen break; 2600f520bb22SYouMin Chen } 2601f520bb22SYouMin Chen } 2602f520bb22SYouMin Chen } 2603f520bb22SYouMin Chen 2604f520bb22SYouMin Chen return ret; 2605f520bb22SYouMin Chen } 2606f520bb22SYouMin Chen 2607f520bb22SYouMin Chen /* return: 0 = success, other = fail */ 2608f520bb22SYouMin Chen static int sdram_init_detect(struct dram_info *dram, 2609f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 2610f520bb22SYouMin Chen { 2611f520bb22SYouMin Chen struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info; 2612f520bb22SYouMin Chen u32 ret; 2613f520bb22SYouMin Chen u32 sys_reg = 0; 2614f520bb22SYouMin Chen u32 sys_reg3 = 0; 26151040f70aSTang Yun ping struct sdram_head_info_index_v2 *index = 26161040f70aSTang Yun ping (struct sdram_head_info_index_v2 *)common_info; 26171040f70aSTang Yun ping struct dq_map_info *map_info; 2618f520bb22SYouMin Chen 26191040f70aSTang Yun ping map_info = (struct dq_map_info *)((void *)common_info + 26201040f70aSTang Yun ping index->dq_map_index.offset * 4); 26211040f70aSTang Yun ping 26221040f70aSTang Yun ping if (sdram_init_(dram, sdram_params, 0)) { 26231040f70aSTang Yun ping if (sdram_params->base.dramtype == DDR3) { 26241040f70aSTang Yun ping clrsetbits_le32(&map_info->byte_map[0], 0xff << 24, 26251040f70aSTang Yun ping ((0x1 << 6) | (0x3 << 4) | (0x2 << 2) | 26261040f70aSTang Yun ping (0x0 << 0)) << 24); 26271040f70aSTang Yun ping if (sdram_init_(dram, sdram_params, 0)) 2628f520bb22SYouMin Chen return -1; 26291040f70aSTang Yun ping } else { 26301040f70aSTang Yun ping return -1; 26311040f70aSTang Yun ping } 26321040f70aSTang Yun ping } 2633f520bb22SYouMin Chen 2634f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR3) { 2635f520bb22SYouMin Chen writel(PATTERN, CONFIG_SYS_SDRAM_BASE); 2636f520bb22SYouMin Chen if (readl(CONFIG_SYS_SDRAM_BASE) != PATTERN) 2637f520bb22SYouMin Chen return -1; 2638f520bb22SYouMin Chen } 2639f520bb22SYouMin Chen 2640f520bb22SYouMin Chen if (dram_detect_cap(dram, sdram_params, 0) != 0) 2641f520bb22SYouMin Chen return -1; 2642f520bb22SYouMin Chen 2643f520bb22SYouMin Chen pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info, 2644f520bb22SYouMin Chen sdram_params->base.dramtype); 2645f520bb22SYouMin Chen ret = sdram_init_(dram, sdram_params, 1); 2646f520bb22SYouMin Chen if (ret != 0) 2647f520bb22SYouMin Chen goto out; 2648f520bb22SYouMin Chen 2649f520bb22SYouMin Chen cap_info->cs1_row = 2650f520bb22SYouMin Chen dram_detect_cs1_row(dram, sdram_params, 0); 2651f520bb22SYouMin Chen if (cap_info->cs1_row) { 2652f520bb22SYouMin Chen sys_reg = readl(&dram->pmugrf->os_reg[2]); 2653f520bb22SYouMin Chen sys_reg3 = readl(&dram->pmugrf->os_reg[3]); 2654f520bb22SYouMin Chen SYS_REG_ENC_CS1_ROW(cap_info->cs1_row, 2655f520bb22SYouMin Chen sys_reg, sys_reg3, 0); 2656f520bb22SYouMin Chen writel(sys_reg, &dram->pmugrf->os_reg[2]); 2657f520bb22SYouMin Chen writel(sys_reg3, &dram->pmugrf->os_reg[3]); 2658f520bb22SYouMin Chen } 2659f520bb22SYouMin Chen 2660f520bb22SYouMin Chen sdram_detect_high_row(cap_info); 2661f520bb22SYouMin Chen 2662f520bb22SYouMin Chen out: 2663f520bb22SYouMin Chen return ret; 2664f520bb22SYouMin Chen } 2665f520bb22SYouMin Chen 2666f520bb22SYouMin Chen struct rv1126_sdram_params *get_default_sdram_config(u32 freq_mhz) 2667f520bb22SYouMin Chen { 2668f520bb22SYouMin Chen u32 i; 2669f520bb22SYouMin Chen u32 offset = 0; 2670f520bb22SYouMin Chen struct ddr2_3_4_lp2_3_info *ddr_info; 2671f520bb22SYouMin Chen 2672f520bb22SYouMin Chen if (!freq_mhz) { 2673f520bb22SYouMin Chen ddr_info = get_ddr_drv_odt_info(sdram_configs[0].base.dramtype); 2674f520bb22SYouMin Chen if (ddr_info) 2675f520bb22SYouMin Chen freq_mhz = 2676f520bb22SYouMin Chen (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) & 2677f520bb22SYouMin Chen DDR_FREQ_MASK; 2678f520bb22SYouMin Chen else 2679f520bb22SYouMin Chen freq_mhz = 0; 2680f520bb22SYouMin Chen } 2681f520bb22SYouMin Chen 2682f520bb22SYouMin Chen for (i = 0; i < ARRAY_SIZE(sdram_configs); i++) { 2683f520bb22SYouMin Chen if (sdram_configs[i].base.ddr_freq == 0 || 2684f520bb22SYouMin Chen freq_mhz < sdram_configs[i].base.ddr_freq) 2685f520bb22SYouMin Chen break; 2686f520bb22SYouMin Chen } 2687f520bb22SYouMin Chen offset = i == 0 ? 0 : i - 1; 2688f520bb22SYouMin Chen 2689f520bb22SYouMin Chen return &sdram_configs[offset]; 2690f520bb22SYouMin Chen } 2691f520bb22SYouMin Chen 2692f520bb22SYouMin Chen static const u16 pctl_need_update_reg[] = { 2693f520bb22SYouMin Chen DDR_PCTL2_RFSHTMG, 2694f520bb22SYouMin Chen DDR_PCTL2_INIT3, 2695f520bb22SYouMin Chen DDR_PCTL2_INIT4, 2696f520bb22SYouMin Chen DDR_PCTL2_INIT6, 2697f520bb22SYouMin Chen DDR_PCTL2_INIT7, 2698f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG0, 2699f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG1, 2700f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG2, 2701f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG3, 2702f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG4, 2703f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG5, 2704f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG6, 2705f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG7, 2706f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG8, 2707f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG9, 2708f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG12, 2709f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG13, 2710f520bb22SYouMin Chen DDR_PCTL2_DRAMTMG14, 2711f520bb22SYouMin Chen DDR_PCTL2_ZQCTL0, 2712f520bb22SYouMin Chen DDR_PCTL2_DFITMG0, 2713f520bb22SYouMin Chen DDR_PCTL2_ODTCFG 2714f520bb22SYouMin Chen }; 2715f520bb22SYouMin Chen 2716f520bb22SYouMin Chen static const u16 phy_need_update_reg[] = { 2717f520bb22SYouMin Chen 0x14, 2718f520bb22SYouMin Chen 0x18, 2719f520bb22SYouMin Chen 0x1c 2720f520bb22SYouMin Chen }; 2721f520bb22SYouMin Chen 2722f520bb22SYouMin Chen static void pre_set_rate(struct dram_info *dram, 2723f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params, 2724f520bb22SYouMin Chen u32 dst_fsp, u32 dst_fsp_lp4) 2725f520bb22SYouMin Chen { 2726f520bb22SYouMin Chen u32 i, j, find; 2727f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 2728f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 2729f520bb22SYouMin Chen u32 phy_offset; 2730f520bb22SYouMin Chen u32 mr_tmp; 2731f520bb22SYouMin Chen u32 dramtype = sdram_params->base.dramtype; 2732f520bb22SYouMin Chen 2733f520bb22SYouMin Chen sw_set_req(dram); 2734f520bb22SYouMin Chen /* pctl timing update */ 2735f520bb22SYouMin Chen for (i = 0, find = 0; i < ARRAY_SIZE(pctl_need_update_reg); i++) { 2736f520bb22SYouMin Chen for (j = find; sdram_params->pctl_regs.pctl[j][0] != 0xFFFFFFFF; 2737f520bb22SYouMin Chen j++) { 2738f520bb22SYouMin Chen if (sdram_params->pctl_regs.pctl[j][0] == 2739f520bb22SYouMin Chen pctl_need_update_reg[i]) { 2740f520bb22SYouMin Chen writel(sdram_params->pctl_regs.pctl[j][1], 2741f520bb22SYouMin Chen pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2742f520bb22SYouMin Chen pctl_need_update_reg[i]); 2743f520bb22SYouMin Chen find = j; 2744f520bb22SYouMin Chen break; 2745f520bb22SYouMin Chen } 2746f520bb22SYouMin Chen } 2747f520bb22SYouMin Chen } 2748ee5f0829STang Yun ping 2749ee5f0829STang Yun ping #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT 2750ee5f0829STang Yun ping u32 tmp, trefi; 2751ee5f0829STang Yun ping 2752ee5f0829STang Yun ping tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG); 2753ee5f0829STang Yun ping trefi = (tmp >> 16) & 0xfff; 2754ee5f0829STang Yun ping writel((tmp & 0xf000ffff) | (trefi / 2) << 16, 2755ee5f0829STang Yun ping pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG); 2756ee5f0829STang Yun ping #endif 2757ee5f0829STang Yun ping 2758f520bb22SYouMin Chen sw_set_ack(dram); 2759f520bb22SYouMin Chen 2760f520bb22SYouMin Chen /* phy timing update */ 2761f520bb22SYouMin Chen if (dst_fsp == 0) 2762f520bb22SYouMin Chen phy_offset = 0; 2763f520bb22SYouMin Chen else 2764f520bb22SYouMin Chen phy_offset = PHY_REG(0, 0x387 - 5 + (dst_fsp - 1) * 3); 2765f520bb22SYouMin Chen /* cl cwl al update */ 2766f520bb22SYouMin Chen for (i = 0, find = 0; i < ARRAY_SIZE(phy_need_update_reg); i++) { 2767f520bb22SYouMin Chen for (j = find; sdram_params->phy_regs.phy[j][0] != 0xFFFFFFFF; 2768f520bb22SYouMin Chen j++) { 2769f520bb22SYouMin Chen if (sdram_params->phy_regs.phy[j][0] == 2770f520bb22SYouMin Chen phy_need_update_reg[i]) { 2771f520bb22SYouMin Chen writel(sdram_params->phy_regs.phy[j][1], 2772f520bb22SYouMin Chen phy_base + phy_offset + 2773f520bb22SYouMin Chen phy_need_update_reg[i]); 2774f520bb22SYouMin Chen find = j; 2775f520bb22SYouMin Chen break; 2776f520bb22SYouMin Chen } 2777f520bb22SYouMin Chen } 2778f520bb22SYouMin Chen } 2779f520bb22SYouMin Chen 2780f520bb22SYouMin Chen set_ds_odt(dram, sdram_params, dst_fsp); 2781f520bb22SYouMin Chen if (dramtype == LPDDR4) { 2782f520bb22SYouMin Chen mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2783f520bb22SYouMin Chen DDR_PCTL2_INIT4); 2784f520bb22SYouMin Chen /* MR13 */ 2785f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 13, 2786f520bb22SYouMin Chen ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT & 2787f520bb22SYouMin Chen PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) | 2788f520bb22SYouMin Chen ((0x2 << 6) >> dst_fsp_lp4), dramtype); 2789f520bb22SYouMin Chen writel(((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT & 2790f520bb22SYouMin Chen PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) | 2791f520bb22SYouMin Chen ((0x2 << 6) >> dst_fsp_lp4), 2792f520bb22SYouMin Chen PHY_REG(phy_base, 0x1b)); 2793f520bb22SYouMin Chen /* MR3 */ 2794f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 3, 2795f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT & 2796f520bb22SYouMin Chen PCTL2_MR_MASK, 2797f520bb22SYouMin Chen dramtype); 2798f520bb22SYouMin Chen writel(mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK, 2799f520bb22SYouMin Chen PHY_REG(phy_base, 0x19)); 2800f520bb22SYouMin Chen 2801f520bb22SYouMin Chen mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2802f520bb22SYouMin Chen DDR_PCTL2_INIT3); 2803f520bb22SYouMin Chen /* MR1 */ 2804f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 1, 2805f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT & 2806f520bb22SYouMin Chen PCTL2_MR_MASK, 2807f520bb22SYouMin Chen dramtype); 2808f520bb22SYouMin Chen writel(mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT & PCTL2_MR_MASK, 2809f520bb22SYouMin Chen PHY_REG(phy_base, 0x17)); 2810f520bb22SYouMin Chen /* MR2 */ 2811f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK, 2812f520bb22SYouMin Chen dramtype); 2813f520bb22SYouMin Chen writel(mr_tmp & PCTL2_MR_MASK, 2814f520bb22SYouMin Chen PHY_REG(phy_base, 0x18)); 2815f520bb22SYouMin Chen 2816f520bb22SYouMin Chen mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2817f520bb22SYouMin Chen DDR_PCTL2_INIT6); 2818f520bb22SYouMin Chen /* MR11 */ 2819f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 11, 2820f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK, 2821f520bb22SYouMin Chen dramtype); 2822f520bb22SYouMin Chen writel(mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK, 2823f520bb22SYouMin Chen PHY_REG(phy_base, 0x1a)); 2824f520bb22SYouMin Chen /* MR12 */ 2825f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 12, 2826f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK, 2827f520bb22SYouMin Chen dramtype); 2828f520bb22SYouMin Chen 2829f520bb22SYouMin Chen mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2830f520bb22SYouMin Chen DDR_PCTL2_INIT7); 2831f520bb22SYouMin Chen /* MR22 */ 2832f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 22, 2833f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK, 2834f520bb22SYouMin Chen dramtype); 2835f520bb22SYouMin Chen writel(mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK, 2836f520bb22SYouMin Chen PHY_REG(phy_base, 0x1d)); 2837f520bb22SYouMin Chen /* MR14 */ 2838f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 14, 2839f520bb22SYouMin Chen mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK, 2840f520bb22SYouMin Chen dramtype); 2841f520bb22SYouMin Chen writel(mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK, 2842f520bb22SYouMin Chen PHY_REG(phy_base, 0x1c)); 2843f520bb22SYouMin Chen } 2844f520bb22SYouMin Chen 2845f520bb22SYouMin Chen update_noc_timing(dram, sdram_params); 2846f520bb22SYouMin Chen } 2847f520bb22SYouMin Chen 2848f520bb22SYouMin Chen static void save_fsp_param(struct dram_info *dram, u32 dst_fsp, 2849f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 2850f520bb22SYouMin Chen { 2851f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 2852f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 2853f520bb22SYouMin Chen struct rv1126_fsp_param *p_fsp_param = &fsp_param[dst_fsp]; 2854f520bb22SYouMin Chen u32 temp, temp1; 2855f520bb22SYouMin Chen struct ddr2_3_4_lp2_3_info *ddr_info; 2856f520bb22SYouMin Chen 2857f520bb22SYouMin Chen ddr_info = get_ddr_drv_odt_info(sdram_params->base.dramtype); 2858f520bb22SYouMin Chen 2859f520bb22SYouMin Chen p_fsp_param->freq_mhz = sdram_params->base.ddr_freq; 2860f520bb22SYouMin Chen 2861f520bb22SYouMin Chen if (sdram_params->base.dramtype == LPDDR4) { 2862f520bb22SYouMin Chen p_fsp_param->rd_odt_up_en = 0; 2863f520bb22SYouMin Chen p_fsp_param->rd_odt_down_en = 1; 2864f520bb22SYouMin Chen } else { 2865f520bb22SYouMin Chen p_fsp_param->rd_odt_up_en = 2866f520bb22SYouMin Chen ODT_INFO_PULLUP_EN(ddr_info->odt_info); 2867f520bb22SYouMin Chen p_fsp_param->rd_odt_down_en = 2868f520bb22SYouMin Chen ODT_INFO_PULLDOWN_EN(ddr_info->odt_info); 2869f520bb22SYouMin Chen } 2870f520bb22SYouMin Chen 2871f520bb22SYouMin Chen if (p_fsp_param->rd_odt_up_en) 2872f520bb22SYouMin Chen p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x111)); 2873f520bb22SYouMin Chen else if (p_fsp_param->rd_odt_down_en) 2874f520bb22SYouMin Chen p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x110)); 2875f520bb22SYouMin Chen else 2876f520bb22SYouMin Chen p_fsp_param->rd_odt = 0; 2877f520bb22SYouMin Chen p_fsp_param->wr_dq_drv = readl(PHY_REG(phy_base, 0x112)); 2878f520bb22SYouMin Chen p_fsp_param->wr_ca_drv = readl(PHY_REG(phy_base, 0x100)); 2879f520bb22SYouMin Chen p_fsp_param->wr_ckcs_drv = readl(PHY_REG(phy_base, 0x102)); 2880f520bb22SYouMin Chen p_fsp_param->vref_inner = readl(PHY_REG(phy_base, 0x128)); 2881f520bb22SYouMin Chen p_fsp_param->vref_out = readl(PHY_REG(phy_base, 0x105)); 2882f520bb22SYouMin Chen 2883f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR3) { 2884f520bb22SYouMin Chen temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2885f520bb22SYouMin Chen DDR_PCTL2_INIT3); 2886f520bb22SYouMin Chen temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK; 28878e4f57b9SYouMin Chen p_fsp_param->ds_pdds = temp & DDR3_DS_MASK; 28888e4f57b9SYouMin Chen p_fsp_param->dq_odt = temp & DDR3_RTT_NOM_MASK; 2889f520bb22SYouMin Chen p_fsp_param->ca_odt = p_fsp_param->dq_odt; 2890f520bb22SYouMin Chen } else if (sdram_params->base.dramtype == DDR4) { 2891f520bb22SYouMin Chen temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2892f520bb22SYouMin Chen DDR_PCTL2_INIT3); 2893f520bb22SYouMin Chen temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK; 28948e4f57b9SYouMin Chen p_fsp_param->ds_pdds = temp & DDR4_DS_MASK; 28958e4f57b9SYouMin Chen p_fsp_param->dq_odt = temp & DDR4_RTT_NOM_MASK; 2896f520bb22SYouMin Chen p_fsp_param->ca_odt = p_fsp_param->dq_odt; 2897f520bb22SYouMin Chen } else if (sdram_params->base.dramtype == LPDDR3) { 2898f520bb22SYouMin Chen temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2899f520bb22SYouMin Chen DDR_PCTL2_INIT4); 2900f520bb22SYouMin Chen temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK; 2901f520bb22SYouMin Chen p_fsp_param->ds_pdds = temp & 0xf; 2902f520bb22SYouMin Chen 2903f520bb22SYouMin Chen p_fsp_param->dq_odt = lp3_odt_value; 2904f520bb22SYouMin Chen p_fsp_param->ca_odt = p_fsp_param->dq_odt; 2905f520bb22SYouMin Chen } else if (sdram_params->base.dramtype == LPDDR4) { 2906f520bb22SYouMin Chen temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2907f520bb22SYouMin Chen DDR_PCTL2_INIT4); 2908f520bb22SYouMin Chen temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK; 29098e4f57b9SYouMin Chen p_fsp_param->ds_pdds = temp & LPDDR4_PDDS_MASK; 2910f520bb22SYouMin Chen 2911f520bb22SYouMin Chen temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 2912f520bb22SYouMin Chen DDR_PCTL2_INIT6); 2913f520bb22SYouMin Chen temp = (temp >> PCTL2_LPDDR4_MR11_SHIFT) & PCTL2_MR_MASK; 29148e4f57b9SYouMin Chen p_fsp_param->dq_odt = temp & LPDDR4_DQODT_MASK; 29158e4f57b9SYouMin Chen p_fsp_param->ca_odt = temp & LPDDR4_CAODT_MASK; 2916f520bb22SYouMin Chen 2917f520bb22SYouMin Chen temp = MAX(readl(PHY_REG(phy_base, 0x3ae)), 2918f520bb22SYouMin Chen readl(PHY_REG(phy_base, 0x3ce))); 2919f520bb22SYouMin Chen temp1 = MIN(readl(PHY_REG(phy_base, 0x3be)), 2920f520bb22SYouMin Chen readl(PHY_REG(phy_base, 0x3de))); 2921f520bb22SYouMin Chen p_fsp_param->vref_ca[0] = (temp + temp1) / 2; 2922f520bb22SYouMin Chen temp = MAX(readl(PHY_REG(phy_base, 0x3af)), 2923f520bb22SYouMin Chen readl(PHY_REG(phy_base, 0x3cf))); 2924f520bb22SYouMin Chen temp1 = MIN(readl(PHY_REG(phy_base, 0x3bf)), 2925f520bb22SYouMin Chen readl(PHY_REG(phy_base, 0x3df))); 2926f520bb22SYouMin Chen p_fsp_param->vref_ca[1] = (temp + temp1) / 2; 2927f520bb22SYouMin Chen p_fsp_param->vref_ca[0] |= 2928f520bb22SYouMin Chen (readl(PHY_REG(phy_base, 0x1e)) & BIT(6)); 2929f520bb22SYouMin Chen p_fsp_param->vref_ca[1] |= 2930f520bb22SYouMin Chen (readl(PHY_REG(phy_base, 0x1e)) & BIT(6)); 2931f520bb22SYouMin Chen 2932f520bb22SYouMin Chen p_fsp_param->lp4_drv_pd_en = (readl(PHY_REG(phy_base, 0x114)) >> 2933f520bb22SYouMin Chen 3) & 0x1; 2934f520bb22SYouMin Chen } 2935f520bb22SYouMin Chen 2936f520bb22SYouMin Chen p_fsp_param->noc_timings.ddrtiminga0 = 2937f520bb22SYouMin Chen sdram_params->ch.noc_timings.ddrtiminga0; 2938f520bb22SYouMin Chen p_fsp_param->noc_timings.ddrtimingb0 = 2939f520bb22SYouMin Chen sdram_params->ch.noc_timings.ddrtimingb0; 2940f520bb22SYouMin Chen p_fsp_param->noc_timings.ddrtimingc0 = 2941f520bb22SYouMin Chen sdram_params->ch.noc_timings.ddrtimingc0; 2942f520bb22SYouMin Chen p_fsp_param->noc_timings.devtodev0 = 2943f520bb22SYouMin Chen sdram_params->ch.noc_timings.devtodev0; 2944f520bb22SYouMin Chen p_fsp_param->noc_timings.ddrmode = 2945f520bb22SYouMin Chen sdram_params->ch.noc_timings.ddrmode; 2946f520bb22SYouMin Chen p_fsp_param->noc_timings.ddr4timing = 2947f520bb22SYouMin Chen sdram_params->ch.noc_timings.ddr4timing; 2948f520bb22SYouMin Chen p_fsp_param->noc_timings.agingx0 = 2949f520bb22SYouMin Chen sdram_params->ch.noc_timings.agingx0; 2950f520bb22SYouMin Chen p_fsp_param->noc_timings.aging0 = 2951f520bb22SYouMin Chen sdram_params->ch.noc_timings.aging0; 2952f520bb22SYouMin Chen p_fsp_param->noc_timings.aging1 = 2953f520bb22SYouMin Chen sdram_params->ch.noc_timings.aging1; 2954f520bb22SYouMin Chen p_fsp_param->noc_timings.aging2 = 2955f520bb22SYouMin Chen sdram_params->ch.noc_timings.aging2; 2956f520bb22SYouMin Chen p_fsp_param->noc_timings.aging3 = 2957f520bb22SYouMin Chen sdram_params->ch.noc_timings.aging3; 2958f520bb22SYouMin Chen 2959f520bb22SYouMin Chen p_fsp_param->flag = FSP_FLAG; 2960f520bb22SYouMin Chen } 2961f520bb22SYouMin Chen 2962958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT 2963f520bb22SYouMin Chen static void copy_fsp_param_to_ddr(void) 2964f520bb22SYouMin Chen { 2965f520bb22SYouMin Chen memcpy((void *)FSP_PARAM_STORE_ADDR, (void *)&fsp_param, 2966f520bb22SYouMin Chen sizeof(fsp_param)); 2967f520bb22SYouMin Chen } 2968d3f5f12cSTang Yun ping #endif 2969f520bb22SYouMin Chen 2970e2dc1cc0SWesley Yao static void pctl_modify_trfc(struct ddr_pctl_regs *pctl_regs, 2971e2dc1cc0SWesley Yao struct sdram_cap_info *cap_info, u32 dram_type, 2972e2dc1cc0SWesley Yao u32 freq) 2973e2dc1cc0SWesley Yao { 2974e2dc1cc0SWesley Yao u64 cs0_cap; 2975e2dc1cc0SWesley Yao u32 die_cap; 2976e2dc1cc0SWesley Yao u32 trfc_ns, trfc4_ns; 2977e2dc1cc0SWesley Yao u32 trfc, txsnr; 2978e2dc1cc0SWesley Yao u32 txs_abort_fast = 0; 2979e2dc1cc0SWesley Yao u32 tmp; 2980e2dc1cc0SWesley Yao 2981e2dc1cc0SWesley Yao cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type); 2982e2dc1cc0SWesley Yao die_cap = (u32)(cs0_cap >> (20 + (cap_info->bw - cap_info->dbw))); 2983e2dc1cc0SWesley Yao 2984e2dc1cc0SWesley Yao switch (dram_type) { 2985e2dc1cc0SWesley Yao case DDR3: 2986e2dc1cc0SWesley Yao if (die_cap <= DIE_CAP_512MBIT) 2987e2dc1cc0SWesley Yao trfc_ns = 90; 2988e2dc1cc0SWesley Yao else if (die_cap <= DIE_CAP_1GBIT) 2989e2dc1cc0SWesley Yao trfc_ns = 110; 2990e2dc1cc0SWesley Yao else if (die_cap <= DIE_CAP_2GBIT) 2991e2dc1cc0SWesley Yao trfc_ns = 160; 2992e2dc1cc0SWesley Yao else if (die_cap <= DIE_CAP_4GBIT) 2993e2dc1cc0SWesley Yao trfc_ns = 260; 2994e2dc1cc0SWesley Yao else 2995e2dc1cc0SWesley Yao trfc_ns = 350; 2996e2dc1cc0SWesley Yao txsnr = MAX(5, ((trfc_ns + 10) * freq + 999) / 1000); 2997e2dc1cc0SWesley Yao break; 2998e2dc1cc0SWesley Yao 2999e2dc1cc0SWesley Yao case DDR4: 3000e2dc1cc0SWesley Yao if (die_cap <= DIE_CAP_2GBIT) { 3001e2dc1cc0SWesley Yao trfc_ns = 160; 3002e2dc1cc0SWesley Yao trfc4_ns = 90; 3003e2dc1cc0SWesley Yao } else if (die_cap <= DIE_CAP_4GBIT) { 3004e2dc1cc0SWesley Yao trfc_ns = 260; 3005e2dc1cc0SWesley Yao trfc4_ns = 110; 3006e2dc1cc0SWesley Yao } else if (die_cap <= DIE_CAP_8GBIT) { 3007e2dc1cc0SWesley Yao trfc_ns = 350; 3008e2dc1cc0SWesley Yao trfc4_ns = 160; 3009e2dc1cc0SWesley Yao } else { 3010e2dc1cc0SWesley Yao trfc_ns = 550; 3011e2dc1cc0SWesley Yao trfc4_ns = 260; 3012e2dc1cc0SWesley Yao } 3013e2dc1cc0SWesley Yao txsnr = ((trfc_ns + 10) * freq + 999) / 1000; 3014e2dc1cc0SWesley Yao txs_abort_fast = ((trfc4_ns + 10) * freq + 999) / 1000; 3015e2dc1cc0SWesley Yao break; 3016e2dc1cc0SWesley Yao 3017e2dc1cc0SWesley Yao case LPDDR3: 3018e2dc1cc0SWesley Yao if (die_cap <= DIE_CAP_4GBIT) 3019e2dc1cc0SWesley Yao trfc_ns = 130; 3020e2dc1cc0SWesley Yao else 3021e2dc1cc0SWesley Yao trfc_ns = 210; 3022e2dc1cc0SWesley Yao txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000); 3023e2dc1cc0SWesley Yao break; 3024e2dc1cc0SWesley Yao 3025e2dc1cc0SWesley Yao case LPDDR4: 3026e2dc1cc0SWesley Yao case LPDDR4X: 3027e2dc1cc0SWesley Yao if (die_cap <= DIE_CAP_4GBIT) 3028e2dc1cc0SWesley Yao trfc_ns = 130; 3029e2dc1cc0SWesley Yao else if (die_cap <= DIE_CAP_8GBIT) 3030e2dc1cc0SWesley Yao trfc_ns = 180; 3031e2dc1cc0SWesley Yao else if (die_cap <= DIE_CAP_16GBIT) 3032e2dc1cc0SWesley Yao trfc_ns = 280; 3033e2dc1cc0SWesley Yao else 3034e2dc1cc0SWesley Yao trfc_ns = 380; 3035e2dc1cc0SWesley Yao txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000); 3036e2dc1cc0SWesley Yao break; 3037e2dc1cc0SWesley Yao 3038e2dc1cc0SWesley Yao default: 3039e2dc1cc0SWesley Yao return; 3040e2dc1cc0SWesley Yao } 3041e2dc1cc0SWesley Yao trfc = (trfc_ns * freq + 999) / 1000; 3042e2dc1cc0SWesley Yao 3043e2dc1cc0SWesley Yao for (int i = 0; pctl_regs->pctl[i][0] != 0xffffffff; i++) { 3044e2dc1cc0SWesley Yao switch (pctl_regs->pctl[i][0]) { 3045e2dc1cc0SWesley Yao case DDR_PCTL2_RFSHTMG: 3046e2dc1cc0SWesley Yao tmp = pctl_regs->pctl[i][1]; 3047e2dc1cc0SWesley Yao /* t_rfc_min */ 3048e2dc1cc0SWesley Yao tmp &= ~((u32)0x3ff); 3049e2dc1cc0SWesley Yao tmp |= ((trfc + 1) / 2) & 0x3ff; 3050e2dc1cc0SWesley Yao pctl_regs->pctl[i][1] = tmp; 3051e2dc1cc0SWesley Yao break; 3052e2dc1cc0SWesley Yao 3053e2dc1cc0SWesley Yao case DDR_PCTL2_DRAMTMG8: 3054e2dc1cc0SWesley Yao if (dram_type == DDR3 || dram_type == DDR4) { 3055e2dc1cc0SWesley Yao tmp = pctl_regs->pctl[i][1]; 3056e2dc1cc0SWesley Yao /* t_xs_x32 */ 3057e2dc1cc0SWesley Yao tmp &= ~((u32)0x7f); 3058e2dc1cc0SWesley Yao tmp |= ((txsnr + 63) / 64) & 0x7f; 3059e2dc1cc0SWesley Yao 3060e2dc1cc0SWesley Yao if (dram_type == DDR4) { 3061e2dc1cc0SWesley Yao /* t_xs_abort_x32 */ 3062e2dc1cc0SWesley Yao tmp &= ~((u32)(0x7f << 16)); 3063e2dc1cc0SWesley Yao tmp |= (((txs_abort_fast + 63) / 64) & 0x7f) << 16; 3064e2dc1cc0SWesley Yao /* t_xs_fast_x32 */ 3065e2dc1cc0SWesley Yao tmp &= ~((u32)(0x7f << 24)); 3066e2dc1cc0SWesley Yao tmp |= (((txs_abort_fast + 63) / 64) & 0x7f) << 24; 3067e2dc1cc0SWesley Yao } 3068e2dc1cc0SWesley Yao 3069e2dc1cc0SWesley Yao pctl_regs->pctl[i][1] = tmp; 3070e2dc1cc0SWesley Yao } 3071e2dc1cc0SWesley Yao break; 3072e2dc1cc0SWesley Yao 3073e2dc1cc0SWesley Yao case DDR_PCTL2_DRAMTMG14: 3074e2dc1cc0SWesley Yao if (dram_type == LPDDR3 || 3075e2dc1cc0SWesley Yao dram_type == LPDDR4 || dram_type == LPDDR4X) { 3076e2dc1cc0SWesley Yao tmp = pctl_regs->pctl[i][1]; 3077e2dc1cc0SWesley Yao /* t_xsr */ 3078e2dc1cc0SWesley Yao tmp &= ~((u32)0xfff); 3079e2dc1cc0SWesley Yao tmp |= ((txsnr + 1) / 2) & 0xfff; 3080e2dc1cc0SWesley Yao pctl_regs->pctl[i][1] = tmp; 3081e2dc1cc0SWesley Yao } 3082e2dc1cc0SWesley Yao break; 3083e2dc1cc0SWesley Yao 3084e2dc1cc0SWesley Yao default: 3085e2dc1cc0SWesley Yao break; 3086e2dc1cc0SWesley Yao } 3087e2dc1cc0SWesley Yao } 3088e2dc1cc0SWesley Yao } 3089e2dc1cc0SWesley Yao 3090f520bb22SYouMin Chen void ddr_set_rate(struct dram_info *dram, 3091f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params, 3092f520bb22SYouMin Chen u32 freq, u32 cur_freq, u32 dst_fsp, 3093f520bb22SYouMin Chen u32 dst_fsp_lp4, u32 training_en) 3094f520bb22SYouMin Chen { 3095f520bb22SYouMin Chen u32 dest_dll_off, cur_init3, dst_init3, cur_fsp, cur_dll_off; 3096f520bb22SYouMin Chen u32 mr_tmp; 3097f520bb22SYouMin Chen u32 lp_stat; 3098f520bb22SYouMin Chen u32 dramtype = sdram_params->base.dramtype; 3099f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params_new; 3100f520bb22SYouMin Chen void __iomem *pctl_base = dram->pctl; 3101f520bb22SYouMin Chen void __iomem *phy_base = dram->phy; 3102f520bb22SYouMin Chen 3103f520bb22SYouMin Chen lp_stat = low_power_update(dram, 0); 3104f520bb22SYouMin Chen sdram_params_new = get_default_sdram_config(freq); 3105f520bb22SYouMin Chen sdram_params_new->ch.cap_info.rank = sdram_params->ch.cap_info.rank; 310638b16f08SYouMin Chen sdram_params_new->ch.cap_info.bw = sdram_params->ch.cap_info.bw; 3107f520bb22SYouMin Chen 3108e2dc1cc0SWesley Yao pctl_modify_trfc(&sdram_params_new->pctl_regs, 3109e2dc1cc0SWesley Yao &sdram_params->ch.cap_info, dramtype, freq); 3110f520bb22SYouMin Chen pre_set_rate(dram, sdram_params_new, dst_fsp, dst_fsp_lp4); 3111f520bb22SYouMin Chen 3112f520bb22SYouMin Chen while ((readl(pctl_base + DDR_PCTL2_STAT) & 3113f520bb22SYouMin Chen PCTL2_OPERATING_MODE_MASK) == 3114f520bb22SYouMin Chen PCTL2_OPERATING_MODE_SR) 3115f520bb22SYouMin Chen continue; 3116f520bb22SYouMin Chen 3117f520bb22SYouMin Chen dest_dll_off = 0; 3118f520bb22SYouMin Chen dst_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 3119f520bb22SYouMin Chen DDR_PCTL2_INIT3); 3120f520bb22SYouMin Chen if ((dramtype == DDR3 && (dst_init3 & 1)) || 3121f520bb22SYouMin Chen (dramtype == DDR4 && !(dst_init3 & 1))) 3122f520bb22SYouMin Chen dest_dll_off = 1; 3123f520bb22SYouMin Chen 3124f520bb22SYouMin Chen cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3; 3125f520bb22SYouMin Chen cur_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + 3126f520bb22SYouMin Chen DDR_PCTL2_INIT3); 3127f520bb22SYouMin Chen cur_init3 &= PCTL2_MR_MASK; 3128f520bb22SYouMin Chen cur_dll_off = 1; 3129f520bb22SYouMin Chen if ((dramtype == DDR3 && !(cur_init3 & 1)) || 3130f520bb22SYouMin Chen (dramtype == DDR4 && (cur_init3 & 1))) 3131f520bb22SYouMin Chen cur_dll_off = 0; 3132f520bb22SYouMin Chen 3133f520bb22SYouMin Chen if (!cur_dll_off) { 3134f520bb22SYouMin Chen if (dramtype == DDR3) 3135f520bb22SYouMin Chen cur_init3 |= 1; 3136f520bb22SYouMin Chen else 3137f520bb22SYouMin Chen cur_init3 &= ~1; 3138f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 2, 1, cur_init3, dramtype); 3139f520bb22SYouMin Chen } 3140f520bb22SYouMin Chen 3141f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 3142f520bb22SYouMin Chen PCTL2_DIS_AUTO_REFRESH); 3143f520bb22SYouMin Chen update_refresh_reg(dram); 3144f520bb22SYouMin Chen 3145f4f57f8eSTang Yun ping enter_sr(dram, 1); 3146f520bb22SYouMin Chen 3147f520bb22SYouMin Chen writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK | 3148f520bb22SYouMin Chen PMUGRF_CON_DDRPHY_BUFFEREN_EN, 3149df8389e3STang Yun ping &dram->pmugrf->soc_con[0]); 3150f520bb22SYouMin Chen sw_set_req(dram); 3151f520bb22SYouMin Chen clrbits_le32(pctl_base + DDR_PCTL2_DFIMISC, 3152f520bb22SYouMin Chen PCTL2_DFI_INIT_COMPLETE_EN); 3153f520bb22SYouMin Chen sw_set_ack(dram); 3154f520bb22SYouMin Chen 3155f520bb22SYouMin Chen sw_set_req(dram); 3156f520bb22SYouMin Chen if ((dramtype == DDR3 || dramtype == DDR4) && dest_dll_off) 3157f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE); 3158f520bb22SYouMin Chen else 3159f520bb22SYouMin Chen clrbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE); 3160f520bb22SYouMin Chen 3161f520bb22SYouMin Chen setbits_le32(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_ZQCTL0, 3162f520bb22SYouMin Chen PCTL2_DIS_SRX_ZQCL); 3163f520bb22SYouMin Chen setbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_ZQCTL0, 3164f520bb22SYouMin Chen PCTL2_DIS_SRX_ZQCL); 3165f520bb22SYouMin Chen sw_set_ack(dram); 3166f520bb22SYouMin Chen 3167f520bb22SYouMin Chen writel(DDR_MSCH_EN_MASK | (0x1 << DDR_MSCH_EN_SHIFT), 3168df8389e3STang Yun ping &dram->cru->clkgate_con[21]); 3169f520bb22SYouMin Chen writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK | 3170f520bb22SYouMin Chen (0x1 << CLK_DDR_UPCTL_EN_SHIFT) | 3171f520bb22SYouMin Chen (0x1 << ACLK_DDR_UPCTL_EN_SHIFT), 3172f520bb22SYouMin Chen BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12); 3173f520bb22SYouMin Chen 3174f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET); 3175f520bb22SYouMin Chen rkclk_set_dpll(dram, freq * MHz / 2); 3176f520bb22SYouMin Chen phy_pll_set(dram, freq * MHz, 0); 3177f520bb22SYouMin Chen phy_pll_set(dram, freq * MHz, 1); 3178f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET); 3179f520bb22SYouMin Chen 3180f520bb22SYouMin Chen writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK | 3181f520bb22SYouMin Chen PMUGRF_CON_DDRPHY_BUFFEREN_DIS, 3182df8389e3STang Yun ping &dram->pmugrf->soc_con[0]); 3183f520bb22SYouMin Chen writel(DDR_MSCH_EN_MASK | (0x0 << DDR_MSCH_EN_SHIFT), 3184df8389e3STang Yun ping &dram->cru->clkgate_con[21]); 3185f520bb22SYouMin Chen writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK | 3186f520bb22SYouMin Chen (0x0 << CLK_DDR_UPCTL_EN_SHIFT) | 3187f520bb22SYouMin Chen (0x0 << ACLK_DDR_UPCTL_EN_SHIFT), 3188f520bb22SYouMin Chen BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12); 3189f520bb22SYouMin Chen while ((readl(pctl_base + DDR_PCTL2_DFISTAT) & 3190f520bb22SYouMin Chen PCTL2_DFI_INIT_COMPLETE) != PCTL2_DFI_INIT_COMPLETE) 3191f520bb22SYouMin Chen continue; 3192f520bb22SYouMin Chen 3193f520bb22SYouMin Chen sw_set_req(dram); 3194f520bb22SYouMin Chen setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29); 3195f520bb22SYouMin Chen clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, dst_fsp); 3196f520bb22SYouMin Chen sw_set_ack(dram); 3197f520bb22SYouMin Chen update_refresh_reg(dram); 3198f520bb22SYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0xc), 0x3 << 2, dst_fsp << 2); 3199f520bb22SYouMin Chen 3200f4f57f8eSTang Yun ping enter_sr(dram, 0); 3201f520bb22SYouMin Chen 3202f520bb22SYouMin Chen setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5); 3203f520bb22SYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5); 3204f520bb22SYouMin Chen 3205f520bb22SYouMin Chen mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_INIT4); 3206f520bb22SYouMin Chen if (dramtype == LPDDR3) { 3207f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 1, 3208f520bb22SYouMin Chen (dst_init3 >> PCTL2_LPDDR234_MR1_SHIFT) & 3209f520bb22SYouMin Chen PCTL2_MR_MASK, 3210f520bb22SYouMin Chen dramtype); 3211f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 2, dst_init3 & PCTL2_MR_MASK, 3212f520bb22SYouMin Chen dramtype); 3213f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 3, 3214f520bb22SYouMin Chen (mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT) & 3215f520bb22SYouMin Chen PCTL2_MR_MASK, 3216f520bb22SYouMin Chen dramtype); 3217f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, dramtype); 3218f520bb22SYouMin Chen } else if ((dramtype == DDR3) || (dramtype == DDR4)) { 3219f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 1, dst_init3 & PCTL2_MR_MASK, 3220f520bb22SYouMin Chen dramtype); 3221f520bb22SYouMin Chen if (!dest_dll_off) { 3222f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 0, 3223f520bb22SYouMin Chen ((dst_init3 >> PCTL2_DDR34_MR0_SHIFT) & 3224f520bb22SYouMin Chen PCTL2_MR_MASK) | DDR3_DLL_RESET, 3225f520bb22SYouMin Chen dramtype); 3226f520bb22SYouMin Chen udelay(2); 3227f520bb22SYouMin Chen } 3228f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 0, 3229f520bb22SYouMin Chen (dst_init3 >> PCTL2_DDR34_MR0_SHIFT & 3230f520bb22SYouMin Chen PCTL2_MR_MASK) & (~DDR3_DLL_RESET), 3231f520bb22SYouMin Chen dramtype); 3232f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 2, 3233f520bb22SYouMin Chen ((mr_tmp >> PCTL2_DDR34_MR2_SHIFT) & 3234f520bb22SYouMin Chen PCTL2_MR_MASK), dramtype); 3235f520bb22SYouMin Chen if (dramtype == DDR4) { 3236f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 3, mr_tmp & PCTL2_MR_MASK, 3237f520bb22SYouMin Chen dramtype); 3238f520bb22SYouMin Chen mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 3239f520bb22SYouMin Chen DDR_PCTL2_INIT6); 3240f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 4, 3241f520bb22SYouMin Chen (mr_tmp >> PCTL2_DDR4_MR4_SHIFT) & 3242f520bb22SYouMin Chen PCTL2_MR_MASK, 3243f520bb22SYouMin Chen dramtype); 3244f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 5, 3245f520bb22SYouMin Chen mr_tmp >> PCTL2_DDR4_MR5_SHIFT & 3246f520bb22SYouMin Chen PCTL2_MR_MASK, 3247f520bb22SYouMin Chen dramtype); 3248f520bb22SYouMin Chen 3249f520bb22SYouMin Chen mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + 3250f520bb22SYouMin Chen DDR_PCTL2_INIT7); 3251f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 6, 3252f520bb22SYouMin Chen mr_tmp >> PCTL2_DDR4_MR6_SHIFT & 3253f520bb22SYouMin Chen PCTL2_MR_MASK, 3254f520bb22SYouMin Chen dramtype); 3255f520bb22SYouMin Chen } 3256f520bb22SYouMin Chen } else if (dramtype == LPDDR4) { 3257f520bb22SYouMin Chen pctl_write_mr(dram->pctl, 3, 13, 3258f520bb22SYouMin Chen ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT & 3259f520bb22SYouMin Chen PCTL2_MR_MASK) & (~(BIT(7)))) | 3260f520bb22SYouMin Chen dst_fsp_lp4 << 7, dramtype); 3261f520bb22SYouMin Chen } 3262f4f57f8eSTang Yun ping clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 3263f4f57f8eSTang Yun ping PCTL2_DIS_AUTO_REFRESH); 3264f4f57f8eSTang Yun ping update_refresh_reg(dram); 3265f520bb22SYouMin Chen 3266f520bb22SYouMin Chen /* training */ 3267f520bb22SYouMin Chen high_freq_training(dram, sdram_params_new, dst_fsp); 3268f520bb22SYouMin Chen low_power_update(dram, lp_stat); 3269f520bb22SYouMin Chen 3270f520bb22SYouMin Chen save_fsp_param(dram, dst_fsp, sdram_params_new); 3271f520bb22SYouMin Chen } 3272f520bb22SYouMin Chen 3273f520bb22SYouMin Chen static void ddr_set_rate_for_fsp(struct dram_info *dram, 3274f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params) 3275f520bb22SYouMin Chen { 3276f520bb22SYouMin Chen struct ddr2_3_4_lp2_3_info *ddr_info; 3277d3f5f12cSTang Yun ping u32 f0; 3278f520bb22SYouMin Chen u32 dramtype = sdram_params->base.dramtype; 3279958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT 3280d3f5f12cSTang Yun ping u32 f1, f2, f3; 3281d3f5f12cSTang Yun ping #endif 3282f520bb22SYouMin Chen 3283f520bb22SYouMin Chen ddr_info = get_ddr_drv_odt_info(dramtype); 3284f520bb22SYouMin Chen if (!ddr_info) 3285f520bb22SYouMin Chen return; 3286f520bb22SYouMin Chen 3287d3f5f12cSTang Yun ping f0 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) & 3288d3f5f12cSTang Yun ping DDR_FREQ_MASK; 3289d3f5f12cSTang Yun ping 3290958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT 3291f520bb22SYouMin Chen memset((void *)FSP_PARAM_STORE_ADDR, 0, sizeof(fsp_param)); 3292f520bb22SYouMin Chen memset((void *)&fsp_param, 0, sizeof(fsp_param)); 3293f520bb22SYouMin Chen 3294f520bb22SYouMin Chen f1 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F1_SHIFT) & 3295f520bb22SYouMin Chen DDR_FREQ_MASK; 3296f520bb22SYouMin Chen f2 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F2_SHIFT) & 3297f520bb22SYouMin Chen DDR_FREQ_MASK; 3298f520bb22SYouMin Chen f3 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F3_SHIFT) & 3299f520bb22SYouMin Chen DDR_FREQ_MASK; 3300d3f5f12cSTang Yun ping #endif 3301f520bb22SYouMin Chen 3302f520bb22SYouMin Chen if (get_wrlvl_val(dram, sdram_params)) 3303f520bb22SYouMin Chen printascii("get wrlvl value fail\n"); 3304d3f5f12cSTang Yun ping 3305958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT 3306f876ce9bSTang Yun ping printascii("change to: "); 3307f520bb22SYouMin Chen printdec(f1); 3308f520bb22SYouMin Chen printascii("MHz\n"); 3309f520bb22SYouMin Chen ddr_set_rate(&dram_info, sdram_params, f1, 3310f520bb22SYouMin Chen sdram_params->base.ddr_freq, 1, 1, 1); 3311f876ce9bSTang Yun ping printascii("change to: "); 3312f520bb22SYouMin Chen printdec(f2); 3313f520bb22SYouMin Chen printascii("MHz\n"); 3314f520bb22SYouMin Chen ddr_set_rate(&dram_info, sdram_params, f2, f1, 2, 0, 1); 3315f876ce9bSTang Yun ping printascii("change to: "); 3316f520bb22SYouMin Chen printdec(f3); 3317f520bb22SYouMin Chen printascii("MHz\n"); 3318f520bb22SYouMin Chen ddr_set_rate(&dram_info, sdram_params, f3, f2, 3, 1, 1); 3319d3f5f12cSTang Yun ping #endif 3320f876ce9bSTang Yun ping printascii("change to: "); 3321f520bb22SYouMin Chen printdec(f0); 3322f876ce9bSTang Yun ping printascii("MHz(final freq)\n"); 3323958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT 3324f520bb22SYouMin Chen ddr_set_rate(&dram_info, sdram_params, f0, f3, 0, 0, 1); 3325d3f5f12cSTang Yun ping #else 3326d3f5f12cSTang Yun ping ddr_set_rate(&dram_info, sdram_params, f0, sdram_params->base.ddr_freq, 1, 1, 1); 3327d3f5f12cSTang Yun ping #endif 3328f520bb22SYouMin Chen } 3329f520bb22SYouMin Chen 3330f520bb22SYouMin Chen int get_uart_config(void) 3331f520bb22SYouMin Chen { 3332f520bb22SYouMin Chen struct sdram_head_info_index_v2 *index = 3333f520bb22SYouMin Chen (struct sdram_head_info_index_v2 *)common_info; 3334f520bb22SYouMin Chen struct global_info *gbl_info; 3335f520bb22SYouMin Chen 3336f520bb22SYouMin Chen gbl_info = (struct global_info *)((void *)common_info + 3337f520bb22SYouMin Chen index->global_index.offset * 4); 3338f520bb22SYouMin Chen 3339f520bb22SYouMin Chen return gbl_info->uart_info; 3340f520bb22SYouMin Chen } 3341f520bb22SYouMin Chen 3342f520bb22SYouMin Chen /* return: 0 = success, other = fail */ 3343f520bb22SYouMin Chen int sdram_init(void) 3344f520bb22SYouMin Chen { 3345f520bb22SYouMin Chen struct rv1126_sdram_params *sdram_params; 3346f520bb22SYouMin Chen int ret = 0; 3347f520bb22SYouMin Chen struct sdram_head_info_index_v2 *index = 3348f520bb22SYouMin Chen (struct sdram_head_info_index_v2 *)common_info; 3349f520bb22SYouMin Chen struct global_info *gbl_info; 3350f520bb22SYouMin Chen 3351f520bb22SYouMin Chen dram_info.phy = (void *)DDR_PHY_BASE_ADDR; 3352f520bb22SYouMin Chen dram_info.pctl = (void *)UPCTL2_BASE_ADDR; 3353f520bb22SYouMin Chen dram_info.grf = (void *)GRF_BASE_ADDR; 3354f520bb22SYouMin Chen dram_info.cru = (void *)CRU_BASE_ADDR; 3355f520bb22SYouMin Chen dram_info.msch = (void *)SERVER_MSCH_BASE_ADDR; 3356f520bb22SYouMin Chen dram_info.ddrgrf = (void *)DDR_GRF_BASE_ADDR; 3357f520bb22SYouMin Chen dram_info.pmugrf = (void *)PMU_GRF_BASE_ADDR; 3358f520bb22SYouMin Chen 3359ee5f0829STang Yun ping #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT 3360ee5f0829STang Yun ping printascii("extended temp support\n"); 3361ee5f0829STang Yun ping #endif 3362f520bb22SYouMin Chen if (index->version_info != 2 || 3363f520bb22SYouMin Chen (index->global_index.size != sizeof(struct global_info) / 4) || 3364f520bb22SYouMin Chen (index->ddr3_index.size != 3365f520bb22SYouMin Chen sizeof(struct ddr2_3_4_lp2_3_info) / 4) || 3366f520bb22SYouMin Chen (index->ddr4_index.size != 3367f520bb22SYouMin Chen sizeof(struct ddr2_3_4_lp2_3_info) / 4) || 3368f520bb22SYouMin Chen (index->lp3_index.size != 3369f520bb22SYouMin Chen sizeof(struct ddr2_3_4_lp2_3_info) / 4) || 3370f520bb22SYouMin Chen (index->lp4_index.size != (sizeof(struct lp4_info) / 4)) || 3371f520bb22SYouMin Chen index->global_index.offset == 0 || 3372f520bb22SYouMin Chen index->ddr3_index.offset == 0 || 3373f520bb22SYouMin Chen index->ddr4_index.offset == 0 || 3374f520bb22SYouMin Chen index->lp3_index.offset == 0 || 3375f520bb22SYouMin Chen index->lp4_index.offset == 0) { 3376f520bb22SYouMin Chen printascii("common info error\n"); 3377f520bb22SYouMin Chen goto error; 3378f520bb22SYouMin Chen } 3379f520bb22SYouMin Chen 3380f520bb22SYouMin Chen gbl_info = (struct global_info *)((void *)common_info + 3381f520bb22SYouMin Chen index->global_index.offset * 4); 3382f520bb22SYouMin Chen 3383f520bb22SYouMin Chen dram_info.sr_idle = SR_INFO(gbl_info->sr_pd_info); 3384f520bb22SYouMin Chen dram_info.pd_idle = PD_INFO(gbl_info->sr_pd_info); 3385f520bb22SYouMin Chen 3386f520bb22SYouMin Chen sdram_params = &sdram_configs[0]; 3387f520bb22SYouMin Chen 3388f520bb22SYouMin Chen if (sdram_params->base.dramtype == DDR3 || 3389f520bb22SYouMin Chen sdram_params->base.dramtype == DDR4) { 3390f520bb22SYouMin Chen if (DDR_2T_INFO(gbl_info->info_2t)) 3391f520bb22SYouMin Chen sdram_params->pctl_regs.pctl[0][1] |= 0x1 << 10; 3392f520bb22SYouMin Chen else 3393f520bb22SYouMin Chen sdram_params->pctl_regs.pctl[0][1] &= 3394f520bb22SYouMin Chen ~(0x1 << 10); 3395f520bb22SYouMin Chen } 3396f520bb22SYouMin Chen ret = sdram_init_detect(&dram_info, sdram_params); 3397f520bb22SYouMin Chen if (ret) { 3398f520bb22SYouMin Chen sdram_print_dram_type(sdram_params->base.dramtype); 3399f520bb22SYouMin Chen printascii(", "); 3400f520bb22SYouMin Chen printdec(sdram_params->base.ddr_freq); 3401f520bb22SYouMin Chen printascii("MHz\n"); 3402f520bb22SYouMin Chen goto error; 3403f520bb22SYouMin Chen } 3404f520bb22SYouMin Chen print_ddr_info(sdram_params); 3405c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL) 3406c71eeac4SWesley Yao init_rw_trn_result_struct(&rw_trn_result, dram_info.phy, 3407c71eeac4SWesley Yao (u8)sdram_params->ch.cap_info.rank); 3408c71eeac4SWesley Yao #endif 3409f520bb22SYouMin Chen 3410f520bb22SYouMin Chen ddr_set_rate_for_fsp(&dram_info, sdram_params); 3411958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT 3412f520bb22SYouMin Chen copy_fsp_param_to_ddr(); 3413d3f5f12cSTang Yun ping #endif 3414f520bb22SYouMin Chen 3415f520bb22SYouMin Chen ddr_set_atags(&dram_info, sdram_params); 3416c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL) 3417c71eeac4SWesley Yao save_rw_trn_result_to_ddr(&rw_trn_result); 3418c71eeac4SWesley Yao #endif 3419f520bb22SYouMin Chen 3420f520bb22SYouMin Chen printascii("out\n"); 3421f520bb22SYouMin Chen 3422f520bb22SYouMin Chen return ret; 3423f520bb22SYouMin Chen error: 3424f520bb22SYouMin Chen printascii("error\n"); 3425f520bb22SYouMin Chen return (-1); 3426f520bb22SYouMin Chen } 3427f520bb22SYouMin Chen #endif /* CONFIG_TPL_BUILD */ 3428