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 13struct 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 59struct 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 102static 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 110static 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 167void get_default_mcu_info(u8 *data) 168{ 169 get_mcu_up_info_default((struct mcu_config *)data); 170} 171 172void 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 179void 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} 191