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