EMAC0: ethernet@ef600e00 {
                                device_type = "network";
-                               compatible = "ibm,emac-460ex", "ibm,emac4";
+                               compatible = "ibm,emac-460ex", "ibm,emac4sync";
                                interrupt-parent = <&EMAC0>;
                                interrupts = <0x0 0x1>;
                                #interrupt-cells = <1>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
                                                 /*Wake*/   0x1 &UIC2 0x14 0x4>;
-                               reg = <0xef600e00 0x00000070>;
+                               reg = <0xef600e00 0x000000c4>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <0>;
 
                        EMAC1: ethernet@ef600f00 {
                                device_type = "network";
-                               compatible = "ibm,emac-460ex", "ibm,emac4";
+                               compatible = "ibm,emac-460ex", "ibm,emac4sync";
                                interrupt-parent = <&EMAC1>;
                                interrupts = <0x0 0x1>;
                                #interrupt-cells = <1>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC2 0x11 0x4
                                                 /*Wake*/   0x1 &UIC2 0x15 0x4>;
-                               reg = <0xef600f00 0x00000070>;
+                               reg = <0xef600f00 0x000000c4>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <1>;
 
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
                                                 /*Wake*/   0x1 &UIC2 0x14 0x4>;
-                               reg = <0xef600e00 0x00000070>;
+                               reg = <0xef600e00 0x00000074>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <0>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC2 0x11 0x4
                                                 /*Wake*/   0x1 &UIC2 0x15 0x4>;
-                               reg = <0xef600f00 0x00000070>;
+                               reg = <0xef600f00 0x00000074>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <1>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC2 0x12 0x4
                                                 /*Wake*/   0x1 &UIC2 0x16 0x4>;
-                               reg = <0xef601100 0x00000070>;
+                               reg = <0xef601100 0x00000074>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <2>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC2 0x13 0x4
                                                 /*Wake*/   0x1 &UIC2 0x17 0x4>;
-                               reg = <0xef601200 0x00000070>;
+                               reg = <0xef601200 0x00000074>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <3>;
 
                        EMAC0: ethernet@ef600900 {
                                linux,network-index = <0x0>;
                                device_type = "network";
-                               compatible = "ibm,emac-405exr", "ibm,emac4";
+                               compatible = "ibm,emac-405exr", "ibm,emac4sync";
                                interrupt-parent = <&EMAC0>;
                                interrupts = <0x0 0x1>;
                                #interrupt-cells = <1>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC0 0x18 0x4
                                                /*Wake*/  0x1 &UIC1 0x1d 0x4>;
-                               reg = <0xef600900 0x00000070>;
+                               reg = <0xef600900 0x000000c4>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <0>;
 
                                compatible = "ibm,emac-440spe", "ibm,emac4";
                                interrupt-parent = <&UIC1>;
                                interrupts = <0x1c 0x4 0x1d 0x4>;
-                               reg = <0x10000800 0x00000070>;
+                               reg = <0x10000800 0x00000074>;
                                local-mac-address = [000000000000];
                                mal-device = <&MAL0>;
                                mal-tx-channel = <0>;
 
                        EMAC0: ethernet@ef600900 {
                                linux,network-index = <0x0>;
                                device_type = "network";
-                               compatible = "ibm,emac-405ex", "ibm,emac4";
+                               compatible = "ibm,emac-405ex", "ibm,emac4sync";
                                interrupt-parent = <&EMAC0>;
                                interrupts = <0x0 0x1>;
                                #interrupt-cells = <1>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC0 0x18 0x4
                                                /*Wake*/  0x1 &UIC1 0x1d 0x4>;
-                               reg = <0xef600900 0x00000070>;
+                               reg = <0xef600900 0x000000c4>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <0>;
                        EMAC1: ethernet@ef600a00 {
                                linux,network-index = <0x1>;
                                device_type = "network";
-                               compatible = "ibm,emac-405ex", "ibm,emac4";
+                               compatible = "ibm,emac-405ex", "ibm,emac4sync";
                                interrupt-parent = <&EMAC1>;
                                interrupts = <0x0 0x1>;
                                #interrupt-cells = <1>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC0 0x19 0x4
                                                /*Wake*/  0x1 &UIC1 0x1f 0x4>;
-                               reg = <0xef600a00 0x00000070>;
+                               reg = <0xef600a00 0x000000c4>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <1>;
 
                        EMAC0: ethernet@ef600900 {
                                linux,network-index = <0x0>;
                                device_type = "network";
-                               compatible = "ibm,emac-405ex", "ibm,emac4";
+                               compatible = "ibm,emac-405ex", "ibm,emac4sync";
                                interrupt-parent = <&EMAC0>;
                                interrupts = <0x0 0x1>;
                                #interrupt-cells = <1>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC0 0x18 0x4
                                                /*Wake*/  0x1 &UIC1 0x1d 0x4>;
-                               reg = <0xef600900 0x00000070>;
+                               reg = <0xef600900 0x000000c4>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <0>;
                        EMAC1: ethernet@ef600a00 {
                                linux,network-index = <0x1>;
                                device_type = "network";
-                               compatible = "ibm,emac-405ex", "ibm,emac4";
+                               compatible = "ibm,emac-405ex", "ibm,emac4sync";
                                interrupt-parent = <&EMAC1>;
                                interrupts = <0x0 0x1>;
                                #interrupt-cells = <1>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC0 0x19 0x4
                                                /*Wake*/  0x1 &UIC1 0x1f 0x4>;
-                               reg = <0xef600a00 0x00000070>;
+                               reg = <0xef600a00 0x000000c4>;
                                local-mac-address = [000000000000]; /* Filled in by U-Boot */
                                mal-device = <&MAL0>;
                                mal-tx-channel = <1>;
 
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC0 0x18 0x4
                                                /*Wake*/  0x1 &UIC1 0x1d 0x4>;
-                               reg = <0xef600e00 0x00000070>;
+                               reg = <0xef600e00 0x00000074>;
                                local-mac-address = [000000000000];
                                mal-device = <&MAL0>;
                                mal-tx-channel = <0>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC0 0x19 0x4
                                                /*Wake*/  0x1 &UIC1 0x1f 0x4>;
-                               reg = <0xef600f00 0x00000070>;
+                               reg = <0xef600f00 0x00000074>;
                                local-mac-address = [000000000000];
                                mal-device = <&MAL0>;
                                mal-tx-channel = <1>;
 
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC0 0x18 0x4
                                                /*Wake*/  0x1 &UIC1 0x1d 0x4>;
-                               reg = <0xef600e00 0x00000070>;
+                               reg = <0xef600e00 0x00000074>;
                                local-mac-address = [000000000000];
                                mal-device = <&MAL0>;
                                mal-tx-channel = <0>;
                                #size-cells = <0>;
                                interrupt-map = </*Status*/ 0x0 &UIC0 0x19 0x4
                                                /*Wake*/  0x1 &UIC1 0x1f 0x4>;
-                               reg = <0xef600f00 0x00000070>;
+                               reg = <0xef600f00 0x00000074>;
                                local-mac-address = [000000000000];
                                mal-device = <&MAL0>;
                                mal-tx-channel = <1>;
 
                                compatible = "ibm,emac-440gx", "ibm,emac4";
                                interrupt-parent = <&UIC1>;
                                interrupts = <0x1c 0x4 0x1d 0x4>;
-                               reg = <0x40000800 0x00000070>;
+                               reg = <0x40000800 0x00000074>;
                                local-mac-address = [000000000000]; // Filled in by zImage
                                mal-device = <&MAL0>;
                                mal-tx-channel = <0>;
                                compatible = "ibm,emac-440gx", "ibm,emac4";
                                interrupt-parent = <&UIC1>;
                                interrupts = <0x1e 0x4 0x1f 0x4>;
-                               reg = <0x40000900 0x00000070>;
+                               reg = <0x40000900 0x00000074>;
                                local-mac-address = [000000000000]; // Filled in by zImage
                                mal-device = <&MAL0>;
                                mal-tx-channel = <1>;
                                compatible = "ibm,emac-440gx", "ibm,emac4";
                                interrupt-parent = <&UIC2>;
                                interrupts = <0x0 0x4 0x1 0x4>;
-                               reg = <0x40000c00 0x00000070>;
+                               reg = <0x40000c00 0x00000074>;
                                local-mac-address = [000000000000]; // Filled in by zImage
                                mal-device = <&MAL0>;
                                mal-tx-channel = <2>;
                                compatible = "ibm,emac-440gx", "ibm,emac4";
                                interrupt-parent = <&UIC2>;
                                interrupts = <0x2 0x4 0x3 0x4>;
-                               reg = <0x40000e00 0x00000070>;
+                               reg = <0x40000e00 0x00000074>;
                                local-mac-address = [000000000000]; // Filled in by zImage
                                mal-device = <&MAL0>;
                                mal-tx-channel = <3>;
 
 
 static void emac_hash_mc(struct emac_instance *dev)
 {
-       struct emac_regs __iomem *p = dev->emacp;
-       u16 gaht[4] = { 0 };
+       const int regs = EMAC_XAHT_REGS(dev);
+       u32 *gaht_base = emac_gaht_base(dev);
+       u32 gaht_temp[regs];
        struct dev_mc_list *dmi;
+       int i;
 
        DBG(dev, "hash_mc %d" NL, dev->ndev->mc_count);
 
+       memset(gaht_temp, 0, sizeof (gaht_temp));
+
        for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) {
-               int bit;
+               int slot, reg, mask;
                DBG2(dev, "mc %02x:%02x:%02x:%02x:%02x:%02x" NL,
                     dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
                     dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
 
-               bit = 63 - (ether_crc(ETH_ALEN, dmi->dmi_addr) >> 26);
-               gaht[bit >> 4] |= 0x8000 >> (bit & 0x0f);
+               slot = EMAC_XAHT_CRC_TO_SLOT(dev, ether_crc(ETH_ALEN, dmi->dmi_addr));
+               reg = EMAC_XAHT_SLOT_TO_REG(dev, slot);
+               mask = EMAC_XAHT_SLOT_TO_MASK(dev, slot);
+
+               gaht_temp[reg] |= mask;
        }
-       out_be32(&p->gaht1, gaht[0]);
-       out_be32(&p->gaht2, gaht[1]);
-       out_be32(&p->gaht3, gaht[2]);
-       out_be32(&p->gaht4, gaht[3]);
+
+       for (i = 0; i < regs; i++)
+               out_be32(gaht_base + i, gaht_temp[i]);
 }
 
 static inline u32 emac_iff2rmr(struct net_device *ndev)
 
        if (ndev->flags & IFF_PROMISC)
                r |= EMAC_RMR_PME;
-       else if (ndev->flags & IFF_ALLMULTI || ndev->mc_count > 32)
+       else if (ndev->flags & IFF_ALLMULTI ||
+                        (ndev->mc_count > EMAC_XAHT_SLOTS(dev)))
                r |= EMAC_RMR_PMME;
        else if (ndev->mc_count > 0)
                r |= EMAC_RMR_MAE;
                        /* Put some arbitrary OUI, Manuf & Rev IDs so we can
                         * identify this GPCS PHY later.
                         */
-                       out_be32(&p->ipcr, 0xdeadbeef);
+                       out_be32(&p->u1.emac4.ipcr, 0xdeadbeef);
                } else
                        mr1 |= EMAC_MR1_MF_1000;
 
 {
        if (emac_has_feature(dev, EMAC_FTR_EMAC4))
                return sizeof(struct emac_ethtool_regs_subhdr) +
-                       EMAC4_ETHTOOL_REGS_SIZE;
+                       EMAC4_ETHTOOL_REGS_SIZE(dev);
        else
                return sizeof(struct emac_ethtool_regs_subhdr) +
-                       EMAC_ETHTOOL_REGS_SIZE;
+                       EMAC_ETHTOOL_REGS_SIZE(dev);
 }
 
 static int emac_ethtool_get_regs_len(struct net_device *ndev)
        hdr->index = dev->cell_index;
        if (emac_has_feature(dev, EMAC_FTR_EMAC4)) {
                hdr->version = EMAC4_ETHTOOL_REGS_VER;
-               memcpy_fromio(hdr + 1, dev->emacp, EMAC4_ETHTOOL_REGS_SIZE);
-               return ((void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE);
+               memcpy_fromio(hdr + 1, dev->emacp, EMAC4_ETHTOOL_REGS_SIZE(dev));
+               return ((void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE(dev));
        } else {
                hdr->version = EMAC_ETHTOOL_REGS_VER;
-               memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE);
-               return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE);
+               memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE(dev));
+               return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE(dev));
        }
 }
 
        }
 
        /* Check EMAC version */
-       if (of_device_is_compatible(np, "ibm,emac4")) {
+       if (of_device_is_compatible(np, "ibm,emac4sync")) {
+               dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC);
+       } else if (of_device_is_compatible(np, "ibm,emac4")) {
                dev->features |= EMAC_FTR_EMAC4;
                if (of_device_is_compatible(np, "ibm,emac-440gx"))
                        dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX;
        }
        memcpy(dev->ndev->dev_addr, p, 6);
 
+       /* IAHT and GAHT filter parameterization */
+       if (emac_has_feature(dev, EMAC_FTR_EMAC4SYNC)) {
+               dev->xaht_slots_shift = EMAC4SYNC_XAHT_SLOTS_SHIFT;
+               dev->xaht_width_shift = EMAC4SYNC_XAHT_WIDTH_SHIFT;
+       } else {
+               dev->xaht_slots_shift = EMAC4_XAHT_SLOTS_SHIFT;
+               dev->xaht_width_shift = EMAC4_XAHT_WIDTH_SHIFT;
+       }
+
        DBG(dev, "features     : 0x%08x / 0x%08x\n", dev->features, EMAC_FTRS_POSSIBLE);
        DBG(dev, "tx_fifo_size : %d (%d gige)\n", dev->tx_fifo_size, dev->tx_fifo_size_gige);
        DBG(dev, "rx_fifo_size : %d (%d gige)\n", dev->rx_fifo_size, dev->rx_fifo_size_gige);
                goto err_irq_unmap;
        }
        // TODO : request_mem_region
-       dev->emacp = ioremap(dev->rsrc_regs.start, sizeof(struct emac_regs));
+       dev->emacp = ioremap(dev->rsrc_regs.start,
+                            dev->rsrc_regs.end - dev->rsrc_regs.start + 1);
        if (dev->emacp == NULL) {
                printk(KERN_ERR "%s: Can't map device registers!\n",
                       np->full_name);
                .type           = "network",
                .compatible     = "ibm,emac4",
        },
+       {
+               .type           = "network",
+               .compatible     = "ibm,emac4sync",
+       },
        {},
 };
 
 
        u32                             fifo_entry_size;
        u32                             mal_burst_size; /* move to MAL ? */
 
