EDAC/amd64: Support asymmetric dual-rank DIMMs
authorYazen Ghannam <yazen.ghannam@amd.com>
Thu, 22 Aug 2019 00:00:02 +0000 (00:00 +0000)
committerBorislav Petkov <bp@suse.de>
Fri, 23 Aug 2019 14:09:52 +0000 (16:09 +0200)
Future AMD systems will support asymmetric dual-rank DIMMs. These are
DIMMs where the ranks are of different sizes.

The even rank will use the Primary Even Chip Select registers and the
odd rank will use the Secondary Odd Chip Select registers.

Recognize if a Secondary Odd Chip Select is being used. Use the
Secondary Odd Address Mask when calculating the chip select size.

 [ bp: move csrow_sec_enabled() to the header, fix CS_ODD define and
   tone-down the capitalized words spelling. ]

Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: "linux-edac@vger.kernel.org" <linux-edac@vger.kernel.org>
Cc: James Morse <james.morse@arm.com>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Link: https://lkml.kernel.org/r/20190821235938.118710-8-Yazen.Ghannam@amd.com
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h

index 23251bba8eb686d86dcfa8b715b6501f500e3109..18ba9c898389ff500fdf32e792d2ed73bf713b71 100644 (file)
@@ -790,9 +790,11 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
 
 #define CS_EVEN_PRIMARY                BIT(0)
 #define CS_ODD_PRIMARY         BIT(1)
+#define CS_EVEN_SECONDARY      BIT(2)
+#define CS_ODD_SECONDARY       BIT(3)
 
-#define CS_EVEN                        CS_EVEN_PRIMARY
-#define CS_ODD                 CS_ODD_PRIMARY
+#define CS_EVEN                        (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY)
+#define CS_ODD                 (CS_ODD_PRIMARY | CS_ODD_SECONDARY)
 
 static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
 {
@@ -804,6 +806,10 @@ static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
        if (csrow_enabled(2 * dimm + 1, ctrl, pvt))
                cs_mode |= CS_ODD_PRIMARY;
 
+       /* Asymmetric dual-rank DIMM support. */
+       if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
+               cs_mode |= CS_ODD_SECONDARY;
+
        return cs_mode;
 }
 
@@ -1600,7 +1606,11 @@ static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
         */
        dimm = csrow_nr >> 1;
 
-       addr_mask_orig = pvt->csels[umc].csmasks[dimm];
+       /* Asymmetric dual-rank DIMM support. */
+       if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
+               addr_mask_orig = pvt->csels[umc].csmasks_sec[dimm];
+       else
+               addr_mask_orig = pvt->csels[umc].csmasks[dimm];
 
        /*
         * The number of zero bits in the mask is equal to the number of bits
index 68f12de6e6544cca0c5cb0d0c5f294fa2c50d997..8addc4d9557712c5420ce298871c66f4e053eb6c 100644 (file)
 #define DCSM0                          0x60
 #define DCSM1                          0x160
 
-#define csrow_enabled(i, dct, pvt)     ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)
+#define csrow_enabled(i, dct, pvt)     ((pvt)->csels[(dct)].csbases[(i)]     & DCSB_CS_ENABLE)
+#define csrow_sec_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases_sec[(i)] & DCSB_CS_ENABLE)
 
 #define DRAM_CONTROL                   0x78