xref: /rk3399_ARM-atf/plat/st/stm32mp2/plat_ddr.c (revision e2d6e5e21adcf9e41a335c31d5c337c65ad0a133)
1*e2d6e5e2SPascal Paillet /*
2*e2d6e5e2SPascal Paillet  * Copyright (C) 2023-2024, STMicroelectronics - All Rights Reserved
3*e2d6e5e2SPascal Paillet  *
4*e2d6e5e2SPascal Paillet  * SPDX-License-Identifier: BSD-3-Clause
5*e2d6e5e2SPascal Paillet  */
6*e2d6e5e2SPascal Paillet 
7*e2d6e5e2SPascal Paillet #include <assert.h>
8*e2d6e5e2SPascal Paillet #include <errno.h>
9*e2d6e5e2SPascal Paillet #include <stdint.h>
10*e2d6e5e2SPascal Paillet 
11*e2d6e5e2SPascal Paillet #include <common/fdt_wrappers.h>
12*e2d6e5e2SPascal Paillet #include <drivers/delay_timer.h>
13*e2d6e5e2SPascal Paillet #include <drivers/st/regulator.h>
14*e2d6e5e2SPascal Paillet #include <drivers/st/stm32mp_ddr.h>
15*e2d6e5e2SPascal Paillet 
16*e2d6e5e2SPascal Paillet #include <libfdt.h>
17*e2d6e5e2SPascal Paillet #include <platform_def.h>
18*e2d6e5e2SPascal Paillet 
19*e2d6e5e2SPascal Paillet #if STM32MP_DDR3_TYPE
20*e2d6e5e2SPascal Paillet struct ddr3_supply {
21*e2d6e5e2SPascal Paillet 	struct rdev *vdd;
22*e2d6e5e2SPascal Paillet 	struct rdev *vref;
23*e2d6e5e2SPascal Paillet 	struct rdev *vtt;
24*e2d6e5e2SPascal Paillet };
25*e2d6e5e2SPascal Paillet 
26*e2d6e5e2SPascal Paillet static void ddr3_supply_read(void *fdt, int node, struct ddr3_supply *supply)
27*e2d6e5e2SPascal Paillet {
28*e2d6e5e2SPascal Paillet 	supply->vdd = regulator_get_by_supply_name(fdt, node, "vdd");
29*e2d6e5e2SPascal Paillet 	supply->vref = regulator_get_by_supply_name(fdt, node, "vref");
30*e2d6e5e2SPascal Paillet 	supply->vtt = regulator_get_by_supply_name(fdt, node, "vtt");
31*e2d6e5e2SPascal Paillet }
32*e2d6e5e2SPascal Paillet 
33*e2d6e5e2SPascal Paillet static int ddr_power_init(void *fdt, int node)
34*e2d6e5e2SPascal Paillet {
35*e2d6e5e2SPascal Paillet 	int status;
36*e2d6e5e2SPascal Paillet 	struct ddr3_supply supply;
37*e2d6e5e2SPascal Paillet 
38*e2d6e5e2SPascal Paillet 	ddr3_supply_read(fdt, node, &supply);
39*e2d6e5e2SPascal Paillet 	if ((supply.vdd == NULL) || (supply.vref == NULL) || (supply.vtt == NULL)) {
40*e2d6e5e2SPascal Paillet 		return -ENOENT;
41*e2d6e5e2SPascal Paillet 	}
42*e2d6e5e2SPascal Paillet 
43*e2d6e5e2SPascal Paillet 	/*
44*e2d6e5e2SPascal Paillet 	 * DDR3 power on sequence is:
45*e2d6e5e2SPascal Paillet 	 * enable VREF_DDR, VTT_DDR, VPP_DDR
46*e2d6e5e2SPascal Paillet 	 */
47*e2d6e5e2SPascal Paillet 	status = regulator_set_min_voltage(supply.vdd);
48*e2d6e5e2SPascal Paillet 	if (status != 0) {
49*e2d6e5e2SPascal Paillet 		return status;
50*e2d6e5e2SPascal Paillet 	}
51*e2d6e5e2SPascal Paillet 
52*e2d6e5e2SPascal Paillet 	status = regulator_enable(supply.vdd);
53*e2d6e5e2SPascal Paillet 	if (status != 0) {
54*e2d6e5e2SPascal Paillet 		return status;
55*e2d6e5e2SPascal Paillet 	}
56*e2d6e5e2SPascal Paillet 
57*e2d6e5e2SPascal Paillet 	status = regulator_enable(supply.vref);
58*e2d6e5e2SPascal Paillet 	if (status != 0) {
59*e2d6e5e2SPascal Paillet 		return status;
60*e2d6e5e2SPascal Paillet 	}
61*e2d6e5e2SPascal Paillet 
62*e2d6e5e2SPascal Paillet 	return regulator_enable(supply.vtt);
63*e2d6e5e2SPascal Paillet }
64*e2d6e5e2SPascal Paillet #endif /* STM32MP_DDR3_TYPE */
65*e2d6e5e2SPascal Paillet 
66*e2d6e5e2SPascal Paillet #if STM32MP_DDR4_TYPE
67*e2d6e5e2SPascal Paillet struct ddr4_supply {
68*e2d6e5e2SPascal Paillet 	struct rdev *vdd;
69*e2d6e5e2SPascal Paillet 	struct rdev *vref;
70*e2d6e5e2SPascal Paillet 	struct rdev *vtt;
71*e2d6e5e2SPascal Paillet 	struct rdev *vpp;
72*e2d6e5e2SPascal Paillet };
73*e2d6e5e2SPascal Paillet 
74*e2d6e5e2SPascal Paillet static void ddr4_supply_read(void *fdt, int node, struct ddr4_supply *supply)
75*e2d6e5e2SPascal Paillet {
76*e2d6e5e2SPascal Paillet 	supply->vpp = regulator_get_by_supply_name(fdt, node, "vpp");
77*e2d6e5e2SPascal Paillet 	supply->vdd = regulator_get_by_supply_name(fdt, node, "vdd");
78*e2d6e5e2SPascal Paillet 	supply->vref = regulator_get_by_supply_name(fdt, node, "vref");
79*e2d6e5e2SPascal Paillet 	supply->vtt = regulator_get_by_supply_name(fdt, node, "vtt");
80*e2d6e5e2SPascal Paillet }
81*e2d6e5e2SPascal Paillet 
82*e2d6e5e2SPascal Paillet static int ddr_power_init(void *fdt, int node)
83*e2d6e5e2SPascal Paillet {
84*e2d6e5e2SPascal Paillet 	int status;
85*e2d6e5e2SPascal Paillet 	struct ddr4_supply supply;
86*e2d6e5e2SPascal Paillet 
87*e2d6e5e2SPascal Paillet 	ddr4_supply_read(fdt, node, &supply);
88*e2d6e5e2SPascal Paillet 	if ((supply.vpp == NULL) || (supply.vdd == NULL) || (supply.vref == NULL) ||
89*e2d6e5e2SPascal Paillet 	    (supply.vtt == NULL)) {
90*e2d6e5e2SPascal Paillet 		return -ENOENT;
91*e2d6e5e2SPascal Paillet 	}
92*e2d6e5e2SPascal Paillet 
93*e2d6e5e2SPascal Paillet 	/*
94*e2d6e5e2SPascal Paillet 	 * DDR4 power on sequence is:
95*e2d6e5e2SPascal Paillet 	 * enable VPP_DDR
96*e2d6e5e2SPascal Paillet 	 * enable VREF_DDR, VTT_DDR, VPP_DDR
97*e2d6e5e2SPascal Paillet 	 */
98*e2d6e5e2SPascal Paillet 	status = regulator_set_min_voltage(supply.vpp);
99*e2d6e5e2SPascal Paillet 	if (status != 0) {
100*e2d6e5e2SPascal Paillet 		return status;
101*e2d6e5e2SPascal Paillet 	}
102*e2d6e5e2SPascal Paillet 
103*e2d6e5e2SPascal Paillet 	status = regulator_set_min_voltage(supply.vdd);
104*e2d6e5e2SPascal Paillet 	if (status != 0) {
105*e2d6e5e2SPascal Paillet 		return status;
106*e2d6e5e2SPascal Paillet 	}
107*e2d6e5e2SPascal Paillet 
108*e2d6e5e2SPascal Paillet 	status = regulator_enable(supply.vpp);
109*e2d6e5e2SPascal Paillet 	if (status != 0) {
110*e2d6e5e2SPascal Paillet 		return status;
111*e2d6e5e2SPascal Paillet 	}
112*e2d6e5e2SPascal Paillet 
113*e2d6e5e2SPascal Paillet 	status = regulator_enable(supply.vdd);
114*e2d6e5e2SPascal Paillet 	if (status != 0) {
115*e2d6e5e2SPascal Paillet 		return status;
116*e2d6e5e2SPascal Paillet 	}
117*e2d6e5e2SPascal Paillet 
118*e2d6e5e2SPascal Paillet 	status = regulator_enable(supply.vref);
119*e2d6e5e2SPascal Paillet 	if (status != 0) {
120*e2d6e5e2SPascal Paillet 		return status;
121*e2d6e5e2SPascal Paillet 	}
122*e2d6e5e2SPascal Paillet 
123*e2d6e5e2SPascal Paillet 	return regulator_enable(supply.vtt);
124*e2d6e5e2SPascal Paillet }
125*e2d6e5e2SPascal Paillet #endif /* STM32MP_DDR4_TYPE */
126*e2d6e5e2SPascal Paillet 
127*e2d6e5e2SPascal Paillet #if STM32MP_LPDDR4_TYPE
128*e2d6e5e2SPascal Paillet struct lpddr4_supply {
129*e2d6e5e2SPascal Paillet 	struct rdev *vdd1;
130*e2d6e5e2SPascal Paillet 	struct rdev *vdd2;
131*e2d6e5e2SPascal Paillet 	struct rdev *vddq;
132*e2d6e5e2SPascal Paillet };
133*e2d6e5e2SPascal Paillet 
134*e2d6e5e2SPascal Paillet static void lpddr4_supply_read(void *fdt, int node, struct lpddr4_supply *supply)
135*e2d6e5e2SPascal Paillet {
136*e2d6e5e2SPascal Paillet 	supply->vdd1 = regulator_get_by_supply_name(fdt, node, "vdd1");
137*e2d6e5e2SPascal Paillet 	supply->vdd2 = regulator_get_by_supply_name(fdt, node, "vdd2");
138*e2d6e5e2SPascal Paillet 	supply->vddq = regulator_get_by_supply_name(fdt, node, "vddq");
139*e2d6e5e2SPascal Paillet }
140*e2d6e5e2SPascal Paillet 
141*e2d6e5e2SPascal Paillet static int ddr_power_init(void *fdt, int node)
142*e2d6e5e2SPascal Paillet {
143*e2d6e5e2SPascal Paillet 	int status;
144*e2d6e5e2SPascal Paillet 	struct lpddr4_supply supply;
145*e2d6e5e2SPascal Paillet 
146*e2d6e5e2SPascal Paillet 	lpddr4_supply_read(fdt, node, &supply);
147*e2d6e5e2SPascal Paillet 	if ((supply.vdd1 == NULL) || (supply.vdd2 == NULL) || (supply.vddq == NULL)) {
148*e2d6e5e2SPascal Paillet 		return -ENOENT;
149*e2d6e5e2SPascal Paillet 	}
150*e2d6e5e2SPascal Paillet 
151*e2d6e5e2SPascal Paillet 	/*
152*e2d6e5e2SPascal Paillet 	 * LPDDR4 power on sequence is:
153*e2d6e5e2SPascal Paillet 	 * enable VDD1_DDR
154*e2d6e5e2SPascal Paillet 	 * enable VDD2_DDR
155*e2d6e5e2SPascal Paillet 	 * enable VDDQ_DDR
156*e2d6e5e2SPascal Paillet 	 */
157*e2d6e5e2SPascal Paillet 	status = regulator_set_min_voltage(supply.vdd1);
158*e2d6e5e2SPascal Paillet 	if (status != 0) {
159*e2d6e5e2SPascal Paillet 		return status;
160*e2d6e5e2SPascal Paillet 	}
161*e2d6e5e2SPascal Paillet 
162*e2d6e5e2SPascal Paillet 	status = regulator_set_min_voltage(supply.vdd2);
163*e2d6e5e2SPascal Paillet 	if (status != 0) {
164*e2d6e5e2SPascal Paillet 		return status;
165*e2d6e5e2SPascal Paillet 	}
166*e2d6e5e2SPascal Paillet 
167*e2d6e5e2SPascal Paillet 	status = regulator_set_min_voltage(supply.vddq);
168*e2d6e5e2SPascal Paillet 	if (status != 0) {
169*e2d6e5e2SPascal Paillet 		return status;
170*e2d6e5e2SPascal Paillet 	}
171*e2d6e5e2SPascal Paillet 
172*e2d6e5e2SPascal Paillet 	status = regulator_enable(supply.vdd1);
173*e2d6e5e2SPascal Paillet 	if (status != 0) {
174*e2d6e5e2SPascal Paillet 		return status;
175*e2d6e5e2SPascal Paillet 	}
176*e2d6e5e2SPascal Paillet 
177*e2d6e5e2SPascal Paillet 	status = regulator_enable(supply.vdd2);
178*e2d6e5e2SPascal Paillet 	if (status != 0) {
179*e2d6e5e2SPascal Paillet 		return status;
180*e2d6e5e2SPascal Paillet 	}
181*e2d6e5e2SPascal Paillet 
182*e2d6e5e2SPascal Paillet 	return regulator_enable(supply.vddq);
183*e2d6e5e2SPascal Paillet }
184*e2d6e5e2SPascal Paillet #endif /* STM32MP_LPDDR4_TYPE */
185*e2d6e5e2SPascal Paillet 
186*e2d6e5e2SPascal Paillet int stm32mp_board_ddr_power_init(enum ddr_type ddr_type)
187*e2d6e5e2SPascal Paillet {
188*e2d6e5e2SPascal Paillet 	void *fdt = NULL;
189*e2d6e5e2SPascal Paillet 	int node;
190*e2d6e5e2SPascal Paillet 
191*e2d6e5e2SPascal Paillet 	VERBOSE("DDR power init, ddr_type = %u\n", ddr_type);
192*e2d6e5e2SPascal Paillet 
193*e2d6e5e2SPascal Paillet #if STM32MP_DDR3_TYPE
194*e2d6e5e2SPascal Paillet 	assert(ddr_type == STM32MP_DDR3);
195*e2d6e5e2SPascal Paillet #elif STM32MP_DDR4_TYPE
196*e2d6e5e2SPascal Paillet 	assert(ddr_type == STM32MP_DDR4);
197*e2d6e5e2SPascal Paillet #elif STM32MP_LPDDR4_TYPE
198*e2d6e5e2SPascal Paillet 	assert(ddr_type == STM32MP_LPDDR4);
199*e2d6e5e2SPascal Paillet #else
200*e2d6e5e2SPascal Paillet 	ERROR("DDR type (%u) not supported\n", ddr_type);
201*e2d6e5e2SPascal Paillet 	panic();
202*e2d6e5e2SPascal Paillet #endif
203*e2d6e5e2SPascal Paillet 
204*e2d6e5e2SPascal Paillet 	if (fdt_get_address(&fdt) == 0) {
205*e2d6e5e2SPascal Paillet 		return -FDT_ERR_NOTFOUND;
206*e2d6e5e2SPascal Paillet 	}
207*e2d6e5e2SPascal Paillet 
208*e2d6e5e2SPascal Paillet 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
209*e2d6e5e2SPascal Paillet 	if (node < 0) {
210*e2d6e5e2SPascal Paillet 		ERROR("%s: Cannot read DDR node in DT\n", __func__);
211*e2d6e5e2SPascal Paillet 		return -EINVAL;
212*e2d6e5e2SPascal Paillet 	}
213*e2d6e5e2SPascal Paillet 
214*e2d6e5e2SPascal Paillet 	return ddr_power_init(fdt, node);
215*e2d6e5e2SPascal Paillet }
216