• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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