aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/xgene_edac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/xgene_edac.c')
-rw-r--r--drivers/edac/xgene_edac.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/edac/xgene_edac.c b/drivers/edac/xgene_edac.c
index 41f876414a18..bf19b6e3bd12 100644
--- a/drivers/edac/xgene_edac.c
+++ b/drivers/edac/xgene_edac.c
@@ -61,6 +61,7 @@ struct xgene_edac {
61 struct regmap *mcba_map; 61 struct regmap *mcba_map;
62 struct regmap *mcbb_map; 62 struct regmap *mcbb_map;
63 struct regmap *efuse_map; 63 struct regmap *efuse_map;
64 struct regmap *rb_map;
64 void __iomem *pcp_csr; 65 void __iomem *pcp_csr;
65 spinlock_t lock; 66 spinlock_t lock;
66 struct dentry *dfs; 67 struct dentry *dfs;
@@ -1057,7 +1058,7 @@ static bool xgene_edac_l3_promote_to_uc_err(u32 l3cesr, u32 l3celr)
1057 case 0x041: 1058 case 0x041:
1058 return true; 1059 return true;
1059 } 1060 }
1060 } else if (L3C_ELR_ERRSYN(l3celr) == 9) 1061 } else if (L3C_ELR_ERRWAY(l3celr) == 9)
1061 return true; 1062 return true;
1062 1063
1063 return false; 1064 return false;
@@ -1353,6 +1354,17 @@ static int xgene_edac_l3_remove(struct xgene_edac_dev_ctx *l3)
1353#define GLBL_MDED_ERRH 0x0848 1354#define GLBL_MDED_ERRH 0x0848
1354#define GLBL_MDED_ERRHMASK 0x084c 1355#define GLBL_MDED_ERRHMASK 0x084c
1355 1356
1357/* IO Bus Registers */
1358#define RBCSR 0x0000
1359#define STICKYERR_MASK BIT(0)
1360#define RBEIR 0x0008
1361#define AGENT_OFFLINE_ERR_MASK BIT(30)
1362#define UNIMPL_RBPAGE_ERR_MASK BIT(29)
1363#define WORD_ALIGNED_ERR_MASK BIT(28)
1364#define PAGE_ACCESS_ERR_MASK BIT(27)
1365#define WRITE_ACCESS_MASK BIT(26)
1366#define RBERRADDR_RD(src) ((src) & 0x03FFFFFF)
1367
1356static const char * const soc_mem_err_v1[] = { 1368static const char * const soc_mem_err_v1[] = {
1357 "10GbE0", 1369 "10GbE0",
1358 "10GbE1", 1370 "10GbE1",
@@ -1470,6 +1482,51 @@ static void xgene_edac_rb_report(struct edac_device_ctl_info *edac_dev)
1470 u32 err_addr_hi; 1482 u32 err_addr_hi;
1471 u32 reg; 1483 u32 reg;
1472 1484
1485 /* If the register bus resource isn't available, just skip it */
1486 if (!ctx->edac->rb_map)
1487 goto rb_skip;
1488
1489 /*
1490 * Check RB access errors
1491 * 1. Out of range
1492 * 2. Un-implemented page
1493 * 3. Un-aligned access
1494 * 4. Offline slave IP
1495 */
1496 if (regmap_read(ctx->edac->rb_map, RBCSR, &reg))
1497 return;
1498 if (reg & STICKYERR_MASK) {
1499 bool write;
1500 u32 address;
1501
1502 dev_err(edac_dev->dev, "IOB bus access error(s)\n");
1503 if (regmap_read(ctx->edac->rb_map, RBEIR, &reg))
1504 return;
1505 write = reg & WRITE_ACCESS_MASK ? 1 : 0;
1506 address = RBERRADDR_RD(reg);
1507 if (reg & AGENT_OFFLINE_ERR_MASK)
1508 dev_err(edac_dev->dev,
1509 "IOB bus %s access to offline agent error\n",
1510 write ? "write" : "read");
1511 if (reg & UNIMPL_RBPAGE_ERR_MASK)
1512 dev_err(edac_dev->dev,
1513 "IOB bus %s access to unimplemented page error\n",
1514 write ? "write" : "read");
1515 if (reg & WORD_ALIGNED_ERR_MASK)
1516 dev_err(edac_dev->dev,
1517 "IOB bus %s word aligned access error\n",
1518 write ? "write" : "read");
1519 if (reg & PAGE_ACCESS_ERR_MASK)
1520 dev_err(edac_dev->dev,
1521 "IOB bus %s to page out of range access error\n",
1522 write ? "write" : "read");
1523 if (regmap_write(ctx->edac->rb_map, RBEIR, 0))
1524 return;
1525 if (regmap_write(ctx->edac->rb_map, RBCSR, 0))
1526 return;
1527 }
1528rb_skip:
1529
1473 /* IOB Bridge agent transaction error interrupt */ 1530 /* IOB Bridge agent transaction error interrupt */
1474 reg = readl(ctx->dev_csr + IOBBATRANSERRINTSTS); 1531 reg = readl(ctx->dev_csr + IOBBATRANSERRINTSTS);
1475 if (!reg) 1532 if (!reg)
@@ -1852,6 +1909,17 @@ static int xgene_edac_probe(struct platform_device *pdev)
1852 goto out_err; 1909 goto out_err;
1853 } 1910 }
1854 1911
1912 /*
1913 * NOTE: The register bus resource is optional for compatibility
1914 * reason.
1915 */
1916 edac->rb_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
1917 "regmap-rb");
1918 if (IS_ERR(edac->rb_map)) {
1919 dev_warn(edac->dev, "missing syscon regmap rb\n");
1920 edac->rb_map = NULL;
1921 }
1922
1855 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1923 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1856 edac->pcp_csr = devm_ioremap_resource(&pdev->dev, res); 1924 edac->pcp_csr = devm_ioremap_resource(&pdev->dev, res);
1857 if (IS_ERR(edac->pcp_csr)) { 1925 if (IS_ERR(edac->pcp_csr)) {