+       /* IAHT and GAHT filter parameterization */
+       u32                             xaht_slots_shift;
+       u32                             xaht_width_shift;
+
        /* Descriptor management
         */
        struct mal_descriptor           *tx_desc;
  * Set if we need phy clock workaround for 440ep or 440gr
  */
 #define EMAC_FTR_440EP_PHY_CLK_FIX     0x00000100
+/*
+ * The 405EX and 460EX contain the EMAC4SYNC core
+ */
+#define EMAC_FTR_EMAC4SYNC             0x00000200
 
 
 /* Right now, we don't quite handle the always/possible masks on the
 
        EMAC_FTRS_POSSIBLE      =
 #ifdef CONFIG_IBM_NEW_EMAC_EMAC4
-           EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR |
+           EMAC_FTR_EMAC4      | EMAC_FTR_EMAC4SYNC    |
+           EMAC_FTR_HAS_NEW_STACR      |
            EMAC_FTR_STACR_OC_INVERT | EMAC_FTR_440GX_PHY_CLK_FIX |
 #endif
 #ifdef CONFIG_IBM_NEW_EMAC_TAH
               (EMAC_FTRS_POSSIBLE & dev->features & feature);
 }
 
+/*
+ * Various instances of the EMAC core have varying 1) number of
+ * address match slots, 2) width of the registers for handling address
+ * match slots, 3) number of registers for handling address match
+ * slots and 4) base offset for those registers.
+ *
+ * These macros and inlines handle these differences based on
+ * parameters supplied by the device structure which are, in turn,
+ * initialized based on the "compatible" entry in the device tree.
+ */
+
+#define        EMAC4_XAHT_SLOTS_SHIFT          6
+#define        EMAC4_XAHT_WIDTH_SHIFT          4
+
+#define        EMAC4SYNC_XAHT_SLOTS_SHIFT      8
+#define        EMAC4SYNC_XAHT_WIDTH_SHIFT      5
+
+#define        EMAC_XAHT_SLOTS(dev)            (1 << (dev)->xaht_slots_shift)
+#define        EMAC_XAHT_WIDTH(dev)            (1 << (dev)->xaht_width_shift)
+#define        EMAC_XAHT_REGS(dev)             (1 << ((dev)->xaht_slots_shift - \
+                                              (dev)->xaht_width_shift))
+
+#define        EMAC_XAHT_CRC_TO_SLOT(dev, crc)                 \
+       ((EMAC_XAHT_SLOTS(dev) - 1) -                   \
+        ((crc) >> ((sizeof (u32) * BITS_PER_BYTE) -    \
+                   (dev)->xaht_slots_shift)))
+
+#define        EMAC_XAHT_SLOT_TO_REG(dev, slot)                \
+       ((slot) >> (dev)->xaht_width_shift)
+
+#define        EMAC_XAHT_SLOT_TO_MASK(dev, slot)               \
+       ((u32)(1 << (EMAC_XAHT_WIDTH(dev) - 1)) >>      \
+        ((slot) & (u32)(EMAC_XAHT_WIDTH(dev) - 1)))
+
+static inline u32 *emac_xaht_base(struct emac_instance *dev)
+{
+       struct emac_regs __iomem *p = dev->emacp;
+       int offset;
+
+       /* The first IAHT entry always is the base of the block of
+        * IAHT and GAHT registers.
+        */
+       if (emac_has_feature(dev, EMAC_FTR_EMAC4SYNC))
+               offset = offsetof(struct emac_regs, u1.emac4sync.iaht1);
+       else
+               offset = offsetof(struct emac_regs, u0.emac4.iaht1);
+
+       return ((u32 *)((ptrdiff_t)p + offset));
+}
+
+static inline u32 *emac_gaht_base(struct emac_instance *dev)
+{
+       /* GAHT registers always come after an identical number of
+        * IAHT registers.
+        */
+       return (emac_xaht_base(dev) + EMAC_XAHT_REGS(dev));
+}
+
+static inline u32 *emac_iaht_base(struct emac_instance *dev)
+{
+       /* IAHT registers always come before an identical number of
+        * GAHT registers.
+        */
+       return (emac_xaht_base(dev));
+}
 
 /* Ethtool get_regs complex data.
  * We want to get not just EMAC registers, but also MAL, ZMII, RGMII, TAH
        u32 index;
 };
 
+#define EMAC_ETHTOOL_REGS_VER          0
+#define EMAC_ETHTOOL_REGS_SIZE(dev)    ((dev)->rsrc_regs.end - \
+                                        (dev)->rsrc_regs.start + 1)
+#define EMAC4_ETHTOOL_REGS_VER         1
+#define EMAC4_ETHTOOL_REGS_SIZE(dev)   ((dev)->rsrc_regs.end - \
+                                        (dev)->rsrc_regs.start + 1)
+
 #endif /* __IBM_NEWEMAC_CORE_H */
 
 static void emac_mac_dump(struct emac_instance *dev)
 {
        struct emac_regs __iomem *p = dev->emacp;
+       const int xaht_regs = EMAC_XAHT_REGS(dev);
+       u32 *gaht_base = emac_gaht_base(dev);
+       u32 *iaht_base = emac_iaht_base(dev);
+       int emac4sync = emac_has_feature(dev, EMAC_FTR_EMAC4SYNC);
+       int n;
 
        printk("** EMAC %s registers **\n"
               "MR0 = 0x%08x MR1 = 0x%08x TMR0 = 0x%08x TMR1 = 0x%08x\n"
               "RMR = 0x%08x ISR = 0x%08x ISER = 0x%08x\n"
-              "IAR = %04x%08x VTPID = 0x%04x VTCI = 0x%04x\n"
-              "IAHT: 0x%04x 0x%04x 0x%04x 0x%04x "
-              "GAHT: 0x%04x 0x%04x 0x%04x 0x%04x\n"
-              "LSA = %04x%08x IPGVR = 0x%04x\n"
-              "STACR = 0x%08x TRTR = 0x%08x RWMR = 0x%08x\n"
-              "OCTX = 0x%08x OCRX = 0x%08x IPCR = 0x%08x\n",
+              "IAR = %04x%08x VTPID = 0x%04x VTCI = 0x%04x\n",
               dev->ofdev->node->full_name, in_be32(&p->mr0), in_be32(&p->mr1),
               in_be32(&p->tmr0), in_be32(&p->tmr1),
               in_be32(&p->rmr), in_be32(&p->isr), in_be32(&p->iser),
               in_be32(&p->iahr), in_be32(&p->ialr), in_be32(&p->vtpid),
-              in_be32(&p->vtci),
-              in_be32(&p->iaht1), in_be32(&p->iaht2), in_be32(&p->iaht3),
-              in_be32(&p->iaht4),
-              in_be32(&p->gaht1), in_be32(&p->gaht2), in_be32(&p->gaht3),
-              in_be32(&p->gaht4),
+              in_be32(&p->vtci)
+              );
+
+       if (emac4sync)
+               printk("MAR = %04x%08x MMAR = %04x%08x\n",
+                      in_be32(&p->u0.emac4sync.mahr),
+                      in_be32(&p->u0.emac4sync.malr),
+                      in_be32(&p->u0.emac4sync.mmahr),
+                      in_be32(&p->u0.emac4sync.mmalr)
+                      );
+
+       for (n = 0; n < xaht_regs; n++)
+               printk("IAHT%02d = 0x%08x\n", n + 1, in_be32(iaht_base + n));
+
+       for (n = 0; n < xaht_regs; n++)
+               printk("GAHT%02d = 0x%08x\n", n + 1, in_be32(gaht_base + n));
+
+       printk("LSA = %04x%08x IPGVR = 0x%04x\n"
+              "STACR = 0x%08x TRTR = 0x%08x RWMR = 0x%08x\n"
+              "OCTX = 0x%08x OCRX = 0x%08x\n",
               in_be32(&p->lsah), in_be32(&p->lsal), in_be32(&p->ipgvr),
               in_be32(&p->stacr), in_be32(&p->trtr), in_be32(&p->rwmr),
-              in_be32(&p->octx), in_be32(&p->ocrx), in_be32(&p->ipcr)
-           );
+              in_be32(&p->octx), in_be32(&p->ocrx)
+              );
+
+       if (!emac4sync) {
+               printk("IPCR = 0x%08x\n",
+                      in_be32(&p->u1.emac4.ipcr)
+                      );
+       } else {
+               printk("REVID = 0x%08x TPC = 0x%08x\n",
+                      in_be32(&p->u1.emac4sync.revid),
+                      in_be32(&p->u1.emac4sync.tpc)
+                      );
+       }
 
        emac_desc_dump(dev);
 }
 
 
 #include <linux/types.h>
 
