net: ethernet: mtk-star-emac: add timing adjustment support
authorBiao Huang <biao.huang@mediatek.com>
Wed, 29 Jun 2022 03:17:39 +0000 (11:17 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 29 Jun 2022 12:45:30 +0000 (13:45 +0100)
Add simple clock inversion for timing adjustment in driver.
Add property "mediatek,txc-inverse" or "mediatek,rxc-inverse" to
device node when necessary.

Signed-off-by: Biao Huang <biao.huang@mediatek.com>
Signed-off-by: Yinghua Pan <ot_yinghua.pan@mediatek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mediatek/mtk_star_emac.c

index b4d3772..05ce622 100644 (file)
@@ -130,6 +130,11 @@ static const char *const mtk_star_clk_names[] = { "core", "reg", "trans" };
 #define MTK_STAR_REG_INT_MASK                  0x0054
 #define MTK_STAR_BIT_INT_MASK_FNRC             BIT(6)
 
+/* Delay-Macro Register */
+#define MTK_STAR_REG_TEST0                     0x0058
+#define MTK_STAR_BIT_INV_RX_CLK                        BIT(30)
+#define MTK_STAR_BIT_INV_TX_CLK                        BIT(31)
+
 /* Misc. Config Register */
 #define MTK_STAR_REG_TEST1                     0x005c
 #define MTK_STAR_BIT_TEST1_RST_HASH_MBIST      BIT(31)
@@ -267,6 +272,8 @@ struct mtk_star_priv {
        int duplex;
        int pause;
        bool rmii_rxc;
+       bool rx_inv;
+       bool tx_inv;
 
        const struct mtk_star_compat *compat_data;
 
@@ -1449,6 +1456,24 @@ static void mtk_star_clk_disable_unprepare(void *data)
        clk_bulk_disable_unprepare(MTK_STAR_NCLKS, priv->clks);
 }
 
+static int mtk_star_set_timing(struct mtk_star_priv *priv)
+{
+       struct device *dev = mtk_star_get_dev(priv);
+       unsigned int delay_val = 0;
+
+       switch (priv->phy_intf) {
+       case PHY_INTERFACE_MODE_RMII:
+               delay_val |= FIELD_PREP(MTK_STAR_BIT_INV_RX_CLK, priv->rx_inv);
+               delay_val |= FIELD_PREP(MTK_STAR_BIT_INV_TX_CLK, priv->tx_inv);
+               break;
+       default:
+               dev_err(dev, "This interface not supported\n");
+               return -EINVAL;
+       }
+
+       return regmap_write(priv->regs, MTK_STAR_REG_TEST0, delay_val);
+}
+
 static int mtk_star_probe(struct platform_device *pdev)
 {
        struct device_node *of_node;
@@ -1531,6 +1556,8 @@ static int mtk_star_probe(struct platform_device *pdev)
        }
 
        priv->rmii_rxc = of_property_read_bool(of_node, "mediatek,rmii-rxc");
+       priv->rx_inv = of_property_read_bool(of_node, "mediatek,rxc-inverse");
+       priv->tx_inv = of_property_read_bool(of_node, "mediatek,txc-inverse");
 
        if (priv->compat_data->set_interface_mode) {
                ret = priv->compat_data->set_interface_mode(ndev);
@@ -1540,6 +1567,12 @@ static int mtk_star_probe(struct platform_device *pdev)
                }
        }
 
+       ret = mtk_star_set_timing(priv);
+       if (ret) {
+               dev_err(dev, "Failed to set timing, err = %d\n", ret);
+               return -EINVAL;
+       }
+
        ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
        if (ret) {
                dev_err(dev, "unsupported DMA mask\n");