summaryrefslogtreecommitdiff
path: root/drivers/edac
diff options
context:
space:
mode:
authorShubhrajyoti Datta <shubhrajyoti.datta@amd.com>2024-07-11 15:36:56 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-10-17 15:20:35 +0200
commit7d77159149a9025c0799a1e733f8ef15dfd9fe53 (patch)
tree6f5e9799c65e4ed8a77a7983d72acece6ad5d7e4 /drivers/edac
parenta8d991719366e2d53b2a7922492b8db265068309 (diff)
downloadlinux-7d77159149a9025c0799a1e733f8ef15dfd9fe53.tar.gz
linux-7d77159149a9025c0799a1e733f8ef15dfd9fe53.tar.bz2
linux-7d77159149a9025c0799a1e733f8ef15dfd9fe53.zip
EDAC/synopsys: Fix error injection on Zynq UltraScale+
[ Upstream commit 35e6dbfe1846caeafabb49b7575adb36b0aa2269 ] The Zynq UltraScale+ MPSoC DDR has a disjoint memory from 2GB to 32GB. The DDR host interface has a contiguous memory so while injecting errors, the driver should remove the hole else the injection fails as the address translation is incorrect. Introduce a get_mem_info() function pointer and set it for Zynq UltraScale+ platform to return host address. Fixes: 1a81361f75d8 ("EDAC, synopsys: Add Error Injection support for ZynqMP DDR controller") Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/r/20240711100656.31376-1-shubhrajyoti.datta@amd.com Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/synopsys_edac.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 014a2176c2c1..e7c18bb61f81 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
+#include <linux/sizes.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -338,6 +339,7 @@ struct synps_edac_priv {
* @get_mtype: Get mtype.
* @get_dtype: Get dtype.
* @get_ecc_state: Get ECC state.
+ * @get_mem_info: Get EDAC memory info
* @quirks: To differentiate IPs.
*/
struct synps_platform_data {
@@ -345,6 +347,9 @@ struct synps_platform_data {
enum mem_type (*get_mtype)(const void __iomem *base);
enum dev_type (*get_dtype)(const void __iomem *base);
bool (*get_ecc_state)(void __iomem *base);
+#ifdef CONFIG_EDAC_DEBUG
+ u64 (*get_mem_info)(struct synps_edac_priv *priv);
+#endif
int quirks;
};
@@ -403,6 +408,25 @@ out:
return 0;
}
+#ifdef CONFIG_EDAC_DEBUG
+/**
+ * zynqmp_get_mem_info - Get the current memory info.
+ * @priv: DDR memory controller private instance data.
+ *
+ * Return: host interface address.
+ */
+static u64 zynqmp_get_mem_info(struct synps_edac_priv *priv)
+{
+ u64 hif_addr = 0, linear_addr;
+
+ linear_addr = priv->poison_addr;
+ if (linear_addr >= SZ_32G)
+ linear_addr = linear_addr - SZ_32G + SZ_2G;
+ hif_addr = linear_addr >> 3;
+ return hif_addr;
+}
+#endif
+
/**
* zynqmp_get_error_info - Get the current ECC error info.
* @priv: DDR memory controller private instance data.
@@ -923,6 +947,9 @@ static const struct synps_platform_data zynqmp_edac_def = {
.get_mtype = zynqmp_get_mtype,
.get_dtype = zynqmp_get_dtype,
.get_ecc_state = zynqmp_get_ecc_state,
+#ifdef CONFIG_EDAC_DEBUG
+ .get_mem_info = zynqmp_get_mem_info,
+#endif
.quirks = (DDR_ECC_INTR_SUPPORT
#ifdef CONFIG_EDAC_DEBUG
| DDR_ECC_DATA_POISON_SUPPORT
@@ -976,10 +1003,16 @@ MODULE_DEVICE_TABLE(of, synps_edac_match);
static void ddr_poison_setup(struct synps_edac_priv *priv)
{
int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval;
+ const struct synps_platform_data *p_data;
int index;
ulong hif_addr = 0;
- hif_addr = priv->poison_addr >> 3;
+ p_data = priv->p_data;
+
+ if (p_data->get_mem_info)
+ hif_addr = p_data->get_mem_info(priv);
+ else
+ hif_addr = priv->poison_addr >> 3;
for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) {
if (priv->row_shift[index])