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