/*  MAC registers */
 #define GMAC_CONFIG                    0x00000000
 #define GMAC_PACKET_FILTER             0x00000008
-#define GMAC_HASH_TAB_0_31             0x00000010
-#define GMAC_HASH_TAB_32_63            0x00000014
+#define GMAC_HASH_TAB(x)               (0x10 + (x) * 4)
 #define GMAC_RX_FLOW_CTRL              0x00000090
 #define GMAC_QX_TX_FLOW_CTRL(x)                (0x70 + x * 4)
 #define GMAC_TXQ_PRTY_MAP0             0x98
 #define GMAC_HW_FEAT_MIISEL            BIT(0)
 
 /* MAC HW features1 bitmap */
+#define GMAC_HW_HASH_TB_SZ             GENMASK(25, 24)
 #define GMAC_HW_FEAT_AVSEL             BIT(20)
 #define GMAC_HW_TSOEN                  BIT(18)
 #define GMAC_HW_TXFIFOSIZE             GENMASK(10, 6)
 
                              struct net_device *dev)
 {
        void __iomem *ioaddr = (void __iomem *)dev->base_addr;
-       unsigned int value = 0;
+       int numhashregs = (hw->multicast_filter_bins >> 5);
+       int mcbitslog2 = hw->mcast_bits_log2;
+       unsigned int value;
+       int i;
 
+       value = readl(ioaddr + GMAC_PACKET_FILTER);
+       value &= ~GMAC_PACKET_FILTER_HMC;
+       value &= ~GMAC_PACKET_FILTER_HPF;
+       value &= ~GMAC_PACKET_FILTER_PCF;
+       value &= ~GMAC_PACKET_FILTER_PM;
+       value &= ~GMAC_PACKET_FILTER_PR;
        if (dev->flags & IFF_PROMISC) {
                value = GMAC_PACKET_FILTER_PR | GMAC_PACKET_FILTER_PCF;
        } else if ((dev->flags & IFF_ALLMULTI) ||
-                       (netdev_mc_count(dev) > HASH_TABLE_SIZE)) {
+                  (netdev_mc_count(dev) > hw->multicast_filter_bins)) {
                /* Pass all multi */
-               value = GMAC_PACKET_FILTER_PM;
-               /* Set the 64 bits of the HASH tab. To be updated if taller
-                * hash table is used
-                */
-               writel(0xffffffff, ioaddr + GMAC_HASH_TAB_0_31);
-               writel(0xffffffff, ioaddr + GMAC_HASH_TAB_32_63);
+               value |= GMAC_PACKET_FILTER_PM;
+               /* Set all the bits of the HASH tab */
+               for (i = 0; i < numhashregs; i++)
+                       writel(0xffffffff, ioaddr + GMAC_HASH_TAB(i));
        } else if (!netdev_mc_empty(dev)) {
-               u32 mc_filter[2];
                struct netdev_hw_addr *ha;
+               u32 mc_filter[8];
 
                /* Hash filter for multicast */
-               value = GMAC_PACKET_FILTER_HMC;
+               value |= GMAC_PACKET_FILTER_HMC;
 
                memset(mc_filter, 0, sizeof(mc_filter));
                netdev_for_each_mc_addr(ha, dev) {
-                       /* The upper 6 bits of the calculated CRC are used to
-                        * index the content of the Hash Table Reg 0 and 1.
+                       /* The upper n bits of the calculated CRC are used to
+                        * index the contents of the hash table. The number of
+                        * bits used depends on the hardware configuration
+                        * selected at core configuration time.
                         */
-                       int bit_nr =
-                               (bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26);
-                       /* The most significant bit determines the register
-                        * to use while the other 5 bits determines the bit
-                        * within the selected register
+                       int bit_nr = bitrev32(~crc32_le(~0, ha->addr,
+                                       ETH_ALEN)) >> (32 - mcbitslog2);
+                       /* The most significant bit determines the register to
+                        * use (H/L) while the other 5 bits determine the bit
+                        * within the register.
                         */
-                       mc_filter[bit_nr >> 5] |= (1 << (bit_nr & 0x1F));
+                       mc_filter[bit_nr >> 5] |= (1 << (bit_nr & 0x1f));
                }
-               writel(mc_filter[0], ioaddr + GMAC_HASH_TAB_0_31);
-               writel(mc_filter[1], ioaddr + GMAC_HASH_TAB_32_63);
+               for (i = 0; i < numhashregs; i++)
+                       writel(mc_filter[i], ioaddr + GMAC_HASH_TAB(i));
        }
 
        value |= GMAC_PACKET_FILTER_HPF;