1 /*
2 * Copyright (c) 2024, Altera Corporation. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <errno.h>
8 #include <stdio.h>
9 #include <string.h>
10
11 #include <common/debug.h>
12 #include <drivers/delay_timer.h>
13
14 #include "agilex5_iossm_mailbox.h"
15
16 /* supported DDR type list */
17 static const char *ddr_type_list[7] = {
18 "DDR4", "DDR5", "DDR5_RDIMM", "LPDDR4", "LPDDR5", "QDRIV", "UNKNOWN"
19 };
20
wait_for_bit(const void * reg,const uint32_t mask,const bool set,const unsigned int timeout_ms)21 static inline int wait_for_bit(const void *reg,
22 const uint32_t mask,
23 const bool set,
24 const unsigned int timeout_ms)
25 {
26 uint32_t val;
27 uint32_t timeout_sec = (timeout_ms / 1000);
28
29 while (timeout_sec > 0) {
30 val = mmio_read_32((uintptr_t)reg);
31
32 INFO("IOSSM: timeout_sec %d, val %x\n", timeout_sec, val);
33
34 if (!set) {
35 val = ~val;
36 }
37
38 if ((val & mask) == mask) {
39 INFO("IOSSM: %s, success\n", __func__);
40 return 0;
41 }
42
43 /* one second delay */
44 mdelay(1000);
45
46 timeout_sec--;
47 }
48
49 ERROR("IOSSM: %s, failed, time out\n", __func__);
50 return -ETIMEDOUT;
51 }
52
io96b_mb_req(phys_addr_t io96b_csr_addr,uint32_t ip_type,uint32_t instance_id,uint32_t usr_cmd_type,uint32_t usr_cmd_opcode,uint32_t cmd_param_0,uint32_t cmd_param_1,uint32_t cmd_param_2,uint32_t cmd_param_3,uint32_t cmd_param_4,uint32_t cmd_param_5,uint32_t cmd_param_6,uint32_t resp_data_len,struct io96b_mb_resp * resp)53 int io96b_mb_req(phys_addr_t io96b_csr_addr, uint32_t ip_type, uint32_t instance_id,
54 uint32_t usr_cmd_type, uint32_t usr_cmd_opcode, uint32_t cmd_param_0,
55 uint32_t cmd_param_1, uint32_t cmd_param_2, uint32_t cmd_param_3,
56 uint32_t cmd_param_4, uint32_t cmd_param_5, uint32_t cmd_param_6,
57 uint32_t resp_data_len, struct io96b_mb_resp *resp)
58 {
59 int i;
60 int ret;
61 uint32_t cmd_req, cmd_resp;
62
63 /* Initialized zeros for responses*/
64 resp->cmd_resp_status = 0;
65 resp->cmd_resp_data_0 = 0;
66 resp->cmd_resp_data_1 = 0;
67 resp->cmd_resp_data_2 = 0;
68
69 /* Ensure CMD_REQ is cleared before write any command request */
70 ret = wait_for_bit((const void *)(io96b_csr_addr + IOSSM_CMD_REQ_OFFSET),
71 GENMASK(31, 0), 0, 10000);
72
73 if (ret != 0) {
74 ERROR("%s: CMD_REQ not ready\n", __func__);
75 return -1;
76 }
77
78 /* Write CMD_PARAM_* */
79 for (i = 0; i < 6 ; i++) {
80 switch (i) {
81 case 0:
82 if (cmd_param_0 != 0) {
83 mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_0_OFFSET,
84 cmd_param_0);
85 }
86 break;
87 case 1:
88 if (cmd_param_1 != 0) {
89 mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_1_OFFSET,
90 cmd_param_1);
91 }
92 break;
93 case 2:
94 if (cmd_param_2 != 0) {
95 mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_2_OFFSET,
96 cmd_param_2);
97 }
98 break;
99 case 3:
100 if (cmd_param_3 != 0) {
101 mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_3_OFFSET,
102 cmd_param_3);
103 }
104 break;
105 case 4:
106 if (cmd_param_4 != 0) {
107 mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_4_OFFSET,
108 cmd_param_4);
109 }
110 break;
111 case 5:
112 if (cmd_param_5 != 0) {
113 mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_5_OFFSET,
114 cmd_param_5);
115 }
116 break;
117 case 6:
118 if (cmd_param_6 != 0) {
119 mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_6_OFFSET,
120 cmd_param_6);
121 }
122 break;
123 default:
124 ERROR("IOSSM: %s: Invalid command parameter\n", __func__);
125 }
126 }
127
128 /* Write CMD_REQ (IP_TYPE, IP_INSTANCE_ID, CMD_TYPE and CMD_OPCODE) */
129 cmd_req = (usr_cmd_opcode << 0) | (usr_cmd_type << 16) | (instance_id << 24) |
130 (ip_type << 29);
131 mmio_write_32(io96b_csr_addr + IOSSM_CMD_REQ_OFFSET, cmd_req);
132 INFO("IOSSM: %s: Write 0x%x to IOSSM_CMD_REQ_OFFSET 0x%llx\n",
133 __func__, cmd_req, io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
134
135 /* Read CMD_RESPONSE_READY in CMD_RESPONSE_STATUS*/
136 ret = wait_for_bit((const void *)(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET),
137 IOSSM_STATUS_COMMAND_RESPONSE_READY, 1, 10000);
138
139 if (ret != 0) {
140 ERROR("%s: CMD_RESPONSE ERROR:\n", __func__);
141 cmd_resp = (io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
142 ERROR("%s: STATUS_GENERAL_ERROR: 0x%x\n", __func__, (cmd_resp >> 1) & 0xF);
143 ERROR("%s: STATUS_CMD_RESPONSE_ERROR: 0x%x\n", __func__, (cmd_resp >> 5) & 0x7);
144 }
145
146 /* read CMD_RESPONSE_STATUS*/
147 resp->cmd_resp_status = mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
148 INFO("IOSSM: %s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n",
149 __func__, io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
150
151 /* read CMD_RESPONSE_DATA_* */
152 for (i = 0; i < resp_data_len; i++) {
153 switch (i) {
154 case 0:
155 resp->cmd_resp_data_0 =
156 mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_0_OFFSET);
157
158 break;
159 case 1:
160 resp->cmd_resp_data_1 =
161 mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_1_OFFSET);
162
163 break;
164 case 2:
165 resp->cmd_resp_data_2 =
166 mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_2_OFFSET);
167 break;
168 default:
169 ERROR("%s: Invalid response data\n", __func__);
170 }
171 }
172
173 resp->cmd_resp_status = mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
174 INFO("IOSSM: %s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n",
175 __func__, io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
176
177 /* write CMD_RESPONSE_READY = 0 */
178 mmio_clrbits_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET,
179 IOSSM_STATUS_COMMAND_RESPONSE_READY);
180
181 resp->cmd_resp_status = mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
182 INFO("IOSSM: %s: CMD_RESPONSE_READY 0x%llx: 0x%x\n",
183 __func__, io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
184
185 return 0;
186 }
187
188 /*
189 * Initial function to be called to set memory interface IP type and instance ID
190 * IP type and instance ID need to be determined before sending mailbox command
191 */
io96b_mb_init(struct io96b_info * io96b_ctrl)192 void io96b_mb_init(struct io96b_info *io96b_ctrl)
193 {
194 struct io96b_mb_resp usr_resp;
195 uint8_t ip_type_ret, instance_id_ret;
196 int i, j, k;
197
198 for (i = 0; i < io96b_ctrl->num_instance; i++) {
199 switch (i) {
200 case 0:
201 /* Get memory interface IP type & instance ID (IP identifier) */
202 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
203 CMD_GET_SYS_INFO, GET_MEM_INTF_INFO, 0, 0,
204 0, 0, 0, 0, 0, 2, &usr_resp);
205 /* Retrieve number of memory interface(s) */
206 io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface =
207 IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status) & 0x3;
208
209 /* Retrieve memory interface IP type and instance ID (IP identifier) */
210 j = 0;
211 for (k = 0; k < MAX_MEM_INTERFACES_SUPPORTED; k++) {
212 switch (k) {
213 case 0:
214 ip_type_ret = (usr_resp.cmd_resp_data_0 >> 29) & 0x7;
215 instance_id_ret = (usr_resp.cmd_resp_data_0 >> 24) & 0x1F;
216 break;
217 case 1:
218 ip_type_ret = (usr_resp.cmd_resp_data_1 >> 29) & 0x7;
219 instance_id_ret = (usr_resp.cmd_resp_data_1 >> 24) & 0x1F;
220 break;
221 }
222
223 if (ip_type_ret != 0) {
224 io96b_ctrl->io96b_0.mb_ctrl.ip_type[j] = ip_type_ret;
225 io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j] =
226 instance_id_ret;
227 j++;
228 }
229 }
230 break;
231 case 1:
232 /* Get memory interface IP type and instance ID (IP identifier) */
233 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0, CMD_GET_SYS_INFO,
234 GET_MEM_INTF_INFO, 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
235
236 /* Retrieve number of memory interface(s) */
237 io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface =
238 IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status) & 0x3;
239
240 /* Retrieve memory interface IP type and instance ID (IP identifier) */
241 j = 0;
242 for (k = 0; k < MAX_MEM_INTERFACES_SUPPORTED; k++) {
243 switch (k) {
244 case 0:
245 ip_type_ret = (usr_resp.cmd_resp_data_0 >> 29) & 0x7;
246 instance_id_ret = (usr_resp.cmd_resp_data_0 >> 24) & 0x1F;
247 break;
248 case 1:
249 ip_type_ret = (usr_resp.cmd_resp_data_1 >> 29) & 0x7;
250 instance_id_ret = (usr_resp.cmd_resp_data_1 >> 24) & 0x1F;
251 break;
252 }
253
254 if (ip_type_ret != 0) {
255 io96b_ctrl->io96b_1.mb_ctrl.ip_type[j] = ip_type_ret;
256 io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j] =
257 instance_id_ret;
258 j++;
259 }
260 }
261 break;
262 }
263
264 }
265 }
266
hang(void)267 static inline void hang(void)
268 {
269 ERROR("IOSSM: %s: system is going to die :(\n", __func__);
270 while (1)
271 ;
272 }
273
io96b_cal_status(phys_addr_t addr)274 int io96b_cal_status(phys_addr_t addr)
275 {
276 int cal_busy_status, cal_success_status;
277 phys_addr_t status_addr = addr + IOSSM_STATUS_OFFSET;
278
279 /* Ensure calibration busy status */
280 cal_busy_status = wait_for_bit((const void *)status_addr, IOSSM_STATUS_CAL_BUSY,
281 false, 15000);
282 if (cal_busy_status != 0) {
283 ERROR("IOSSM: One or more EMIF instances are busy with calibration\n");
284 return -EBUSY;
285 }
286
287 /* Calibration success status check */
288 NOTICE("IOSSM: Calibration success status check...\n");
289 cal_success_status = wait_for_bit((const void *)status_addr, IOSSM_STATUS_CAL_SUCCESS,
290 true, 15000);
291 if (cal_success_status != 0) {
292 ERROR("IOSSM: One/more EMIF instances either failed to calibrate/not completed\n");
293 return -EBUSY;
294 }
295
296 NOTICE("IOSSM: All EMIF instances within the IO96 have calibrated successfully!\n");
297 return 0;
298 }
299
init_mem_cal(struct io96b_info * io96b_ctrl)300 void init_mem_cal(struct io96b_info *io96b_ctrl)
301 {
302 int count, i, ret;
303
304 /* Initialize overall calibration status */
305 io96b_ctrl->overall_cal_status = false;
306
307 /* Check initial calibration status for the assigned IO96B */
308 count = 0;
309 for (i = 0; i < io96b_ctrl->num_instance; i++) {
310 switch (i) {
311 case 0:
312 ret = io96b_cal_status(io96b_ctrl->io96b_0.io96b_csr_addr);
313 if (ret != 0) {
314 io96b_ctrl->io96b_0.cal_status = false;
315 ERROR("%s: Initial DDR calibration IO96B_0 failed %d\n",
316 __func__, ret);
317 break;
318 }
319 io96b_ctrl->io96b_0.cal_status = true;
320 INFO("IOSSM: %s: Initial DDR calibration IO96B_0 succeed\n", __func__);
321 count++;
322 break;
323 case 1:
324 ret = io96b_cal_status(io96b_ctrl->io96b_1.io96b_csr_addr);
325 if (ret != 0) {
326 io96b_ctrl->io96b_1.cal_status = false;
327 ERROR("%s: Initial DDR calibration IO96B_1 failed %d\n",
328 __func__, ret);
329 break;
330 }
331 io96b_ctrl->io96b_1.cal_status = true;
332 INFO("IOSSM: %s: Initial DDR calibration IO96B_1 succeed\n", __func__);
333 count++;
334 break;
335 }
336 }
337
338 if (count == io96b_ctrl->num_instance)
339 io96b_ctrl->overall_cal_status = true;
340 }
341
342 /*
343 * Trying 3 times re-calibration if initial calibration failed
344 */
trig_mem_cal(struct io96b_info * io96b_ctrl)345 int trig_mem_cal(struct io96b_info *io96b_ctrl)
346 {
347 struct io96b_mb_resp usr_resp;
348 bool recal_success;
349 int i;
350 uint8_t cal_stat;
351
352 for (i = 0; i < io96b_ctrl->num_instance; i++) {
353 switch (i) {
354 case 0:
355 if (!(io96b_ctrl->io96b_0.cal_status)) {
356 /* Get the memory calibration status for first memory interface */
357 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
358 CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0,
359 0, 0, 0, 0, 0, 0, 2, &usr_resp);
360
361 recal_success = false;
362
363 /* Re-calibration first memory interface with failed calibration */
364 for (i = 0; i < 3; i++) {
365 cal_stat = usr_resp.cmd_resp_data_0 & GENMASK(2, 0);
366 if (cal_stat < 0x2) {
367 recal_success = true;
368 break;
369 }
370 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
371 io96b_ctrl->io96b_0.mb_ctrl.ip_type[0],
372 io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[0],
373 CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0,
374 0, 0, 0, 2, &usr_resp);
375 mdelay(1000);
376 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
377 CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS,
378 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
379 }
380
381 if (!recal_success) {
382 ERROR("%s: Error as SDRAM calibration failed\n", __func__);
383 hang();
384 }
385
386 /* Get the memory calibration status for second memory interface */
387 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
388 CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0, 0, 0,
389 0, 0, 0, 0, 2, &usr_resp);
390
391 recal_success = false;
392
393 /* Re-calibration second memory interface with failed calibration*/
394 for (i = 0; i < 3; i++) {
395 cal_stat = usr_resp.cmd_resp_data_1 & GENMASK(2, 0);
396 if (cal_stat < 0x2) {
397 recal_success = true;
398 break;
399 }
400 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
401 io96b_ctrl->io96b_0.mb_ctrl.ip_type[1],
402 io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[1],
403 CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0,
404 0, 0, 0, 2, &usr_resp);
405 mdelay(1000);
406 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
407 CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS,
408 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
409 }
410
411 if (!recal_success) {
412 ERROR("IOSSMM: Error as SDRAM calibration failed\n");
413 hang();
414 }
415
416 io96b_ctrl->io96b_0.cal_status = true;
417 }
418 break;
419 case 1:
420 if (!(io96b_ctrl->io96b_1.cal_status)) {
421 /* Get the memory calibration status for first memory interface */
422 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0,
423 CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0,
424 0, 0, 0, 0, 0, 0, 2, &usr_resp);
425
426 recal_success = false;
427
428 /* Re-calibration first memory interface with failed calibration */
429 for (i = 0; i < 3; i++) {
430 cal_stat = usr_resp.cmd_resp_data_0 & GENMASK(2, 0);
431 if (cal_stat < 0x2) {
432 recal_success = true;
433 break;
434 }
435 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
436 io96b_ctrl->io96b_1.mb_ctrl.ip_type[0],
437 io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[0],
438 CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0,
439 0, 0, 0, 2, &usr_resp);
440 mdelay(1000);
441 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0,
442 CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS,
443 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
444 }
445
446 if (!recal_success) {
447 ERROR("IOSSM: Error as SDRAM calibration failed\n");
448 hang();
449 }
450
451 /* Get the memory calibration status for second memory interface */
452 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0,
453 CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0, 0, 0,
454 0, 0, 0, 0, 2, &usr_resp);
455
456 recal_success = false;
457
458 /* Re-calibration second memory interface with failed calibration*/
459 for (i = 0; i < 3; i++) {
460 cal_stat = usr_resp.cmd_resp_data_0 & GENMASK(2, 0);
461 if (cal_stat < 0x2) {
462 recal_success = true;
463 break;
464 }
465 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
466 io96b_ctrl->io96b_1.mb_ctrl.ip_type[1],
467 io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[1],
468 CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0,
469 0, 0, 0, 2, &usr_resp);
470 mdelay(1000);
471 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0,
472 CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS,
473 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
474 }
475
476 if (!recal_success) {
477 ERROR("IOSSM: Error as SDRAM calibration failed\n");
478 hang();
479 }
480
481 io96b_ctrl->io96b_1.cal_status = true;
482 }
483 break;
484 }
485 }
486
487 if (io96b_ctrl->io96b_0.cal_status && io96b_ctrl->io96b_1.cal_status) {
488 INFO("IOSSM: %s: Overall SDRAM calibration success\n", __func__);
489 io96b_ctrl->overall_cal_status = true;
490 }
491
492 return 0;
493 }
494
get_mem_technology(struct io96b_info * io96b_ctrl)495 int get_mem_technology(struct io96b_info *io96b_ctrl)
496 {
497 struct io96b_mb_resp usr_resp;
498 int i, j;
499 uint8_t ddr_type_ret;
500
501 /* Initialize ddr type */
502 io96b_ctrl->ddr_type = ddr_type_list[6];
503
504 /* Get and ensure all memory interface(s) same DDR type */
505 for (i = 0; i < io96b_ctrl->num_instance; i++) {
506 switch (i) {
507 case 0:
508 for (j = 0; j < io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
509 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
510 io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
511 io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
512 CMD_GET_MEM_INFO, GET_MEM_TECHNOLOGY, 0, 0, 0, 0,
513 0, 0, 0, 0, &usr_resp);
514
515 ddr_type_ret =
516 IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
517 & GENMASK(2, 0);
518
519 if (strcmp(io96b_ctrl->ddr_type, "UNKNOWN") == 0)
520 io96b_ctrl->ddr_type = ddr_type_list[ddr_type_ret];
521
522 if (ddr_type_list[ddr_type_ret] != io96b_ctrl->ddr_type) {
523 ERROR("IOSSM: Mismatch DDR type on IO96B_0\n");
524 return -ENOEXEC;
525 }
526 }
527 break;
528 case 1:
529 for (j = 0; j < io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
530 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
531 io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
532 io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
533 CMD_GET_MEM_INFO, GET_MEM_TECHNOLOGY, 0, 0, 0,
534 0, 0, 0, 0, 0, &usr_resp);
535
536 ddr_type_ret =
537 IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
538 & GENMASK(2, 0);
539
540 if (strcmp(io96b_ctrl->ddr_type, "UNKNOWN") == 0)
541 io96b_ctrl->ddr_type = ddr_type_list[ddr_type_ret];
542
543 if (ddr_type_list[ddr_type_ret] != io96b_ctrl->ddr_type) {
544 ERROR("IOSSM: Mismatch DDR type on IO96B_1\n");
545 return -ENOEXEC;
546 }
547 }
548 break;
549 }
550 }
551
552 return 0;
553 }
554
get_mem_width_info(struct io96b_info * io96b_ctrl)555 int get_mem_width_info(struct io96b_info *io96b_ctrl)
556 {
557 struct io96b_mb_resp usr_resp;
558 int i, j;
559 uint16_t memory_size = 0U;
560 uint16_t total_memory_size = 0U;
561
562 /* Get all memory interface(s) total memory size on all instance(s) */
563 for (i = 0; i < io96b_ctrl->num_instance; i++) {
564 switch (i) {
565 case 0:
566 memory_size = 0;
567 for (j = 0; j < io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
568 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
569 io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
570 io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
571 CMD_GET_MEM_INFO, GET_MEM_WIDTH_INFO, 0, 0, 0,
572 0, 0, 0, 0, 2, &usr_resp);
573
574 memory_size = memory_size +
575 (usr_resp.cmd_resp_data_1 & GENMASK(7, 0));
576 }
577
578 if (memory_size == 0U) {
579 ERROR("IOSSM: %s: Failed to get valid memory size\n", __func__);
580 return -ENOEXEC;
581 }
582
583 io96b_ctrl->io96b_0.size = memory_size;
584
585 break;
586 case 1:
587 memory_size = 0;
588 for (j = 0; j < io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
589 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
590 io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
591 io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
592 CMD_GET_MEM_INFO, GET_MEM_WIDTH_INFO, 0, 0, 0,
593 0, 0, 0, 0, 2, &usr_resp);
594
595 memory_size = memory_size +
596 (usr_resp.cmd_resp_data_1 & GENMASK(7, 0));
597 }
598
599 if (memory_size == 0U) {
600 ERROR("IOSSM: %s: Failed to get valid memory size\n", __func__);
601 return -ENOEXEC;
602 }
603
604 io96b_ctrl->io96b_1.size = memory_size;
605
606 break;
607 }
608
609 total_memory_size = total_memory_size + memory_size;
610 }
611
612 if (total_memory_size == 0U) {
613 ERROR("IOSSM: %s: Failed to get valid memory size\n", __func__);
614 return -ENOEXEC;
615 }
616
617 io96b_ctrl->overall_size = total_memory_size;
618
619 return 0;
620 }
621
ecc_enable_status(struct io96b_info * io96b_ctrl)622 int ecc_enable_status(struct io96b_info *io96b_ctrl)
623 {
624 struct io96b_mb_resp usr_resp;
625 int i, j;
626 bool ecc_stat_set = false;
627 bool ecc_stat;
628
629 /* Initialize ECC status */
630 io96b_ctrl->ecc_status = false;
631
632 /* Get and ensure all memory interface(s) same ECC status */
633 for (i = 0; i < io96b_ctrl->num_instance; i++) {
634 switch (i) {
635 case 0:
636 for (j = 0; j < io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
637 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
638 io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
639 io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
640 CMD_TRIG_CONTROLLER_OP, ECC_ENABLE_STATUS, 0, 0,
641 0, 0, 0, 0, 0, 0, &usr_resp);
642
643 ecc_stat = ((IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
644 & GENMASK(1, 0)) == 0 ? false : true);
645
646 if (!ecc_stat_set) {
647 io96b_ctrl->ecc_status = ecc_stat;
648 ecc_stat_set = true;
649 }
650
651 if (ecc_stat != io96b_ctrl->ecc_status) {
652 ERROR("IOSSM: %s: Mismatch DDR ECC status on IO96B_0\n",
653 __func__);
654 return -ENOEXEC;
655 }
656 }
657 break;
658 case 1:
659 for (j = 0; j < io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
660 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
661 io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
662 io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
663 CMD_TRIG_CONTROLLER_OP, ECC_ENABLE_STATUS, 0, 0,
664 0, 0, 0, 0, 0, 0, &usr_resp);
665
666 ecc_stat = ((IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
667 & GENMASK(1, 0)) == 0 ? false : true);
668
669 if (!ecc_stat_set) {
670 io96b_ctrl->ecc_status = ecc_stat;
671 ecc_stat_set = true;
672 }
673
674 if (ecc_stat != io96b_ctrl->ecc_status) {
675 ERROR("%s: Mismatch DDR ECC status on IO96B_1\n"
676 , __func__);
677 return -ENOEXEC;
678 }
679 }
680 break;
681 }
682 }
683 return 0;
684 }
685
bist_mem_init_start(struct io96b_info * io96b_ctrl)686 int bist_mem_init_start(struct io96b_info *io96b_ctrl)
687 {
688 struct io96b_mb_resp usr_resp;
689 int i, j;
690 bool bist_start, bist_success;
691 uint32_t read_count;
692 uint32_t read_interval_ms;
693
694 /* Full memory initialization BIST performed on all memory interface(s) */
695 for (i = 0; i < io96b_ctrl->num_instance; i++) {
696 switch (i) {
697 case 0:
698 for (j = 0; j < io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
699 bist_start = false;
700 bist_success = false;
701 read_interval_ms = 500U;
702
703 /* Start memory initialization BIST on full memory address */
704 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
705 io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
706 io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
707 CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START, 0x40,
708 0, 0, 0, 0, 0, 0, 0, &usr_resp);
709
710 bist_start =
711 (IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
712 & 1);
713
714 if (!bist_start) {
715 ERROR("IOSSM: %s: Failed to initialized memory on IO96B_0\n"
716 , __func__);
717 ERROR("IOSSM: %s: BIST_MEM_INIT_START Error code 0x%x\n",
718 __func__,
719 (IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
720 & GENMASK(2, 1)) > 0x1);
721 return -ENOEXEC;
722 }
723
724 /* Polling for the initiated memory initialization BIST status */
725 read_count = read_interval_ms / TIMEOUT;
726 while (!bist_success) {
727 io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
728 io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
729 io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
730 CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_STATUS,
731 0, 0, 0, 0, 0, 0, 0, 0, &usr_resp);
732
733 bist_success = (IOSSM_CMD_RESPONSE_DATA_SHORT
734 (usr_resp.cmd_resp_status) & 1);
735
736 if ((!bist_success) && (read_count == 0U)) {
737 ERROR("IOSSM: %s: Timeout init memory on IO96B_0\n"
738 , __func__);
739 ERROR("IOSSM: %s: BIST_MEM_INIT_STATUS Err code%x\n"
740 , __func__, (IOSSM_CMD_RESPONSE_DATA_SHORT
741 (usr_resp.cmd_resp_status)
742 & GENMASK(2, 1)) > 0x1);
743 return -ETIMEDOUT;
744 }
745 read_count--;
746 mdelay(read_interval_ms);
747 }
748 }
749
750 NOTICE("IOSSM: %s: Memory initialized successfully on IO96B_0\n", __func__);
751 break;
752
753 case 1:
754 for (j = 0; j < io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
755 bist_start = false;
756 bist_success = false;
757 read_interval_ms = 500U;
758
759 /* Start memory initialization BIST on full memory address */
760 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
761 io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
762 io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
763 CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START, 0x40,
764 0, 0, 0, 0, 0, 0, 0, &usr_resp);
765
766 bist_start =
767 (IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
768 & 1);
769
770 if (!bist_start) {
771 ERROR("IOSSM: %s: Failed to initialized memory on IO96B_1\n"
772 , __func__);
773 ERROR("IOSSM: %s: BIST_MEM_INIT_START Error code 0x%x\n",
774 __func__,
775 (IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
776 & GENMASK(2, 1)) > 0x1);
777 return -ENOEXEC;
778 }
779
780 /* Polling for the initiated memory initialization BIST status */
781 read_count = read_interval_ms / TIMEOUT;
782 while (!bist_success) {
783 io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
784 io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
785 io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
786 CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_STATUS,
787 0, 0, 0, 0, 0, 0, 0, 0, &usr_resp);
788
789 bist_success = (IOSSM_CMD_RESPONSE_DATA_SHORT
790 (usr_resp.cmd_resp_status) & 1);
791
792 if ((!bist_success) && (read_count == 0U)) {
793 ERROR("IOSSM: %s: Timeout init memory on IO96B_1\n"
794 , __func__);
795 ERROR("IOSSM: %s: BIST_MEM_INIT_STATUS ErrCode %x\n"
796 , __func__, (IOSSM_CMD_RESPONSE_DATA_SHORT
797 (usr_resp.cmd_resp_status)
798 & GENMASK(2, 1)) > 0x1);
799 return -ETIMEDOUT;
800 }
801 read_count--;
802 mdelay(read_interval_ms);
803 }
804 }
805
806 NOTICE("IOSSM: %s: Memory initialized successfully on IO96B_1\n", __func__);
807 break;
808 }
809 }
810 return 0;
811 }
812