Re: [PATCH v3 4/4] edac: xilinx: Add EDAC support for Versal XilSem
"Pandey, Radhey Shyam" <[email protected]>
| Newsgroups | org.kernel.vger.linux-edac,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
> Xilinx Versal Soft Error Mitigation (XilSEM) is responsible for reporting > and optionally correcting soft errors in Configuration Memory of Versal. > The Configuration Memory includes Configuration RAM and > Network on Chip (NoC) peripheral interconnect (NPI) Registers. > > The Configuration RAM (CRAM) memory is used for storing configuration > data for the programmable logic (PL) fabric. The NPI registers are used > for configuring the memory controllers, miscellaneous integrated hardware, > NoC interface units in the Veral device. > > Add support to handle correctable and uncorrectable error events > from XilSEM. > > Add sysfs interface for XilSEM scan operations > initialize, start, stop scan, error inject, read ECC, scan status and > configuration values. > > Signed-off-by: Rama devi Veggalam <[email protected]> > --- <snip> > static int mc_probe(struct platform_device *pdev) > { > - void __iomem *ddrmc_baseaddr, *ddrmc_noc_baseaddr; > + void __iomem *ddrmc_baseaddr, *ddrmc_noc_baseaddr, *sem_baseaddr; > struct edac_mc_layer layers[2]; > struct mem_ctl_info *mci; > u8 num_chans, num_csrows; > struct edac_priv *priv; > u32 edac_mc_id, regval; > + u32 family_code; > int rc; > > ddrmc_baseaddr = devm_platform_ioremap_resource_byname(pdev, "base"); > @@ -1094,6 +2365,10 @@ static int mc_probe(struct platform_device *pdev) > if (!get_ecc_state(ddrmc_baseaddr)) > return -ENXIO; > > + sem_baseaddr = devm_platform_ioremap_resource_byname(pdev, "semrtca"); > + if (IS_ERR(sem_baseaddr)) > + return PTR_ERR(sem_baseaddr); > + As mentioned by Krzysztof in DT review this change breaks existing system. Please ioremap this semrtca resource only for xilSEM support. We can make use of compatible based match data. > /* Allocate ID number for the EMIF controller */ > edac_mc_id = emif_get_id(pdev->dev.of_node); > > @@ -1124,9 +2399,29 @@ static int mc_probe(struct platform_device *pdev) > priv = mci->pvt_info; > priv->ddrmc_baseaddr = ddrmc_baseaddr; > priv->ddrmc_noc_baseaddr = ddrmc_noc_baseaddr; > + priv->sem_baseaddr = sem_baseaddr; > priv->ce_cnt = 0; > priv->ue_cnt = 0; > priv->mc_id = edac_mc_id; > + priv->xsem_rtca = NULL; > + > + /* Allocate and initialize XilSem RTCA structure */ > + priv->xsem_rtca = devm_kzalloc(&pdev->dev, > + sizeof(struct xsem_rtca_priv), > + GFP_KERNEL); > + if (!priv->xsem_rtca) { > + edac_printk(KERN_ERR, EDAC_MC, > + "Failed to allocate xsem_rtca\n"); > + rc = -ENOMEM; > + goto free_edac_mc; > + } > + > + priv->xsem_rtca->slr_info = devm_kzalloc(&pdev->dev, sizeof(struct xsem_ssit_status), > + GFP_KERNEL); > + if (!priv->xsem_rtca->slr_info) { > + rc = -ENOMEM; > + goto free_edac_mc; > + } > > mc_init(mci, pdev); > > @@ -1147,6 +2442,41 @@ static int mc_probe(struct platform_device *pdev) > goto del_mc; > } > > + /* Create XilSem sysfs attributes only if XilSem is available */ > + rc = xsem_edac_create_sysfs_attributes(mci); > + if (rc) { > + edac_printk(KERN_ERR, EDAC_MC, > + "Failed to create sysfs entries\n"); > + goto remove_sysfs; > + } > + > + /* > + * Firmware driver returns -ENODEV if it is not probed. In this case > + * defer XilSEM error event registration. > + */ > + rc = zynqmp_pm_get_family_info(&family_code); > + if (rc) { > + if (rc == -ENODEV) > + rc = -EPROBE_DEFER; > + > + goto del_mc; > + } > + if (family_code == PM_VERSAL_FAMILY_CODE) { > + priv->xsem_rtca->sw_event_node_id = VERSAL_EVENT_ERROR_SW_ERR; > + priv->xsem_rtca->cram_ce_mask = XPM_VERSAL_EVENT_ERROR_MASK_XSEM_CRAM_CE_5; > + priv->xsem_rtca->cram_ue_mask = XPM_VERSAL_EVENT_ERROR_MASK_XSEM_CRAM_UE_6; > + priv->xsem_rtca->npi_ue_mask = XPM_VERSAL_EVENT_ERROR_MASK_XSEM_NPI_UE_7; > + } else { > + edac_printk(KERN_ERR, EDAC_MC, "Invalid Device family code %d\n", family_code); > + } > + > + rc = xlnx_register_event(PM_NOTIFY_CB, priv->xsem_rtca->sw_event_node_id, > + priv->xsem_rtca->cram_ce_mask | priv->xsem_rtca->cram_ue_mask | > + priv->xsem_rtca->npi_ue_mask, > + false, xsem_err_callback, mci); > + if (rc) > + goto del_mc; > + > #ifdef CONFIG_EDAC_DEBUG > create_debugfs_attributes(mci); > setup_address_map(priv); > @@ -1154,6 +2484,8 @@ static int mc_probe(struct platform_device *pdev) > enable_intr(priv); > return rc; > > +remove_sysfs: > + xsem_edac_remove_sysfs_attributes(mci); > del_mc: > edac_mc_del_mc(&pdev->dev); > free_edac_mc: > @@ -1173,9 +2505,21 @@ static void mc_remove(struct platform_device *pdev) > debugfs_remove_recursive(priv->debugfs); > #endif > > + /* Unregister XilSem events if they were registered */ > + if (priv->xsem_rtca) { > + xlnx_unregister_event(PM_NOTIFY_CB, priv->xsem_rtca->sw_event_node_id, > + priv->xsem_rtca->cram_ce_mask | > + priv->xsem_rtca->cram_ue_mask | > + priv->xsem_rtca->npi_ue_mask, > + xsem_err_callback, mci); > + } > xlnx_unregister_event(PM_NOTIFY_CB, VERSAL_EVENT_ERROR_PMC_ERR1, > XPM_EVENT_ERROR_MASK_DDRMC_CR | > XPM_EVENT_ERROR_MASK_DDRMC_NCR, err_callback, mci); > + /* Remove XilSem sysfs attributes if they were created */ > + if (priv->xsem_rtca) > + xsem_edac_remove_sysfs_attributes(mci); > + > edac_mc_del_mc(&pdev->dev); > edac_mc_free(mci); > }