blob: 26602858777da576ddcccc83f7a2aedd36b56561 [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)
101
102/* offset info of ECC_ERR_DATA */
103#define ECC_ERR_IP_TYPE_MASK GENMASK(24, 22)
104#define ECC_ERR_INSTANCE_ID_MASK GENMASK(21, 17)
105#define ECC_ERR_SOURCE_ID_MASK GENMASK(16, 10)
106#define ECC_ERR_TYPE_MASK GENMASK(9, 6)
107#define ECC_ERR_ADDR_UPPER_MASK GENMASK(5, 0)
108#define ECC_ERR_ADDR_LOWER_MASK GENMASK(31, 0)
109
110#define MAX_ECC_ERR_INFO_COUNT 16
111
Tingting Mengdc6c9272025-04-15 14:50:51 +0800112#define BIST_START_ADDR_SPACE_MASK GENMASK(5, 0)
113#define BIST_START_ADDR_LOW_MASK GENMASK(31, 0)
114#define BIST_START_ADDR_HIGH_MASK GENMASK(37, 32)
115
Tingting Menga1a24f12025-02-21 21:49:41 +0800116#define IO96B_MB_REQ_SETUP(v, w, x, y, z) \
117 usr_req.ip_type = v; \
118 usr_req.ip_id = w; \
119 usr_req.usr_cmd_type = x; \
120 usr_req.usr_cmd_opcode = y; \
121 usr_req.cmd_param[0] = z; \
122 for (n = 1; n < NUM_CMD_PARAM; n++) \
123 usr_req.cmd_param[n] = 0
124#define MAX_RETRY_COUNT 3
125#define NUM_CMD_RESPONSE_DATA 3
126
127#define IO96B0_PLL_A_MASK BIT(0)
128#define IO96B0_PLL_B_MASK BIT(1)
129#define IO96B1_PLL_A_MASK BIT(2)
130#define IO96B1_PLL_B_MASK BIT(3)
131
132/* supported DDR type list */
133static const char *ddr_type_list[7] = {
134 "DDR4", "DDR5", "DDR5_RDIMM", "LPDDR4", "LPDDR5", "QDRIV", "UNKNOWN"
135};
136
137/* Define an enumeration for ECC error types */
138enum ecc_error_type {
139 SINGLE_BIT_ERROR = 0, /* 0b0000 */
140 MULTIPLE_SINGLE_BIT_ERRORS = 1, /* 0b0001 */
141 DOUBLE_BIT_ERROR = 2, /* 0b0010 */
142 MULTIPLE_DOUBLE_BIT_ERRORS = 3, /* 0b0011 */
143 SINGLE_BIT_ERROR_SCRUBBING = 8, /* 0b1000 */
144 WRITE_LINK_SINGLE_BIT_ERROR = 9, /* 0b1001 */
145 WRITE_LINK_DOUBLE_BIT_ERROR = 10, /* 0b1010 */
146 READ_LINK_SINGLE_BIT_ERROR = 11, /* 0b1011 */
147 READ_LINK_DOUBLE_BIT_ERROR = 12, /* 0b1100 */
148 READ_MODIFY_WRITE_DOUBLE_BIT_ERROR = 13 /* 0b1101 */
149};
150
151/*
152 * ecc error info
153 *
154 * @ip_type: The IP type of the interface that produced the ECC interrupt.
155 * @instance_id: The instance ID of the interface that produced the ECC interrupt.
156 * @ecc_err_source_id: The source ID associated with the ECC event.
157 * @ecc_err_type: The ECC error type of the ECC event.
158 * @ecc_err_addr_upper: Upper 6 bits of the address of the read data that caused the ECC event.
159 * @ecc_err_addr_lower: Lower 32 bits of the address of the read data that caused the ECC event.
160 */
161struct ecc_err_info {
162 u32 ip_type;
163 u32 instance_id;
164 u32 source_id;
165 enum ecc_error_type err_type;
166 u32 addr_upper;
167 u32 addr_lower;
168};
169
170static int is_ddr_csr_clkgen_locked(u8 io96b_pll)
171{
172 int ret = 0;
173 const char *pll_names[MAX_IO96B_SUPPORTED][2] = {
174 {"io96b_0 clkgenA", "io96b_0 clkgenB"},
175 {"io96b_1 clkgenA", "io96b_1 clkgenB"}
176 };
177 u32 masks[MAX_IO96B_SUPPORTED][2] = {
178 {IO96B0_PLL_A_MASK, IO96B0_PLL_B_MASK},
179 {IO96B1_PLL_A_MASK, IO96B1_PLL_B_MASK}
180 };
181 u32 lock_masks[MAX_IO96B_SUPPORTED] = {
182 DDR_CSR_CLKGEN_LOCKED_IO96B0_MASK,
183 DDR_CSR_CLKGEN_LOCKED_IO96B1_MASK
184 };
185
186 for (int i = 0; i < MAX_IO96B_SUPPORTED ; i++) {
187 /* Check for PLL_A */
188 if (io96b_pll & masks[i][0]) {
189 ret = wait_for_bit_le32((const void *)(ECC_INTSTATUS_SERR), lock_masks[i],
190 true, TIMEOUT, false);
191
192 if (ret) {
193 debug("%s: ddr csr %s locked is timeout\n",
194 __func__, pll_names[i][0]);
195 goto err;
196 } else {
197 debug("%s: ddr csr %s is successfully locked\n",
198 __func__, pll_names[i][0]);
199 }
200 }
201
202 /* Check for PLL_B */
203 if (io96b_pll & masks[i][1]) {
204 ret = wait_for_bit_le32((const void *)(ECC_INISTATUS_DERR), lock_masks[i],
205 true, TIMEOUT, false);
206
207 if (ret) {
208 debug("%s: ddr csr %s locked is timeout\n",
209 __func__, pll_names[i][1]);
210 goto err;
211 } else {
212 debug("%s: ddr csr %s is successfully locked\n",
213 __func__, pll_names[i][1]);
214 }
215 }
216 }
217
218err:
219 return ret;
220}
221
222/*
223 * Mailbox request function
224 * This function will send the request to IOSSM mailbox and wait for response return
225 *
226 * @io96b_csr_addr: CSR address for the target IO96B
227 * @req: Structure contain command request for IOSSM mailbox command
228 * @resp_data_len: User desire extra response data fields other than
229 * CMD_RESPONSE_DATA_SHORT field on CMD_RESPONSE_STATUS
230 * @resp: Structure contain responses returned from the requested IOSSM
231 * mailbox command
232 */
233int io96b_mb_req(phys_addr_t io96b_csr_addr, struct io96b_mb_req req,
234 u32 resp_data_len, struct io96b_mb_resp *resp)
235{
236 int i, ret;
237 u32 cmd_req;
238
239 if (!resp) {
240 ret = -EINVAL;
241 goto err;
242 }
243
244 /* Zero initialization for responses */
245 resp->cmd_resp_status = 0;
246
247 /* Ensure CMD_REQ is cleared before write any command request */
248 ret = wait_for_bit_le32((const void *)(io96b_csr_addr + IOSSM_CMD_REQ_OFFSET),
249 GENMASK(31, 0), false, TIMEOUT, false);
250 if (ret) {
251 printf("%s: Timeout of waiting DDR mailbox ready to be functioned!\n",
252 __func__);
253 goto err;
254 }
255
256 /* Write CMD_PARAM_* */
257 for (i = 0; i < NUM_CMD_PARAM ; i++) {
258 switch (i) {
259 case 0:
260 if (req.cmd_param[0])
261 writel(req.cmd_param[0], io96b_csr_addr + IOSSM_CMD_PARAM_0_OFFSET);
262 break;
263 case 1:
264 if (req.cmd_param[1])
265 writel(req.cmd_param[1], io96b_csr_addr + IOSSM_CMD_PARAM_1_OFFSET);
266 break;
267 case 2:
268 if (req.cmd_param[2])
269 writel(req.cmd_param[2], io96b_csr_addr + IOSSM_CMD_PARAM_2_OFFSET);
270 break;
271 case 3:
272 if (req.cmd_param[3])
273 writel(req.cmd_param[3], io96b_csr_addr + IOSSM_CMD_PARAM_3_OFFSET);
274 break;
275 case 4:
276 if (req.cmd_param[4])
277 writel(req.cmd_param[4], io96b_csr_addr + IOSSM_CMD_PARAM_4_OFFSET);
278 break;
279 case 5:
280 if (req.cmd_param[5])
281 writel(req.cmd_param[5], io96b_csr_addr + IOSSM_CMD_PARAM_5_OFFSET);
282 break;
283 case 6:
284 if (req.cmd_param[6])
285 writel(req.cmd_param[6], io96b_csr_addr + IOSSM_CMD_PARAM_6_OFFSET);
286 break;
287 }
288 }
289
290 /* Write CMD_REQ (IP_TYPE, IP_INSTANCE_ID, CMD_TYPE and CMD_OPCODE) */
291 cmd_req = FIELD_PREP(CMD_TARGET_IP_TYPE_MASK, req.ip_type) |
292 FIELD_PREP(CMD_TARGET_IP_INSTANCE_ID_MASK, req.ip_id) |
293 FIELD_PREP(CMD_TYPE_MASK, req.usr_cmd_type) |
294 FIELD_PREP(CMD_OPCODE_MASK, req.usr_cmd_opcode);
295 writel(cmd_req, io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
296
297 debug("%s: Write 0x%x to IOSSM_CMD_REQ_OFFSET 0x%llx\n", __func__, cmd_req,
298 io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
299
300 /* Read CMD_RESPONSE_READY in CMD_RESPONSE_STATUS */
301 ret = wait_for_bit_le32((const void *)(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET),
302 IOSSM_STATUS_COMMAND_RESPONSE_READY, true, TIMEOUT, false);
303
304 /* read CMD_RESPONSE_STATUS */
305 resp->cmd_resp_status = readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
306
307 debug("%s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n", __func__, io96b_csr_addr +
308 IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
309
310 if (ret) {
311 printf("%s: CMD_RESPONSE ERROR:\n", __func__);
312
313 printf("%s: STATUS_GENERAL_ERROR: 0x%lx\n", __func__,
314 IOSSM_STATUS_GENERAL_ERROR(resp->cmd_resp_status));
315 printf("%s: STATUS_CMD_RESPONSE_ERROR: 0x%lx\n", __func__,
316 IOSSM_STATUS_CMD_RESPONSE_ERROR(resp->cmd_resp_status));
317 goto err;
318 }
319
320 /* read CMD_RESPONSE_DATA_* */
321 for (i = 0; i < resp_data_len; i++) {
322 switch (i) {
323 case 0:
324 resp->cmd_resp_data[i] =
325 readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_0_OFFSET);
326
327 debug("%s: IOSSM_CMD_RESPONSE_DATA_0_OFFSET 0x%llx: 0x%x\n", __func__,
328 io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_0_OFFSET,
329 resp->cmd_resp_data[i]);
330 break;
331 case 1:
332 resp->cmd_resp_data[i] =
333 readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_1_OFFSET);
334
335 debug("%s: IOSSM_CMD_RESPONSE_DATA_1_OFFSET 0x%llx: 0x%x\n", __func__,
336 io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_1_OFFSET,
337 resp->cmd_resp_data[i]);
338 break;
339 case 2:
340 resp->cmd_resp_data[i] =
341 readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_2_OFFSET);
342
343 debug("%s: IOSSM_CMD_RESPONSE_DATA_2_OFFSET 0x%llx: 0x%x\n", __func__,
344 io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_2_OFFSET,
345 resp->cmd_resp_data[i]);
346 break;
347 default:
348 resp->cmd_resp_data[i] = 0;
349 printf("%s: Invalid response data\n", __func__);
350 }
351 }
352
353 /* write CMD_RESPONSE_READY = 0 */
354 clrbits_le32((u32 *)(uintptr_t)(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET),
355 IOSSM_STATUS_COMMAND_RESPONSE_READY);
356
357 debug("%s: After clear CMD_RESPONSE_READY bit: 0x%llx: 0x%x\n", __func__,
358 io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET,
359 readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET));
360
361err:
362 return ret;
363}
364
365/*
366 * Initial function to be called to set memory interface IP type and instance ID
367 * IP type and instance ID need to be determined before sending mailbox command
368 */
369void io96b_mb_init(struct io96b_info *io96b_ctrl)
370{
371 int i, j;
372 u32 mem_intf_info_0, mem_intf_info_1;
373
374 debug("%s: num_instance %d\n", __func__, io96b_ctrl->num_instance);
375
376 for (i = 0; i < io96b_ctrl->num_instance; i++) {
377 debug("%s: get memory interface IO96B %d\n", __func__, i);
378 io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface = 0;
379
380 mem_intf_info_0 = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
381 IOSSM_MEM_INTF_INFO_0_OFFSET);
382 mem_intf_info_1 = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
383 IOSSM_MEM_INTF_INFO_1_OFFSET);
384
385 io96b_ctrl->io96b[i].mb_ctrl.ip_type[0] = FIELD_GET(INTF_IP_TYPE_MASK,
386 mem_intf_info_0);
387 io96b_ctrl->io96b[i].mb_ctrl.ip_id[0] = FIELD_GET(INTF_INSTANCE_ID_MASK,
388 mem_intf_info_0);
389 io96b_ctrl->io96b[i].mb_ctrl.ip_type[1] = FIELD_GET(INTF_IP_TYPE_MASK,
390 mem_intf_info_1);
391 io96b_ctrl->io96b[i].mb_ctrl.ip_id[1] = FIELD_GET(INTF_INSTANCE_ID_MASK,
392 mem_intf_info_1);
393
394 for (j = 0; j < MAX_MEM_INTERFACE_SUPPORTED; j++) {
395 if (io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]) {
396 io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface++;
397
398 debug("%s: IO96B %d mem_interface %d: ip_type_ret: 0x%x\n",
399 __func__, i, j, io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]);
400 debug("%s: IO96B %d mem_interface %d: instance_id_ret: 0x%x\n",
401 __func__, i, j, io96b_ctrl->io96b[i].mb_ctrl.ip_id[j]);
402 }
403 }
404
405 debug("%s: IO96B %d: num_mem_interface: 0x%x\n", __func__, i,
406 io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface);
407 }
408}
409
410int io96b_cal_status(phys_addr_t addr)
411{
412 u32 cal_success, cal_fail;
413 phys_addr_t status_addr = addr + IOSSM_STATUS_OFFSET;
414 u32 start = get_timer(0);
415
416 do {
417 if (get_timer(start) > TIMEOUT_60000MS) {
418 printf("%s: SDRAM calibration for IO96B instance 0x%llx timeout!\n",
419 __func__, status_addr);
420 hang();
421 }
422
423 udelay(1);
424 schedule();
425
426 /* Polling until getting any calibration result */
427 cal_success = readl(status_addr) & IOSSM_STATUS_CAL_SUCCESS;
428 cal_fail = readl(status_addr) & IOSSM_STATUS_CAL_FAIL;
429 } while (!cal_success && !cal_fail);
430
431 debug("%s: Calibration for IO96B instance 0x%llx done at %ld msec!\n",
432 __func__, status_addr, get_timer(start));
433
434 if (cal_success && !cal_fail)
435 return 0;
436 else
437 return -EPERM;
438}
439
440void init_mem_cal(struct io96b_info *io96b_ctrl)
441{
442 int count, i, ret;
443
444 /* Initialize overall calibration status */
445 io96b_ctrl->overall_cal_status = false;
446
447 if (io96b_ctrl->ckgen_lock) {
448 ret = is_ddr_csr_clkgen_locked(io96b_ctrl->io96b_pll);
449 if (ret) {
450 printf("%s: iossm IO96B ckgena_lock is not locked\n", __func__);
451 hang();
452 }
453 }
454
455 /* Check initial calibration status for the assigned IO96B */
456 count = 0;
457 for (i = 0; i < io96b_ctrl->num_instance; i++) {
458 ret = io96b_cal_status(io96b_ctrl->io96b[i].io96b_csr_addr);
459 if (ret) {
460 io96b_ctrl->io96b[i].cal_status = false;
461
462 printf("%s: Initial DDR calibration IO96B_%d failed %d\n", __func__,
463 i, ret);
464
465 hang();
466 }
467
468 io96b_ctrl->io96b[i].cal_status = true;
469
470 printf("%s: Initial DDR calibration IO96B_%d succeed\n", __func__, i);
471
472 count++;
473 }
474
475 if (count == io96b_ctrl->num_instance)
476 io96b_ctrl->overall_cal_status = true;
477}
478
479int get_mem_technology(struct io96b_info *io96b_ctrl)
480{
481 int i, j, ret = 0;
482 u32 mem_technology_intf;
483 u8 ddr_type_ret;
484
485 u32 mem_technology_intf_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
486 IOSSM_MEM_TECHNOLOGY_INTF0_OFFSET,
487 IOSSM_MEM_TECHNOLOGY_INTF1_OFFSET
488 };
489
490 /* Initialize ddr type */
491 io96b_ctrl->ddr_type = ddr_type_list[6];
492
493 /* Get and ensure all memory interface(s) same DDR type */
494 for (i = 0; i < io96b_ctrl->num_instance; i++) {
495 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
496 mem_technology_intf = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
497 mem_technology_intf_offset[j]);
498
499 ddr_type_ret = FIELD_GET(INTF_DDR_TYPE_MASK, mem_technology_intf);
500
501 if (!strcmp(io96b_ctrl->ddr_type, "UNKNOWN"))
502 io96b_ctrl->ddr_type = ddr_type_list[ddr_type_ret];
503
504 if (ddr_type_list[ddr_type_ret] != io96b_ctrl->ddr_type) {
505 printf("%s: Mismatch DDR type on IO96B_%d\n", __func__, i);
506
507 ret = -EINVAL;
508 goto err;
509 }
510 }
511 }
512
513err:
514 return ret;
515}
516
517int get_mem_width_info(struct io96b_info *io96b_ctrl)
518{
519 int i, j, ret = 0;
520 u32 mem_width_info;
Tingting Mengdc6c9272025-04-15 14:50:51 +0800521 phys_size_t memory_size, total_memory_size = 0;
Tingting Menga1a24f12025-02-21 21:49:41 +0800522
523 u32 mem_total_capacity_intf_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
524 IOSSM_MEM_TOTAL_CAPACITY_INTF0_OFFSET,
525 IOSSM_MEM_TOTAL_CAPACITY_INTF1_OFFSET
526 };
527
528 /* Get all memory interface(s) total memory size on all instance(s) */
529 for (i = 0; i < io96b_ctrl->num_instance; i++) {
530 memory_size = 0;
531 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
532 mem_width_info = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
533 mem_total_capacity_intf_offset[j]);
534
Tingting Mengdc6c9272025-04-15 14:50:51 +0800535 io96b_ctrl->io96b[i].mb_ctrl.memory_size[j] =
536 FIELD_GET(INTF_CAPACITY_GBITS_MASK, mem_width_info) * SZ_1G / SZ_8;
537
538 if (io96b_ctrl->io96b[i].mb_ctrl.memory_size[j] != 0)
539 memory_size += io96b_ctrl->io96b[i].mb_ctrl.memory_size[j];
Tingting Menga1a24f12025-02-21 21:49:41 +0800540 }
541
542 if (!memory_size) {
543 printf("%s: Failed to get valid memory size\n", __func__);
544 ret = -EINVAL;
545 goto err;
546 }
547
Tingting Menga1a24f12025-02-21 21:49:41 +0800548 total_memory_size = total_memory_size + memory_size;
549 }
550
551 if (!total_memory_size) {
552 printf("%s: Failed to get valid memory size\n", __func__);
553 ret = -EINVAL;
554 }
555
556 io96b_ctrl->overall_size = total_memory_size;
557
558err:
559 return ret;
560}
561
562int ecc_enable_status(struct io96b_info *io96b_ctrl)
563{
564 int i, j, ret = 0;
565 u32 ecc_enable_intf;
Tingting Mengdc6c9272025-04-15 14:50:51 +0800566 bool ecc_status, ecc_status_set = false, inline_ecc = false;
Tingting Menga1a24f12025-02-21 21:49:41 +0800567
568 u32 ecc_enable_intf_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
569 IOSSM_ECC_ENABLE_INTF0_OFFSET,
570 IOSSM_ECC_ENABLE_INTF1_OFFSET
571 };
572
573 /* Initialize ECC status */
574 io96b_ctrl->ecc_status = false;
Tingting Mengdc6c9272025-04-15 14:50:51 +0800575 io96b_ctrl->inline_ecc = false;
Tingting Menga1a24f12025-02-21 21:49:41 +0800576
577 /* Get and ensure all memory interface(s) same ECC status */
578 for (i = 0; i < io96b_ctrl->num_instance; i++) {
579 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
580 ecc_enable_intf = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
581 ecc_enable_intf_offset[j]);
582
Tingting Mengdc6c9272025-04-15 14:50:51 +0800583 ecc_status = (FIELD_GET(INTF_ECC_ENABLE_TYPE_MASK, ecc_enable_intf)
Tingting Menga1a24f12025-02-21 21:49:41 +0800584 == 0) ? false : true;
Tingting Mengdc6c9272025-04-15 14:50:51 +0800585 inline_ecc = FIELD_GET(INTF_ECC_TYPE_MASK, ecc_enable_intf);
Tingting Menga1a24f12025-02-21 21:49:41 +0800586
Tingting Mengdc6c9272025-04-15 14:50:51 +0800587 if (!ecc_status_set) {
588 io96b_ctrl->ecc_status = ecc_status;
589
590 if (io96b_ctrl->ecc_status)
591 io96b_ctrl->inline_ecc = inline_ecc;
592
593 ecc_status_set = true;
Tingting Menga1a24f12025-02-21 21:49:41 +0800594 }
595
Tingting Mengdc6c9272025-04-15 14:50:51 +0800596 if (ecc_status != io96b_ctrl->ecc_status ||
597 (io96b_ctrl->ecc_status && inline_ecc != io96b_ctrl->inline_ecc)) {
Tingting Menga1a24f12025-02-21 21:49:41 +0800598 printf("%s: Mismatch DDR ECC status on IO96B_%d\n", __func__, i);
599
600 ret = -EINVAL;
601 goto err;
602 }
603 }
604 }
605
606 debug("%s: ECC enable status: %d\n", __func__, io96b_ctrl->ecc_status);
607
608err:
609 return ret;
610}
611
612bool is_double_bit_error(enum ecc_error_type err_type)
613{
614 switch (err_type) {
615 case DOUBLE_BIT_ERROR:
616 case MULTIPLE_DOUBLE_BIT_ERRORS:
617 case WRITE_LINK_DOUBLE_BIT_ERROR:
618 case READ_LINK_DOUBLE_BIT_ERROR:
619 case READ_MODIFY_WRITE_DOUBLE_BIT_ERROR:
620 return true;
621
622 default:
623 return false;
624 }
625}
626
627bool ecc_interrupt_status(struct io96b_info *io96b_ctrl)
628{
629 int i, j;
630 u32 ecc_err_status;
631 u16 ecc_err_counter;
632 bool ecc_error_flag = false;
633
634 /* Get ECC double-bit error status */
635 for (i = 0; i < io96b_ctrl->num_instance; i++) {
636 ecc_err_status = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
637 IOSSM_ECC_ERR_STATUS_OFFSET);
638 ecc_err_counter = FIELD_GET(ECC_ERR_COUNTER_MASK, ecc_err_status);
639 debug("%s: ECC error number detected on IO96B_%d: %d\n",
640 __func__, i, ecc_err_counter);
641
642 if (ecc_err_counter != 0) {
643 phys_addr_t address;
644 u32 ecc_err_data;
645 struct ecc_err_info err_info;
646
647 address = io96b_ctrl->io96b[i].io96b_csr_addr +
648 IOSSM_ECC_ERR_DATA_START_OFFSET;
649
650 for (j = 0; j < ecc_err_counter && j < MAX_ECC_ERR_INFO_COUNT; j++) {
651 ecc_err_data = readl(address);
652 err_info.err_type = FIELD_GET(ECC_ERR_TYPE_MASK,
653 ecc_err_data);
654 err_info.ip_type = FIELD_GET(ECC_ERR_IP_TYPE_MASK,
655 ecc_err_data);
656 err_info.instance_id = FIELD_GET(ECC_ERR_INSTANCE_ID_MASK,
657 ecc_err_data);
658 err_info.source_id = FIELD_GET(ECC_ERR_SOURCE_ID_MASK,
659 ecc_err_data);
660 err_info.addr_upper = FIELD_GET(ECC_ERR_ADDR_UPPER_MASK,
661 ecc_err_data);
662 err_info.addr_lower = readl(address + sizeof(u32));
663
664 debug("%s: ECC double-bit error detected on IO96B_%d:\n",
665 __func__, i);
666 debug("- error info address :0x%llx\n", address);
667 debug("- error ip type: %d\n", err_info.ip_type);
668 debug("- error instance id: %d\n", err_info.instance_id);
669 debug("- error source id: %d\n", err_info.source_id);
670 debug("- error type: %d\n", err_info.err_type);
671 debug("- error address upper: 0x%x\n", err_info.addr_upper);
672 debug("- error address lower: 0x%x\n", err_info.addr_lower);
673
674 if (is_double_bit_error(err_info.err_type)) {
675 if (!ecc_error_flag)
676 ecc_error_flag = true;
677 }
678
679 address += sizeof(u32) * 2;
680 }
681 }
682 }
683
684 if (ecc_error_flag)
685 printf("\n%s: ECC double-bit error detected!\n", __func__);
686
687 return ecc_error_flag;
688}
689
Tingting Mengdc6c9272025-04-15 14:50:51 +0800690int out_of_band_bist_mem_init_start(struct io96b_info *io96b_ctrl)
Tingting Menga1a24f12025-02-21 21:49:41 +0800691{
692 struct io96b_mb_req usr_req;
693 struct io96b_mb_resp usr_resp;
694 int i, j, n, ret = 0;
695 bool bist_start, bist_success;
696 u32 mem_init_status_intf, start;
697
698 u32 mem_init_status_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
699 IOSSM_MEM_INIT_STATUS_INTF0_OFFSET,
700 IOSSM_MEM_INIT_STATUS_INTF1_OFFSET
701 };
702
703 /* Full memory initialization BIST performed on all memory interface(s) */
704 for (i = 0; i < io96b_ctrl->num_instance; i++) {
705 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
706 bist_start = false;
707 bist_success = false;
708
709 /* Start memory initialization BIST on full memory address */
710 IO96B_MB_REQ_SETUP(io96b_ctrl->io96b[i].mb_ctrl.ip_type[j],
711 io96b_ctrl->io96b[i].mb_ctrl.ip_id[j],
712 CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START,
713 BIST_FULL_MEM);
714
715 ret = io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr,
716 usr_req, 0, &usr_resp);
717 if (ret)
718 goto err;
719
720 bist_start = IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
721 & BIT(0);
722
723 if (!bist_start) {
724 printf("%s: Failed to initialize memory on IO96B_%d\n", __func__,
725 i);
726 printf("%s: BIST_MEM_INIT_START Error code 0x%lx\n", __func__,
727 IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status));
728
729 ret = -EINVAL;
730 goto err;
731 }
732
733 /* Polling for the initiated memory initialization BIST status */
734 start = get_timer(0);
735 while (!bist_success) {
736 udelay(1);
737
738 mem_init_status_intf = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
739 mem_init_status_offset[j]);
740
741 bist_success = FIELD_GET(INTF_BIST_STATUS_MASK,
742 mem_init_status_intf);
743
744 if (!bist_success && (get_timer(start) > TIMEOUT)) {
745 printf("%s: Timeout initialize memory on IO96B_%d\n",
746 __func__, i);
747 printf("%s: BIST_MEM_INIT_STATUS Error code 0x%lx\n",
748 __func__,
749 IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status));
750
751 ret = -ETIMEDOUT;
752 goto err;
753 }
754 }
755 }
756
757 debug("%s: Memory initialized successfully on IO96B_%d\n", __func__, i);
758 }
759
760err:
761 return ret;
762}
Tingting Mengdc6c9272025-04-15 14:50:51 +0800763
764int bist_mem_init_by_addr(struct io96b_info *io96b_ctrl, int inst_id, int intf_id,
765 phys_addr_t base_addr, phys_size_t size)
766{
767 struct io96b_mb_req usr_req;
768 struct io96b_mb_resp usr_resp;
769 int n, ret = 0;
770 bool bist_start, bist_success;
771 u32 mem_exp, mem_init_status_intf, start;
772 phys_size_t chunk_size;
773
774 u32 mem_init_status_offset[MAX_MEM_INTERFACE_SUPPORTED] = {
775 IOSSM_MEM_INIT_STATUS_INTF0_OFFSET,
776 IOSSM_MEM_INIT_STATUS_INTF1_OFFSET
777 };
778
779 /* Check if size is a power of 2 */
780 if (size == 0 || (size & (size - 1)) != 0) {
781 ret = -EINVAL;
782 goto err;
783 }
784
785 mem_exp = 0;
786 chunk_size = size;
787
788 while (chunk_size >>= 1)
789 mem_exp++;
790
791 /* Start memory initialization BIST on the specified address range */
792 IO96B_MB_REQ_SETUP(io96b_ctrl->io96b[inst_id].mb_ctrl.ip_type[intf_id],
793 io96b_ctrl->io96b[inst_id].mb_ctrl.ip_id[intf_id],
794 CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START, 0);
795
796 /* CMD_PARAM_0 bit[5:0] = mem_exp */
797 /* CMD_PARAM_0 bit[6]: 0 - on the specified address range */
798 usr_req.cmd_param[0] = FIELD_PREP(BIST_START_ADDR_SPACE_MASK, mem_exp);
799 /* Extract address fields START_ADDR[31:0] */
800 usr_req.cmd_param[1] = FIELD_GET(BIST_START_ADDR_LOW_MASK, base_addr);
801 /* Extract address fields START_ADDR[37:32] */
802 usr_req.cmd_param[2] = FIELD_GET(BIST_START_ADDR_HIGH_MASK, base_addr);
803 /* Initialize memory to all zeros */
804 usr_req.cmd_param[3] = 0;
805
806 bist_start = false;
807 bist_success = false;
808
809 /* Send request to DDR controller */
810 debug("%s:Initializing memory: Addr=0x%llx, Size=2^%u\n", __func__,
811 base_addr, mem_exp);
812 ret = io96b_mb_req(io96b_ctrl->io96b[inst_id].io96b_csr_addr,
813 usr_req, 0, &usr_resp);
814 if (ret)
815 goto err;
816
817 bist_start = IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
818 & BIT(0);
819
820 if (!bist_start) {
821 printf("%s: Failed to initialize memory on IO96B_%d\n", __func__,
822 inst_id);
823 printf("%s: BIST_MEM_INIT_START Error code 0x%lx\n", __func__,
824 IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status));
825
826 ret = -EINVAL;
827 goto err;
828 }
829
830 /* Polling for the initiated memory initialization BIST status */
831 start = get_timer(0);
832 while (!bist_success) {
833 udelay(1);
834
835 mem_init_status_intf = readl(io96b_ctrl->io96b[inst_id].io96b_csr_addr +
836 mem_init_status_offset[intf_id]);
837
838 bist_success = FIELD_GET(INTF_BIST_STATUS_MASK, mem_init_status_intf);
839
840 if (!bist_success && (get_timer(start) > TIMEOUT)) {
841 printf("%s: Timeout initialize memory on IO96B_%d\n",
842 __func__, inst_id);
843 printf("%s: BIST_MEM_INIT_STATUS Error code 0x%lx\n",
844 __func__,
845 IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status));
846
847 ret = -ETIMEDOUT;
848 goto err;
849 }
850 }
851
852 debug("%s:DDR memory initializationat 0x%llx completed.\n", __func__, base_addr);
853
854err:
855 return ret;
856}
857
858int inline_ecc_bist_mem_init(struct io96b_info *io96b_ctrl)
859{
860 int i, j, ret = 0;
861
862 /* Memory initialization BIST performed on all memory interfaces */
863 for (i = 0; i < io96b_ctrl->num_instance; i++) {
864 for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
865 ret = bist_mem_init_by_addr(io96b_ctrl, i, j, 0,
866 io96b_ctrl->io96b[i].mb_ctrl.memory_size[j]);
867 if (ret) {
868 printf("Error: Memory init failed at Instance %d, Interface %d\n",
869 i, j);
870 goto err;
871 }
872 }
873 }
874
875err:
876 return ret;
877}
878
879int bist_mem_init_start(struct io96b_info *io96b_ctrl)
880{
881 if (io96b_ctrl->inline_ecc)
882 return inline_ecc_bist_mem_init(io96b_ctrl);
883 else
884 return out_of_band_bist_mem_init_start(io96b_ctrl);
885}