return mv88e6xxx_g1_atu_set_age_time(chip, 300000);
 }
 
+static int mv88e6xxx_irl_setup(struct mv88e6xxx_chip *chip)
+{
+       int port;
+       int err;
+
+       if (!chip->info->ops->irl_init_all)
+               return 0;
+
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               /* Disable ingress rate limiting by resetting all per port
+                * ingress rate limit resources to their initial state.
+                */
+               err = chip->info->ops->irl_init_all(chip, port);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
 {
        u16 pvlan = 0;
                        goto unlock;
        }
 
+       err = mv88e6xxx_irl_setup(chip);
+       if (err)
+               goto unlock;
+
        err = mv88e6xxx_phy_setup(chip);
        if (err)
                goto unlock;
 
 static const struct mv88e6xxx_ops mv88e6085_ops = {
        /* MV88E6XXX_FAMILY_6097 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
        .phy_read = mv88e6185_phy_ppu_read,
        .phy_write = mv88e6185_phy_ppu_write,
 
 static const struct mv88e6xxx_ops mv88e6097_ops = {
        /* MV88E6XXX_FAMILY_6097 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
        .phy_read = mv88e6xxx_g2_smi_phy_read,
        .phy_write = mv88e6xxx_g2_smi_phy_write,
 
 static const struct mv88e6xxx_ops mv88e6123_ops = {
        /* MV88E6XXX_FAMILY_6165 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
        .phy_read = mv88e6xxx_g2_smi_phy_read,
        .phy_write = mv88e6xxx_g2_smi_phy_write,
 
 static const struct mv88e6xxx_ops mv88e6141_ops = {
        /* MV88E6XXX_FAMILY_6341 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6161_ops = {
        /* MV88E6XXX_FAMILY_6165 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
        .phy_read = mv88e6xxx_g2_smi_phy_read,
        .phy_write = mv88e6xxx_g2_smi_phy_write,
 
 static const struct mv88e6xxx_ops mv88e6165_ops = {
        /* MV88E6XXX_FAMILY_6165 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
        .phy_read = mv88e6165_phy_read,
        .phy_write = mv88e6165_phy_write,
 
 static const struct mv88e6xxx_ops mv88e6171_ops = {
        /* MV88E6XXX_FAMILY_6351 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
        .phy_read = mv88e6xxx_g2_smi_phy_read,
        .phy_write = mv88e6xxx_g2_smi_phy_write,
 
 static const struct mv88e6xxx_ops mv88e6172_ops = {
        /* MV88E6XXX_FAMILY_6352 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6175_ops = {
        /* MV88E6XXX_FAMILY_6351 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
        .phy_read = mv88e6xxx_g2_smi_phy_read,
        .phy_write = mv88e6xxx_g2_smi_phy_write,
 
 static const struct mv88e6xxx_ops mv88e6176_ops = {
        /* MV88E6XXX_FAMILY_6352 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6190_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6190x_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6191_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6240_ops = {
        /* MV88E6XXX_FAMILY_6352 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6290_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6320_ops = {
        /* MV88E6XXX_FAMILY_6320 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6321_ops = {
        /* MV88E6XXX_FAMILY_6321 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6341_ops = {
        /* MV88E6XXX_FAMILY_6341 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6350_ops = {
        /* MV88E6XXX_FAMILY_6351 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
        .phy_read = mv88e6xxx_g2_smi_phy_read,
        .phy_write = mv88e6xxx_g2_smi_phy_write,
 
 static const struct mv88e6xxx_ops mv88e6351_ops = {
        /* MV88E6XXX_FAMILY_6351 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
        .phy_read = mv88e6xxx_g2_smi_phy_read,
        .phy_write = mv88e6xxx_g2_smi_phy_write,
 
 static const struct mv88e6xxx_ops mv88e6352_ops = {
        /* MV88E6XXX_FAMILY_6352 */
+       .irl_init_all = mv88e6352_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom16,
        .set_eeprom = mv88e6xxx_g2_set_eeprom16,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6390_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
 static const struct mv88e6xxx_ops mv88e6390x_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
        .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 
        MV88E6XXX_CAP_G2_INT,           /* (0x00) Interrupt Status */
        MV88E6XXX_CAP_G2_MGMT_EN_2X,    /* (0x02) MGMT Enable Register 2x */
        MV88E6XXX_CAP_G2_MGMT_EN_0X,    /* (0x03) MGMT Enable Register 0x */
-       MV88E6XXX_CAP_G2_IRL_CMD,       /* (0x09) Ingress Rate Command */
-       MV88E6XXX_CAP_G2_IRL_DATA,      /* (0x0a) Ingress Rate Data */
        MV88E6XXX_CAP_G2_POT,           /* (0x0f) Priority Override Table */
 
        /* Per VLAN Spanning Tree Unit (STU).
 #define MV88E6XXX_FLAG_G2_INT          BIT_ULL(MV88E6XXX_CAP_G2_INT)
 #define MV88E6XXX_FLAG_G2_MGMT_EN_2X   BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_2X)
 #define MV88E6XXX_FLAG_G2_MGMT_EN_0X   BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_0X)
-#define MV88E6XXX_FLAG_G2_IRL_CMD      BIT_ULL(MV88E6XXX_CAP_G2_IRL_CMD)
-#define MV88E6XXX_FLAG_G2_IRL_DATA     BIT_ULL(MV88E6XXX_CAP_G2_IRL_DATA)
 #define MV88E6XXX_FLAG_G2_POT          BIT_ULL(MV88E6XXX_CAP_G2_POT)
 
-/* Ingress Rate Limit unit */
-#define MV88E6XXX_FLAGS_IRL            \
-       (MV88E6XXX_FLAG_G2_IRL_CMD |    \
-        MV88E6XXX_FLAG_G2_IRL_DATA)
-
 /* Multi-chip Addressing Mode */
 #define MV88E6XXX_FLAGS_MULTI_CHIP     \
        (MV88E6XXX_FLAG_SMI_CMD |       \
         MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
         MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
         MV88E6XXX_FLAG_G2_POT |        \
-        MV88E6XXX_FLAGS_IRL |          \
         MV88E6XXX_FLAGS_MULTI_CHIP)
 
 #define MV88E6XXX_FLAGS_FAMILY_6165    \
         MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
         MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
         MV88E6XXX_FLAG_G2_POT |        \
-        MV88E6XXX_FLAGS_IRL |          \
         MV88E6XXX_FLAGS_MULTI_CHIP)
 
 #define MV88E6XXX_FLAGS_FAMILY_6185    \
         MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
         MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
         MV88E6XXX_FLAG_G2_POT |        \
-        MV88E6XXX_FLAGS_IRL |          \
         MV88E6XXX_FLAGS_MULTI_CHIP)
 
 #define MV88E6XXX_FLAGS_FAMILY_6341    \
         MV88E6XXX_FLAG_GLOBAL2 |       \
         MV88E6XXX_FLAG_G2_INT |        \
         MV88E6XXX_FLAG_G2_POT |        \
