xref: /rk3399_ARM-atf/drivers/st/ddr/phy/phyinit/src/ddrphy_phyinit_calcmb.c (revision b47dddd061e92054c3b2096fc8aa9688bfef68d6)
1 /*
2  * Copyright (C) 2021-2024, STMicroelectronics - All Rights Reserved
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdlib.h>
8 
9 #include <common/debug.h>
10 
11 #include <ddrphy_phyinit.h>
12 
13 /*
14  * Reads PhyInit inputs structures and sets relevant message block
15  * parameters.
16  *
17  * This function sets Message Block parameters based on user_input_basic and
18  * user_input_advanced. user changes in these files takes precedence
19  * over this function call.
20  *
21  * MessageBlock fields set :
22  *  - dramtype
23  *  - pstate
24  *  - dramfreq
25  *  - pllbypassen
26  *  - dfifreqratio
27  *  - phyodtimpedance
28  *  - phydrvimpedance
29  *  - bpznresval
30  *  - enableddqscha (LPDDR4)
31  *  - cspresentcha (LPDDR4)
32  *  - enableddqsChb (LPDDR4)
33  *  - cspresentchb (LPDDR4)
34  *  - enableddqs (DDR3/DDR4)
35  *  - phycfg (DDR3/DDR4)
36  *  - x16present (DDR4)
37  *
38  * \return 0 on success.
39  */
40 int ddrphy_phyinit_calcmb(struct stm32mp_ddr_config *config, struct pmu_smb_ddr_1d *mb_ddr_1d)
41 {
42 	uint32_t nad0 = config->uib.numactivedbytedfi0;
43 	uint32_t nad1 = 0;
44 	uint16_t mr4 __maybe_unused;
45 	uint16_t disableddbyte __maybe_unused;
46 	uint32_t dbyte __maybe_unused;
47 	int ret;
48 
49 #if STM32MP_LPDDR4_TYPE
50 	nad1 = config->uib.numactivedbytedfi1;
51 #endif /* STM32MP_LPDDR4_TYPE */
52 
53 	/* A few checks to make sure valid programming */
54 	if ((nad0 == 0U) || (config->uib.numdbyte == 0U)) {
55 		ERROR("%s %d\n", __func__, __LINE__);
56 		VERBOSE("%s numactivedbytedfi0, numactivedbytedfi0, NumByte out of range.\n",
57 			__func__);
58 		return -1;
59 	}
60 
61 	if ((nad0 + nad1) > config->uib.numdbyte) {
62 		ERROR("%s %d\n", __func__, __LINE__);
63 		VERBOSE("%s numactivedbytedfi0+numactivedbytedfi1 is larger than numdbyteDfi0\n",
64 			__func__);
65 		return -1;
66 	}
67 
68 	if ((config->uib.dfi1exists == 0U) && (nad1 != 0U)) {
69 		ERROR("%s %d\n", __func__, __LINE__);
70 		VERBOSE("%s dfi1exists==0 but numdbyteDfi0 != 0\n", __func__);
71 		return -1;
72 	}
73 
74 #if STM32MP_DDR4_TYPE
75 	/* OR all mr4 masked values, to help check in next loop */
76 	mr4 = mb_ddr_1d->mr4 & 0x1C0U;
77 
78 	/* 1D message block defaults */
79 	if (mr4 != 0x0U) {
80 		ERROR("mr4 != 0x0\n");
81 		VERBOSE("%s Setting DRAM CAL mode is not supported by the PHY.\n", __func__);
82 		VERBOSE("Memory controller may set CAL mode after PHY has entered mission\n");
83 		VERBOSE("mode. Please check value programmed in mb_ddr_1d[*].mr4\n");
84 		VERBOSE("and unset A8:6\n");
85 		return -1;
86 	}
87 #endif /* STM32MP_DDR4_TYPE */
88 
89 #if STM32MP_DDR3_TYPE
90 	if (config->uib.dimmtype == DDR_DIMMTYPE_NODIMM) {
91 		ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DRAMTYPE, 0x1U);
92 		if (ret != 0) {
93 			return ret;
94 		}
95 	}
96 #elif STM32MP_DDR4_TYPE
97 	if (config->uib.dimmtype == DDR_DIMMTYPE_NODIMM) {
98 		ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DRAMTYPE, 0x2U);
99 		if (ret != 0) {
100 			return ret;
101 		}
102 	}
103 #else /* STM32MP_LPDDR4_TYPE */
104 	/* Nothing to do */
105 #endif /* STM32MP_DDR3_TYPE */
106 
107 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PSTATE, 0U);
108 	if (ret != 0) {
109 		return ret;
110 	}
111 
112 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DRAMFREQ, config->uib.frequency * 2U);
113 	if (ret != 0) {
114 		return ret;
115 	}
116 
117 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PLLBYPASSEN, config->uib.pllbypass);
118 	if (ret != 0) {
119 		return ret;
120 	}
121 
122 	if (config->uib.dfifreqratio == 1U) {
123 		ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DFIFREQRATIO, 0x2U);
124 		if (ret != 0) {
125 			return ret;
126 		}
127 	}
128 
129 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PHYODTIMPEDANCE, 0U);
130 	if (ret != 0) {
131 		return ret;
132 	}
133 
134 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PHYDRVIMPEDANCE, 0U);
135 	if (ret != 0) {
136 		return ret;
137 	}
138 
139 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_BPZNRESVAL, 0U);
140 	if (ret != 0) {
141 		return ret;
142 	}
143 
144 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
145 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_ENABLEDDQS, nad0 * 8U);
146 	if (ret != 0) {
147 		return ret;
148 	}
149 
150 	disableddbyte = 0x0U;
151 
152 	for (dbyte = 0U; (dbyte < config->uib.numdbyte) && (dbyte < 8U); dbyte++) {
153 		if (ddrphy_phyinit_isdbytedisabled(config, mb_ddr_1d, dbyte) != 0) {
154 			disableddbyte |= 0x1U << dbyte;
155 		}
156 	}
157 
158 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DISABLEDDBYTE, disableddbyte);
159 	if (ret != 0) {
160 		return ret;
161 	}
162 
163 #if STM32MP_DDR3_TYPE
164 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PHYCFG, config->uia.is2ttiming);
165 	if (ret != 0) {
166 		return ret;
167 	}
168 #else /* STM32MP_DDR4_TYPE */
169 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PHYCFG,
170 				       ((mb_ddr_1d->mr3 & 0x8U) != 0U) ?
171 				       0U : config->uia.is2ttiming);
172 	if (ret != 0) {
173 		return ret;
174 	}
175 
176 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_X16PRESENT,
177 				       (config->uib.dramdatawidth == 0x10U) ?
178 				       mb_ddr_1d->cspresent : 0x0U);
179 	if (ret != 0) {
180 		return ret;
181 	}
182 #endif /* STM32MP_DDR3_TYPE */
183 #else /* STM32MP_LPDDR4_TYPE */
184 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_ENABLEDDQSCHA, nad0 * 8U);
185 	if (ret != 0) {
186 		return ret;
187 	}
188 
189 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_CSPRESENTCHA,
190 				       (config->uib.numrank_dfi0 == 2U) ?
191 				       0x3U : config->uib.numrank_dfi0);
192 	if (ret != 0) {
193 		return ret;
194 	}
195 
196 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_ENABLEDDQSCHB, nad1 * 8U);
197 	if (ret != 0) {
198 		return ret;
199 	}
200 
201 	ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_CSPRESENTCHB,
202 				       (config->uib.numrank_dfi1 == 2U) ?
203 				       0x3U : config->uib.numrank_dfi1);
204 	if (ret != 0) {
205 		return ret;
206 	}
207 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
208 
209 	return 0;
210 }
211