#define CS_ODD_PRIMARY         BIT(1)
 #define CS_EVEN_SECONDARY      BIT(2)
 #define CS_ODD_SECONDARY       BIT(3)
+#define CS_3R_INTERLEAVE       BIT(4)
 
 #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)
 {
+       u8 base, count = 0;
        int cs_mode = 0;
 
        if (csrow_enabled(2 * dimm, ctrl, pvt))
        if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
                cs_mode |= CS_ODD_SECONDARY;
 
+       /*
+        * 3 Rank inteleaving support.
+        * There should be only three bases enabled and their two masks should
+        * be equal.
+        */
+       for_each_chip_select(base, ctrl, pvt)
+               count += csrow_enabled(base, ctrl, pvt);
+
+       if (count == 3 &&
+           pvt->csels[ctrl].csmasks[0] == pvt->csels[ctrl].csmasks[1]) {
+               edac_dbg(1, "3R interleaving in use.\n");
+               cs_mode |= CS_3R_INTERLEAVE;
+       }
+
        return cs_mode;
 }
 
         *
         * The MSB is the number of bits in the full mask because BIT[0] is
         * always 0.
+        *
+        * In the special 3 Rank interleaving case, a single bit is flipped
+        * without swapping with the most significant bit. This can be handled
+        * by keeping the MSB where it is and ignoring the single zero bit.
         */
        msb = fls(addr_mask_orig) - 1;
        weight = hweight_long(addr_mask_orig);
-       num_zero_bits = msb - weight;
+       num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);
 
        /* Take the number of zero bits off from the top of the mask. */
        addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);