-/* EMAC registers              Write Access rules */
+/* EMAC registers                      Write Access rules */
 struct emac_regs {
-       u32 mr0;                /* special      */
-       u32 mr1;                /* Reset        */
-       u32 tmr0;               /* special      */
-       u32 tmr1;               /* special      */
-       u32 rmr;                /* Reset        */
-       u32 isr;                /* Always       */
-       u32 iser;               /* Reset        */
-       u32 iahr;               /* Reset, R, T  */
-       u32 ialr;               /* Reset, R, T  */
-       u32 vtpid;              /* Reset, R, T  */
-       u32 vtci;               /* Reset, R, T  */
-       u32 ptr;                /* Reset,    T  */
-       u32 iaht1;              /* Reset, R     */
-       u32 iaht2;              /* Reset, R     */
-       u32 iaht3;              /* Reset, R     */
-       u32 iaht4;              /* Reset, R     */
-       u32 gaht1;              /* Reset, R     */
-       u32 gaht2;              /* Reset, R     */
-       u32 gaht3;              /* Reset, R     */
-       u32 gaht4;              /* Reset, R     */
+       /* Common registers across all EMAC implementations. */
+       u32 mr0;                        /* Special      */
+       u32 mr1;                        /* Reset        */
+       u32 tmr0;                       /* Special      */
+       u32 tmr1;                       /* Special      */
+       u32 rmr;                        /* Reset        */
+       u32 isr;                        /* Always       */
+       u32 iser;                       /* Reset        */
+       u32 iahr;                       /* Reset, R, T  */
+       u32 ialr;                       /* Reset, R, T  */
+       u32 vtpid;                      /* Reset, R, T  */
+       u32 vtci;                       /* Reset, R, T  */
+       u32 ptr;                        /* Reset,    T  */
+       union {
+               /* Registers unique to EMAC4 implementations */
+               struct {
+                       u32 iaht1;      /* Reset, R     */
+                       u32 iaht2;      /* Reset, R     */
+                       u32 iaht3;      /* Reset, R     */
+                       u32 iaht4;      /* Reset, R     */
+                       u32 gaht1;      /* Reset, R     */
+                       u32 gaht2;      /* Reset, R     */
+                       u32 gaht3;      /* Reset, R     */
+                       u32 gaht4;      /* Reset, R     */
+               } emac4;
+               /* Registers unique to EMAC4SYNC implementations */
+               struct {
+                       u32 mahr;       /* Reset, R, T  */
+                       u32 malr;       /* Reset, R, T  */
+                       u32 mmahr;      /* Reset, R, T  */
+                       u32 mmalr;      /* Reset, R, T  */
+                       u32 rsvd0[4];
+               } emac4sync;
+       } u0;
+       /* Common registers across all EMAC implementations. */
        u32 lsah;
        u32 lsal;
-       u32 ipgvr;              /* Reset,    T  */
-       u32 stacr;              /* special      */
-       u32 trtr;               /* special      */
-       u32 rwmr;               /* Reset        */
+       u32 ipgvr;                      /* Reset,    T  */
+       u32 stacr;                      /* Special      */
+       u32 trtr;                       /* Special      */
+       u32 rwmr;                       /* Reset        */
        u32 octx;
        u32 ocrx;
-       u32 ipcr;
+       union {
+               /* Registers unique to EMAC4 implementations */
+               struct {
+                       u32 ipcr;
+               } emac4;
+               /* Registers unique to EMAC4SYNC implementations */
+               struct {
+                       u32 rsvd1;
+                       u32 revid;
+                       u32 rsvd2[2];
+                       u32 iaht1;      /* Reset, R     */
+                       u32 iaht2;      /* Reset, R     */
+                       u32 iaht3;      /* Reset, R     */
+                       u32 iaht4;      /* Reset, R     */
+                       u32 iaht5;      /* Reset, R     */
+                       u32 iaht6;      /* Reset, R     */
+                       u32 iaht7;      /* Reset, R     */
+                       u32 iaht8;      /* Reset, R     */
+                       u32 gaht1;      /* Reset, R     */
+                       u32 gaht2;      /* Reset, R     */
+                       u32 gaht3;      /* Reset, R     */
+                       u32 gaht4;      /* Reset, R     */
+                       u32 gaht5;      /* Reset, R     */
+                       u32 gaht6;      /* Reset, R     */
+                       u32 gaht7;      /* Reset, R     */
+                       u32 gaht8;      /* Reset, R     */
+                       u32 tpc;        /* Reset, T     */
+               } emac4sync;
+       } u1;
 };
 
 /*
 #define PHY_MODE_RTBI  7
 #define PHY_MODE_SGMII 8
 
-
-#define EMAC_ETHTOOL_REGS_VER          0
-#define EMAC_ETHTOOL_REGS_SIZE         (sizeof(struct emac_regs) - sizeof(u32))
-#define EMAC4_ETHTOOL_REGS_VER         1
-#define EMAC4_ETHTOOL_REGS_SIZE                sizeof(struct emac_regs)
-
 /* EMACx_MR0 */
 #define EMAC_MR0_RXI                   0x80000000
 #define EMAC_MR0_TXI                   0x40000000