1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 * DMC-500 driver
9 */
10
11 /* The use of "primary" may not be in sync with older versions of TRM */
12
13 #include <mod_dmc500.h>
14 #include <mod_timer.h>
15
16 #include <fwk_assert.h>
17 #include <fwk_log.h>
18 #include <fwk_module.h>
19 #include <fwk_module_idx.h>
20 #include <fwk_status.h>
21
22 #include <stddef.h>
23
24 static struct mod_dmc_ddr_phy_api *ddr_phy_api;
25 static struct mod_timer_api *timer_api;
26
27 static int dmc500_config(struct mod_dmc500_reg *dmc, fwk_id_t ddr_phy_id);
28
29 /* Framework API */
mod_dmc500_init(fwk_id_t module_id,unsigned int element_count,const void * data)30 static int mod_dmc500_init(fwk_id_t module_id, unsigned int element_count,
31 const void *data)
32 {
33 return FWK_SUCCESS;
34 }
35
mod_dmc500_element_init(fwk_id_t element_id,unsigned int unused,const void * data)36 static int mod_dmc500_element_init(fwk_id_t element_id, unsigned int unused,
37 const void *data)
38 {
39 fwk_assert(data != NULL);
40
41 return FWK_SUCCESS;
42 }
43
mod_dmc500_bind(fwk_id_t id,unsigned int round)44 static int mod_dmc500_bind(fwk_id_t id, unsigned int round)
45 {
46 int status;
47 const struct mod_dmc500_module_config *module_config;
48
49 /* Nothing to do in the second round of calls. */
50 if (round == 1)
51 return FWK_SUCCESS;
52
53 /* Nothing to do in case of elements. */
54 if (fwk_module_is_valid_element_id(id))
55 return FWK_SUCCESS;
56
57 module_config = fwk_module_get_data(fwk_module_id_dmc500);
58 fwk_assert(module_config != NULL);
59
60 status = fwk_module_bind(module_config->ddr_phy_module_id,
61 module_config->ddr_phy_api_id, &ddr_phy_api);
62 if (status != FWK_SUCCESS)
63 return status;
64
65 status = fwk_module_bind(module_config->timer_id,
66 FWK_ID_API(FWK_MODULE_IDX_TIMER, 0), &timer_api);
67 if (status != FWK_SUCCESS)
68 return status;
69
70 return FWK_SUCCESS;
71 }
72
mod_dmc500_start(fwk_id_t id)73 static int mod_dmc500_start(fwk_id_t id)
74 {
75 const struct mod_dmc500_element_config *element_config;
76 struct mod_dmc500_reg *dmc;
77
78 /* Nothing to start for the module */
79 if (fwk_module_is_valid_module_id(id))
80 return FWK_SUCCESS;
81
82 element_config = fwk_module_get_data(id);
83 dmc = (struct mod_dmc500_reg *)element_config->dmc;
84
85 return dmc500_config(dmc, element_config->ddr_phy_id);
86 }
87
88 const struct fwk_module module_dmc500 = {
89 .type = FWK_MODULE_TYPE_DRIVER,
90 .init = mod_dmc500_init,
91 .element_init = mod_dmc500_element_init,
92 .bind = mod_dmc500_bind,
93 .start = mod_dmc500_start,
94 .api_count = 0,
95 .event_count = 0,
96 };
97
98
dmc500_config(struct mod_dmc500_reg * dmc,fwk_id_t ddr_phy_id)99 static int dmc500_config(struct mod_dmc500_reg *dmc, fwk_id_t ddr_phy_id)
100 {
101 int status;
102 uint64_t timeout;
103 uint64_t remaining_ticks;
104 uint64_t counter;
105 const struct mod_dmc500_reg *reg_val;
106 const struct mod_dmc500_module_config *module_config;
107
108 module_config = fwk_module_get_data(fwk_module_id_dmc500);
109 reg_val = module_config->reg_val;
110
111 FWK_LOG_INFO("[DDR] Initialising DMC500 at 0x%x", (uintptr_t)dmc);
112
113 dmc->ADDRESS_CONTROL = reg_val->ADDRESS_CONTROL;
114 dmc->RANK_REMAP_CONTROL = reg_val->RANK_REMAP_CONTROL;
115 dmc->MEMORY_TYPE = reg_val->MEMORY_TYPE;
116 dmc->FORMAT_CONTROL = reg_val->FORMAT_CONTROL;
117 dmc->DECODE_CONTROL = reg_val->DECODE_CONTROL;
118 dmc->FEATURE_CONTROL = reg_val->FEATURE_CONTROL;
119 dmc->ODT_WR_CONTROL_31_00 = reg_val->ODT_WR_CONTROL_31_00;
120 dmc->ODT_RD_CONTROL_31_00 = reg_val->ODT_RD_CONTROL_31_00;
121 dmc->ODT_TIMING = reg_val->ODT_TIMING;
122
123 FWK_LOG_INFO("[DDR] Setting timing settings");
124
125 dmc->T_REFI = reg_val->T_REFI;
126 dmc->T_RFC = reg_val->T_RFC;
127 dmc->T_RDPDEN = reg_val->T_RDPDEN;
128 dmc->T_RCD = reg_val->T_RCD;
129 dmc->T_RAS = reg_val->T_RAS;
130 dmc->T_RP = reg_val->T_RP;
131 dmc->T_RRD = reg_val->T_RRD;
132 dmc->T_ACT_WINDOW = reg_val->T_ACT_WINDOW;
133 dmc->T_RTR = reg_val->T_RTR;
134 dmc->T_RTW = reg_val->T_RTW;
135 dmc->T_RTP = reg_val->T_RTP;
136 dmc->T_WR = reg_val->T_WR;
137 dmc->T_WTR = reg_val->T_WTR;
138 dmc->T_WTW = reg_val->T_WTW;
139 dmc->T_XTMW = reg_val->T_XTMW;
140 dmc->T_CLOCK_CONTROL = reg_val->T_CLOCK_CONTROL;
141 dmc->T_EP = reg_val->T_EP;
142 dmc->T_XP = reg_val->T_XP;
143 dmc->T_ESR = reg_val->T_ESR;
144 dmc->T_XSR = reg_val->T_XSR;
145
146 FWK_LOG_INFO("[DDR] Setting address map");
147
148 dmc->ADDRESS_MAP = reg_val->ADDRESS_MAP;
149
150 FWK_LOG_INFO("[DDR] Setting PMU settings");
151
152 dmc->SI0_SI_INTERRUPT_CONTROL = reg_val->SI0_SI_INTERRUPT_CONTROL;
153 dmc->SI0_PMU_REQ_CONTROL = reg_val->SI0_PMU_REQ_CONTROL;
154 dmc->SI0_PMU_REQ_ATTRIBUTE_MASK_0 = reg_val->SI0_PMU_REQ_ATTRIBUTE_MASK_0;
155 dmc->SI0_PMU_REQ_ATTRIBUTE_MATCH_0 = reg_val->SI0_PMU_REQ_ATTRIBUTE_MATCH_0;
156 dmc->SI0_PMU_REQ_ATTRIBUTE_MASK_1 = reg_val->SI0_PMU_REQ_ATTRIBUTE_MASK_1;
157 dmc->SI0_PMU_REQ_ATTRIBUTE_MATCH_1 = reg_val->SI0_PMU_REQ_ATTRIBUTE_MATCH_1;
158 dmc->SI0_PMU_REQ_ATTRIBUTE_MASK_2 = reg_val->SI0_PMU_REQ_ATTRIBUTE_MASK_2;
159 dmc->SI0_PMU_REQ_ATTRIBUTE_MATCH_2 = reg_val->SI0_PMU_REQ_ATTRIBUTE_MATCH_2;
160 dmc->SI0_PMU_REQ_ATTRIBUTE_MASK_3 = reg_val->SI0_PMU_REQ_ATTRIBUTE_MASK_3;
161 dmc->SI0_PMU_REQ_ATTRIBUTE_MATCH_3 = reg_val->SI0_PMU_REQ_ATTRIBUTE_MATCH_3;
162 dmc->SI0_THRESHOLD_CONTROL = reg_val->SI0_THRESHOLD_CONTROL;
163 dmc->SI1_SI_INTERRUPT_CONTROL = reg_val->SI1_SI_INTERRUPT_CONTROL;
164 dmc->SI1_PMU_REQ_CONTROL = reg_val->SI1_PMU_REQ_CONTROL;
165 dmc->SI1_PMU_REQ_ATTRIBUTE_MASK_0 = reg_val->SI1_PMU_REQ_ATTRIBUTE_MASK_0;
166 dmc->SI1_PMU_REQ_ATTRIBUTE_MATCH_0 = reg_val->SI1_PMU_REQ_ATTRIBUTE_MATCH_0;
167 dmc->SI1_PMU_REQ_ATTRIBUTE_MASK_1 = reg_val->SI1_PMU_REQ_ATTRIBUTE_MASK_1;
168 dmc->SI1_PMU_REQ_ATTRIBUTE_MATCH_1 = reg_val->SI1_PMU_REQ_ATTRIBUTE_MATCH_1;
169 dmc->SI1_PMU_REQ_ATTRIBUTE_MASK_2 = reg_val->SI1_PMU_REQ_ATTRIBUTE_MASK_2;
170 dmc->SI1_PMU_REQ_ATTRIBUTE_MATCH_2 = reg_val->SI1_PMU_REQ_ATTRIBUTE_MATCH_2;
171 dmc->SI1_PMU_REQ_ATTRIBUTE_MASK_3 = reg_val->SI1_PMU_REQ_ATTRIBUTE_MASK_3;
172 dmc->SI1_PMU_REQ_ATTRIBUTE_MATCH_3 = reg_val->SI1_PMU_REQ_ATTRIBUTE_MATCH_3;
173 dmc->SI1_THRESHOLD_CONTROL = reg_val->SI1_THRESHOLD_CONTROL;
174 dmc->QUEUE_THRESHOLD_CONTROL_31_00 = reg_val->QUEUE_THRESHOLD_CONTROL_31_00;
175 dmc->QUEUE_THRESHOLD_CONTROL_63_32 = reg_val->QUEUE_THRESHOLD_CONTROL_63_32;
176 dmc->DCB_INTERRUPT_CONTROL = reg_val->DCB_INTERRUPT_CONTROL;
177 dmc->PMU_DCB_CONTROL = reg_val->PMU_DCB_CONTROL;
178 dmc->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MASK_0 =
179 reg_val->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MASK_0;
180 dmc->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MATCH_0 =
181 reg_val->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MATCH_0;
182 dmc->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MASK_1 =
183 reg_val->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MASK_1;
184 dmc->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MATCH_1 =
185 reg_val->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MATCH_1;
186 dmc->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MASK_2 =
187 reg_val->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MASK_2;
188 dmc->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MATCH_2 =
189 reg_val->PMU_DATA_CONTROL_BLOCK_ATTRIBUTE_MATCH_2;
190 dmc->PMU_TAG_ENTRIES_ATTRIBUTE_MASK =
191 reg_val->PMU_TAG_ENTRIES_ATTRIBUTE_MASK;
192 dmc->PMU_TAG_ENTRIES_ATTRIBUTE_MATCH =
193 reg_val->PMU_TAG_ENTRIES_ATTRIBUTE_MATCH;
194 dmc->QE_INTERRUPT_CONTROL = reg_val->QE_INTERRUPT_CONTROL;
195 dmc->RANK_TURNAROUND_CONTROL = reg_val->RANK_TURNAROUND_CONTROL;
196 dmc->HIT_TURNAROUND_CONTROL = reg_val->HIT_TURNAROUND_CONTROL;
197 dmc->QOS_CLASS_CONTROL = reg_val->QOS_CLASS_CONTROL;
198 dmc->ESCALATION_CONTROL = reg_val->ESCALATION_CONTROL;
199 dmc->QV_CONTROL_31_00 = reg_val->QV_CONTROL_31_00;
200 dmc->QV_CONTROL_63_32 = reg_val->QV_CONTROL_63_32;
201 dmc->RT_CONTROL_31_00 = reg_val->RT_CONTROL_31_00;
202 dmc->RT_CONTROL_63_32 = reg_val->RT_CONTROL_63_32;
203 dmc->TIMEOUT_CONTROL = reg_val->TIMEOUT_CONTROL;
204 dmc->WRITE_PRIORITY_CONTROL_31_00 = reg_val->WRITE_PRIORITY_CONTROL_31_00;
205 dmc->WRITE_PRIORITY_CONTROL_63_32 = reg_val->WRITE_PRIORITY_CONTROL_63_32;
206 dmc->DIR_TURNAROUND_CONTROL = reg_val->DIR_TURNAROUND_CONTROL;
207 dmc->HIT_PREDICTION_CONTROL = reg_val->HIT_PREDICTION_CONTROL;
208 dmc->REFRESH_PRIORITY = reg_val->REFRESH_PRIORITY;
209 dmc->MC_UPDATE_CONTROL = reg_val->MC_UPDATE_CONTROL;
210 dmc->PHY_UPDATE_CONTROL = reg_val->PHY_UPDATE_CONTROL;
211 dmc->PHY_PRIMARY_CONTROL = reg_val->PHY_PRIMARY_CONTROL;
212 dmc->LOW_POWER_CONTROL = reg_val->LOW_POWER_CONTROL;
213 dmc->PMU_QE_CONTROL = reg_val->PMU_QE_CONTROL;
214 dmc->PMU_QE_MUX = reg_val->PMU_QE_MUX;
215 dmc->PMU_QOS_ENGINE_ATTRIBUTE_MASK_0 =
216 reg_val->PMU_QOS_ENGINE_ATTRIBUTE_MASK_0;
217 dmc->PMU_QOS_ENGINE_ATTRIBUTE_MATCH_0 =
218 reg_val->PMU_QOS_ENGINE_ATTRIBUTE_MATCH_0;
219 dmc->PMU_QOS_ENGINE_ATTRIBUTE_MASK_1 =
220 reg_val->PMU_QOS_ENGINE_ATTRIBUTE_MASK_1;
221 dmc->PMU_QOS_ENGINE_ATTRIBUTE_MATCH_1 =
222 reg_val->PMU_QOS_ENGINE_ATTRIBUTE_MATCH_1;
223 dmc->PMU_QOS_ENGINE_ATTRIBUTE_MASK_2 =
224 reg_val->PMU_QOS_ENGINE_ATTRIBUTE_MASK_2;
225 dmc->PMU_QOS_ENGINE_ATTRIBUTE_MATCH_2 =
226 reg_val->PMU_QOS_ENGINE_ATTRIBUTE_MATCH_2;
227 dmc->PMU_QUEUED_ENTRIES_ATTRIBUTE_MASK =
228 reg_val->PMU_QUEUED_ENTRIES_ATTRIBUTE_MASK;
229 dmc->PMU_QUEUED_ENTRIES_ATTRIBUTE_MATCH =
230 reg_val->PMU_QUEUED_ENTRIES_ATTRIBUTE_MATCH;
231 dmc->MI_INTERRUPT_CONTROL = reg_val->MI_INTERRUPT_CONTROL;
232 dmc->POWER_DOWN_CONTROL = reg_val->POWER_DOWN_CONTROL;
233 dmc->REFRESH_CONTROL = reg_val->REFRESH_CONTROL;
234 dmc->PMU_MI_CONTROL = reg_val->PMU_MI_CONTROL;
235 dmc->PMU_MEMORY_IF_ATTRIBUTE_MASK_0 =
236 reg_val->PMU_MEMORY_IF_ATTRIBUTE_MASK_0;
237 dmc->PMU_MEMORY_IF_ATTRIBUTE_MATCH_0 =
238 reg_val->PMU_MEMORY_IF_ATTRIBUTE_MATCH_0;
239 dmc->PMU_MEMORY_IF_ATTRIBUTE_MASK_1 =
240 reg_val->PMU_MEMORY_IF_ATTRIBUTE_MASK_1;
241 dmc->PMU_MEMORY_IF_ATTRIBUTE_MATCH_1 =
242 reg_val->PMU_MEMORY_IF_ATTRIBUTE_MATCH_1;
243 dmc->PMU_BANK_STATES_ATTRIBUTE_MASK =
244 reg_val->PMU_BANK_STATES_ATTRIBUTE_MASK;
245 dmc->PMU_BANK_STATES_ATTRIBUTE_MATCH =
246 reg_val->PMU_BANK_STATES_ATTRIBUTE_MATCH;
247 dmc->PMU_RANK_STATES_ATTRIBUTE_MASK =
248 reg_val->PMU_RANK_STATES_ATTRIBUTE_MASK;
249 dmc->PMU_RANK_STATES_ATTRIBUTE_MATCH =
250 reg_val->PMU_RANK_STATES_ATTRIBUTE_MATCH;
251 dmc->CFG_INTERRUPT_CONTROL = reg_val->CFG_INTERRUPT_CONTROL;
252 dmc->T_RDDATA_EN = reg_val->T_RDDATA_EN;
253 dmc->T_PHYRDLAT = reg_val->T_PHYRDLAT;
254 dmc->T_PHYWRLAT = reg_val->T_PHYWRLAT;
255
256 dmc->ERR_RAMECC_CTLR = reg_val->ERR_RAMECC_CTLR;
257
258 FWK_LOG_INFO("[DDR] Setting PHY-related settings");
259
260 dmc->PHY_POWER_CONTROL = reg_val->PHY_POWER_CONTROL;
261 dmc->T_PHY_TRAIN = reg_val->T_PHY_TRAIN;
262 dmc->PHYUPD_INIT = reg_val->PHYUPD_INIT;
263
264 dmc->PHY_CONFIG = 0x03000000;
265 dmc->PHY_CONFIG = 0x0600000A;
266 dmc->PHY_CONFIG = 0x01000001;
267
268 status = ddr_phy_api->configure(ddr_phy_id);
269 if (status != FWK_SUCCESS)
270 return status;
271
272 dmc->PHY_CONFIG = 0x01000001;
273 dmc->PHY_CONFIG = 0x01000000;
274 dmc->PHY_CONFIG = 0x00000003;
275
276 FWK_LOG_INFO("[DDR] Doing direct DDR commands");
277
278 module_config->direct_ddr_cmd(dmc);
279
280 dmc->REFRESH_ENABLE = reg_val->REFRESH_ENABLE;
281
282 FWK_LOG_INFO("[DDR] Setting dmc in READY mode");
283
284 status = timer_api->time_to_timestamp(module_config->timer_id,
285 1000 * 1000, &timeout);
286 if (status != FWK_SUCCESS)
287 return status;
288
289 status = timer_api->get_counter(module_config->timer_id, &counter);
290 if (status != FWK_SUCCESS)
291 return status;
292
293 timeout += counter;
294
295 while ((dmc->MI_STATUS & MOD_DMC500_MI_STATUS_IDLE) !=
296 MOD_DMC500_MI_STATUS_IDLE) {
297 status = timer_api->remaining(module_config->timer_id, timeout,
298 &remaining_ticks);
299 if (status != FWK_SUCCESS)
300 return status;
301
302 if (remaining_ticks == 0)
303 goto timeout;
304 }
305
306 dmc->MI_STATE_CONTROL = reg_val->MI_STATE_CONTROL;
307 dmc->QUEUE_STATE_CONTROL = reg_val->QUEUE_STATE_CONTROL;
308 dmc->SI0_SI_STATE_CONTROL = reg_val->SI0_SI_STATE_CONTROL;
309 dmc->SI1_SI_STATE_CONTROL = reg_val->SI1_SI_STATE_CONTROL;
310
311 FWK_LOG_INFO("[DDR] Waiting for Queue stall = 0...");
312
313 while ((dmc->QUEUE_STATUS & MOD_DMC500_QUEUE_STATUS_STALL_ACK) != 0) {
314 status = timer_api->remaining(module_config->timer_id, timeout,
315 &remaining_ticks);
316 if (status != FWK_SUCCESS)
317 return status;
318
319 if (remaining_ticks == 0)
320 goto timeout;
321 }
322
323 FWK_LOG_INFO("[DDR] Waiting for SI0 stall = 0...");
324
325 while ((dmc->SI0_SI_STATUS & MOD_DMC500_SI_STATUS_STALL_ACK) != 0) {
326 status = timer_api->remaining(module_config->timer_id, timeout,
327 &remaining_ticks);
328 if (status != FWK_SUCCESS)
329 return status;
330
331 if (remaining_ticks == 0)
332 goto timeout;
333 }
334
335 FWK_LOG_INFO("[DDR] Waiting for SI1 stall = 0...");
336
337 while ((dmc->SI1_SI_STATUS & MOD_DMC500_SI_STATUS_STALL_ACK) != 0) {
338 status = timer_api->remaining(module_config->timer_id, timeout,
339 &remaining_ticks);
340 if (status != FWK_SUCCESS)
341 return status;
342
343 if (remaining_ticks == 0)
344 goto timeout;
345 }
346
347 FWK_LOG_INFO("[DDR] DMC init done.");
348
349 return FWK_SUCCESS;
350
351 timeout:
352 FWK_LOG_ERR("[DDR] Timed out in DMC500 init.");
353
354 return FWK_E_TIMEOUT;
355 }
356