TracyMg_Li | 734d577 | 2023-12-25 11:21:34 +0800 | [diff] [blame^] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* |
| 3 | * Copyright (C) 2023, Phytium Technology Co., Ltd. |
| 4 | * lixinde <lixinde@phytium.com.cn> |
| 5 | * weichangzheng <weichangzheng@phytium.com.cn> |
| 6 | */ |
| 7 | |
| 8 | #include <stdio.h> |
| 9 | #include <linux/arm-smccc.h> |
| 10 | #include <init.h> |
| 11 | #include "cpu.h" |
| 12 | |
| 13 | struct ddr_spd { |
| 14 | /***************** read from spd ******************/ |
| 15 | u8 dimm_type; /* 1: RDIMM; 2: UDIMM; 3: SODIMM; 4: LRDIMM */ |
| 16 | u8 data_width; /* 0: x4; 1: x8; 2: x16; 3: x32 */ |
| 17 | u8 mirror_type; /* 0: standard; 1: mirror */ |
| 18 | u8 ecc_type; /* 0: no-ecc; 1: ecc */ |
| 19 | u8 dram_type; /* 0xB: DDR3; 0xC: DDR4 */ |
| 20 | u8 rank_num; |
| 21 | u8 row_num; |
| 22 | u8 col_num; |
| 23 | |
| 24 | u8 bg_num; /* DDR4/DDR5 */ |
| 25 | u8 bank_num; |
| 26 | u16 module_manufacturer_id; |
| 27 | u16 taamin; |
| 28 | u16 trcdmin; |
| 29 | |
| 30 | u16 trpmin; |
| 31 | u16 trasmin; |
| 32 | u16 trcmin; |
| 33 | u16 tfawmin; /* only DDR3/DDR4 */ |
| 34 | |
| 35 | u16 trrd_smin; /* only DDR4 */ |
| 36 | u16 trrd_lmin; /* only DDR4 */ |
| 37 | u16 tccd_lmin; /* only DDR4 */ |
| 38 | u16 twrmin; |
| 39 | |
| 40 | u16 twtr_smin; /* only DDR4 */ |
| 41 | u16 twtr_lmin; /* only DDR4 */ |
| 42 | u32 trfc1min; |
| 43 | |
| 44 | u32 trfc2min; |
| 45 | u32 trfc4_rfcsbmin; /* DDR4: tRFC4min; DDR5: tRFCsbmin */ |
| 46 | u8 resv[8]; |
| 47 | |
| 48 | /***************** RCD control words ******************/ |
| 49 | u8 f0rc03; /* bit[3:2]:CS bit[1:0]:CA */ |
| 50 | u8 f0rc04; /* bit[3:2]:ODT bit[1:0]:CKE */ |
| 51 | u8 f0rc05; /* bit[3:2]:CLK-A side bit[1:0]:CLK-B side */ |
| 52 | u8 rcd_num; /* Registers used on RDIMM */ |
| 53 | |
| 54 | u8 lrdimm_resv[4]; |
| 55 | u8 lrdimm_resv1[8]; |
| 56 | u8 lrdimm_resv2[8]; |
| 57 | } __attribute((aligned(4))); |
| 58 | |
| 59 | struct mcu_config { |
| 60 | u32 magic; |
| 61 | u32 version; |
| 62 | u32 size; |
| 63 | u8 rev1[4]; |
| 64 | |
| 65 | u8 ch_enable; |
| 66 | u8 resv1[7]; |
| 67 | |
| 68 | u64 misc_enable; |
| 69 | |
| 70 | u8 train_debug; |
| 71 | u8 train_recover; |
| 72 | u8 train_param_type; |
| 73 | u8 train_param_1; /* DDR4: cpu_odt */ |
| 74 | u8 train_param_2; /* DDR4: cpu_drv */ |
| 75 | u8 train_param_3; /* DDR4: mr_drv */ |
| 76 | u8 train_param_4; /* DDR4: rtt_nom */ |
| 77 | u8 train_param_5; /* DDR4: rtt_park */ |
| 78 | |
| 79 | u8 train_param_6; /* DDR4: rtt_wr */ |
| 80 | u8 resv2[7]; |
| 81 | |
| 82 | /***************** for LPDDR4 dq swap ******************/ |
| 83 | u32 data_byte_swap; |
| 84 | u32 slice0_dq_swizzle; |
| 85 | |
| 86 | u32 slice1_dq_swizzle; |
| 87 | u32 slice2_dq_swizzle; |
| 88 | |
| 89 | u32 slice3_dq_swizzle; |
| 90 | u32 slice4_dq_swizzle; |
| 91 | |
| 92 | u32 slice5_dq_swizzle; |
| 93 | u32 slice6_dq_swizzle; |
| 94 | |
| 95 | u32 slice7_dq_swizzle; |
| 96 | u8 resv3[4]; |
| 97 | u8 resv4[8]; |
| 98 | |
| 99 | struct ddr_spd ddr_spd_info; |
| 100 | } __attribute((aligned(4))); |
| 101 | |
| 102 | static void get_mcu_up_info_default(struct mcu_config *pm) |
| 103 | { |
| 104 | pm->magic = PARAMETER_MCU_MAGIC; |
| 105 | pm->version = PARAM_MCU_VERSION; |
| 106 | pm->size = PARAM_MCU_SIZE; |
| 107 | pm->ch_enable = PARAM_CH_ENABLE; |
| 108 | } |
| 109 | |
| 110 | static u8 init_dimm_param(struct mcu_config *pm) |
| 111 | { |
| 112 | debug("manual config dimm info...\n"); |
| 113 | pm->misc_enable = 0x2001; |
| 114 | pm->train_debug = 0x0; |
| 115 | pm->train_recover = 0x0; |
| 116 | pm->train_param_type = 0x0; |
| 117 | pm->train_param_1 = 0x0; |
| 118 | pm->train_param_2 = 0x0; |
| 119 | pm->train_param_3 = 0x0; |
| 120 | pm->train_param_4 = 0x0; |
| 121 | pm->train_param_5 = 0x0; |
| 122 | pm->train_param_6 = 0x0; |
| 123 | |
| 124 | pm->data_byte_swap = 0x76543210; |
| 125 | pm->slice0_dq_swizzle = 0x3145726; |
| 126 | |
| 127 | pm->slice1_dq_swizzle = 0x54176230; |
| 128 | pm->slice2_dq_swizzle = 0x57604132; |
| 129 | |
| 130 | pm->slice3_dq_swizzle = 0x20631547; |
| 131 | pm->slice4_dq_swizzle = 0x16057423; |
| 132 | |
| 133 | pm->slice5_dq_swizzle = 0x16057423; |
| 134 | pm->slice6_dq_swizzle = 0x16057423; |
| 135 | |
| 136 | pm->slice7_dq_swizzle = 0x16057423; |
| 137 | |
| 138 | pm->ddr_spd_info.dimm_type = RDIMM_TYPE; |
| 139 | pm->ddr_spd_info.data_width = DIMM_X16; |
| 140 | pm->ddr_spd_info.mirror_type = NO_MIRROR; |
| 141 | pm->ddr_spd_info.ecc_type = NO_ECC_TYPE; |
| 142 | pm->ddr_spd_info.dram_type = LPDDR4_TYPE; |
| 143 | pm->ddr_spd_info.rank_num = 0x1; |
| 144 | pm->ddr_spd_info.row_num = 0x10; |
| 145 | pm->ddr_spd_info.col_num = 0xa; |
| 146 | pm->ddr_spd_info.bg_num = 0x0; |
| 147 | pm->ddr_spd_info.bank_num = 0x8; |
| 148 | pm->ddr_spd_info.taamin = 0x0; |
| 149 | pm->ddr_spd_info.trcdmin = 0x0; |
| 150 | |
| 151 | pm->ddr_spd_info.trpmin = 0x0; |
| 152 | pm->ddr_spd_info.trasmin = 0x0; |
| 153 | pm->ddr_spd_info.trcmin = 0x0; |
| 154 | pm->ddr_spd_info.tfawmin = 0x0; |
| 155 | |
| 156 | pm->ddr_spd_info.trrd_smin = 0x0; |
| 157 | pm->ddr_spd_info.trrd_lmin = 0x0; |
| 158 | pm->ddr_spd_info.tccd_lmin = 0x0; |
| 159 | pm->ddr_spd_info.twrmin = 0x0; |
| 160 | |
| 161 | pm->ddr_spd_info.twtr_smin = 0x0; |
| 162 | pm->ddr_spd_info.twtr_lmin = 0x0; |
| 163 | |
| 164 | return 0; |
| 165 | } |
| 166 | |
| 167 | void get_default_mcu_info(u8 *data) |
| 168 | { |
| 169 | get_mcu_up_info_default((struct mcu_config *)data); |
| 170 | } |
| 171 | |
| 172 | void fix_mcu_info(u8 *data) |
| 173 | { |
| 174 | struct mcu_config *mcu_info = (struct mcu_config *)data; |
| 175 | |
| 176 | init_dimm_param(mcu_info); |
| 177 | } |
| 178 | |
| 179 | void ddr_init(void) |
| 180 | { |
| 181 | u8 buffer[0x100]; |
| 182 | struct arm_smccc_res res; |
| 183 | |
| 184 | get_default_mcu_info(buffer); |
| 185 | fix_mcu_info(buffer); |
| 186 | |
| 187 | arm_smccc_smc(CPU_INIT_MEM, 0, (u64)buffer, 0, 0, 0, 0, 0, &res); |
| 188 | if (res.a0 != 0) |
| 189 | panic("DRAM init failed :0x%lx\n", res.a0); |
| 190 | } |