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