-        MV88E6XXX_FLAGS_IRL |          \
         MV88E6XXX_FLAGS_MULTI_CHIP)
 
 #define MV88E6XXX_FLAGS_FAMILY_6351    \
         MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
         MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
         MV88E6XXX_FLAG_G2_POT |        \
-        MV88E6XXX_FLAGS_IRL |          \
         MV88E6XXX_FLAGS_MULTI_CHIP)
 
 #define MV88E6XXX_FLAGS_FAMILY_6352    \
         MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
         MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
         MV88E6XXX_FLAG_G2_POT |        \
-        MV88E6XXX_FLAGS_IRL |          \
         MV88E6XXX_FLAGS_MULTI_CHIP)
 
 #define MV88E6XXX_FLAGS_FAMILY_6390    \
        (MV88E6XXX_FLAG_EEE |           \
         MV88E6XXX_FLAG_GLOBAL2 |       \
         MV88E6XXX_FLAG_G2_INT |        \
-        MV88E6XXX_FLAGS_IRL |          \
         MV88E6XXX_FLAGS_MULTI_CHIP)
 
 struct mv88e6xxx_ops;
 };
 
 struct mv88e6xxx_ops {
+       /* Ingress Rate Limit unit (IRL) operations */
+       int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port);
+
        int (*get_eeprom)(struct mv88e6xxx_chip *chip,
                          struct ethtool_eeprom *eeprom, u8 *data);
        int (*set_eeprom)(struct mv88e6xxx_chip *chip,
 
  * Offset 0x0A: Ingress Rate Data register
  */
 
-static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip)
+static int mv88e6xxx_g2_irl_wait(struct mv88e6xxx_chip *chip)
 {
-       int port, err;
-
-       /* Init all Ingress Rate Limit resources of all ports */
-       for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
-               /* XXX newer chips (like 88E6390) have different 2-bit ops */
-               err = mv88e6xxx_g2_write(chip, GLOBAL2_IRL_CMD,
-                                        GLOBAL2_IRL_CMD_OP_INIT_ALL |
-                                        (port << 8));
-               if (err)
-                       break;
+       return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_IRL_CMD,
+                                MV88E6XXX_G2_IRL_CMD_BUSY);
+}
 
