summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/edac/synopsys_edac.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 6f445d338ece..185872f6d2ae 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -977,20 +977,6 @@ static inline enum dev_type snps_get_dtype(u32 mstr)
}
/**
- * snps_get_memsize - Read the size of the attached memory device.
- *
- * Return: the memory size in bytes.
- */
-static u32 snps_get_memsize(void)
-{
- struct sysinfo inf;
-
- si_meminfo(&inf);
-
- return inf.totalram * inf.mem_unit;
-}
-
-/**
* snps_get_mtype - Returns controller memory type.
* @mstr: Master CSR value.
*
@@ -1411,6 +1397,51 @@ static void snps_get_addr_map(struct snps_edac_priv *priv)
}
/**
+ * snps_get_sdram_size - Calculate SDRAM size.
+ * @priv: DDR memory controller private data.
+ *
+ * The total size of the attached memory is calculated based on the HIF/SDRAM
+ * mapping table. It can be done since the hardware reference manual demands
+ * that none two SDRAM bits should be mapped to the same HIF bit and that the
+ * unused SDRAM address bits mapping must be disabled.
+ *
+ * Return: the memory size in bytes.
+ */
+static u64 snps_get_sdram_size(struct snps_edac_priv *priv)
+{
+ struct snps_hif_sdram_map *map = &priv->hif_sdram_map;
+ u64 size = 0;
+ int i;
+
+ for (i = 0; i < DDR_MAX_ROW_WIDTH; i++) {
+ if (map->row[i] != DDR_ADDRMAP_UNUSED)
+ size++;
+ }
+
+ for (i = 0; i < DDR_MAX_COL_WIDTH; i++) {
+ if (map->col[i] != DDR_ADDRMAP_UNUSED)
+ size++;
+ }
+
+ for (i = 0; i < DDR_MAX_BANK_WIDTH; i++) {
+ if (map->bank[i] != DDR_ADDRMAP_UNUSED)
+ size++;
+ }
+
+ for (i = 0; i < DDR_MAX_BANKGRP_WIDTH; i++) {
+ if (map->bankgrp[i] != DDR_ADDRMAP_UNUSED)
+ size++;
+ }
+
+ for (i = 0; i < DDR_MAX_RANK_WIDTH; i++) {
+ if (map->rank[i] != DDR_ADDRMAP_UNUSED)
+ size++;
+ }
+
+ return 1ULL << (size + priv->info.dq_width);
+}
+
+/**
* snps_init_csrows - Initialize the csrow data.
* @mci: EDAC memory controller instance.
*
@@ -1422,7 +1453,8 @@ static void snps_init_csrows(struct mem_ctl_info *mci)
struct snps_edac_priv *priv = mci->pvt_info;
struct csrow_info *csi;
struct dimm_info *dimm;
- u32 size, row, width;
+ u32 row, width;
+ u64 size;
int j;
/* Actual SDRAM-word width for which ECC is calculated */
@@ -1430,13 +1462,13 @@ static void snps_init_csrows(struct mem_ctl_info *mci)
for (row = 0; row < mci->nr_csrows; row++) {
csi = mci->csrows[row];
- size = snps_get_memsize();
+ size = snps_get_sdram_size(priv);
for (j = 0; j < csi->nr_channels; j++) {
dimm = csi->channels[j]->dimm;
dimm->edac_mode = EDAC_SECDED;
dimm->mtype = priv->info.sdram_mode;
- dimm->nr_pages = (size >> PAGE_SHIFT) / csi->nr_channels;
+ dimm->nr_pages = PHYS_PFN(size) / csi->nr_channels;
dimm->grain = width;
dimm->dtype = priv->info.dev_cfg;
}