blob: fc09dde3f9eaa6d15bd14e7503bb3a0aac00d7e6 [file] [log] [blame]
Tingting Menga1a24f12025-02-21 21:49:41 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2025 Altera Corporation <www.altera.com>
4 *
5 */
6
7#include <hang.h>
8#include <string.h>
9#include <wait_bit.h>
10#include <asm/arch/base_addr_soc64.h>
11#include <asm/io.h>
12#include <linux/bitfield.h>
Tingting Mengdc6c9272025-04-15 14:50:51 +080013#include <linux/sizes.h>
Tingting Menga1a24f12025-02-21 21:49:41 +080014#include "iossm_mailbox.h"
15
16#define TIMEOUT_120000MS 120000
17#define TIMEOUT_60000MS 60000
18#define TIMEOUT TIMEOUT_120000MS
19#define IOSSM_STATUS_CAL_SUCCESS BIT(0)
20#define IOSSM_STATUS_CAL_FAIL BIT(1)
21#define IOSSM_STATUS_CAL_BUSY BIT(2)
22#define IOSSM_STATUS_COMMAND_RESPONSE_READY BIT(0)
23#define IOSSM_CMD_RESPONSE_STATUS_OFFSET 0x45C
24#define IOSSM_CMD_RESPONSE_DATA_0_OFFSET 0x458
25#define IOSSM_CMD_RESPONSE_DATA_1_OFFSET 0x454
26#define IOSSM_CMD_RESPONSE_DATA_2_OFFSET 0x450
27#define IOSSM_CMD_REQ_OFFSET 0x43C
28#define IOSSM_CMD_PARAM_0_OFFSET 0x438
29#define IOSSM_CMD_PARAM_1_OFFSET 0x434
30#define IOSSM_CMD_PARAM_2_OFFSET 0x430
31#define IOSSM_CMD_PARAM_3_OFFSET 0x42C
32#define IOSSM_CMD_PARAM_4_OFFSET 0x428
33#define IOSSM_CMD_PARAM_5_OFFSET 0x424
34#define IOSSM_CMD_PARAM_6_OFFSET 0x420
35#define IOSSM_CMD_RESPONSE_DATA_SHORT_MASK GENMASK(31, 16)
36#define IOSSM_CMD_RESPONSE_DATA_SHORT(n) FIELD_GET(IOSSM_CMD_RESPONSE_DATA_SHORT_MASK, n)
37#define IOSSM_STATUS_CMD_RESPONSE_ERROR_MASK GENMASK(7, 5)
38#define IOSSM_STATUS_CMD_RESPONSE_ERROR(n) FIELD_GET(IOSSM_STATUS_CMD_RESPONSE_ERROR_MASK, n)
39#define IOSSM_STATUS_GENERAL_ERROR_MASK GENMASK(4, 1)
40#define IOSSM_STATUS_GENERAL_ERROR(n) FIELD_GET(IOSSM_STATUS_GENERAL_ERROR_MASK, n)
41
42/* Offset of Mailbox Read-only Registers */
43#define IOSSM_MAILBOX_HEADER_OFFSET 0x0
44#define IOSSM_MEM_INTF_INFO_0_OFFSET 0X200
45#define IOSSM_MEM_INTF_INFO_1_OFFSET 0x280
46#define IOSSM_MEM_TECHNOLOGY_INTF0_OFFSET 0x210
47#define IOSSM_MEM_TECHNOLOGY_INTF1_OFFSET 0x290
48#define IOSSM_MEM_WIDTH_INFO_INTF0_OFFSET 0x230
49#define IOSSM_MEM_WIDTH_INFO_INTF1_OFFSET 0x2B0
50#define IOSSM_MEM_TOTAL_CAPACITY_INTF0_OFFSET 0x234
51#define IOSSM_MEM_TOTAL_CAPACITY_INTF1_OFFSET 0x2B4
52#define IOSSM_ECC_ENABLE_INTF0_OFFSET 0x240
53#define IOSSM_ECC_ENABLE_INTF1_OFFSET 0x2C0
54#define IOSSM_ECC_SCRUB_STATUS_INTF0_OFFSET 0x244
55#define IOSSM_ECC_SCRUB_STATUS_INTF1_OFFSET 0x2C4
56#define IOSSM_LP_MODE_INTF0_OFFSET 0x250
57#define IOSSM_LP_MODE_INTF1_OFFSET 0x2D0
58#define IOSSM_MEM_INIT_STATUS_INTF0_OFFSET 0x260
59#define IOSSM_MEM_INIT_STATUS_INTF1_OFFSET 0x2E0
60#define IOSSM_BIST_STATUS_INTF0_OFFSET 0x264
61#define IOSSM_BIST_STATUS_INTF1_OFFSET 0x2E4
62#define IOSSM_ECC_ERR_STATUS_OFFSET 0x300
63#define IOSSM_ECC_ERR_DATA_START_OFFSET 0x310
64#define IOSSM_STATUS_OFFSET 0x400
65#define IOSSM_STATUS_CAL_INTF0_OFFSET 0x404
66#define IOSSM_STATUS_CAL_INTF1_OFFSET 0x408
67
68#define ECC_INTSTATUS_SERR SOCFPGA_SYSMGR_ADDRESS + 0x9C
69#define ECC_INISTATUS_DERR SOCFPGA_SYSMGR_ADDRESS + 0xA0
70#define DDR_CSR_CLKGEN_LOCKED_IO96B0_MASK BIT(16)
71#define DDR_CSR_CLKGEN_LOCKED_IO96B1_MASK BIT(17)
72
73/* offset info of GET_MEM_INTF_INFO */
74#define INTF_IP_TYPE_MASK GENMASK(31, 29)
75#define INTF_INSTANCE_ID_MASK GENMASK(28, 24)
76
77/* offset info of GET_MEM_CAL_STATUS */
78#define INTF_UNUSED 0x0
79#define INTF_MEM_CAL_STATUS_SUCCESS 0x1
80#define INTF_MEM_CAL_STATUS_FAIL 0x2
81#define INTF_MEM_CAL_STATUS_ONGOING 0x4
82
83/* offset info of MEM_TECHNOLOGY_INTF */
84#define INTF_DDR_TYPE_MASK GENMASK(2, 0)
85
86/* offset info of MEM_TOTAL_CAPACITY_INTF */
87#define INTF_CAPACITY_GBITS_MASK GENMASK(7, 0)
88
89/* offset info of ECC_ENABLE_INTF */
90#define INTF_ECC_ENABLE_TYPE_MASK GENMASK(1, 0)
Tingting Mengdc6c9272025-04-15 14:50:51 +080091#define INTF_ECC_TYPE_MASK BIT(8)
Tingting Menga1a24f12025-02-21 21:49:41 +080092
93/* cmd opcode BIST_MEM_INIT_START, BIST performed on full memory address range */
94#define BIST_FULL_MEM BIT(6)
95
96/* offset info of ECC_ENABLE_INTF */
97#define INTF_BIST_STATUS_MASK BIT(0)
98
99/* offset info of ECC_ERR_STATUS */
100#define ECC_ERR_COUNTER_MASK GENMASK(15, 0)
Tingting Meng2e820f32025-04-07 10:47:24 +0800101#define ECC_ERR_OVERFLOW_MASK GENMASK(31, 16)
Tingting Menga1a24f12025-02-21 21:49:41 +0800102
103/* offset info of ECC_ERR_DATA */
104#define ECC_ERR_IP_TYPE_MASK GENMASK(24, 22)
105#define ECC_ERR_INSTANCE_ID_MASK GENMASK(21, 17)
106#define ECC_ERR_SOURCE_ID_MASK GENMASK(16, 10)
107#define ECC_ERR_TYPE_MASK GENMASK(9, 6)
108#define ECC_ERR_ADDR_UPPER_MASK GENMASK(5, 0)
109#define ECC_ERR_ADDR_LOWER_MASK GENMASK(31, 0)
Tingting Meng2e820f32025-04-07 10:47:24 +0800110#define ECC_FULL_ADDR_UPPER_MASK GENMASK(63, 32)
111#define ECC_FULL_ADDR_LOWER_MASK GENMASK(31, 0)
Tingting Menga1a24f12025-02-21 21:49:41 +0800112
113#define MAX_ECC_ERR_INFO_COUNT 16
114
Tingting Mengdc6c9272025-04-15 14:50:51 +0800115#define BIST_START_ADDR_SPACE_MASK GENMASK(5, 0)
116#define BIST_START_ADDR_LOW_MASK GENMASK(31, 0)
117#define BIST_START_ADDR_HIGH_MASK GENMASK(37, 32)
118
Tingting Menga1a24f12025-02-21 21:49:41 +0800119#define IO96B_MB_REQ_SETUP(v, w, x, y, z) \
120 usr_req.ip_type = v; \
121 usr_req.ip_id = w; \
122 usr_req.usr_cmd_type = x; \
123 usr_req.usr_cmd_opcode = y; \
124 usr_req.cmd_param[0] = z; \
125 for (n = 1; n < NUM_CMD_PARAM; n++) \
126 usr_req.cmd_param[n] = 0
127#define MAX_RETRY_COUNT 3
128#define NUM_CMD_RESPONSE_DATA 3
129
130#define IO96B0_PLL_A_MASK BIT(0)
131#define IO96B0_PLL_B_MASK BIT(1)
132#define IO96B1_PLL_A_MASK BIT(2)
133#define IO96B1_PLL_B_MASK BIT(3)
134
135/* supported DDR type list */
136static const char *ddr_type_list[7] = {
137 "DDR4", "DDR5", "DDR5_RDIMM", "LPDDR4", "LPDDR5", "QDRIV", "UNKNOWN"
138};
139
140/* Define an enumeration for ECC error types */
141enum ecc_error_type {
142 SINGLE_BIT_ERROR = 0, /* 0b0000 */
143 MULTIPLE_SINGLE_BIT_ERRORS = 1, /* 0b0001 */
144 DOUBLE_BIT_ERROR = 2, /* 0b0010 */
145 MULTIPLE_DOUBLE_BIT_ERRORS = 3, /* 0b0011 */
146 SINGLE_BIT_ERROR_SCRUBBING = 8, /* 0b1000 */
147 WRITE_LINK_SINGLE_BIT_ERROR = 9, /* 0b1001 */
148 WRITE_LINK_DOUBLE_BIT_ERROR = 10, /* 0b1010 */
149 READ_LINK_SINGLE_BIT_ERROR = 11, /* 0b1011 */
150 READ_LINK_DOUBLE_BIT_ERROR = 12, /* 0b1100 */
151 READ_MODIFY_WRITE_DOUBLE_BIT_ERROR = 13 /* 0b1101 */
152};
153
154/*
155 * ecc error info
156 *
157 * @ip_type: The IP type of the interface that produced the ECC interrupt.
158 * @instance_id: The instance ID of the interface that produced the ECC interrupt.
159 * @ecc_err_source_id: The source ID associated with the ECC event.
160 * @ecc_err_type: The ECC error type of the ECC event.
161 * @ecc_err_addr_upper: Upper 6 bits of the address of the read data that caused the ECC event.
162 * @ecc_err_addr_lower: Lower 32 bits of the address of the read data that caused the ECC event.
163 */
164struct ecc_err_info {
165 u32 ip_type;
166 u32 instance_id;
167 u32 source_id;
168 enum ecc_error_type err_type;
169 u32 addr_upper;
170 u32 addr_lower;
171};
172
Tingting Meng2e820f32025-04-07 10:47:24 +0800173struct ecc_overflow_error_desc {
174 int bit;
175 const char *msg;
176};
177
178static const struct ecc_overflow_error_desc ecc_overflow_errors[] = {
179 { 0, " - Single-bit error\n" },
180 { 1, " - Multiple single-bit errors\n" },
181 { 2, " - Double-bit error\n" },
182 { 3, " - Multiple double-bit errors\n" },
183 { 8, " - Single-bit error during ECC scrubbing\n" },
184 { 9, " - Write link ECC single-bit error (LPDDR5 only)\n" },
185 { 10, " - Write link ECC double-bit error (LPDDR5 only)\n" },
186 { 11, " - Read link ECC single-bit error (LPDDR5 only)\n" },
187 { 12, " - Read link ECC double-bit error (LPDDR5 only)\n" },
188 { 13, " - RMW read link ECC double-bit error (LPDDR5 only)\n" },
189};
190
Tingting Menga1a24f12025-02-21 21:49:41 +0800191static int is_ddr_csr_clkgen_locked(u8 io96b_pll)
192{
193 int ret = 0;
194 const char *pll_names[MAX_IO96B_SUPPORTED][2] = {
195 {"io96b_0 clkgenA", "io96b_0 clkgenB"},
196 {"io96b_1 clkgenA", "io96b_1 clkgenB"}
197 };
198 u32 masks[MAX_IO96B_SUPPORTED][2] = {
199 {IO96B0_PLL_A_MASK, IO96B0_PLL_B_MASK},
200 {IO96B1_PLL_A_MASK, IO96B1_PLL_B_MASK}
201 };
202 u32 lock_masks[MAX_IO96B_SUPPORTED] = {
203 DDR_CSR_CLKGEN_LOCKED_IO96B0_MASK,
204 DDR_CSR_CLKGEN_LOCKED_IO96B1_MASK
205 };
206
207 for (int i = 0; i < MAX_IO96B_SUPPORTED ; i++) {
208 /* Check for PLL_A */
209 if (io96b_pll & masks[i][0]) {
210 ret = wait_for_bit_le32((const void *)(ECC_INTSTATUS_SERR), lock_masks[i],
211 true, TIMEOUT, false);
212
213 if (ret) {
214 debug("%s: ddr csr %s locked is timeout\n",
215 __func__, pll_names[i][0]);
216 goto err;
217 } else {
218 debug("%s: ddr csr %s is successfully locked\n",
219 __func__, pll_names[i][0]);
220 }
221 }
222
223 /* Check for PLL_B */
224 if (io96b_pll & masks[i][1]) {
225 ret = wait_for_bit_le32((const void *)(ECC_INISTATUS_DERR), lock_masks[i],
226 true, TIMEOUT, false);
227
228 if (ret) {
229 debug("%s: ddr csr %s locked is timeout\n",
230 __func__, pll_names[i][1]);
231 goto err;
232 } else {
233 debug("%s: ddr csr %s is successfully locked\n",
234 __func__, pll_names[i][1]);
235 }
236 }
237 }
238
239err:
240 return ret;
241}
242
243/*
244 * Mailbox request function
245 * This function will send the request to IOSSM mailbox and wait for response return
246 *
247 * @io96b_csr_addr: CSR address for the target IO96B
248 * @req: Structure contain command request for IOSSM mailbox command
249 * @resp_data_len: User desire extra response data fields other than
250 * CMD_RESPONSE_DATA_SHORT field on CMD_RESPONSE_STATUS
251 * @resp: Structure contain responses returned from the requested IOSSM
252 * mailbox command
253 */
254int io96b_mb_req(phys_addr_t io96b_csr_addr, struct io96b_mb_req req,
255 u32 resp_data_len, struct io96b_mb_resp *resp)
256{
257 int i, ret;
258 u32 cmd_req;
259
260 if (!resp) {
261 ret = -EINVAL;
262 goto err;
263 }
264
265 /* Zero initialization for responses */
266 resp->cmd_resp_status = 0;
267
268 /* Ensure CMD_REQ is cleared before write any command request */
269 ret = wait_for_bit_le32((const void *)(io96b_csr_addr + IOSSM_CMD_REQ_OFFSET),
270 GENMASK(31, 0), false, TIMEOUT, false);
271 if (ret) {
272 printf("%s: Timeout of waiting DDR mailbox ready to be functioned!\n",
273 __func__);
274 goto err;
275 }
276
277 /* Write CMD_PARAM_* */
278 for (i = 0; i < NUM_CMD_PARAM ; i++) {
279 switch (i) {
280 case 0:
281 if (req.cmd_param[0])
282 writel(req.cmd_param[0], io96b_csr_addr + IOSSM_CMD_PARAM_0_OFFSET);
283 break;
284 case 1:
285 if (req.cmd_param[1])
286 writel(req.cmd_param[1], io96b_csr_addr + IOSSM_CMD_PARAM_1_OFFSET);
287 break;
288 case 2:
289 if (req.cmd_param[2])
290 writel(req.cmd_param[2], io96b_csr_addr + IOSSM_CMD_PARAM_2_OFFSET);
291 break;
292 case 3:
293 if (req.cmd_param[3])
294 writel(req.cmd_param[3], io96b_csr_addr + IOSSM_CMD_PARAM_3_OFFSET);
295 break;
296 case 4:
297 if (req.cmd_param[4])
298 writel(req.cmd_param[4], io96b_csr_addr + IOSSM_CMD_PARAM_4_OFFSET);
299 break;
300 case 5:
301 if (req.cmd_param[5])
302 writel(req.cmd_param[5], io96b_csr_addr + IOSSM_CMD_PARAM_5_OFFSET);
303 break;
304 case 6:
305 if (req.cmd_param[6])
306 writel(req.cmd_param[6], io96b_csr_addr + IOSSM_CMD_PARAM_6_OFFSET);
307 break;
308 }
309 }
310
311 /* Write CMD_REQ (IP_TYPE, IP_INSTANCE_ID, CMD_TYPE and CMD_OPCODE) */
312 cmd_req = FIELD_PREP(CMD_TARGET_IP_TYPE_MASK, req.ip_type) |
313 FIELD_PREP(CMD_TARGET_IP_INSTANCE_ID_MASK, req.ip_id) |
314 FIELD_PREP(CMD_TYPE_MASK, req.usr_cmd_type) |
315 FIELD_PREP(CMD_OPCODE_MASK, req.usr_cmd_opcode);
316 writel(cmd_req, io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
317
318 debug("%s: Write 0x%x to IOSSM_CMD_REQ_OFFSET 0x%llx\n", __func__, cmd_req,
319 io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
320
321 /* Read CMD_RESPONSE_READY in CMD_RESPONSE_STATUS */
322 ret = wait_for_bit_le32((const void *)(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET),
323 IOSSM_STATUS_COMMAND_RESPONSE_READY, true, TIMEOUT, false);
324
325 /* read CMD_RESPONSE_STATUS */
326 resp->cmd_resp_status = readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
327
328 debug("%s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n", __func__, io96b_csr_addr +
329 IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
330
331 if (ret) {
332 printf("%s: CMD_RESPONSE ERROR:\n", __func__);
333
334 printf("%s: STATUS_GENERAL_ERROR: 0x%lx\n", __func__,
335 IOSSM_STATUS_GENERAL_ERROR(resp->cmd_resp_status));
336 printf("%s: STATUS_CMD_RESPONSE_ERROR: 0x%lx\n", __func__,
337 IOSSM_STATUS_CMD_RESPONSE_ERROR(resp->cmd_resp_status));
338 goto err;
339 }
340
341 /* read CMD_RESPONSE_DATA_* */
342 for (i = 0; i < resp_data_len; i++) {
343 switch (i) {
344 case 0:
345 resp->cmd_resp_data[i] =
346 readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_0_OFFSET);
347
348 debug("%s: IOSSM_CMD_RESPONSE_DATA_0_OFFSET 0x%llx: 0x%x\n", __func__,
349 io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_0_OFFSET,
350 resp->cmd_resp_data[i]);
351 break;
352 case 1:
353 resp->cmd_resp_data[i] =
354 readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_1_OFFSET);
355
356 debug("%s: IOSSM_CMD_RESPONSE_DATA_1_OFFSET 0x%llx: 0x%x\n", __func__,
357 io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_1_OFFSET,
358 resp->cmd_resp_data[i]);
359 break;
360 case 2:
361 resp->cmd_resp_data[i] =
362 readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_2_OFFSET);
363
364 debug("%s: IOSSM_CMD_RESPONSE_DATA_2_OFFSET 0x%llx: 0x%x\n", __func__,
365 io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_2_OFFSET,
366 resp->cmd_resp_data[i]);
367 break;
368 default:
369 resp->cmd_resp_data[i] = 0;
370 printf("%s: Invalid response data\n", __func__);
371 }
372 }
373
374 /* write CMD_RESPONSE_READY = 0 */
375 clrbits_le32((u32 *)(uintptr_t)(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET),
376 IOSSM_STATUS_COMMAND_RESPONSE_READY);
377
378 debug("%s: After clear CMD_RESPONSE_READY bit: 0x%llx: 0x%x\n", __func__,
379 io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET,
380 readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET));
381
382err:
383 return ret;
384}
385
386/*
387 * Initial function to be called to set memory interface IP type and instance ID
388 * IP type and instance ID need to be determined before sending mailbox command
389 */
390void io96b_mb_init(struct io96b_info *io96b_ctrl)
391{
392 int i, j;
393 u32 mem_intf_info_0, mem_intf_info_1;
394
395 debug("%s: num_instance %d\n", __func__, io96b_ctrl->num_instance);
396
397 for (i = 0; i < io96b_ctrl->num_instance; i++) {
398 debug("%s: get memory interface IO96B %d\n", __func__, i);
399 io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface = 0;
400
401 mem_intf_info_0 = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
402 IOSSM_MEM_INTF_INFO_0_OFFSET);
403 mem_intf_info_1 = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
404 IOSSM_MEM_INTF_INFO_1_OFFSET);
405
406 io96b_ctrl->io96b[i].mb_ctrl.ip_type[0] = FIELD_GET(INTF_IP_TYPE_MASK,
407 mem_intf_info_0);
408 io96b_ctrl->io96b[i].mb_ctrl.ip_id[0] = FIELD_GET(INTF_INSTANCE_ID_MASK,
409 mem_intf_info_0);
410 io96b_ctrl->io96b[i].mb_ctrl.ip_type[1] = FIELD_GET(INTF_IP_TYPE_MASK,
411 mem_intf_info_1);
412 io96b_ctrl->io96b[i].mb_ctrl.ip_id[1] = FIELD_GET(INTF_INSTANCE_ID_MASK,
413 mem_intf_info_1);
414
415 for (j = 0; j < MAX_MEM_INTERFACE_SUPPORTED; j++) {
416 if (io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]) {
417 io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface++;
418
419 debug("%s: IO96B %d mem_interface %d: ip_type_ret: 0x%x\n",
420 __func__, i, j, io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]);
421 debug("%s: IO96B %d mem_interface %d: instance_id_ret: 0x%x\n",
422 __func__, i, j, io96b_ctrl->io96b[i].mb_ctrl.ip_id[j]);
423 }
424 }
425
426 debug("%s: IO96B %d: num_mem_interface: 0x%x\n", __func__, i,
427 io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface);
428 }
429}
430
431int io96b_cal_status(phys_addr_t addr)
432{
433 u32 cal_success, cal_fail;
434 phys_addr_t status_addr = addr + IOSSM_STATUS_OFFSET;
435 u32 start = get_timer(0);
436
437 do {
438 if (get_timer(start) > TIMEOUT_60000MS) {
439 printf("%s: SDRAM calibration for IO96B instance 0x%llx timeout!\n",
440 __func__, status_addr);
441 hang();
442 }
443
444 udelay(1);
445 schedule();
446
447 /* Polling until getting any calibration result */
448 cal_success = readl(status_addr) & IOSSM_STATUS_CAL_SUCCESS;
449 cal_fail = readl(status_addr) & IOSSM_STATUS_CAL_FAIL;
450 } while (!cal_success && !cal_fail);
451
452 debug("%s: Calibration for IO96B instance 0x%llx done at %ld msec!\n",
453 __func__, status_addr, get_timer(start));
454
455 if (cal_success && !cal_fail)
456 return 0;
457 else
458 return -EPERM;
459}
460
461void init_mem_cal(struct io96b_info *io96b_ctrl)
462{
463 int count, i, ret;
464
465 /* Initialize overall calibration status */
466 io96b_ctrl->overall_cal_status = false;
467
468 if (io96b_ctrl->ckgen_lock) {
469 ret = is_ddr_csr_clkgen_locked(io96b_ctrl->io96b_pll);
470 if (ret) {
471 printf("%s: iossm IO96B ckgena_lock is not locked\n", __func__);
472 hang();
473 }
474 }
475
476 /* Check initial calibration status for the assigned IO96B */
477 count = 0;
478 for (i = 0; i < io96b_ctrl->num_instance; i++) {
479 ret = io96b_cal_status(io96b_ctrl->io96b[i].io96b_csr_addr);
480 if (ret) {
481 io96b_ctrl->io96b[i].cal_status = false;
482
483 printf("%s: Initial DDR calibration IO96B_%d failed %d\n", __func__,
484 i, ret);
485
486 hang();
487 }
488
489 io96b_ctrl->io96b[i].cal_status = true;
490
491 printf("%s: Initial DDR calibration IO96B_%d succeed\n", __func__, i);
492
493 count++;
494 }
495
496 if (count == io96b_ctrl->num_instance)
497 io96b_ctrl->overall_cal_status = true;
498}
499
500int get_mem_technology(struct io96b_info *io96b_ctrl)
501{
502 int i, j, ret = 0;
503 u32 mem_technology_intf;
504 u8 ddr_type_ret;
505
506 u32 mem_technology_intf_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
507 IOSSM_MEM_TECHNOLOGY_INTF0_OFFSET,
508 IOSSM_MEM_TECHNOLOGY_INTF1_OFFSET
509 };
510
511 /* Initialize ddr type */
512 io96b_ctrl->ddr_type = ddr_type_list[6];
513
514 /* Get and ensure all memory interface(s) same DDR type */
515 for (i = 0; i < io96b_ctrl->num_instance; i++) {
516 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
517 mem_technology_intf = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
518 mem_technology_intf_offset[j]);
519
520 ddr_type_ret = FIELD_GET(INTF_DDR_TYPE_MASK, mem_technology_intf);
521
522 if (!strcmp(io96b_ctrl->ddr_type, "UNKNOWN"))
523 io96b_ctrl->ddr_type = ddr_type_list[ddr_type_ret];
524
525 if (ddr_type_list[ddr_type_ret] != io96b_ctrl->ddr_type) {
526 printf("%s: Mismatch DDR type on IO96B_%d\n", __func__, i);
527
528 ret = -EINVAL;
529 goto err;
530 }
531 }
532 }
533
534err:
535 return ret;
536}
537
538int get_mem_width_info(struct io96b_info *io96b_ctrl)
539{
540 int i, j, ret = 0;
541 u32 mem_width_info;
Tingting Mengdc6c9272025-04-15 14:50:51 +0800542 phys_size_t memory_size, total_memory_size = 0;
Tingting Menga1a24f12025-02-21 21:49:41 +0800543
544 u32 mem_total_capacity_intf_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
545 IOSSM_MEM_TOTAL_CAPACITY_INTF0_OFFSET,
546 IOSSM_MEM_TOTAL_CAPACITY_INTF1_OFFSET
547 };
548
549 /* Get all memory interface(s) total memory size on all instance(s) */
550 for (i = 0; i < io96b_ctrl->num_instance; i++) {
551 memory_size = 0;
552 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
553 mem_width_info = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
554 mem_total_capacity_intf_offset[j]);
555
Tingting Mengdc6c9272025-04-15 14:50:51 +0800556 io96b_ctrl->io96b[i].mb_ctrl.memory_size[j] =
557 FIELD_GET(INTF_CAPACITY_GBITS_MASK, mem_width_info) * SZ_1G / SZ_8;
558
559 if (io96b_ctrl->io96b[i].mb_ctrl.memory_size[j] != 0)
560 memory_size += io96b_ctrl->io96b[i].mb_ctrl.memory_size[j];
Tingting Menga1a24f12025-02-21 21:49:41 +0800561 }
562
563 if (!memory_size) {
564 printf("%s: Failed to get valid memory size\n", __func__);
565 ret = -EINVAL;
566 goto err;
567 }
568
Tingting Menga1a24f12025-02-21 21:49:41 +0800569 total_memory_size = total_memory_size + memory_size;
570 }
571
572 if (!total_memory_size) {
573 printf("%s: Failed to get valid memory size\n", __func__);
574 ret = -EINVAL;
575 }
576
577 io96b_ctrl->overall_size = total_memory_size;
578
579err:
580 return ret;
581}
582
583int ecc_enable_status(struct io96b_info *io96b_ctrl)
584{
585 int i, j, ret = 0;
586 u32 ecc_enable_intf;
Tingting Mengdc6c9272025-04-15 14:50:51 +0800587 bool ecc_status, ecc_status_set = false, inline_ecc = false;
Tingting Menga1a24f12025-02-21 21:49:41 +0800588
589 u32 ecc_enable_intf_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
590 IOSSM_ECC_ENABLE_INTF0_OFFSET,
591 IOSSM_ECC_ENABLE_INTF1_OFFSET
592 };
593
594 /* Initialize ECC status */
595 io96b_ctrl->ecc_status = false;
Tingting Mengdc6c9272025-04-15 14:50:51 +0800596 io96b_ctrl->inline_ecc = false;
Tingting Menga1a24f12025-02-21 21:49:41 +0800597
598 /* Get and ensure all memory interface(s) same ECC status */
599 for (i = 0; i < io96b_ctrl->num_instance; i++) {
600 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
601 ecc_enable_intf = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
602 ecc_enable_intf_offset[j]);
603
Tingting Mengdc6c9272025-04-15 14:50:51 +0800604 ecc_status = (FIELD_GET(INTF_ECC_ENABLE_TYPE_MASK, ecc_enable_intf)
Tingting Menga1a24f12025-02-21 21:49:41 +0800605 == 0) ? false : true;
Tingting Mengdc6c9272025-04-15 14:50:51 +0800606 inline_ecc = FIELD_GET(INTF_ECC_TYPE_MASK, ecc_enable_intf);
Tingting Menga1a24f12025-02-21 21:49:41 +0800607
Tingting Mengdc6c9272025-04-15 14:50:51 +0800608 if (!ecc_status_set) {
609 io96b_ctrl->ecc_status = ecc_status;
610
611 if (io96b_ctrl->ecc_status)
612 io96b_ctrl->inline_ecc = inline_ecc;
613
614 ecc_status_set = true;
Tingting Menga1a24f12025-02-21 21:49:41 +0800615 }
616
Tingting Mengdc6c9272025-04-15 14:50:51 +0800617 if (ecc_status != io96b_ctrl->ecc_status ||
618 (io96b_ctrl->ecc_status && inline_ecc != io96b_ctrl->inline_ecc)) {
Tingting Menga1a24f12025-02-21 21:49:41 +0800619 printf("%s: Mismatch DDR ECC status on IO96B_%d\n", __func__, i);
620
621 ret = -EINVAL;
622 goto err;
623 }
624 }
625 }
626
627 debug("%s: ECC enable status: %d\n", __func__, io96b_ctrl->ecc_status);
628
629err:
630 return ret;
631}
632
633bool is_double_bit_error(enum ecc_error_type err_type)
634{
635 switch (err_type) {
636 case DOUBLE_BIT_ERROR:
637 case MULTIPLE_DOUBLE_BIT_ERRORS:
638 case WRITE_LINK_DOUBLE_BIT_ERROR:
639 case READ_LINK_DOUBLE_BIT_ERROR:
640 case READ_MODIFY_WRITE_DOUBLE_BIT_ERROR:
641 return true;
642
643 default:
644 return false;
645 }
646}
647
648bool ecc_interrupt_status(struct io96b_info *io96b_ctrl)
649{
650 int i, j;
651 u32 ecc_err_status;
Tingting Meng2e820f32025-04-07 10:47:24 +0800652 u16 ecc_err_counter, ecc_overflow_status;
Tingting Menga1a24f12025-02-21 21:49:41 +0800653 bool ecc_error_flag = false;
654
655 /* Get ECC double-bit error status */
656 for (i = 0; i < io96b_ctrl->num_instance; i++) {
657 ecc_err_status = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
658 IOSSM_ECC_ERR_STATUS_OFFSET);
Tingting Meng2e820f32025-04-07 10:47:24 +0800659
Tingting Menga1a24f12025-02-21 21:49:41 +0800660 ecc_err_counter = FIELD_GET(ECC_ERR_COUNTER_MASK, ecc_err_status);
Tingting Meng2e820f32025-04-07 10:47:24 +0800661 log_err("%s: ECC error number detected on IO96B_%d: %d\n",
662 __func__, i, ecc_err_counter);
663
664 ecc_overflow_status = FIELD_GET(ECC_ERR_OVERFLOW_MASK, ecc_err_status);
665 if (ecc_overflow_status != 0) {
666 log_err("ECC Error Overflow Flags:\n");
667
668 for (int i = 0; i < ARRAY_SIZE(ecc_overflow_errors); i++) {
669 if (ecc_overflow_status & BIT(ecc_overflow_errors[i].bit)) {
670 log_err("%s", ecc_overflow_errors[i].msg);
671 }
672 }
673 }
Tingting Menga1a24f12025-02-21 21:49:41 +0800674
675 if (ecc_err_counter != 0) {
676 phys_addr_t address;
677 u32 ecc_err_data;
678 struct ecc_err_info err_info;
679
680 address = io96b_ctrl->io96b[i].io96b_csr_addr +
681 IOSSM_ECC_ERR_DATA_START_OFFSET;
682
683 for (j = 0; j < ecc_err_counter && j < MAX_ECC_ERR_INFO_COUNT; j++) {
684 ecc_err_data = readl(address);
685 err_info.err_type = FIELD_GET(ECC_ERR_TYPE_MASK,
686 ecc_err_data);
687 err_info.ip_type = FIELD_GET(ECC_ERR_IP_TYPE_MASK,
688 ecc_err_data);
689 err_info.instance_id = FIELD_GET(ECC_ERR_INSTANCE_ID_MASK,
690 ecc_err_data);
691 err_info.source_id = FIELD_GET(ECC_ERR_SOURCE_ID_MASK,
692 ecc_err_data);
693 err_info.addr_upper = FIELD_GET(ECC_ERR_ADDR_UPPER_MASK,
694 ecc_err_data);
695 err_info.addr_lower = readl(address + sizeof(u32));
696
Tingting Meng2e820f32025-04-07 10:47:24 +0800697 log_err(" %s: DDR ECC Error Detected on IO96B_%d number:%d\n",
698 __func__, i, j);
699 log_err(" - error info address :0x%llx\n", address);
700 log_err(" - error ip type: %d\n", err_info.ip_type);
701 log_err(" - error instance id: %d\n", err_info.instance_id);
702 log_err(" - error source id: %d\n", err_info.source_id);
703 log_err(" - error type: %s\n",
704 is_double_bit_error(err_info.err_type) ?
705 "Double-bit error" : "Single-bit error");
706 log_err(" - error address: 0x%016llx\n",
707 (u64)FIELD_PREP(ECC_FULL_ADDR_UPPER_MASK,
708 err_info.addr_upper) |
709 FIELD_PREP(ECC_FULL_ADDR_LOWER_MASK,
710 err_info.addr_lower));
Tingting Menga1a24f12025-02-21 21:49:41 +0800711
712 if (is_double_bit_error(err_info.err_type)) {
713 if (!ecc_error_flag)
714 ecc_error_flag = true;
715 }
716
717 address += sizeof(u32) * 2;
718 }
719 }
720 }
721
722 if (ecc_error_flag)
Tingting Meng2e820f32025-04-07 10:47:24 +0800723 log_err("\n%s: ECC double-bit error detected!\n", __func__);
Tingting Menga1a24f12025-02-21 21:49:41 +0800724
725 return ecc_error_flag;
726}
727
Tingting Mengdc6c9272025-04-15 14:50:51 +0800728int out_of_band_bist_mem_init_start(struct io96b_info *io96b_ctrl)
Tingting Menga1a24f12025-02-21 21:49:41 +0800729{
730 struct io96b_mb_req usr_req;
731 struct io96b_mb_resp usr_resp;
732 int i, j, n, ret = 0;
733 bool bist_start, bist_success;
734 u32 mem_init_status_intf, start;
735
736 u32 mem_init_status_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
737 IOSSM_MEM_INIT_STATUS_INTF0_OFFSET,
738 IOSSM_MEM_INIT_STATUS_INTF1_OFFSET
739 };
740
741 /* Full memory initialization BIST performed on all memory interface(s) */
742 for (i = 0; i < io96b_ctrl->num_instance; i++) {
743 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
744 bist_start = false;
745 bist_success = false;
746
747 /* Start memory initialization BIST on full memory address */
748 IO96B_MB_REQ_SETUP(io96b_ctrl->io96b[i].mb_ctrl.ip_type[j],
749 io96b_ctrl->io96b[i].mb_ctrl.ip_id[j],
750 CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START,
751 BIST_FULL_MEM);
752
753 ret = io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr,
754 usr_req, 0, &usr_resp);
755 if (ret)
756 goto err;
757
758 bist_start = IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
759 & BIT(0);
760
761 if (!bist_start) {
762 printf("%s: Failed to initialize memory on IO96B_%d\n", __func__,
763 i);
764 printf("%s: BIST_MEM_INIT_START Error code 0x%lx\n", __func__,
765 IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status));
766
767 ret = -EINVAL;
768 goto err;
769 }
770
771 /* Polling for the initiated memory initialization BIST status */
772 start = get_timer(0);
773 while (!bist_success) {
774 udelay(1);
775
776 mem_init_status_intf = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
777 mem_init_status_offset[j]);
778
779 bist_success = FIELD_GET(INTF_BIST_STATUS_MASK,
780 mem_init_status_intf);
781
782 if (!bist_success && (get_timer(start) > TIMEOUT)) {
783 printf("%s: Timeout initialize memory on IO96B_%d\n",
784 __func__, i);
785 printf("%s: BIST_MEM_INIT_STATUS Error code 0x%lx\n",
786 __func__,
787 IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status));
788
789 ret = -ETIMEDOUT;
790 goto err;
791 }
792 }
793 }
794
795 debug("%s: Memory initialized successfully on IO96B_%d\n", __func__, i);
796 }
797
798err:
799 return ret;
800}
Tingting Mengdc6c9272025-04-15 14:50:51 +0800801
802int bist_mem_init_by_addr(struct io96b_info *io96b_ctrl, int inst_id, int intf_id,
803 phys_addr_t base_addr, phys_size_t size)
804{
805 struct io96b_mb_req usr_req;
806 struct io96b_mb_resp usr_resp;
807 int n, ret = 0;
808 bool bist_start, bist_success;
809 u32 mem_exp, mem_init_status_intf, start;
810 phys_size_t chunk_size;
811
812 u32 mem_init_status_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
813 IOSSM_MEM_INIT_STATUS_INTF0_OFFSET,
814 IOSSM_MEM_INIT_STATUS_INTF1_OFFSET
815 };
816
817 /* Check if size is a power of 2 */
818 if (size == 0 || (size & (size - 1)) != 0) {
819 ret = -EINVAL;
820 goto err;
821 }
822
823 mem_exp = 0;
824 chunk_size = size;
825
826 while (chunk_size >>= 1)
827 mem_exp++;
828
829 /* Start memory initialization BIST on the specified address range */
830 IO96B_MB_REQ_SETUP(io96b_ctrl->io96b[inst_id].mb_ctrl.ip_type[intf_id],
831 io96b_ctrl->io96b[inst_id].mb_ctrl.ip_id[intf_id],
832 CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START, 0);
833
834 /* CMD_PARAM_0 bit[5:0] = mem_exp */
835 /* CMD_PARAM_0 bit[6]: 0 - on the specified address range */
836 usr_req.cmd_param[0] = FIELD_PREP(BIST_START_ADDR_SPACE_MASK, mem_exp);
837 /* Extract address fields START_ADDR[31:0] */
838 usr_req.cmd_param[1] = FIELD_GET(BIST_START_ADDR_LOW_MASK, base_addr);
839 /* Extract address fields START_ADDR[37:32] */
840 usr_req.cmd_param[2] = FIELD_GET(BIST_START_ADDR_HIGH_MASK, base_addr);
841 /* Initialize memory to all zeros */
842 usr_req.cmd_param[3] = 0;
843
844 bist_start = false;
845 bist_success = false;
846
847 /* Send request to DDR controller */
848 debug("%s:Initializing memory: Addr=0x%llx, Size=2^%u\n", __func__,
849 base_addr, mem_exp);
850 ret = io96b_mb_req(io96b_ctrl->io96b[inst_id].io96b_csr_addr,
851 usr_req, 0, &usr_resp);
852 if (ret)
853 goto err;
854
855 bist_start = IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
856 & BIT(0);
857
858 if (!bist_start) {
859 printf("%s: Failed to initialize memory on IO96B_%d\n", __func__,
860 inst_id);
861 printf("%s: BIST_MEM_INIT_START Error code 0x%lx\n", __func__,
862 IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status));
863
864 ret = -EINVAL;
865 goto err;
866 }
867
868 /* Polling for the initiated memory initialization BIST status */
869 start = get_timer(0);
870 while (!bist_success) {
871 udelay(1);
872
873 mem_init_status_intf = readl(io96b_ctrl->io96b[inst_id].io96b_csr_addr +
874 mem_init_status_offset[intf_id]);
875
876 bist_success = FIELD_GET(INTF_BIST_STATUS_MASK, mem_init_status_intf);
877
878 if (!bist_success && (get_timer(start) > TIMEOUT)) {
879 printf("%s: Timeout initialize memory on IO96B_%d\n",
880 __func__, inst_id);
881 printf("%s: BIST_MEM_INIT_STATUS Error code 0x%lx\n",
882 __func__,
883 IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status));
884
885 ret = -ETIMEDOUT;
886 goto err;
887 }
888 }
889
890 debug("%s:DDR memory initializationat 0x%llx completed.\n", __func__, base_addr);
891
892err:
893 return ret;
894}
895
896int inline_ecc_bist_mem_init(struct io96b_info *io96b_ctrl)
897{
898 int i, j, ret = 0;
899
900 /* Memory initialization BIST performed on all memory interfaces */
901 for (i = 0; i < io96b_ctrl->num_instance; i++) {
902 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
903 ret = bist_mem_init_by_addr(io96b_ctrl, i, j, 0,
904 io96b_ctrl->io96b[i].mb_ctrl.memory_size[j]);
905 if (ret) {
906 printf("Error: Memory init failed at Instance %d, Interface %d\n",
907 i, j);
908 goto err;
909 }
910 }
911 }
912
913err:
914 return ret;
915}
916
917int bist_mem_init_start(struct io96b_info *io96b_ctrl)
918{
919 if (io96b_ctrl->inline_ecc)
920 return inline_ecc_bist_mem_init(io96b_ctrl);
921 else
922 return out_of_band_bist_mem_init_start(io96b_ctrl);
923}