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