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