• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
25 static struct stm32mp_ddr_priv ddr_priv_data;
26 static bool ddr_self_refresh;
27 
ddr_dt_get_ui_param(void * fdt,int node,struct stm32mp_ddr_config * config)28 static 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 
stm32mp2_ddr_setup(void)72 static 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 
stm32mp2_ddr_is_restored(void)190 bool stm32mp2_ddr_is_restored(void)
191 {
192 	return ddr_self_refresh;
193 }
194 
stm32mp2_ddr_probe(void)195 int 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 }
211