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