-               /* Wait for the operation to complete */
-               err = mv88e6xxx_g2_wait(chip, GLOBAL2_IRL_CMD,
-                                       GLOBAL2_IRL_CMD_BUSY);
-               if (err)
-                       break;
-       }
+static int mv88e6xxx_g2_irl_op(struct mv88e6xxx_chip *chip, u16 op, int port,
+                              int res, int reg)
+{
+       int err;
 
-       return err;
+       err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_IRL_CMD,
+                                MV88E6XXX_G2_IRL_CMD_BUSY | op | (port << 8) |
+                                (res << 5) | reg);
+       if (err)
+               return err;
+
+       return mv88e6xxx_g2_irl_wait(chip);
+}
+
+int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port)
+{
+       return mv88e6xxx_g2_irl_op(chip, MV88E6352_G2_IRL_CMD_OP_INIT_ALL, port,
+                                  0, 0);
+}
+
+int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port)
+{
+       return mv88e6xxx_g2_irl_op(chip, MV88E6390_G2_IRL_CMD_OP_INIT_ALL, port,
+                                  0, 0);
 }
 
 /* Offset 0x0B: Cross-chip Port VLAN (Addr) Register
        if (err)
                return err;
 
-       if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_IRL)) {
-               /* Disable ingress rate limiting by resetting all per port
-                * ingress rate limit resources to their initial state.
-                */
-               err = mv88e6xxx_g2_clear_irl(chip);
-                       if (err)
-                               return err;
-       }
-
        if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) {
                /* Clear the priority override table. */
                err = mv88e6xxx_g2_clear_pot(chip);
 
 #define GLOBAL2_TRUNK_MAPPING  0x08
 #define GLOBAL2_TRUNK_MAPPING_UPDATE           BIT(15)
 #define GLOBAL2_TRUNK_MAPPING_ID_SHIFT         11
-#define GLOBAL2_IRL_CMD                0x09
-#define GLOBAL2_IRL_CMD_BUSY   BIT(15)
-#define GLOBAL2_IRL_CMD_OP_INIT_ALL    ((0x001 << 12) | GLOBAL2_IRL_CMD_BUSY)
-#define GLOBAL2_IRL_CMD_OP_INIT_SEL    ((0x010 << 12) | GLOBAL2_IRL_CMD_BUSY)
-#define GLOBAL2_IRL_CMD_OP_WRITE_SEL   ((0x011 << 12) | GLOBAL2_IRL_CMD_BUSY)
-#define GLOBAL2_IRL_CMD_OP_READ_SEL    ((0x100 << 12) | GLOBAL2_IRL_CMD_BUSY)
-#define GLOBAL2_IRL_DATA       0x0a
+
+/* Offset 0x09: Ingress Rate Command Register */
+#define MV88E6XXX_G2_IRL_CMD                   0x09
+#define MV88E6XXX_G2_IRL_CMD_BUSY              0x8000
+#define MV88E6352_G2_IRL_CMD_OP_MASK           0x7000
+#define MV88E6352_G2_IRL_CMD_OP_NOOP           0x0000
+#define MV88E6352_G2_IRL_CMD_OP_INIT_ALL       0x1000
+#define MV88E6352_G2_IRL_CMD_OP_INIT_RES       0x2000
+#define MV88E6352_G2_IRL_CMD_OP_WRITE_REG      0x3000
+#define MV88E6352_G2_IRL_CMD_OP_READ_REG       0x4000
+#define MV88E6390_G2_IRL_CMD_OP_MASK           0x6000
+#define MV88E6390_G2_IRL_CMD_OP_READ_REG       0x0000
+#define MV88E6390_G2_IRL_CMD_OP_INIT_ALL       0x2000
+#define MV88E6390_G2_IRL_CMD_OP_INIT_RES       0x4000
+#define MV88E6390_G2_IRL_CMD_OP_WRITE_REG      0x6000
+#define MV88E6352_G2_IRL_CMD_PORT_MASK         0x0f00
+#define MV88E6390_G2_IRL_CMD_PORT_MASK         0x1f00
+#define MV88E6XXX_G2_IRL_CMD_RES_MASK          0x00e0
+#define MV88E6XXX_G2_IRL_CMD_REG_MASK          0x000f
+
+/* Offset 0x0A: Ingress Rate Data Register */
+#define MV88E6XXX_G2_IRL_DATA          0x0a
+#define MV88E6XXX_G2_IRL_DATA_MASK     0xffff
+
 #define GLOBAL2_PVT_ADDR       0x0b
 #define GLOBAL2_PVT_ADDR_BUSY  BIT(15)
 #define GLOBAL2_PVT_ADDR_OP_INIT_ONES  ((0x01 << 12) | GLOBAL2_PVT_ADDR_BUSY)
        return 0;
 }
 
+int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port);
+
 int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip,
                              struct mii_bus *bus,
                              int addr, int reg, u16 *val);
        return 0;
 }
 
+static inline int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip,
+                                           int port)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip,
+                                           int port)
+{
+       return -EOPNOTSUPP;
+}
+
 static inline int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip,
                                            struct mii_bus *bus,
                                            int addr, int reg, u16 *val)