blob: 549d211ccdcaa0fbe82c815dd3271659cc3cdae1 [file] [log] [blame]
TracyMg_Li734d5772023-12-25 11:21:34 +08001// 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}