return 0;
 }
 
+static int
+qca8k_setup_of_rgmii_delay(struct qca8k_priv *priv)
+{
+       struct device_node *port_dn;
+       phy_interface_t mode;
+       struct dsa_port *dp;
+       u32 val;
+
+       /* CPU port is already checked */
+       dp = dsa_to_port(priv->ds, 0);
+
+       port_dn = dp->dn;
+
+       /* Check if port 0 is set to the correct type */
+       of_get_phy_mode(port_dn, &mode);
+       if (mode != PHY_INTERFACE_MODE_RGMII_ID &&
+           mode != PHY_INTERFACE_MODE_RGMII_RXID &&
+           mode != PHY_INTERFACE_MODE_RGMII_TXID) {
+               return 0;
+       }
+
+       switch (mode) {
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+               if (of_property_read_u32(port_dn, "rx-internal-delay-ps", &val))
+                       val = 2;
+               else
+                       /* Switch regs accept value in ns, convert ps to ns */
+                       val = val / 1000;
+
+               if (val > QCA8K_MAX_DELAY) {
+                       dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value");
+                       val = 3;
+               }
+
+               priv->rgmii_rx_delay = val;
+               /* Stop here if we need to check only for rx delay */
+               if (mode != PHY_INTERFACE_MODE_RGMII_ID)
+                       break;
+
+               fallthrough;
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+               if (of_property_read_u32(port_dn, "tx-internal-delay-ps", &val))
+                       val = 1;
+               else
+                       /* Switch regs accept value in ns, convert ps to ns */
+                       val = val / 1000;
+
+               if (val > QCA8K_MAX_DELAY) {
+                       dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value");
+                       val = 3;
+               }
+
+               priv->rgmii_tx_delay = val;
+               break;
+       default:
+               return 0;
+       }
+
+       return 0;
+}
+
 static int
 qca8k_setup(struct dsa_switch *ds)
 {
        if (ret)
                return ret;
 
+       ret = qca8k_setup_of_rgmii_delay(priv);
+       if (ret)
+               return ret;
+
        /* Enable CPU Port */
        ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
                            QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
        case 0: /* 1st CPU port */
                if (state->interface != PHY_INTERFACE_MODE_RGMII &&
                    state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
+                   state->interface != PHY_INTERFACE_MODE_RGMII_TXID &&
+                   state->interface != PHY_INTERFACE_MODE_RGMII_RXID &&
                    state->interface != PHY_INTERFACE_MODE_SGMII)
                        return;
 
        case 6: /* 2nd CPU port / external PHY */
                if (state->interface != PHY_INTERFACE_MODE_RGMII &&
                    state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
+                   state->interface != PHY_INTERFACE_MODE_RGMII_TXID &&
+                   state->interface != PHY_INTERFACE_MODE_RGMII_RXID &&
                    state->interface != PHY_INTERFACE_MODE_SGMII &&
                    state->interface != PHY_INTERFACE_MODE_1000BASEX)
                        return;
                qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
                break;
        case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
                /* RGMII_ID needs internal delay. This is enabled through
                 * PORT5_PAD_CTRL for all ports, rather than individual port
                 * registers
                 */
                qca8k_write(priv, reg,
                            QCA8K_PORT_PAD_RGMII_EN |
-                           QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) |
-                           QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY));
+                           QCA8K_PORT_PAD_RGMII_TX_DELAY(priv->rgmii_tx_delay) |
+                           QCA8K_PORT_PAD_RGMII_RX_DELAY(priv->rgmii_rx_delay) |
+                           QCA8K_PORT_PAD_RGMII_TX_DELAY_EN |
+                           QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
                /* QCA8337 requires to set rgmii rx delay */
                if (priv->switch_id == QCA8K_ID_QCA8337)
                        qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
                if (state->interface != PHY_INTERFACE_MODE_NA &&
                    state->interface != PHY_INTERFACE_MODE_RGMII &&
                    state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
+                   state->interface != PHY_INTERFACE_MODE_RGMII_TXID &&
+                   state->interface != PHY_INTERFACE_MODE_RGMII_RXID &&
                    state->interface != PHY_INTERFACE_MODE_SGMII)
                        goto unsupported;
                break;
                if (state->interface != PHY_INTERFACE_MODE_NA &&
                    state->interface != PHY_INTERFACE_MODE_RGMII &&
                    state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
+                   state->interface != PHY_INTERFACE_MODE_RGMII_TXID &&
+                   state->interface != PHY_INTERFACE_MODE_RGMII_RXID &&
                    state->interface != PHY_INTERFACE_MODE_SGMII &&
                    state->interface != PHY_INTERFACE_MODE_1000BASEX)
                        goto unsupported;
 
 #define QCA8K_REG_PORT5_PAD_CTRL                       0x008
 #define QCA8K_REG_PORT6_PAD_CTRL                       0x00c
 #define   QCA8K_PORT_PAD_RGMII_EN                      BIT(26)
-#define   QCA8K_PORT_PAD_RGMII_TX_DELAY(x)             \
-                                               ((0x8 + (x & 0x3)) << 22)
-#define   QCA8K_PORT_PAD_RGMII_RX_DELAY(x)             \
-                                               ((0x10 + (x & 0x3)) << 20)
-#define   QCA8K_MAX_DELAY                              3
+#define   QCA8K_PORT_PAD_RGMII_TX_DELAY(x)             ((x) << 22)
+#define   QCA8K_PORT_PAD_RGMII_RX_DELAY(x)             ((x) << 20)
+#define          QCA8K_PORT_PAD_RGMII_TX_DELAY_EN              BIT(25)
 #define   QCA8K_PORT_PAD_RGMII_RX_DELAY_EN             BIT(24)
+#define   QCA8K_MAX_DELAY                              3
 #define   QCA8K_PORT_PAD_SGMII_EN                      BIT(7)
 #define QCA8K_REG_PWS                                  0x010
 #define   QCA8K_PWS_SERDES_AEN_DIS                     BIT(7)
 struct qca8k_priv {
        u8 switch_id;
        u8 switch_revision;
+       u8 rgmii_tx_delay;
+       u8 rgmii_rx_delay;
        struct regmap *regmap;
        struct mii_bus *bus;
        struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];