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