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