blob: 95f05e7bc10b8b71df70fce76859dffd30f4b332 [file] [log] [blame]
Nicolas Le Bayon068d3412021-07-01 14:44:22 +02001/*
2 * Copyright (C) 2021-2024, STMicroelectronics - All Rights Reserved
3 *
4 * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
5 */
6
7#include <errno.h>
8
9#include <arch_helpers.h>
10#include <common/debug.h>
11#include <common/fdt_wrappers.h>
12#include <drivers/clk.h>
13#include <drivers/st/stm32mp2_ddr.h>
14#include <drivers/st/stm32mp2_ddr_helpers.h>
15#include <drivers/st/stm32mp2_ram.h>
16#include <drivers/st/stm32mp_ddr.h>
17#include <drivers/st/stm32mp_ddr_test.h>
18#include <drivers/st/stm32mp_ram.h>
19
20#include <lib/mmio.h>
21#include <libfdt.h>
22
23#include <platform_def.h>
24
25static struct stm32mp_ddr_priv ddr_priv_data;
26static bool ddr_self_refresh;
27
28static int ddr_dt_get_ui_param(void *fdt, int node, struct stm32mp_ddr_config *config)
29{
30 int ret;
31 uint32_t size;
32
33 size = sizeof(struct user_input_basic) / sizeof(int);
34 ret = fdt_read_uint32_array(fdt, node, "st,phy-basic", size, (uint32_t *)&config->uib);
35
36 VERBOSE("%s: %s[0x%x] = %d\n", __func__, "st,phy-basic", size, ret);
37 if (ret != 0) {
38 ERROR("%s: can't read %s, error=%d\n", __func__, "st,phy-basic", ret);
39 return -EINVAL;
40 }
41
42 size = sizeof(struct user_input_advanced) / sizeof(int);
43 ret = fdt_read_uint32_array(fdt, node, "st,phy-advanced", size, (uint32_t *)&config->uia);
44
45 VERBOSE("%s: %s[0x%x] = %d\n", __func__, "st,phy-advanced", size, ret);
46 if (ret != 0) {
47 ERROR("%s: can't read %s, error=%d\n", __func__, "st,phy-advanced", ret);
48 return -EINVAL;
49 }
50
51 size = sizeof(struct user_input_mode_register) / sizeof(int);
52 ret = fdt_read_uint32_array(fdt, node, "st,phy-mr", size, (uint32_t *)&config->uim);
53
54 VERBOSE("%s: %s[0x%x] = %d\n", __func__, "st,phy-mr", size, ret);
55 if (ret != 0) {
56 ERROR("%s: can't read %s, error=%d\n", __func__, "st,phy-mr", ret);
57 return -EINVAL;
58 }
59
60 size = sizeof(struct user_input_swizzle) / sizeof(int);
61 ret = fdt_read_uint32_array(fdt, node, "st,phy-swizzle", size, (uint32_t *)&config->uis);
62
63 VERBOSE("%s: %s[0x%x] = %d\n", __func__, "st,phy-swizzle", size, ret);
64 if (ret != 0) {
65 ERROR("%s: can't read %s, error=%d\n", __func__, "st,phy-swizzle", ret);
66 return -EINVAL;
67 }
68
69 return 0;
70}
71
72static int stm32mp2_ddr_setup(void)
73{
74 struct stm32mp_ddr_priv *priv = &ddr_priv_data;
75 int ret;
76 struct stm32mp_ddr_config config;
77 int node;
78 uintptr_t uret;
79 void *fdt;
80
81 const struct stm32mp_ddr_param param[] = {
82 CTL_PARAM(reg),
83 CTL_PARAM(timing),
84 CTL_PARAM(map),
85 CTL_PARAM(perf)
86 };
87
88 if (fdt_get_address(&fdt) == 0) {
89 return -ENOENT;
90 }
91
92 node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
93 if (node < 0) {
94 ERROR("%s: can't read DDR node in DT\n", __func__);
95 return -EINVAL;
96 }
97
98 ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info);
99 if (ret < 0) {
100 return ret;
101 }
102
103 ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config);
104 if (ret < 0) {
105 return ret;
106 }
107
108 ret = ddr_dt_get_ui_param(fdt, node, &config);
109 if (ret < 0) {
110 return ret;
111 }
112
113 config.self_refresh = false;
114
115 if (stm32mp_is_wakeup_from_standby()) {
116 config.self_refresh = true;
117 }
118
119 /* Map dynamically RETRAM area to save or restore PHY retention registers */
120 if (stm32mp_map_retram() != 0) {
121 panic();
122 }
123
124 stm32mp2_ddr_init(priv, &config);
125
126 /* Unmap RETRAM, no more used until next DDR initialization call */
127 if (stm32mp_unmap_retram() != 0) {
128 panic();
129 }
130
131 priv->info.size = config.info.size;
132
133 VERBOSE("%s : ram size(%lx, %lx)\n", __func__, priv->info.base, priv->info.size);
134
135 if (stm32mp_map_ddr_non_cacheable() != 0) {
136 panic();
137 }
138
139 if (config.self_refresh) {
140 uret = stm32mp_ddr_test_rw_access();
141 if (uret != 0UL) {
142 ERROR("DDR rw test: can't access memory @ 0x%lx\n", uret);
143 panic();
144 }
145
146 /* TODO Restore area overwritten by training */
147 //stm32_restore_ddr_training_area();
148 } else {
149 size_t retsize;
150
151 uret = stm32mp_ddr_test_data_bus();
152 if (uret != 0UL) {
153 ERROR("DDR data bus test: can't access memory @ 0x%lx\n", uret);
154 panic();
155 }
156
157 uret = stm32mp_ddr_test_addr_bus(config.info.size);
158 if (uret != 0UL) {
159 ERROR("DDR addr bus test: can't access memory @ 0x%lx\n", uret);
160 panic();
161 }
162
163 retsize = stm32mp_ddr_check_size();
164 if (retsize < config.info.size) {
165 ERROR("DDR size: 0x%zx does not match DT config: 0x%zx\n",
166 retsize, config.info.size);
167 panic();
168 }
169
170 INFO("Memory size = 0x%zx (%zu MB)\n", retsize, retsize / (1024U * 1024U));
171 }
172
173 /*
174 * Initialization sequence has configured DDR registers with settings.
175 * The Self Refresh (SR) mode corresponding to these settings has now
176 * to be set.
177 */
178 ddr_set_sr_mode(ddr_read_sr_mode());
179
180 if (stm32mp_unmap_ddr() != 0) {
181 panic();
182 }
183
184 /* Save DDR self_refresh state */
185 ddr_self_refresh = config.self_refresh;
186
187 return 0;
188}
189
190bool stm32mp2_ddr_is_restored(void)
191{
192 return ddr_self_refresh;
193}
194
195int stm32mp2_ddr_probe(void)
196{
197 struct stm32mp_ddr_priv *priv = &ddr_priv_data;
198
199 VERBOSE("STM32MP DDR probe\n");
200
201 priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base();
202 priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base();
203 priv->pwr = stm32mp_pwr_base();
204 priv->rcc = stm32mp_rcc_base();
205
206 priv->info.base = STM32MP_DDR_BASE;
207 priv->info.size = 0;
208
209 return stm32mp2_ddr_setup();
210}