Lines Matching +full:versal +full:- +full:net +full:- +full:ddrmc5

1 // SPDX-License-Identifier: GPL-2.0
3 * AMD Versal NET memory controller driver
74 * struct ecc_error_info - ECC error log information.
122 * struct ecc_status - ECC status information to report.
136 * struct mc_priv - DDR memory controller private instance data.
227 p = &priv->stat; in get_ddr_info()
230 p->channel = 1; in get_ddr_info()
232 p->channel = 0; in get_ddr_info()
237 p->ceinfo[0].i = reglo | (u64)reghi << 32; in get_ddr_info()
239 p->ueinfo[0].i = reglo | (u64)reghi << 32; in get_ddr_info()
248 p->ceinfo[1].i = reglo | (u64)reghi << 32; in get_ddr_info()
250 p->ueinfo[1].i = reglo | (u64)reghi << 32; in get_ddr_info()
260 * convert_to_physical - Convert @error_data to a physical address.
264 * @error_data: the DDRMC5 ADEC address decoder register data
387 high_mem_base = (priv->adec[ADEC2 + offset] & MC5_MEM_MASK) * MC5_HIMEM_BASE; in convert_to_physical()
388 interleave = priv->adec[ADEC13 + offset] & MC5_INTERLEAVE_SEL; in convert_to_physical()
390 high_mem_offset = priv->adec[ADEC3 + offset] & MC5_MEM_MASK; in convert_to_physical()
391 low_mem_offset = priv->adec[ADEC1 + offset] & MC5_MEM_MASK; in convert_to_physical()
392 reg = priv->adec[ADEC14 + offset]; in convert_to_physical()
396 ilc_base_ctrl_add = ilcmem_base - high_mem_offset; in convert_to_physical()
398 ilc_base_ctrl_add = ilcmem_base - low_mem_offset; in convert_to_physical()
400 if (priv->dwidth == DEV_X16) { in convert_to_physical()
410 if ((priv->adec[ADEC2 + offset] & MC5_HIGH_MEM_EN) && err_addr >= high_mem_base) in convert_to_physical()
411 addr = err_addr - high_mem_offset; in convert_to_physical()
413 addr = err_addr - low_mem_offset; in convert_to_physical()
419 * handle_error - Handle errors.
439 mci = priv->mci[ctl_num]; in handle_error()
441 if (stat->error_type == MC5_ERR_TYPE_CE) { in handle_error()
442 pinf = stat->ceinfo[stat->channel]; in handle_error()
443 snprintf(priv->message, sizeof(priv->message), in handle_error()
448 1, 0, 0, 0, 0, 0, -1, in handle_error()
449 priv->message, ""); in handle_error()
452 if (stat->error_type == MC5_ERR_TYPE_UE) { in handle_error()
453 pinf = stat->ueinfo[stat->channel]; in handle_error()
454 snprintf(priv->message, sizeof(priv->message), in handle_error()
459 1, 0, 0, 0, 0, 0, -1, in handle_error()
460 priv->message, ""); in handle_error()
476 struct mc_priv *priv = mci->pvt_info; in mc_init()
483 mci->mtype_cap = MEM_FLAG_DDR5; in mc_init()
484 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; in mc_init()
485 mci->scrub_cap = SCRUB_HW_SRC; in mc_init()
486 mci->scrub_mode = SCRUB_NONE; in mc_init()
488 mci->edac_cap = EDAC_FLAG_SECDED; in mc_init()
489 mci->ctl_name = "VersalNET DDR5"; in mc_init()
490 mci->dev_name = dev_name(dev); in mc_init()
491 mci->mod_name = "versalnet_edac"; in mc_init()
495 for (row = 0; row < mci->nr_csrows; row++) { in mc_init()
496 csi = mci->csrows[row]; in mc_init()
497 for (ch = 0; ch < csi->nr_channels; ch++) { in mc_init()
498 dimm = csi->channels[ch]->dimm; in mc_init()
499 dimm->edac_mode = EDAC_SECDED; in mc_init()
500 dimm->mtype = MEM_DDR5; in mc_init()
501 dimm->grain = MC5_ERR_GRAIN; in mc_init()
502 dimm->dtype = priv->dwidth; in mc_init()
528 ret = rpmsg_send(cdx->ept, send_buf, hdr_len + sdu_len); in mcdi_request()
530 dev_err(&cdx->rpdev->dev, "Failed to send rpmsg data: %d\n", ret); in mcdi_request()
564 return -ENOMEM; in setup_mcdi()
566 amd_mcdi->mcdi_ops = &mcdi_ops; in setup_mcdi()
573 amd_mcdi->ept = mc_priv->ept; in setup_mcdi()
574 mc_priv->mcdi = amd_mcdi; in setup_mcdi()
577 get_ddr_config(i, &mc_priv->adec[ADEC_NUM * i], amd_mcdi); in setup_mcdi()
589 struct mc_priv *mc_priv = dev_get_drvdata(&rpdev->dev); in rpmsg_cb()
599 cdx_mcdi_process_cmd(mc_priv->mcdi, (struct cdx_dword *)data, len); in rpmsg_cb()
609 if (!mc_priv->part_len) in rpmsg_cb()
610 mc_priv->part_len = length; in rpmsg_cb()
612 mc_priv->part_len += length; in rpmsg_cb()
621 mc_priv->regs[k] = result[j]; in rpmsg_cb()
623 if (mc_priv->part_len < result[TOTAL_ERR_LENGTH]) in rpmsg_cb()
625 mc_priv->part_len = 0; in rpmsg_cb()
628 mc_priv->error_id = error_id; in rpmsg_cb()
629 mc_priv->error_level = result[ERROR_LEVEL]; in rpmsg_cb()
632 case 5: err_str = "General Software Non-Correctable error"; break; in rpmsg_cb()
636 case 11: err_str = "DDRMC Microblaze Non-Correctable ECC error"; break; in rpmsg_cb()
639 case 17: err_str = "HNICX Non-Correctable error"; break; in rpmsg_cb()
642 p = &mc_priv->stat; in rpmsg_cb()
644 p->error_type = MC5_ERR_TYPE_CE; in rpmsg_cb()
646 if (get_ddr_info(&mc_priv->regs[i * REGS_PER_CONTROLLER], mc_priv)) { in rpmsg_cb()
647 adec_data = mc_priv->adec + ADEC_NUM * i; in rpmsg_cb()
648 handle_error(mc_priv, &mc_priv->stat, i, adec_data); in rpmsg_cb()
653 p = &mc_priv->stat; in rpmsg_cb()
655 p->error_type = MC5_ERR_TYPE_UE; in rpmsg_cb()
657 if (get_ddr_info(&mc_priv->regs[i * REGS_PER_CONTROLLER], mc_priv)) { in rpmsg_cb()
658 adec_data = mc_priv->adec + ADEC_NUM * i; in rpmsg_cb()
659 handle_error(mc_priv, &mc_priv->stat, i, adec_data); in rpmsg_cb()
664 case 21: err_str = "GT Non-Correctable error"; break; in rpmsg_cb()
666 case 23: err_str = "PL Sysmon Non-Correctable error"; break; in rpmsg_cb()
668 case 114: err_str = "INT_LPD Non-Correctable error"; break; in rpmsg_cb()
669 case 116: err_str = "INT_OCM Non-Correctable error"; break; in rpmsg_cb()
671 case 118: err_str = "INT_FPD Non-Correctable error"; break; in rpmsg_cb()
672 case 120: err_str = "INT_IOU Non-Correctable error"; break; in rpmsg_cb()
693 case 150: err_str = "OCM0 Un-correctable error"; break; in rpmsg_cb()
694 case 151: err_str = "OCM1 Un-correctable error"; break; in rpmsg_cb()
697 case 232: err_str = "CRAM Un-Correctable error"; break; in rpmsg_cb()
701 snprintf(mc_priv->message, in rpmsg_cb()
702 sizeof(mc_priv->message), in rpmsg_cb()
707 log_non_standard_event(sec_type, &amd_versalnet_guid, mc_priv->message, in rpmsg_cb()
726 chinfo.dst = rpdev->dst; in rpmsg_probe()
730 pg->ept = rpmsg_create_ept(rpdev, rpmsg_cb, NULL, chinfo); in rpmsg_probe()
731 if (!pg->ept) in rpmsg_probe()
732 return dev_err_probe(&rpdev->dev, -ENXIO, "Failed to create ept for channel %s\n", in rpmsg_probe()
735 dev_set_drvdata(&rpdev->dev, pg); in rpmsg_probe()
742 struct mc_priv *mc_priv = dev_get_drvdata(&rpdev->dev); in rpmsg_remove()
744 rpmsg_destroy_ept(mc_priv->ept); in rpmsg_remove()
745 dev_set_drvdata(&rpdev->dev, NULL); in rpmsg_remove()
772 config = priv->adec[CONF + i * ADEC_NUM]; in init_versalnet()
802 rc = -ENOMEM; in init_versalnet()
810 priv->mci[i] = mci; in init_versalnet()
811 priv->dwidth = dt; in init_versalnet()
814 dev->release = versal_edac_release; in init_versalnet()
816 sprintf(name, "versal-net-ddrmc5-edac-%d", i); in init_versalnet()
817 dev->init_name = name; in init_versalnet()
822 mci->pdev = dev; in init_versalnet()
836 while (i--) { in init_versalnet()
837 mci = priv->mci[i]; in init_versalnet()
841 if (mci->pdev) { in init_versalnet()
842 device_unregister(mci->pdev); in init_versalnet()
843 edac_mc_del_mc(mci->pdev); in init_versalnet()
858 device_unregister(priv->mci[i]->pdev); in remove_versalnet()
859 mci = edac_mc_del_mc(priv->mci[i]->pdev); in remove_versalnet()
874 r5_core_node = of_parse_phandle(pdev->dev.of_node, "amd,rproc", 0); in mc_probe()
876 dev_err(&pdev->dev, "amd,rproc: invalid phandle\n"); in mc_probe()
877 return -EINVAL; in mc_probe()
880 rp = rproc_get_by_phandle(r5_core_node->phandle); in mc_probe()
882 return -EPROBE_DEFER; in mc_probe()
886 dev_err(&pdev->dev, "Failed to attach to remote processor\n"); in mc_probe()
890 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in mc_probe()
892 rc = -ENOMEM; in mc_probe()
908 priv->mcdi->r5_rproc = rp; in mc_probe()
917 cdx_mcdi_finish(priv->mcdi); in mc_probe()
937 rproc_shutdown(priv->mcdi->r5_rproc); in mc_remove()
938 cdx_mcdi_finish(priv->mcdi); in mc_remove()
942 { .compatible = "xlnx,versal-net-ddrmc5", },
949 .name = "versal-net-edac",
959 MODULE_DESCRIPTION("Versal NET EDAC driver");