net: ethernet: mediatek: support MT7621 SoC ethernet hardware
authorBjørn Mork <bjorn@mork.no>
Wed, 30 Jan 2019 01:24:04 +0000 (11:24 +1000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 30 Jan 2019 22:26:07 +0000 (14:26 -0800)
The Mediatek MT7621 SoC contains the same ethernet hardware module as
used on a number of other MediaTek SoC parts. There are some minor
differences to deal with but we can use the same driver to support
them all.

This patch is based on work by Bjørn Mork <bjorn@mork.no>, and his
original patch is at:

https://github.com/bmork/LEDE/commit/3293bc63f5461ca1eb0bbc4ed90145335e7e3404

There is an additional compatible devicetree type added, and the primary
change to the code required is to support a single interrupt (for both
RX and TX interrupts).

Signed-off-by: Bjørn Mork <bjorn@mork.no>
[gerg@kernel.org: rebase to mainline and irq handler fix]
Signed-off-by: Greg Ungerer <gerg@kernel.org>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Sean Wang <sean.wang@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mediatek/Kconfig
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_eth_soc.h

index f9149d2a469409925d960275df13913881010ed7..43656f9618910af841d9591ab70a1058fd3eb0e6 100644 (file)
@@ -1,6 +1,6 @@
 config NET_VENDOR_MEDIATEK
        bool "MediaTek ethernet driver"
-       depends on ARCH_MEDIATEK
+       depends on ARCH_MEDIATEK || SOC_MT7621
        ---help---
          If you have a Mediatek SoC with ethernet, say Y.
 
index 49f926b7a91cffa90e07d08850632ba1d340722d..94d4663e39335570929cd7c2467d10224f100c26 100644 (file)
@@ -1745,6 +1745,22 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t mtk_handle_irq(int irq, void *_eth)
+{
+       struct mtk_eth *eth = _eth;
+
+       if (mtk_r32(eth, MTK_PDMA_INT_MASK) & MTK_RX_DONE_INT) {
+               if (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT)
+                       mtk_handle_irq_rx(irq, _eth);
+       }
+       if (mtk_r32(eth, MTK_QDMA_INT_MASK) & MTK_TX_DONE_INT) {
+               if (mtk_r32(eth, MTK_QMTK_INT_STATUS) & MTK_TX_DONE_INT)
+                       mtk_handle_irq_tx(irq, _eth);
+       }
+
+       return IRQ_HANDLED;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void mtk_poll_controller(struct net_device *dev)
 {
@@ -2485,7 +2501,10 @@ static int mtk_probe(struct platform_device *pdev)
        }
 
        for (i = 0; i < 3; i++) {
-               eth->irq[i] = platform_get_irq(pdev, i);
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0)
+                       eth->irq[i] = eth->irq[0];
+               else
+                       eth->irq[i] = platform_get_irq(pdev, i);
                if (eth->irq[i] < 0) {
                        dev_err(&pdev->dev, "no IRQ%d resource found\n", i);
                        return -ENXIO;
@@ -2528,13 +2547,21 @@ static int mtk_probe(struct platform_device *pdev)
                        goto err_deinit_hw;
        }
 
-       err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
-                              dev_name(eth->dev), eth);
-       if (err)
-               goto err_free_dev;
+       if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
+               err = devm_request_irq(eth->dev, eth->irq[0],
+                                      mtk_handle_irq, 0,
+                                      dev_name(eth->dev), eth);
+       } else {
+               err = devm_request_irq(eth->dev, eth->irq[1],
+                                      mtk_handle_irq_tx, 0,
+                                      dev_name(eth->dev), eth);
+               if (err)
+                       goto err_free_dev;
 
-       err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
-                              dev_name(eth->dev), eth);
+               err = devm_request_irq(eth->dev, eth->irq[2],
+                                      mtk_handle_irq_rx, 0,
+                                      dev_name(eth->dev), eth);
+       }
        if (err)
                goto err_free_dev;
 
@@ -2607,6 +2634,12 @@ static const struct mtk_soc_data mt2701_data = {
        .required_pctl = true,
 };
 
+static const struct mtk_soc_data mt7621_data = {
+       .caps = MTK_SHARED_INT,
+       .required_clks = MT7621_CLKS_BITMAP,
+       .required_pctl = false,
+};
+
 static const struct mtk_soc_data mt7622_data = {
        .caps = MTK_DUAL_GMAC_SHARED_SGMII | MTK_GMAC1_ESW | MTK_HWLRO,
        .required_clks = MT7622_CLKS_BITMAP,
@@ -2621,6 +2654,7 @@ static const struct mtk_soc_data mt7623_data = {
 
 const struct of_device_id of_mtk_match[] = {
        { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data},
+       { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data},
        { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data},
        { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
        {},
index 46819297fc3ed4f15934eb9bd8173aa2eec80a5b..f7501997cea08a0c31f9ebceb938384a9b1a5539 100644 (file)
 #define ETHSYS_CHIPID4_7       0x4
 #define MT7623_ETH             7623
 #define MT7622_ETH             7622
+#define MT7621_ETH             7621
 
 /* ethernet subsystem config register */
 #define ETHSYS_SYSCFG0         0x14
@@ -488,6 +489,8 @@ enum mtk_clks_map {
                                 BIT(MTK_CLK_SGMII_CDR_FB) | \
                                 BIT(MTK_CLK_SGMII_CK) | \
                                 BIT(MTK_CLK_ETH2PLL))
+#define MT7621_CLKS_BITMAP     (0)
+
 enum mtk_dev_state {
        MTK_HW_INIT,
        MTK_RESETTING
@@ -567,6 +570,7 @@ struct mtk_rx_ring {
 #define MTK_DUAL_GMAC_SHARED_SGMII     (BIT(11) | MTK_GMAC1_SGMII | \
                                         MTK_GMAC2_SGMII)
 #define MTK_HWLRO                      BIT(12)
+#define MTK_SHARED_INT                 BIT(13)
 #define MTK_HAS_CAPS(caps, _x)         (((caps) & (_x)) == (_x))
 
 /* struct mtk_eth_data -       This is the structure holding all differences