blob: 5302e45b691c1b83b1b70334599f20174d07ff3a [file] [log] [blame]
Pascal Paillet0e1727c2023-01-18 11:47:10 +01001/*
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>
Nicolas Le Bayon068d3412021-07-01 14:44:22 +020012
Pascal Paillet0e1727c2023-01-18 11:47:10 +010013#include <drivers/delay_timer.h>
14#include <drivers/st/regulator.h>
15#include <drivers/st/stm32mp_ddr.h>
16
17#include <libfdt.h>
Nicolas Le Bayon068d3412021-07-01 14:44:22 +020018
Pascal Paillet0e1727c2023-01-18 11:47:10 +010019#include <platform_def.h>
20
21#if STM32MP_DDR3_TYPE
22struct ddr3_supply {
23 struct rdev *vdd;
24 struct rdev *vref;
25 struct rdev *vtt;
26};
27
28static 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
35static 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
69struct ddr4_supply {
70 struct rdev *vdd;
71 struct rdev *vref;
72 struct rdev *vtt;
73 struct rdev *vpp;
74};
75
76static 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
84static 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
130struct lpddr4_supply {
131 struct rdev *vdd1;
132 struct rdev *vdd2;
133 struct rdev *vddq;
134};
135
136static 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
143static 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
188int 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}